OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef ToV8_h | 5 // This file has been moved to platform/bindings/ToV8.h. |
6 #define ToV8_h | 6 // TODO(adithyas): Remove this file. |
7 | 7 #include "platform/bindings/ToV8.h" |
8 // ToV8() provides C++ -> V8 conversion. Note that ToV8() can return an empty | |
9 // handle. Call sites must check IsEmpty() before using return value. | |
10 | |
11 #include <utility> | |
12 | |
13 #include "bindings/core/v8/DOMDataStore.h" | |
14 #include "bindings/core/v8/IDLDictionaryBase.h" | |
15 #include "bindings/core/v8/ScriptState.h" | |
16 #include "bindings/core/v8/ScriptValue.h" | |
17 #include "bindings/core/v8/ScriptWrappable.h" | |
18 #include "bindings/core/v8/V8Binding.h" | |
19 #include "core/CoreExport.h" | |
20 #include "core/dom/ArrayBufferViewHelpers.h" | |
21 #include "platform/heap/Handle.h" | |
22 #include "platform/wtf/Forward.h" | |
23 #include "v8/include/v8.h" | |
24 | |
25 namespace blink { | |
26 | |
27 // ScriptWrappable | |
28 | |
29 inline v8::Local<v8::Value> ToV8(ScriptWrappable* impl, | |
30 v8::Local<v8::Object> creation_context, | |
31 v8::Isolate* isolate) { | |
32 if (UNLIKELY(!impl)) | |
33 return v8::Null(isolate); | |
34 v8::Local<v8::Value> wrapper = DOMDataStore::GetWrapper(impl, isolate); | |
35 if (!wrapper.IsEmpty()) | |
36 return wrapper; | |
37 | |
38 wrapper = impl->Wrap(isolate, creation_context); | |
39 DCHECK(!wrapper.IsEmpty()); | |
40 return wrapper; | |
41 } | |
42 | |
43 // Primitives | |
44 | |
45 inline v8::Local<v8::Value> ToV8(const String& value, | |
46 v8::Local<v8::Object> creation_context, | |
47 v8::Isolate* isolate) { | |
48 return V8String(isolate, value); | |
49 } | |
50 | |
51 inline v8::Local<v8::Value> ToV8(const char* value, | |
52 v8::Local<v8::Object> creation_context, | |
53 v8::Isolate* isolate) { | |
54 return V8String(isolate, value); | |
55 } | |
56 | |
57 template <size_t sizeOfValue> | |
58 inline v8::Local<v8::Value> ToV8SignedIntegerInternal(int64_t value, | |
59 v8::Isolate*); | |
60 | |
61 template <> | |
62 inline v8::Local<v8::Value> ToV8SignedIntegerInternal<4>(int64_t value, | |
63 v8::Isolate* isolate) { | |
64 return v8::Integer::New(isolate, static_cast<int32_t>(value)); | |
65 } | |
66 | |
67 template <> | |
68 inline v8::Local<v8::Value> ToV8SignedIntegerInternal<8>(int64_t value, | |
69 v8::Isolate* isolate) { | |
70 int32_t value_in32_bit = static_cast<int32_t>(value); | |
71 if (value_in32_bit == value) | |
72 return v8::Integer::New(isolate, value); | |
73 // V8 doesn't have a 64-bit integer implementation. | |
74 return v8::Number::New(isolate, value); | |
75 } | |
76 | |
77 template <size_t sizeOfValue> | |
78 inline v8::Local<v8::Value> ToV8UnsignedIntegerInternal(uint64_t value, | |
79 v8::Isolate*); | |
80 | |
81 template <> | |
82 inline v8::Local<v8::Value> ToV8UnsignedIntegerInternal<4>( | |
83 uint64_t value, | |
84 v8::Isolate* isolate) { | |
85 return v8::Integer::NewFromUnsigned(isolate, static_cast<uint32_t>(value)); | |
86 } | |
87 | |
88 template <> | |
89 inline v8::Local<v8::Value> ToV8UnsignedIntegerInternal<8>( | |
90 uint64_t value, | |
91 v8::Isolate* isolate) { | |
92 uint32_t value_in32_bit = static_cast<uint32_t>(value); | |
93 if (value_in32_bit == value) | |
94 return v8::Integer::NewFromUnsigned(isolate, value); | |
95 // V8 doesn't have a 64-bit integer implementation. | |
96 return v8::Number::New(isolate, value); | |
97 } | |
98 | |
99 inline v8::Local<v8::Value> ToV8(int value, | |
100 v8::Local<v8::Object> creation_context, | |
101 v8::Isolate* isolate) { | |
102 return ToV8SignedIntegerInternal<sizeof value>(value, isolate); | |
103 } | |
104 | |
105 inline v8::Local<v8::Value> ToV8(long value, | |
106 v8::Local<v8::Object> creation_context, | |
107 v8::Isolate* isolate) { | |
108 return ToV8SignedIntegerInternal<sizeof value>(value, isolate); | |
109 } | |
110 | |
111 inline v8::Local<v8::Value> ToV8(long long value, | |
112 v8::Local<v8::Object> creation_context, | |
113 v8::Isolate* isolate) { | |
114 return ToV8SignedIntegerInternal<sizeof value>(value, isolate); | |
115 } | |
116 | |
117 inline v8::Local<v8::Value> ToV8(unsigned value, | |
118 v8::Local<v8::Object> creation_context, | |
119 v8::Isolate* isolate) { | |
120 return ToV8UnsignedIntegerInternal<sizeof value>(value, isolate); | |
121 } | |
122 | |
123 inline v8::Local<v8::Value> ToV8(unsigned long value, | |
124 v8::Local<v8::Object> creation_context, | |
125 v8::Isolate* isolate) { | |
126 return ToV8UnsignedIntegerInternal<sizeof value>(value, isolate); | |
127 } | |
128 | |
129 inline v8::Local<v8::Value> ToV8(unsigned long long value, | |
130 v8::Local<v8::Object> creation_context, | |
131 v8::Isolate* isolate) { | |
132 return ToV8UnsignedIntegerInternal<sizeof value>(value, isolate); | |
133 } | |
134 | |
135 inline v8::Local<v8::Value> ToV8(double value, | |
136 v8::Local<v8::Object> creation_context, | |
137 v8::Isolate* isolate) { | |
138 return v8::Number::New(isolate, value); | |
139 } | |
140 | |
141 inline v8::Local<v8::Value> ToV8(bool value, | |
142 v8::Local<v8::Object> creation_context, | |
143 v8::Isolate* isolate) { | |
144 return v8::Boolean::New(isolate, value); | |
145 } | |
146 | |
147 // Identity operator | |
148 | |
149 inline v8::Local<v8::Value> ToV8(v8::Local<v8::Value> value, | |
150 v8::Local<v8::Object> creation_context, | |
151 v8::Isolate*) { | |
152 return value; | |
153 } | |
154 | |
155 // Undefined | |
156 | |
157 struct ToV8UndefinedGenerator { | |
158 DISALLOW_NEW(); | |
159 }; // Used only for having toV8 return v8::Undefined. | |
160 | |
161 inline v8::Local<v8::Value> ToV8(const ToV8UndefinedGenerator& value, | |
162 v8::Local<v8::Object> creation_context, | |
163 v8::Isolate* isolate) { | |
164 return v8::Undefined(isolate); | |
165 } | |
166 | |
167 // ScriptValue | |
168 | |
169 inline v8::Local<v8::Value> ToV8(const ScriptValue& value, | |
170 v8::Local<v8::Object> creation_context, | |
171 v8::Isolate* isolate) { | |
172 if (value.IsEmpty()) | |
173 return v8::Undefined(isolate); | |
174 return value.V8Value(); | |
175 } | |
176 | |
177 // Dictionary | |
178 | |
179 inline v8::Local<v8::Value> ToV8(const IDLDictionaryBase& value, | |
180 v8::Local<v8::Object> creation_context, | |
181 v8::Isolate* isolate) { | |
182 return value.ToV8Impl(creation_context, isolate); | |
183 } | |
184 | |
185 // Array | |
186 | |
187 // Declare the function here but define it later so it can call the ToV8() | |
188 // overloads below. | |
189 template <typename Sequence> | |
190 inline v8::Local<v8::Value> ToV8SequenceInternal( | |
191 const Sequence&, | |
192 v8::Local<v8::Object> creation_context, | |
193 v8::Isolate*); | |
194 | |
195 template <typename T, size_t inlineCapacity> | |
196 inline v8::Local<v8::Value> ToV8(const Vector<T, inlineCapacity>& value, | |
197 v8::Local<v8::Object> creation_context, | |
198 v8::Isolate* isolate) { | |
199 return ToV8SequenceInternal(value, creation_context, isolate); | |
200 } | |
201 | |
202 template <typename T, size_t inlineCapacity> | |
203 inline v8::Local<v8::Value> ToV8(const HeapVector<T, inlineCapacity>& value, | |
204 v8::Local<v8::Object> creation_context, | |
205 v8::Isolate* isolate) { | |
206 return ToV8SequenceInternal(value, creation_context, isolate); | |
207 } | |
208 | |
209 // The following two overloads are also used to convert record<K,V> IDL types | |
210 // back into ECMAScript Objects. | |
211 template <typename T> | |
212 inline v8::Local<v8::Value> ToV8(const Vector<std::pair<String, T>>& value, | |
213 v8::Local<v8::Object> creation_context, | |
214 v8::Isolate* isolate) { | |
215 v8::Local<v8::Object> object; | |
216 { | |
217 v8::Context::Scope context_scope(creation_context->CreationContext()); | |
218 object = v8::Object::New(isolate); | |
219 } | |
220 for (unsigned i = 0; i < value.size(); ++i) { | |
221 v8::Local<v8::Value> v8_value = ToV8(value[i].second, object, isolate); | |
222 if (v8_value.IsEmpty()) | |
223 v8_value = v8::Undefined(isolate); | |
224 if (!V8CallBoolean(object->CreateDataProperty( | |
225 isolate->GetCurrentContext(), V8String(isolate, value[i].first), | |
226 v8_value))) | |
227 return v8::Local<v8::Value>(); | |
228 } | |
229 return object; | |
230 } | |
231 | |
232 template <typename T> | |
233 inline v8::Local<v8::Value> ToV8(const HeapVector<std::pair<String, T>>& value, | |
234 v8::Local<v8::Object> creation_context, | |
235 v8::Isolate* isolate) { | |
236 v8::Local<v8::Object> object; | |
237 { | |
238 v8::Context::Scope context_scope(creation_context->CreationContext()); | |
239 object = v8::Object::New(isolate); | |
240 } | |
241 for (unsigned i = 0; i < value.size(); ++i) { | |
242 v8::Local<v8::Value> v8_value = ToV8(value[i].second, object, isolate); | |
243 if (v8_value.IsEmpty()) | |
244 v8_value = v8::Undefined(isolate); | |
245 if (!V8CallBoolean(object->CreateDataProperty( | |
246 isolate->GetCurrentContext(), V8String(isolate, value[i].first), | |
247 v8_value))) | |
248 return v8::Local<v8::Value>(); | |
249 } | |
250 return object; | |
251 } | |
252 | |
253 template <typename Sequence> | |
254 inline v8::Local<v8::Value> ToV8SequenceInternal( | |
255 const Sequence& sequence, | |
256 v8::Local<v8::Object> creation_context, | |
257 v8::Isolate* isolate) { | |
258 v8::Local<v8::Array> array; | |
259 { | |
260 v8::Context::Scope context_scope(creation_context->CreationContext()); | |
261 array = v8::Array::New(isolate, sequence.size()); | |
262 } | |
263 uint32_t index = 0; | |
264 typename Sequence::const_iterator end = sequence.end(); | |
265 for (typename Sequence::const_iterator iter = sequence.begin(); iter != end; | |
266 ++iter) { | |
267 v8::Local<v8::Value> value = ToV8(*iter, array, isolate); | |
268 if (value.IsEmpty()) | |
269 value = v8::Undefined(isolate); | |
270 if (!V8CallBoolean(array->CreateDataProperty(isolate->GetCurrentContext(), | |
271 index++, value))) | |
272 return v8::Local<v8::Value>(); | |
273 } | |
274 return array; | |
275 } | |
276 | |
277 // In all cases allow script state instead of creation context + isolate. | |
278 // Use this function only if the call site does not otherwise need the global, | |
279 // since v8::Context::Global is heavy. | |
280 template <typename T> | |
281 inline v8::Local<v8::Value> ToV8(T&& value, ScriptState* script_state) { | |
282 return ToV8(std::forward<T>(value), script_state->GetContext()->Global(), | |
283 script_state->GetIsolate()); | |
284 } | |
285 | |
286 // Only declare ToV8(void*,...) for checking function overload mismatch. | |
287 // This ToV8(void*,...) should be never used. So we will find mismatch | |
288 // because of "unresolved external symbol". | |
289 // Without ToV8(void*, ...), call to toV8 with T* will match with | |
290 // ToV8(bool, ...) if T is not a subclass of ScriptWrappable or if T is | |
291 // declared but not defined (so it's not clear that T is a subclass of | |
292 // ScriptWrappable). | |
293 // This hack helps detect such unwanted implicit conversions from T* to bool. | |
294 v8::Local<v8::Value> ToV8(void* value, | |
295 v8::Local<v8::Object> creation_context, | |
296 v8::Isolate*) = delete; | |
297 | |
298 // Cannot define in ScriptValue because of the circular dependency between toV8 | |
299 // and ScriptValue | |
300 template <typename T> | |
301 inline ScriptValue ScriptValue::From(ScriptState* script_state, T&& value) { | |
302 return ScriptValue(script_state, ToV8(std::forward<T>(value), script_state)); | |
303 } | |
304 | |
305 } // namespace blink | |
306 | |
307 #endif // ToV8ForPlatform_h | |
OLD | NEW |