| // 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-inl.h" | |
| #include "src/handles.h" | |
| #include "src/isolate.h" | |
| #include "src/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) {} | |
| virtual ~SimpleStringResource() { delete[] data_; } | |
| virtual const Char* data() const { return data_; } | |
| virtual size_t length() const { return length_; } | |
| private: | |
| Char* const data_; | |
| const size_t length_; | |
| }; | |
| typedef SimpleStringResource<char, v8::String::ExternalOneByteStringResource> | |
| SimpleOneByteStringResource; | |
| typedef SimpleStringResource<uc16, v8::String::ExternalStringResource> | |
| SimpleTwoByteStringResource; | |
| 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::NewFromUtf8( | |
| args.GetIsolate(), | |
| "First parameter to externalizeString() must be a string.", | |
| NewStringType::kNormal).ToLocalChecked()); | |
| return; | |
| } | |
| bool force_two_byte = false; | |
| if (args.Length() >= 2) { | |
| if (args[1]->IsBoolean()) { | |
| force_two_byte = | |
| args[1] | |
| ->BooleanValue(args.GetIsolate()->GetCurrentContext()) | |
| .FromJust(); | |
| } else { | |
| args.GetIsolate()->ThrowException( | |
| v8::String::NewFromUtf8( | |
| args.GetIsolate(), | |
| "Second parameter to externalizeString() must be a boolean.", | |
| NewStringType::kNormal).ToLocalChecked()); | |
| return; | |
| } | |
| } | |
| bool result = false; | |
| Handle<String> string = Utils::OpenHandle(*args[0].As<v8::String>()); | |
| if (!string->SupportsExternalization()) { | |
| args.GetIsolate()->ThrowException( | |
| v8::String::NewFromUtf8(args.GetIsolate(), | |
| "string does not support externalization.", | |
| NewStringType::kNormal) | |
| .ToLocalChecked()); | |
| 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::NewFromUtf8(args.GetIsolate(), | |
| "externalizeString() failed.", | |
| NewStringType::kNormal).ToLocalChecked()); | |
| return; | |
| } | |
| } | |
| void ExternalizeStringExtension::IsOneByte( | |
| const v8::FunctionCallbackInfo<v8::Value>& args) { | |
| if (args.Length() != 1 || !args[0]->IsString()) { | |
| args.GetIsolate()->ThrowException( | |
| v8::String::NewFromUtf8( | |
| args.GetIsolate(), | |
| "isOneByteString() requires a single string argument.", | |
| NewStringType::kNormal).ToLocalChecked()); | |
| return; | |
| } | |
| bool is_one_byte = | |
| Utils::OpenHandle(*args[0].As<v8::String>())->IsOneByteRepresentation(); | |
| args.GetReturnValue().Set(is_one_byte); | |
| } | |
| } // namespace internal | |
| } // namespace v8 |