|  | // Copyright 2010 the V8 project authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "src/extensions/externalize-string-extension.h" | 
|  |  | 
|  | #include "src/api/api-inl.h" | 
|  | #include "src/execution/isolate.h" | 
|  | #include "src/handles/handles.h" | 
|  | #include "src/objects/objects-inl.h" | 
|  |  | 
|  | namespace v8 { | 
|  | namespace internal { | 
|  |  | 
|  | template <typename Char, typename Base> | 
|  | class SimpleStringResource : public Base { | 
|  | public: | 
|  | // Takes ownership of |data|. | 
|  | SimpleStringResource(Char* data, size_t length) | 
|  | : data_(data), | 
|  | length_(length) {} | 
|  |  | 
|  | ~SimpleStringResource() override { delete[] data_; } | 
|  |  | 
|  | const Char* data() const override { return data_; } | 
|  |  | 
|  | size_t length() const override { return length_; } | 
|  |  | 
|  | private: | 
|  | Char* const data_; | 
|  | const size_t length_; | 
|  | }; | 
|  |  | 
|  | using SimpleOneByteStringResource = | 
|  | SimpleStringResource<char, v8::String::ExternalOneByteStringResource>; | 
|  | using SimpleTwoByteStringResource = | 
|  | SimpleStringResource<uc16, v8::String::ExternalStringResource>; | 
|  |  | 
|  | const char* const ExternalizeStringExtension::kSource = | 
|  | "native function externalizeString();" | 
|  | "native function isOneByteString();" | 
|  | "function x() { return 1; }"; | 
|  |  | 
|  | v8::Local<v8::FunctionTemplate> | 
|  | ExternalizeStringExtension::GetNativeFunctionTemplate( | 
|  | v8::Isolate* isolate, v8::Local<v8::String> str) { | 
|  | if (strcmp(*v8::String::Utf8Value(isolate, str), "externalizeString") == 0) { | 
|  | return v8::FunctionTemplate::New(isolate, | 
|  | ExternalizeStringExtension::Externalize); | 
|  | } else { | 
|  | DCHECK_EQ(strcmp(*v8::String::Utf8Value(isolate, str), "isOneByteString"), | 
|  | 0); | 
|  | return v8::FunctionTemplate::New(isolate, | 
|  | ExternalizeStringExtension::IsOneByte); | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | void ExternalizeStringExtension::Externalize( | 
|  | const v8::FunctionCallbackInfo<v8::Value>& args) { | 
|  | if (args.Length() < 1 || !args[0]->IsString()) { | 
|  | args.GetIsolate()->ThrowException(v8::String::NewFromUtf8Literal( | 
|  | args.GetIsolate(), | 
|  | "First parameter to externalizeString() must be a string.")); | 
|  | return; | 
|  | } | 
|  | bool force_two_byte = false; | 
|  | if (args.Length() >= 2) { | 
|  | if (args[1]->IsBoolean()) { | 
|  | force_two_byte = args[1]->BooleanValue(args.GetIsolate()); | 
|  | } else { | 
|  | args.GetIsolate()->ThrowException(v8::String::NewFromUtf8Literal( | 
|  | args.GetIsolate(), | 
|  | "Second parameter to externalizeString() must be a boolean.")); | 
|  | return; | 
|  | } | 
|  | } | 
|  | bool result = false; | 
|  | Handle<String> string = Utils::OpenHandle(*args[0].As<v8::String>()); | 
|  | if (!string->SupportsExternalization()) { | 
|  | args.GetIsolate()->ThrowException(v8::String::NewFromUtf8Literal( | 
|  | args.GetIsolate(), "string does not support externalization.")); | 
|  | return; | 
|  | } | 
|  | if (string->IsOneByteRepresentation() && !force_two_byte) { | 
|  | uint8_t* data = new uint8_t[string->length()]; | 
|  | String::WriteToFlat(*string, data, 0, string->length()); | 
|  | SimpleOneByteStringResource* resource = new SimpleOneByteStringResource( | 
|  | reinterpret_cast<char*>(data), string->length()); | 
|  | result = Utils::ToLocal(string)->MakeExternal(resource); | 
|  | if (!result) delete resource; | 
|  | } else { | 
|  | uc16* data = new uc16[string->length()]; | 
|  | String::WriteToFlat(*string, data, 0, string->length()); | 
|  | SimpleTwoByteStringResource* resource = new SimpleTwoByteStringResource( | 
|  | data, string->length()); | 
|  | result = Utils::ToLocal(string)->MakeExternal(resource); | 
|  | if (!result) delete resource; | 
|  | } | 
|  | if (!result) { | 
|  | args.GetIsolate()->ThrowException(v8::String::NewFromUtf8Literal( | 
|  | args.GetIsolate(), "externalizeString() failed.")); | 
|  | return; | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | void ExternalizeStringExtension::IsOneByte( | 
|  | const v8::FunctionCallbackInfo<v8::Value>& args) { | 
|  | if (args.Length() != 1 || !args[0]->IsString()) { | 
|  | args.GetIsolate()->ThrowException(v8::String::NewFromUtf8Literal( | 
|  | args.GetIsolate(), | 
|  | "isOneByteString() requires a single string argument.")); | 
|  | return; | 
|  | } | 
|  | bool is_one_byte = | 
|  | Utils::OpenHandle(*args[0].As<v8::String>())->IsOneByteRepresentation(); | 
|  | args.GetReturnValue().Set(is_one_byte); | 
|  | } | 
|  |  | 
|  | }  // namespace internal | 
|  | }  // namespace v8 |