• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
14 namespace v8 {
15 namespace internal {
16 
17 template <typename Char, typename Base>
18 class SimpleStringResource : public Base {
19  public:
20   // Takes ownership of |data|.
SimpleStringResource(Char * data,size_t length)21   SimpleStringResource(Char* data, size_t length)
22       : data_(data),
23         length_(length) {}
24 
~SimpleStringResource()25   ~SimpleStringResource() override { delete[] data_; }
26 
data() const27   const Char* data() const override { return data_; }
28 
length() const29   size_t length() const override { return length_; }
30 
31  private:
32   Char* const data_;
33   const size_t length_;
34 };
35 
36 using SimpleOneByteStringResource =
37     SimpleStringResource<char, v8::String::ExternalOneByteStringResource>;
38 using SimpleTwoByteStringResource =
39     SimpleStringResource<base::uc16, v8::String::ExternalStringResource>;
40 
41 const char* const ExternalizeStringExtension::kSource =
42     "native function externalizeString();"
43     "native function isOneByteString();"
44     "function x() { return 1; }";
45 
46 v8::Local<v8::FunctionTemplate>
GetNativeFunctionTemplate(v8::Isolate * isolate,v8::Local<v8::String> str)47 ExternalizeStringExtension::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 
Externalize(const v8::FunctionCallbackInfo<v8::Value> & args)61 void 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 
IsOneByte(const v8::FunctionCallbackInfo<v8::Value> & args)106 void 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