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