14a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com// Copyright 2010 the V8 project authors. All rights reserved. 23484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// Use of this source code is governed by a BSD-style license that can be 33484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// found in the LICENSE file. 44a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com 5196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/extensions/externalize-string-extension.h" 64a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com 74a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.comnamespace v8 { 84a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.comnamespace internal { 94a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com 104a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.comtemplate <typename Char, typename Base> 114a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.comclass SimpleStringResource : public Base { 124a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com public: 134a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com // Takes ownership of |data|. 144a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com SimpleStringResource(Char* data, size_t length) 154a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com : data_(data), 164a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com length_(length) {} 174a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com 184a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com virtual ~SimpleStringResource() { delete[] data_; } 194a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com 204a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com virtual const Char* data() const { return data_; } 214a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com 224a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com virtual size_t length() const { return length_; } 234a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com 244a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com private: 254a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com Char* const data_; 264a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com const size_t length_; 274a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com}; 284a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com 294a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com 302c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.orgtypedef SimpleStringResource<char, v8::String::ExternalOneByteStringResource> 312c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org SimpleOneByteStringResource; 324a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.comtypedef SimpleStringResource<uc16, v8::String::ExternalStringResource> 334a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com SimpleTwoByteStringResource; 344a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com 354a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com 364a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.comconst char* const ExternalizeStringExtension::kSource = 374a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com "native function externalizeString();" 382c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org "native function isOneByteString();"; 394a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com 409f18d9111f676f2899d9aa2444130c985eb75395machenbach@chromium.orgv8::Handle<v8::FunctionTemplate> 419f18d9111f676f2899d9aa2444130c985eb75395machenbach@chromium.orgExternalizeStringExtension::GetNativeFunctionTemplate( 429f18d9111f676f2899d9aa2444130c985eb75395machenbach@chromium.org v8::Isolate* isolate, v8::Handle<v8::String> str) { 43906e2fb760f52fe6e75b744b1ea42576ea5b2c29ulan@chromium.org if (strcmp(*v8::String::Utf8Value(str), "externalizeString") == 0) { 444f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org return v8::FunctionTemplate::New(isolate, 454f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org ExternalizeStringExtension::Externalize); 464a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com } else { 472c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org DCHECK(strcmp(*v8::String::Utf8Value(str), "isOneByteString") == 0); 484f99be9ff2091451687891a05d99cc31990de709hpayer@chromium.org return v8::FunctionTemplate::New(isolate, 492c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org ExternalizeStringExtension::IsOneByte); 504a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com } 514a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com} 524a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com 534a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com 54d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.orgvoid ExternalizeStringExtension::Externalize( 55d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org const v8::FunctionCallbackInfo<v8::Value>& args) { 564a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com if (args.Length() < 1 || !args[0]->IsString()) { 57f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org args.GetIsolate()->ThrowException(v8::String::NewFromUtf8( 58f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org args.GetIsolate(), 594a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com "First parameter to externalizeString() must be a string.")); 60d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org return; 614a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com } 624a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com bool force_two_byte = false; 634a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com if (args.Length() >= 2) { 644a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com if (args[1]->IsBoolean()) { 654a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com force_two_byte = args[1]->BooleanValue(); 664a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com } else { 67f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org args.GetIsolate()->ThrowException(v8::String::NewFromUtf8( 68f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org args.GetIsolate(), 69d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org "Second parameter to externalizeString() must be a boolean.")); 70d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org return; 714a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com } 724a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com } 734a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com bool result = false; 744a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com Handle<String> string = Utils::OpenHandle(*args[0].As<v8::String>()); 754a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com if (string->IsExternalString()) { 76f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org args.GetIsolate()->ThrowException(v8::String::NewFromUtf8( 77f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org args.GetIsolate(), 784a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com "externalizeString() can't externalize twice.")); 79d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org return; 804a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com } 818e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org if (string->IsOneByteRepresentation() && !force_two_byte) { 8259297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org uint8_t* data = new uint8_t[string->length()]; 834a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com String::WriteToFlat(*string, data, 0, string->length()); 842c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org SimpleOneByteStringResource* resource = new SimpleOneByteStringResource( 8559297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org reinterpret_cast<char*>(data), string->length()); 864a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com result = string->MakeExternal(resource); 87bcc36723a2ace28fa3b0d7dd0d1de926d313fff9machenbach@chromium.org if (result) { 88c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); 89c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org isolate->heap()->external_string_table()->AddString(*string); 904a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com } 914a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com if (!result) delete resource; 924a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com } else { 934a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com uc16* data = new uc16[string->length()]; 944a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com String::WriteToFlat(*string, data, 0, string->length()); 954a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com SimpleTwoByteStringResource* resource = new SimpleTwoByteStringResource( 964a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com data, string->length()); 974a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com result = string->MakeExternal(resource); 98bcc36723a2ace28fa3b0d7dd0d1de926d313fff9machenbach@chromium.org if (result) { 99c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); 100c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org isolate->heap()->external_string_table()->AddString(*string); 1014a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com } 1024a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com if (!result) delete resource; 1034a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com } 1044a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com if (!result) { 105f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org args.GetIsolate()->ThrowException(v8::String::NewFromUtf8( 106f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org args.GetIsolate(), "externalizeString() failed.")); 107d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org return; 1084a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com } 1094a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com} 1104a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com 1114a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com 1122c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.orgvoid ExternalizeStringExtension::IsOneByte( 113d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org const v8::FunctionCallbackInfo<v8::Value>& args) { 1144a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com if (args.Length() != 1 || !args[0]->IsString()) { 115f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org args.GetIsolate()->ThrowException(v8::String::NewFromUtf8( 116f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org args.GetIsolate(), 1172c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org "isOneByteString() requires a single string argument.")); 118d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org return; 1194a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com } 120d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org bool is_one_byte = 121d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org Utils::OpenHandle(*args[0].As<v8::String>())->IsOneByteRepresentation(); 122d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org args.GetReturnValue().Set(is_one_byte); 1234a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com} 1244a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com 1254a6c3279070e8f133607a74c08d8c08ac394ab98erik.corry@gmail.com} } // namespace v8::internal 126