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