1 // Copyright 2010 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "src/extensions/externalize-string-extension.h" 6 7 #include "src/api.h" 8 #include "src/handles.h" 9 #include "src/isolate.h" 10 #include "src/objects-inl.h" 11 12 namespace v8 { 13 namespace internal { 14 15 template <typename Char, typename Base> 16 class SimpleStringResource : public Base { 17 public: 18 // Takes ownership of |data|. 19 SimpleStringResource(Char* data, size_t length) 20 : data_(data), 21 length_(length) {} 22 23 virtual ~SimpleStringResource() { delete[] data_; } 24 25 virtual const Char* data() const { return data_; } 26 27 virtual size_t length() const { return length_; } 28 29 private: 30 Char* const data_; 31 const size_t length_; 32 }; 33 34 35 typedef SimpleStringResource<char, v8::String::ExternalOneByteStringResource> 36 SimpleOneByteStringResource; 37 typedef SimpleStringResource<uc16, v8::String::ExternalStringResource> 38 SimpleTwoByteStringResource; 39 40 const char* const ExternalizeStringExtension::kSource = 41 "native function externalizeString();" 42 "native function isOneByteString();" 43 "function x() { return 1; }"; 44 45 v8::Local<v8::FunctionTemplate> 46 ExternalizeStringExtension::GetNativeFunctionTemplate( 47 v8::Isolate* isolate, v8::Local<v8::String> str) { 48 if (strcmp(*v8::String::Utf8Value(str), "externalizeString") == 0) { 49 return v8::FunctionTemplate::New(isolate, 50 ExternalizeStringExtension::Externalize); 51 } else { 52 DCHECK(strcmp(*v8::String::Utf8Value(str), "isOneByteString") == 0); 53 return v8::FunctionTemplate::New(isolate, 54 ExternalizeStringExtension::IsOneByte); 55 } 56 } 57 58 59 void ExternalizeStringExtension::Externalize( 60 const v8::FunctionCallbackInfo<v8::Value>& args) { 61 if (args.Length() < 1 || !args[0]->IsString()) { 62 args.GetIsolate()->ThrowException( 63 v8::String::NewFromUtf8( 64 args.GetIsolate(), 65 "First parameter to externalizeString() must be a string.", 66 NewStringType::kNormal).ToLocalChecked()); 67 return; 68 } 69 bool force_two_byte = false; 70 if (args.Length() >= 2) { 71 if (args[1]->IsBoolean()) { 72 force_two_byte = 73 args[1] 74 ->BooleanValue(args.GetIsolate()->GetCurrentContext()) 75 .FromJust(); 76 } else { 77 args.GetIsolate()->ThrowException( 78 v8::String::NewFromUtf8( 79 args.GetIsolate(), 80 "Second parameter to externalizeString() must be a boolean.", 81 NewStringType::kNormal).ToLocalChecked()); 82 return; 83 } 84 } 85 bool result = false; 86 Handle<String> string = Utils::OpenHandle(*args[0].As<v8::String>()); 87 if (string->IsExternalString()) { 88 args.GetIsolate()->ThrowException( 89 v8::String::NewFromUtf8(args.GetIsolate(), 90 "externalizeString() can't externalize twice.", 91 NewStringType::kNormal).ToLocalChecked()); 92 return; 93 } 94 if (string->IsOneByteRepresentation() && !force_two_byte) { 95 uint8_t* data = new uint8_t[string->length()]; 96 String::WriteToFlat(*string, data, 0, string->length()); 97 SimpleOneByteStringResource* resource = new SimpleOneByteStringResource( 98 reinterpret_cast<char*>(data), string->length()); 99 result = string->MakeExternal(resource); 100 if (result) { 101 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); 102 isolate->heap()->RegisterExternalString(*string); 103 } 104 if (!result) delete resource; 105 } else { 106 uc16* data = new uc16[string->length()]; 107 String::WriteToFlat(*string, data, 0, string->length()); 108 SimpleTwoByteStringResource* resource = new SimpleTwoByteStringResource( 109 data, string->length()); 110 result = string->MakeExternal(resource); 111 if (result) { 112 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); 113 isolate->heap()->RegisterExternalString(*string); 114 } 115 if (!result) delete resource; 116 } 117 if (!result) { 118 args.GetIsolate()->ThrowException( 119 v8::String::NewFromUtf8(args.GetIsolate(), 120 "externalizeString() failed.", 121 NewStringType::kNormal).ToLocalChecked()); 122 return; 123 } 124 } 125 126 127 void ExternalizeStringExtension::IsOneByte( 128 const v8::FunctionCallbackInfo<v8::Value>& args) { 129 if (args.Length() != 1 || !args[0]->IsString()) { 130 args.GetIsolate()->ThrowException( 131 v8::String::NewFromUtf8( 132 args.GetIsolate(), 133 "isOneByteString() requires a single string argument.", 134 NewStringType::kNormal).ToLocalChecked()); 135 return; 136 } 137 bool is_one_byte = 138 Utils::OpenHandle(*args[0].As<v8::String>())->IsOneByteRepresentation(); 139 args.GetReturnValue().Set(is_one_byte); 140 } 141 142 } // namespace internal 143 } // namespace v8 144