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