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-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 508 : length_(length) {}
22 :
23 1016 : ~SimpleStringResource() override { delete[] data_; }
24 :
25 11926 : const Char* data() const override { return data_; }
26 :
27 513 : 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 140 : ExternalizeStringExtension::GetNativeFunctionTemplate(
47 : v8::Isolate* isolate, v8::Local<v8::String> str) {
48 140 : if (strcmp(*v8::String::Utf8Value(isolate, str), "externalizeString") == 0) {
49 : return v8::FunctionTemplate::New(isolate,
50 70 : ExternalizeStringExtension::Externalize);
51 : } else {
52 : DCHECK_EQ(strcmp(*v8::String::Utf8Value(isolate, str), "isOneByteString"),
53 : 0);
54 : return v8::FunctionTemplate::New(isolate,
55 70 : ExternalizeStringExtension::IsOneByte);
56 : }
57 : }
58 :
59 :
60 879 : void ExternalizeStringExtension::Externalize(
61 : const v8::FunctionCallbackInfo<v8::Value>& args) {
62 1758 : if (args.Length() < 1 || !args[0]->IsString()) {
63 : args.GetIsolate()->ThrowException(
64 0 : 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 879 : if (args.Length() >= 2) {
72 780 : if (args[1]->IsBoolean()) {
73 780 : force_two_byte = args[1]->BooleanValue(args.GetIsolate());
74 : } else {
75 : args.GetIsolate()->ThrowException(
76 0 : v8::String::NewFromUtf8(
77 : args.GetIsolate(),
78 : "Second parameter to externalizeString() must be a boolean.",
79 0 : NewStringType::kNormal).ToLocalChecked());
80 0 : return;
81 : }
82 : }
83 : bool result = false;
84 : Handle<String> string = Utils::OpenHandle(*args[0].As<v8::String>());
85 879 : if (!string->SupportsExternalization()) {
86 : args.GetIsolate()->ThrowException(
87 371 : v8::String::NewFromUtf8(args.GetIsolate(),
88 : "string does not support externalization.",
89 : NewStringType::kNormal)
90 371 : .ToLocalChecked());
91 371 : return;
92 : }
93 508 : if (string->IsOneByteRepresentation() && !force_two_byte) {
94 244 : uint8_t* data = new uint8_t[string->length()];
95 244 : String::WriteToFlat(*string, data, 0, string->length());
96 : SimpleOneByteStringResource* resource = new SimpleOneByteStringResource(
97 244 : reinterpret_cast<char*>(data), string->length());
98 244 : result = Utils::ToLocal(string)->MakeExternal(resource);
99 244 : if (!result) delete resource;
100 : } else {
101 264 : uc16* data = new uc16[string->length()];
102 264 : String::WriteToFlat(*string, data, 0, string->length());
103 : SimpleTwoByteStringResource* resource = new SimpleTwoByteStringResource(
104 264 : data, string->length());
105 264 : result = Utils::ToLocal(string)->MakeExternal(resource);
106 264 : if (!result) delete resource;
107 : }
108 508 : if (!result) {
109 : args.GetIsolate()->ThrowException(
110 0 : v8::String::NewFromUtf8(args.GetIsolate(),
111 : "externalizeString() failed.",
112 0 : NewStringType::kNormal).ToLocalChecked());
113 0 : return;
114 : }
115 : }
116 :
117 :
118 1530 : void ExternalizeStringExtension::IsOneByte(
119 : const v8::FunctionCallbackInfo<v8::Value>& args) {
120 3060 : if (args.Length() != 1 || !args[0]->IsString()) {
121 : args.GetIsolate()->ThrowException(
122 0 : v8::String::NewFromUtf8(
123 : args.GetIsolate(),
124 : "isOneByteString() requires a single string argument.",
125 0 : NewStringType::kNormal).ToLocalChecked());
126 0 : return;
127 : }
128 : bool is_one_byte =
129 1530 : Utils::OpenHandle(*args[0].As<v8::String>())->IsOneByteRepresentation();
130 : args.GetReturnValue().Set(is_one_byte);
131 : }
132 :
133 : } // namespace internal
134 120216 : } // namespace v8
|