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