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