Line data Source code
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 : #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 581 : length_(length) {}
22 :
23 1162 : virtual ~SimpleStringResource() { delete[] data_; }
24 :
25 9434 : virtual const Char* data() const { return data_; }
26 :
27 0 : virtual size_t length() const { 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 130 : ExternalizeStringExtension::GetNativeFunctionTemplate(
47 : v8::Isolate* isolate, v8::Local<v8::String> str) {
48 130 : if (strcmp(*v8::String::Utf8Value(isolate, str), "externalizeString") == 0) {
49 : return v8::FunctionTemplate::New(isolate,
50 65 : ExternalizeStringExtension::Externalize);
51 : } else {
52 : DCHECK_EQ(strcmp(*v8::String::Utf8Value(isolate, str), "isOneByteString"),
53 : 0);
54 : return v8::FunctionTemplate::New(isolate,
55 65 : ExternalizeStringExtension::IsOneByte);
56 : }
57 : }
58 :
59 :
60 965 : void ExternalizeStringExtension::Externalize(
61 3169 : const v8::FunctionCallbackInfo<v8::Value>& args) {
62 1930 : 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 0 : NewStringType::kNormal).ToLocalChecked());
68 0 : return;
69 : }
70 : bool force_two_byte = false;
71 965 : if (args.Length() >= 2) {
72 855 : if (args[1]->IsBoolean()) {
73 : force_two_byte =
74 : args[1]
75 855 : ->BooleanValue(args.GetIsolate()->GetCurrentContext())
76 1710 : .FromJust();
77 : } else {
78 : args.GetIsolate()->ThrowException(
79 : v8::String::NewFromUtf8(
80 : args.GetIsolate(),
81 : "Second parameter to externalizeString() must be a boolean.",
82 0 : NewStringType::kNormal).ToLocalChecked());
83 0 : return;
84 : }
85 : }
86 : bool result = false;
87 : Handle<String> string = Utils::OpenHandle(*args[0].As<v8::String>());
88 965 : if (string->IsExternalString()) {
89 : args.GetIsolate()->ThrowException(
90 : v8::String::NewFromUtf8(args.GetIsolate(),
91 : "externalizeString() can't externalize twice.",
92 768 : NewStringType::kNormal).ToLocalChecked());
93 384 : return;
94 : }
95 581 : if (string->IsOneByteRepresentation() && !force_two_byte) {
96 283 : uint8_t* data = new uint8_t[string->length()];
97 283 : String::WriteToFlat(*string, data, 0, string->length());
98 : SimpleOneByteStringResource* resource = new SimpleOneByteStringResource(
99 283 : reinterpret_cast<char*>(data), string->length());
100 283 : result = string->MakeExternal(resource);
101 283 : if (result) {
102 : i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate());
103 : isolate->heap()->RegisterExternalString(*string);
104 : }
105 283 : if (!result) delete resource;
106 : } else {
107 298 : uc16* data = new uc16[string->length()];
108 298 : String::WriteToFlat(*string, data, 0, string->length());
109 : SimpleTwoByteStringResource* resource = new SimpleTwoByteStringResource(
110 298 : data, string->length());
111 298 : result = string->MakeExternal(resource);
112 298 : if (result) {
113 : i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate());
114 : isolate->heap()->RegisterExternalString(*string);
115 : }
116 298 : if (!result) delete resource;
117 : }
118 581 : if (!result) {
119 : args.GetIsolate()->ThrowException(
120 : v8::String::NewFromUtf8(args.GetIsolate(),
121 : "externalizeString() failed.",
122 0 : NewStringType::kNormal).ToLocalChecked());
123 0 : return;
124 : }
125 : }
126 :
127 :
128 1520 : void ExternalizeStringExtension::IsOneByte(
129 3040 : const v8::FunctionCallbackInfo<v8::Value>& args) {
130 3040 : if (args.Length() != 1 || !args[0]->IsString()) {
131 : args.GetIsolate()->ThrowException(
132 : v8::String::NewFromUtf8(
133 : args.GetIsolate(),
134 : "isOneByteString() requires a single string argument.",
135 0 : NewStringType::kNormal).ToLocalChecked());
136 1520 : return;
137 : }
138 : bool is_one_byte =
139 : Utils::OpenHandle(*args[0].As<v8::String>())->IsOneByteRepresentation();
140 : args.GetReturnValue().Set(is_one_byte);
141 : }
142 :
143 : } // namespace internal
144 : } // namespace v8
|