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 namespace v8 { 8 namespace internal { 9 10 template <typename Char, typename Base> 11 class SimpleStringResource : public Base { 12 public: 13 // Takes ownership of |data|. 14 SimpleStringResource(Char* data, size_t length) 15 : data_(data), 16 length_(length) {} 17 18 virtual ~SimpleStringResource() { delete[] data_; } 19 20 virtual const Char* data() const { return data_; } 21 22 virtual size_t length() const { return length_; } 23 24 private: 25 Char* const data_; 26 const size_t length_; 27 }; 28 29 30 typedef SimpleStringResource<char, v8::String::ExternalAsciiStringResource> 31 SimpleAsciiStringResource; 32 typedef SimpleStringResource<uc16, v8::String::ExternalStringResource> 33 SimpleTwoByteStringResource; 34 35 36 const char* const ExternalizeStringExtension::kSource = 37 "native function externalizeString();" 38 "native function isAsciiString();"; 39 40 v8::Handle<v8::FunctionTemplate> 41 ExternalizeStringExtension::GetNativeFunctionTemplate( 42 v8::Isolate* isolate, v8::Handle<v8::String> str) { 43 if (strcmp(*v8::String::Utf8Value(str), "externalizeString") == 0) { 44 return v8::FunctionTemplate::New(isolate, 45 ExternalizeStringExtension::Externalize); 46 } else { 47 ASSERT(strcmp(*v8::String::Utf8Value(str), "isAsciiString") == 0); 48 return v8::FunctionTemplate::New(isolate, 49 ExternalizeStringExtension::IsAscii); 50 } 51 } 52 53 54 void ExternalizeStringExtension::Externalize( 55 const v8::FunctionCallbackInfo<v8::Value>& args) { 56 if (args.Length() < 1 || !args[0]->IsString()) { 57 args.GetIsolate()->ThrowException(v8::String::NewFromUtf8( 58 args.GetIsolate(), 59 "First parameter to externalizeString() must be a string.")); 60 return; 61 } 62 bool force_two_byte = false; 63 if (args.Length() >= 2) { 64 if (args[1]->IsBoolean()) { 65 force_two_byte = args[1]->BooleanValue(); 66 } else { 67 args.GetIsolate()->ThrowException(v8::String::NewFromUtf8( 68 args.GetIsolate(), 69 "Second parameter to externalizeString() must be a boolean.")); 70 return; 71 } 72 } 73 bool result = false; 74 Handle<String> string = Utils::OpenHandle(*args[0].As<v8::String>()); 75 if (string->IsExternalString()) { 76 args.GetIsolate()->ThrowException(v8::String::NewFromUtf8( 77 args.GetIsolate(), 78 "externalizeString() can't externalize twice.")); 79 return; 80 } 81 if (string->IsOneByteRepresentation() && !force_two_byte) { 82 uint8_t* data = new uint8_t[string->length()]; 83 String::WriteToFlat(*string, data, 0, string->length()); 84 SimpleAsciiStringResource* resource = new SimpleAsciiStringResource( 85 reinterpret_cast<char*>(data), string->length()); 86 result = string->MakeExternal(resource); 87 if (result) { 88 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); 89 isolate->heap()->external_string_table()->AddString(*string); 90 } 91 if (!result) delete resource; 92 } else { 93 uc16* data = new uc16[string->length()]; 94 String::WriteToFlat(*string, data, 0, string->length()); 95 SimpleTwoByteStringResource* resource = new SimpleTwoByteStringResource( 96 data, string->length()); 97 result = string->MakeExternal(resource); 98 if (result) { 99 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); 100 isolate->heap()->external_string_table()->AddString(*string); 101 } 102 if (!result) delete resource; 103 } 104 if (!result) { 105 args.GetIsolate()->ThrowException(v8::String::NewFromUtf8( 106 args.GetIsolate(), "externalizeString() failed.")); 107 return; 108 } 109 } 110 111 112 void ExternalizeStringExtension::IsAscii( 113 const v8::FunctionCallbackInfo<v8::Value>& args) { 114 if (args.Length() != 1 || !args[0]->IsString()) { 115 args.GetIsolate()->ThrowException(v8::String::NewFromUtf8( 116 args.GetIsolate(), 117 "isAsciiString() requires a single string argument.")); 118 return; 119 } 120 bool is_one_byte = 121 Utils::OpenHandle(*args[0].As<v8::String>())->IsOneByteRepresentation(); 122 args.GetReturnValue().Set(is_one_byte); 123 } 124 125 } } // namespace v8::internal 126