• 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 "src/api.h"
8 #include "src/handles.h"
9 #include "src/isolate.h"
10 
11 namespace v8 {
12 namespace internal {
13 
14 template <typename Char, typename Base>
15 class SimpleStringResource : public Base {
16  public:
17   // Takes ownership of |data|.
SimpleStringResource(Char * data,size_t length)18   SimpleStringResource(Char* data, size_t length)
19       : data_(data),
20         length_(length) {}
21 
~SimpleStringResource()22   virtual ~SimpleStringResource() { delete[] data_; }
23 
data() const24   virtual const Char* data() const { return data_; }
25 
length() const26   virtual size_t length() const { return length_; }
27 
28  private:
29   Char* const data_;
30   const size_t length_;
31 };
32 
33 
34 typedef SimpleStringResource<char, v8::String::ExternalOneByteStringResource>
35     SimpleOneByteStringResource;
36 typedef SimpleStringResource<uc16, v8::String::ExternalStringResource>
37     SimpleTwoByteStringResource;
38 
39 
40 const char* const ExternalizeStringExtension::kSource =
41     "native function externalizeString();"
42     "native function isOneByteString();";
43 
44 v8::Local<v8::FunctionTemplate>
GetNativeFunctionTemplate(v8::Isolate * isolate,v8::Local<v8::String> str)45 ExternalizeStringExtension::GetNativeFunctionTemplate(
46     v8::Isolate* isolate, v8::Local<v8::String> str) {
47   if (strcmp(*v8::String::Utf8Value(str), "externalizeString") == 0) {
48     return v8::FunctionTemplate::New(isolate,
49                                      ExternalizeStringExtension::Externalize);
50   } else {
51     DCHECK(strcmp(*v8::String::Utf8Value(str), "isOneByteString") == 0);
52     return v8::FunctionTemplate::New(isolate,
53                                      ExternalizeStringExtension::IsOneByte);
54   }
55 }
56 
57 
Externalize(const v8::FunctionCallbackInfo<v8::Value> & args)58 void ExternalizeStringExtension::Externalize(
59     const v8::FunctionCallbackInfo<v8::Value>& args) {
60   if (args.Length() < 1 || !args[0]->IsString()) {
61     args.GetIsolate()->ThrowException(
62         v8::String::NewFromUtf8(
63             args.GetIsolate(),
64             "First parameter to externalizeString() must be a string.",
65             NewStringType::kNormal).ToLocalChecked());
66     return;
67   }
68   bool force_two_byte = false;
69   if (args.Length() >= 2) {
70     if (args[1]->IsBoolean()) {
71       force_two_byte =
72           args[1]
73               ->BooleanValue(args.GetIsolate()->GetCurrentContext())
74               .FromJust();
75     } else {
76       args.GetIsolate()->ThrowException(
77           v8::String::NewFromUtf8(
78               args.GetIsolate(),
79               "Second parameter to externalizeString() must be a boolean.",
80               NewStringType::kNormal).ToLocalChecked());
81       return;
82     }
83   }
84   bool result = false;
85   Handle<String> string = Utils::OpenHandle(*args[0].As<v8::String>());
86   if (string->IsExternalString()) {
87     args.GetIsolate()->ThrowException(
88         v8::String::NewFromUtf8(args.GetIsolate(),
89                                 "externalizeString() can't externalize twice.",
90                                 NewStringType::kNormal).ToLocalChecked());
91     return;
92   }
93   if (string->IsOneByteRepresentation() && !force_two_byte) {
94     uint8_t* data = new uint8_t[string->length()];
95     String::WriteToFlat(*string, data, 0, string->length());
96     SimpleOneByteStringResource* resource = new SimpleOneByteStringResource(
97         reinterpret_cast<char*>(data), string->length());
98     result = string->MakeExternal(resource);
99     if (result) {
100       i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate());
101       isolate->heap()->RegisterExternalString(*string);
102     }
103     if (!result) delete resource;
104   } else {
105     uc16* data = new uc16[string->length()];
106     String::WriteToFlat(*string, data, 0, string->length());
107     SimpleTwoByteStringResource* resource = new SimpleTwoByteStringResource(
108         data, string->length());
109     result = string->MakeExternal(resource);
110     if (result) {
111       i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate());
112       isolate->heap()->RegisterExternalString(*string);
113     }
114     if (!result) delete resource;
115   }
116   if (!result) {
117     args.GetIsolate()->ThrowException(
118         v8::String::NewFromUtf8(args.GetIsolate(),
119                                 "externalizeString() failed.",
120                                 NewStringType::kNormal).ToLocalChecked());
121     return;
122   }
123 }
124 
125 
IsOneByte(const v8::FunctionCallbackInfo<v8::Value> & args)126 void ExternalizeStringExtension::IsOneByte(
127     const v8::FunctionCallbackInfo<v8::Value>& args) {
128   if (args.Length() != 1 || !args[0]->IsString()) {
129     args.GetIsolate()->ThrowException(
130         v8::String::NewFromUtf8(
131             args.GetIsolate(),
132             "isOneByteString() requires a single string argument.",
133             NewStringType::kNormal).ToLocalChecked());
134     return;
135   }
136   bool is_one_byte =
137       Utils::OpenHandle(*args[0].As<v8::String>())->IsOneByteRepresentation();
138   args.GetReturnValue().Set(is_one_byte);
139 }
140 
141 }  // namespace internal
142 }  // namespace v8
143