Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(189)

Side by Side Diff: sky/engine/bindings/core/v8/V8Binding.cpp

Issue 922053002: Remove unused V8 integration code in Sky (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « sky/engine/bindings/core/v8/V8Binding.h ('k') | sky/engine/bindings/core/v8/V8BindingMacros.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2006, 2007, 2008, 2009 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "sky/engine/config.h"
32 #include "sky/engine/bindings/core/v8/V8Binding.h"
33
34 #include "bindings/core/v8/V8Element.h"
35 #include "bindings/core/v8/V8Window.h"
36 #include "sky/engine/bindings/core/v8/ScriptController.h"
37 #include "sky/engine/bindings/core/v8/V8AbstractEventListener.h"
38 #include "sky/engine/bindings/core/v8/V8BindingMacros.h"
39 #include "sky/engine/bindings/core/v8/V8ObjectConstructor.h"
40 #include "sky/engine/bindings/core/v8/WindowProxy.h"
41 #include "sky/engine/core/dom/Document.h"
42 #include "sky/engine/core/dom/Element.h"
43 #include "sky/engine/core/dom/QualifiedName.h"
44 #include "sky/engine/core/frame/LocalFrame.h"
45 #include "sky/engine/core/frame/Settings.h"
46 #include "sky/engine/core/loader/FrameLoaderClient.h"
47 #include "sky/engine/platform/JSONValues.h"
48 #include "sky/engine/wtf/ArrayBufferContents.h"
49 #include "sky/engine/wtf/MainThread.h"
50 #include "sky/engine/wtf/MathExtras.h"
51 #include "sky/engine/wtf/StdLibExtras.h"
52 #include "sky/engine/wtf/Threading.h"
53 #include "sky/engine/wtf/text/AtomicString.h"
54 #include "sky/engine/wtf/text/CString.h"
55 #include "sky/engine/wtf/text/StringBuffer.h"
56 #include "sky/engine/wtf/text/StringHash.h"
57 #include "sky/engine/wtf/text/WTFString.h"
58 #include "sky/engine/wtf/unicode/CharacterNames.h"
59 #include "sky/engine/wtf/unicode/Unicode.h"
60
61 namespace blink {
62
63 void setArityTypeError(ExceptionState& exceptionState, const char* valid, unsign ed provided)
64 {
65 exceptionState.throwTypeError(ExceptionMessages::invalidArity(valid, provide d));
66 }
67
68 v8::Local<v8::Value> createMinimumArityTypeErrorForMethod(const char* method, co nst char* type, unsigned expected, unsigned provided, v8::Isolate* isolate)
69 {
70 return V8ThrowException::createTypeError(ExceptionMessages::failedToExecute( method, type, ExceptionMessages::notEnoughArguments(expected, provided)), isolat e);
71 }
72
73 v8::Local<v8::Value> createMinimumArityTypeErrorForConstructor(const char* type, unsigned expected, unsigned provided, v8::Isolate* isolate)
74 {
75 return V8ThrowException::createTypeError(ExceptionMessages::failedToConstruc t(type, ExceptionMessages::notEnoughArguments(expected, provided)), isolate);
76 }
77
78 void setMinimumArityTypeError(ExceptionState& exceptionState, unsigned expected, unsigned provided)
79 {
80 exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(expected , provided));
81 }
82
83 class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
84 virtual void* Allocate(size_t size) override
85 {
86 void* data;
87 WTF::ArrayBufferContents::allocateMemory(size, WTF::ArrayBufferContents: :ZeroInitialize, data);
88 return data;
89 }
90
91 virtual void* AllocateUninitialized(size_t size) override
92 {
93 void* data;
94 WTF::ArrayBufferContents::allocateMemory(size, WTF::ArrayBufferContents: :DontInitialize, data);
95 return data;
96 }
97
98 virtual void Free(void* data, size_t size) override
99 {
100 WTF::ArrayBufferContents::freeMemory(data, size);
101 }
102 };
103
104 v8::ArrayBuffer::Allocator* v8ArrayBufferAllocator()
105 {
106 DEFINE_STATIC_LOCAL(ArrayBufferAllocator, arrayBufferAllocator, ());
107 return &arrayBufferAllocator;
108 }
109
110 const int32_t kMaxInt32 = 0x7fffffff;
111 const int32_t kMinInt32 = -kMaxInt32 - 1;
112 const uint32_t kMaxUInt32 = 0xffffffff;
113 const int64_t kJSMaxInteger = 0x20000000000000LL - 1; // 2^53 - 1, maximum uniqu ely representable integer in ECMAScript.
114
115 static double enforceRange(double x, double minimum, double maximum, const char* typeName, ExceptionState& exceptionState)
116 {
117 if (std::isnan(x) || std::isinf(x)) {
118 exceptionState.throwTypeError("Value is" + String(std::isinf(x) ? " infi nite and" : "") + " not of type '" + String(typeName) + "'.");
119 return 0;
120 }
121 x = trunc(x);
122 if (x < minimum || x > maximum) {
123 exceptionState.throwTypeError("Value is outside the '" + String(typeName ) + "' value range.");
124 return 0;
125 }
126 return x;
127 }
128
129 template <typename T>
130 struct IntTypeLimits {
131 };
132
133 template <>
134 struct IntTypeLimits<int8_t> {
135 static const int8_t minValue = -128;
136 static const int8_t maxValue = 127;
137 static const unsigned numberOfValues = 256; // 2^8
138 };
139
140 template <>
141 struct IntTypeLimits<uint8_t> {
142 static const uint8_t maxValue = 255;
143 static const unsigned numberOfValues = 256; // 2^8
144 };
145
146 template <>
147 struct IntTypeLimits<int16_t> {
148 static const short minValue = -32768;
149 static const short maxValue = 32767;
150 static const unsigned numberOfValues = 65536; // 2^16
151 };
152
153 template <>
154 struct IntTypeLimits<uint16_t> {
155 static const unsigned short maxValue = 65535;
156 static const unsigned numberOfValues = 65536; // 2^16
157 };
158
159 template <typename T>
160 static inline T toSmallerInt(v8::Handle<v8::Value> value, IntegerConversionConfi guration configuration, const char* typeName, ExceptionState& exceptionState)
161 {
162 typedef IntTypeLimits<T> LimitsTrait;
163
164 // Fast case. The value is already a 32-bit integer in the right range.
165 if (value->IsInt32()) {
166 int32_t result = value->Int32Value();
167 if (result >= LimitsTrait::minValue && result <= LimitsTrait::maxValue)
168 return static_cast<T>(result);
169 if (configuration == EnforceRange) {
170 exceptionState.throwTypeError("Value is outside the '" + String(type Name) + "' value range.");
171 return 0;
172 }
173 result %= LimitsTrait::numberOfValues;
174 return static_cast<T>(result > LimitsTrait::maxValue ? result - LimitsTr ait::numberOfValues : result);
175 }
176
177 // Can the value be converted to a number?
178 TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::Number>, numberObject, value-> ToNumber(), exceptionState, 0);
179 if (numberObject.IsEmpty()) {
180 exceptionState.throwTypeError("Not convertible to a number value (of typ e '" + String(typeName) + "'.");
181 return 0;
182 }
183
184 if (configuration == EnforceRange)
185 return enforceRange(numberObject->Value(), LimitsTrait::minValue, Limits Trait::maxValue, typeName, exceptionState);
186
187 double numberValue = numberObject->Value();
188 if (std::isnan(numberValue) || std::isinf(numberValue) || !numberValue)
189 return 0;
190
191 numberValue = numberValue < 0 ? -floor(fabs(numberValue)) : floor(fabs(numbe rValue));
192 numberValue = fmod(numberValue, LimitsTrait::numberOfValues);
193
194 return static_cast<T>(numberValue > LimitsTrait::maxValue ? numberValue - Li mitsTrait::numberOfValues : numberValue);
195 }
196
197 template <typename T>
198 static inline T toSmallerUInt(v8::Handle<v8::Value> value, IntegerConversionConf iguration configuration, const char* typeName, ExceptionState& exceptionState)
199 {
200 typedef IntTypeLimits<T> LimitsTrait;
201
202 // Fast case. The value is a 32-bit signed integer - possibly positive?
203 if (value->IsInt32()) {
204 int32_t result = value->Int32Value();
205 if (result >= 0 && result <= LimitsTrait::maxValue)
206 return static_cast<T>(result);
207 if (configuration == EnforceRange) {
208 exceptionState.throwTypeError("Value is outside the '" + String(type Name) + "' value range.");
209 return 0;
210 }
211 return static_cast<T>(result);
212 }
213
214 // Can the value be converted to a number?
215 TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::Number>, numberObject, value-> ToNumber(), exceptionState, 0);
216 if (numberObject.IsEmpty()) {
217 exceptionState.throwTypeError("Not convertible to a number value (of typ e '" + String(typeName) + "'.");
218 return 0;
219 }
220
221 if (configuration == EnforceRange)
222 return enforceRange(numberObject->Value(), 0, LimitsTrait::maxValue, typ eName, exceptionState);
223
224 // Does the value convert to nan or to an infinity?
225 double numberValue = numberObject->Value();
226 if (std::isnan(numberValue) || std::isinf(numberValue) || !numberValue)
227 return 0;
228
229 if (configuration == Clamp)
230 return clampTo<T>(numberObject->Value());
231
232 numberValue = numberValue < 0 ? -floor(fabs(numberValue)) : floor(fabs(numbe rValue));
233 return static_cast<T>(fmod(numberValue, LimitsTrait::numberOfValues));
234 }
235
236 int8_t toInt8(v8::Handle<v8::Value> value, IntegerConversionConfiguration config uration, ExceptionState& exceptionState)
237 {
238 return toSmallerInt<int8_t>(value, configuration, "byte", exceptionState);
239 }
240
241 int8_t toInt8(v8::Handle<v8::Value> value)
242 {
243 NonThrowableExceptionState exceptionState;
244 return toInt8(value, NormalConversion, exceptionState);
245 }
246
247 uint8_t toUInt8(v8::Handle<v8::Value> value, IntegerConversionConfiguration conf iguration, ExceptionState& exceptionState)
248 {
249 return toSmallerUInt<uint8_t>(value, configuration, "octet", exceptionState) ;
250 }
251
252 uint8_t toUInt8(v8::Handle<v8::Value> value)
253 {
254 NonThrowableExceptionState exceptionState;
255 return toUInt8(value, NormalConversion, exceptionState);
256 }
257
258 int16_t toInt16(v8::Handle<v8::Value> value, IntegerConversionConfiguration conf iguration, ExceptionState& exceptionState)
259 {
260 return toSmallerInt<int16_t>(value, configuration, "short", exceptionState);
261 }
262
263 int16_t toInt16(v8::Handle<v8::Value> value)
264 {
265 NonThrowableExceptionState exceptionState;
266 return toInt16(value, NormalConversion, exceptionState);
267 }
268
269 uint16_t toUInt16(v8::Handle<v8::Value> value, IntegerConversionConfiguration co nfiguration, ExceptionState& exceptionState)
270 {
271 return toSmallerUInt<uint16_t>(value, configuration, "unsigned short", excep tionState);
272 }
273
274 uint16_t toUInt16(v8::Handle<v8::Value> value)
275 {
276 NonThrowableExceptionState exceptionState;
277 return toUInt16(value, NormalConversion, exceptionState);
278 }
279
280 int32_t toInt32(v8::Handle<v8::Value> value, IntegerConversionConfiguration conf iguration, ExceptionState& exceptionState)
281 {
282 // Fast case. The value is already a 32-bit integer.
283 if (value->IsInt32())
284 return value->Int32Value();
285
286 // Can the value be converted to a number?
287 TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::Number>, numberObject, value-> ToNumber(), exceptionState, 0);
288 if (numberObject.IsEmpty()) {
289 exceptionState.throwTypeError("Not convertible to a number value (of typ e 'long'.)");
290 return 0;
291 }
292
293 if (configuration == EnforceRange)
294 return enforceRange(numberObject->Value(), kMinInt32, kMaxInt32, "long", exceptionState);
295
296 // Does the value convert to nan or to an infinity?
297 double numberValue = numberObject->Value();
298 if (std::isnan(numberValue) || std::isinf(numberValue))
299 return 0;
300
301 if (configuration == Clamp)
302 return clampTo<int32_t>(numberObject->Value());
303
304 TONATIVE_DEFAULT_EXCEPTIONSTATE(int32_t, result, numberObject->Int32Value(), exceptionState, 0);
305 return result;
306 }
307
308 int32_t toInt32(v8::Handle<v8::Value> value)
309 {
310 NonThrowableExceptionState exceptionState;
311 return toInt32(value, NormalConversion, exceptionState);
312 }
313
314 uint32_t toUInt32(v8::Handle<v8::Value> value, IntegerConversionConfiguration co nfiguration, ExceptionState& exceptionState)
315 {
316 // Fast case. The value is already a 32-bit unsigned integer.
317 if (value->IsUint32())
318 return value->Uint32Value();
319
320 // Fast case. The value is a 32-bit signed integer - possibly positive?
321 if (value->IsInt32()) {
322 int32_t result = value->Int32Value();
323 if (result >= 0)
324 return result;
325 if (configuration == EnforceRange) {
326 exceptionState.throwTypeError("Value is outside the 'unsigned long' value range.");
327 return 0;
328 }
329 return result;
330 }
331
332 // Can the value be converted to a number?
333 TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::Number>, numberObject, value-> ToNumber(), exceptionState, 0);
334 if (numberObject.IsEmpty()) {
335 exceptionState.throwTypeError("Not convertible to a number value (of typ e 'unsigned long'.)");
336 return 0;
337 }
338
339 if (configuration == EnforceRange)
340 return enforceRange(numberObject->Value(), 0, kMaxUInt32, "unsigned long ", exceptionState);
341
342 // Does the value convert to nan or to an infinity?
343 double numberValue = numberObject->Value();
344 if (std::isnan(numberValue) || std::isinf(numberValue))
345 return 0;
346
347 if (configuration == Clamp)
348 return clampTo<uint32_t>(numberObject->Value());
349
350 TONATIVE_DEFAULT(uint32_t, result, numberObject->Uint32Value(), 0);
351 return result;
352 }
353
354 uint32_t toUInt32(v8::Handle<v8::Value> value)
355 {
356 NonThrowableExceptionState exceptionState;
357 return toUInt32(value, NormalConversion, exceptionState);
358 }
359
360 int64_t toInt64(v8::Handle<v8::Value> value, IntegerConversionConfiguration conf iguration, ExceptionState& exceptionState)
361 {
362 // Fast case. The value is a 32-bit integer.
363 if (value->IsInt32())
364 return value->Int32Value();
365
366 // Can the value be converted to a number?
367 TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::Number>, numberObject, value-> ToNumber(), exceptionState, 0);
368 if (numberObject.IsEmpty()) {
369 exceptionState.throwTypeError("Not convertible to a number value (of typ e 'long long'.)");
370 return 0;
371 }
372
373 double x = numberObject->Value();
374
375 if (configuration == EnforceRange)
376 return enforceRange(x, -kJSMaxInteger, kJSMaxInteger, "long long", excep tionState);
377
378 // Does the value convert to nan or to an infinity?
379 if (std::isnan(x) || std::isinf(x))
380 return 0;
381
382 // NaNs and +/-Infinity should be 0, otherwise modulo 2^64.
383 unsigned long long integer;
384 doubleToInteger(x, integer);
385 return integer;
386 }
387
388 int64_t toInt64(v8::Handle<v8::Value> value)
389 {
390 NonThrowableExceptionState exceptionState;
391 return toInt64(value, NormalConversion, exceptionState);
392 }
393
394 uint64_t toUInt64(v8::Handle<v8::Value> value, IntegerConversionConfiguration co nfiguration, ExceptionState& exceptionState)
395 {
396 // Fast case. The value is a 32-bit unsigned integer.
397 if (value->IsUint32())
398 return value->Uint32Value();
399
400 // Fast case. The value is a 32-bit integer.
401 if (value->IsInt32()) {
402 int32_t result = value->Int32Value();
403 if (result >= 0)
404 return result;
405 if (configuration == EnforceRange) {
406 exceptionState.throwTypeError("Value is outside the 'unsigned long l ong' value range.");
407 return 0;
408 }
409 return result;
410 }
411
412 // Can the value be converted to a number?
413 TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::Number>, numberObject, value-> ToNumber(), exceptionState, 0);
414 if (numberObject.IsEmpty()) {
415 exceptionState.throwTypeError("Not convertible to a number value (of typ e 'unsigned long long'.)");
416 return 0;
417 }
418
419 double x = numberObject->Value();
420
421 if (configuration == EnforceRange)
422 return enforceRange(x, 0, kJSMaxInteger, "unsigned long long", exception State);
423
424 // Does the value convert to nan or to an infinity?
425 if (std::isnan(x) || std::isinf(x))
426 return 0;
427
428 // NaNs and +/-Infinity should be 0, otherwise modulo 2^64.
429 unsigned long long integer;
430 doubleToInteger(x, integer);
431 return integer;
432 }
433
434 uint64_t toUInt64(v8::Handle<v8::Value> value)
435 {
436 NonThrowableExceptionState exceptionState;
437 return toUInt64(value, NormalConversion, exceptionState);
438 }
439
440 float toFloat(v8::Handle<v8::Value> value, ExceptionState& exceptionState)
441 {
442 TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::Number>, numberObject, value-> ToNumber(), exceptionState, 0);
443 return numberObject->NumberValue();
444 }
445
446 String toByteString(v8::Handle<v8::Value> value, ExceptionState& exceptionState)
447 {
448 // Handle null default value.
449 if (value.IsEmpty())
450 return String();
451
452 // From the Web IDL spec: http://heycam.github.io/webidl/#es-ByteString
453 if (value.IsEmpty())
454 return String();
455
456 // 1. Let x be ToString(v)
457 TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::String>, stringObject, value-> ToString(), exceptionState, String());
458 String x = toCoreString(stringObject);
459
460 // 2. If the value of any element of x is greater than 255, then throw a Typ eError.
461 if (!x.containsOnlyLatin1()) {
462 exceptionState.throwTypeError("Value is not a valid ByteString.");
463 return String();
464 }
465
466 // 3. Return an IDL ByteString value whose length is the length of x, and wh ere the
467 // value of each element is the value of the corresponding element of x.
468 // Blink: A ByteString is simply a String with a range constrained per the a bove, so
469 // this is the identity operation.
470 return x;
471 }
472
473 static bool hasUnmatchedSurrogates(const String& string)
474 {
475 // By definition, 8-bit strings are confined to the Latin-1 code page and
476 // have no surrogates, matched or otherwise.
477 if (string.is8Bit())
478 return false;
479
480 const UChar* characters = string.characters16();
481 const unsigned length = string.length();
482
483 for (unsigned i = 0; i < length; ++i) {
484 UChar c = characters[i];
485 if (U16_IS_SINGLE(c))
486 continue;
487 if (U16_IS_TRAIL(c))
488 return true;
489 ASSERT(U16_IS_LEAD(c));
490 if (i == length - 1)
491 return true;
492 UChar d = characters[i + 1];
493 if (!U16_IS_TRAIL(d))
494 return true;
495 ++i;
496 }
497 return false;
498 }
499
500 // Replace unmatched surrogates with REPLACEMENT CHARACTER U+FFFD.
501 static String replaceUnmatchedSurrogates(const String& string)
502 {
503 // This roughly implements http://heycam.github.io/webidl/#dfn-obtain-unicod e
504 // but since Blink strings are 16-bits internally, the output is simply
505 // re-encoded to UTF-16.
506
507 // The concept of surrogate pairs is explained at:
508 // http://www.unicode.org/versions/Unicode6.2.0/ch03.pdf#G2630
509
510 // Blink-specific optimization to avoid making an unnecessary copy.
511 if (!hasUnmatchedSurrogates(string))
512 return string;
513 ASSERT(!string.is8Bit());
514
515 // 1. Let S be the DOMString value.
516 const UChar* s = string.characters16();
517
518 // 2. Let n be the length of S.
519 const unsigned n = string.length();
520
521 // 3. Initialize i to 0.
522 unsigned i = 0;
523
524 // 4. Initialize U to be an empty sequence of Unicode characters.
525 StringBuilder u;
526 u.reserveCapacity(n);
527
528 // 5. While i < n:
529 while (i < n) {
530 // 1. Let c be the code unit in S at index i.
531 UChar c = s[i];
532 // 2. Depending on the value of c:
533 if (U16_IS_SINGLE(c)) {
534 // c < 0xD800 or c > 0xDFFF
535 // Append to U the Unicode character with code point c.
536 u.append(c);
537 } else if (U16_IS_TRAIL(c)) {
538 // 0xDC00 <= c <= 0xDFFF
539 // Append to U a U+FFFD REPLACEMENT CHARACTER.
540 u.append(WTF::Unicode::replacementCharacter);
541 } else {
542 // 0xD800 <= c <= 0xDBFF
543 ASSERT(U16_IS_LEAD(c));
544 if (i == n - 1) {
545 // 1. If i = n−1, then append to U a U+FFFD REPLACEMENT CHARACTE R.
546 u.append(WTF::Unicode::replacementCharacter);
547 } else {
548 // 2. Otherwise, i < n−1:
549 ASSERT(i < n - 1);
550 // ....1. Let d be the code unit in S at index i+1.
551 UChar d = s[i + 1];
552 if (U16_IS_TRAIL(d)) {
553 // 2. If 0xDC00 <= d <= 0xDFFF, then:
554 // ..1. Let a be c & 0x3FF.
555 // ..2. Let b be d & 0x3FF.
556 // ..3. Append to U the Unicode character with code point 2^ 16+2^10*a+b.
557 u.append(U16_GET_SUPPLEMENTARY(c, d));
558 // Blink: This is equivalent to u.append(c); u.append(d);
559 ++i;
560 } else {
561 // 3. Otherwise, d < 0xDC00 or d > 0xDFFF. Append to U a U+F FFD REPLACEMENT CHARACTER.
562 u.append(WTF::Unicode::replacementCharacter);
563 }
564 }
565 }
566 // 3. Set i to i+1.
567 ++i;
568 }
569
570 // 6. Return U.
571 ASSERT(u.length() == string.length());
572 return u.toString();
573 }
574
575 String toScalarValueString(v8::Handle<v8::Value> value, ExceptionState& exceptio nState)
576 {
577 // From the Encoding standard (with a TODO to move to Web IDL):
578 // http://encoding.spec.whatwg.org/#type-scalarvaluestring
579 if (value.IsEmpty())
580 return String();
581 TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::String>, stringObject, value-> ToString(), exceptionState, String());
582
583 // ScalarValueString is identical to DOMString except that "convert a
584 // DOMString to a sequence of Unicode characters" is used subsequently
585 // when converting to an IDL value
586 String x = toCoreString(stringObject);
587 return replaceUnmatchedSurrogates(x);
588 }
589
590 LocalDOMWindow* toDOMWindow(v8::Handle<v8::Value> value, v8::Isolate* isolate)
591 {
592 if (value.IsEmpty() || !value->IsObject())
593 return 0;
594
595 v8::Handle<v8::Object> windowWrapper = V8Window::findInstanceInPrototypeChai n(v8::Handle<v8::Object>::Cast(value), isolate);
596 if (!windowWrapper.IsEmpty())
597 return V8Window::toNative(windowWrapper);
598 return 0;
599 }
600
601 LocalDOMWindow* toDOMWindow(v8::Handle<v8::Context> context)
602 {
603 if (context.IsEmpty())
604 return 0;
605 return toDOMWindow(context->Global(), context->GetIsolate());
606 }
607
608 LocalDOMWindow* enteredDOMWindow(v8::Isolate* isolate)
609 {
610 LocalDOMWindow* window = toDOMWindow(isolate->GetEnteredContext());
611 if (!window) {
612 // We don't always have an entered DOM window, for example during microt ask callbacks from V8
613 // (where the entered context may be the DOM-in-JS context). In that cas e, we fall back
614 // to the current context.
615 window = currentDOMWindow(isolate);
616 ASSERT(window);
617 }
618 return window;
619 }
620
621 LocalDOMWindow* currentDOMWindow(v8::Isolate* isolate)
622 {
623 return toDOMWindow(isolate->GetCurrentContext());
624 }
625
626 LocalDOMWindow* callingDOMWindow(v8::Isolate* isolate)
627 {
628 v8::Handle<v8::Context> context = isolate->GetCallingContext();
629 if (context.IsEmpty()) {
630 // Unfortunately, when processing script from a plug-in, we might not
631 // have a calling context. In those cases, we fall back to the
632 // entered context.
633 context = isolate->GetEnteredContext();
634 }
635 return toDOMWindow(context);
636 }
637
638 ExecutionContext* toExecutionContext(v8::Handle<v8::Context> context)
639 {
640 if (context.IsEmpty())
641 return 0;
642 v8::Handle<v8::Object> global = context->Global();
643 v8::Handle<v8::Object> windowWrapper = V8Window::findInstanceInPrototypeChai n(global, context->GetIsolate());
644 if (!windowWrapper.IsEmpty())
645 return V8Window::toNative(windowWrapper)->executionContext();
646 // FIXME: Is this line of code reachable?
647 return 0;
648 }
649
650 ExecutionContext* currentExecutionContext(v8::Isolate* isolate)
651 {
652 return toExecutionContext(isolate->GetCurrentContext());
653 }
654
655 ExecutionContext* callingExecutionContext(v8::Isolate* isolate)
656 {
657 v8::Handle<v8::Context> context = isolate->GetCallingContext();
658 if (context.IsEmpty()) {
659 // Unfortunately, when processing script from a plug-in, we might not
660 // have a calling context. In those cases, we fall back to the
661 // entered context.
662 context = isolate->GetEnteredContext();
663 }
664 return toExecutionContext(context);
665 }
666
667 LocalFrame* toFrameIfNotDetached(v8::Handle<v8::Context> context)
668 {
669 return toDOMWindow(context)->frame();
670 }
671
672 v8::Local<v8::Context> toV8Context(ExecutionContext* context, DOMWrapperWorld& w orld)
673 {
674 ASSERT(context);
675 if (LocalFrame* frame = toDocument(context)->frame())
676 return frame->script().windowProxy(world)->context();
677 return v8::Local<v8::Context>();
678 }
679
680 v8::Local<v8::Context> toV8Context(LocalFrame* frame, DOMWrapperWorld& world)
681 {
682 if (!frame)
683 return v8::Local<v8::Context>();
684 v8::Local<v8::Context> context = frame->script().windowProxy(world)->context ();
685 if (context.IsEmpty())
686 return v8::Local<v8::Context>();
687 LocalFrame* attachedFrame= toFrameIfNotDetached(context);
688 return frame == attachedFrame ? context : v8::Local<v8::Context>();
689 }
690
691 void crashIfV8IsDead()
692 {
693 if (v8::V8::IsDead()) {
694 // FIXME: We temporarily deal with V8 internal error situations
695 // such as out-of-memory by crashing the renderer.
696 CRASH();
697 }
698 }
699
700 v8::Handle<v8::Function> getBoundFunction(v8::Handle<v8::Function> function)
701 {
702 v8::Handle<v8::Value> boundFunction = function->GetBoundFunction();
703 return boundFunction->IsFunction() ? v8::Handle<v8::Function>::Cast(boundFun ction) : function;
704 }
705
706 void addHiddenValueToArray(v8::Handle<v8::Object> object, v8::Local<v8::Value> v alue, int arrayIndex, v8::Isolate* isolate)
707 {
708 v8::Local<v8::Value> arrayValue = object->GetInternalField(arrayIndex);
709 if (arrayValue->IsNull() || arrayValue->IsUndefined()) {
710 arrayValue = v8::Array::New(isolate);
711 object->SetInternalField(arrayIndex, arrayValue);
712 }
713
714 v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(arrayValue);
715 array->Set(v8::Integer::New(isolate, array->Length()), value);
716 }
717
718 void removeHiddenValueFromArray(v8::Handle<v8::Object> object, v8::Local<v8::Val ue> value, int arrayIndex, v8::Isolate* isolate)
719 {
720 v8::Local<v8::Value> arrayValue = object->GetInternalField(arrayIndex);
721 if (!arrayValue->IsArray())
722 return;
723 v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(arrayValue);
724 for (int i = array->Length() - 1; i >= 0; --i) {
725 v8::Local<v8::Value> item = array->Get(v8::Integer::New(isolate, i));
726 if (item->StrictEquals(value)) {
727 array->Delete(i);
728 return;
729 }
730 }
731 }
732
733 void moveEventListenerToNewWrapper(v8::Handle<v8::Object> object, EventListener* oldValue, v8::Local<v8::Value> newValue, int arrayIndex, v8::Isolate* isolate)
734 {
735 if (oldValue) {
736 V8AbstractEventListener* oldListener = V8AbstractEventListener::cast(old Value);
737 if (oldListener) {
738 v8::Local<v8::Object> oldListenerObject = oldListener->getExistingLi stenerObject();
739 if (!oldListenerObject.IsEmpty())
740 removeHiddenValueFromArray(object, oldListenerObject, arrayIndex , isolate);
741 }
742 }
743 // Non-callable input is treated as null and ignored
744 if (newValue->IsFunction())
745 addHiddenValueToArray(object, newValue, arrayIndex, isolate);
746 }
747
748 v8::Isolate* toIsolate(ExecutionContext* context)
749 {
750 if (context && context->isDocument())
751 return V8PerIsolateData::mainThreadIsolate();
752 return v8::Isolate::GetCurrent();
753 }
754
755 v8::Isolate* toIsolate(LocalFrame* frame)
756 {
757 ASSERT(frame);
758 return frame->script().isolate();
759 }
760
761 PassRefPtr<JSONValue> v8ToJSONValue(v8::Isolate* isolate, v8::Handle<v8::Value> value, int maxDepth)
762 {
763 if (value.IsEmpty()) {
764 ASSERT_NOT_REACHED();
765 return nullptr;
766 }
767
768 if (!maxDepth)
769 return nullptr;
770 maxDepth--;
771
772 if (value->IsNull() || value->IsUndefined())
773 return JSONValue::null();
774 if (value->IsBoolean())
775 return JSONBasicValue::create(value->BooleanValue());
776 if (value->IsNumber())
777 return JSONBasicValue::create(value->NumberValue());
778 if (value->IsString())
779 return JSONString::create(toCoreString(value.As<v8::String>()));
780 if (value->IsArray()) {
781 v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(value);
782 RefPtr<JSONArray> inspectorArray = JSONArray::create();
783 uint32_t length = array->Length();
784 for (uint32_t i = 0; i < length; i++) {
785 v8::Local<v8::Value> value = array->Get(v8::Int32::New(isolate, i));
786 RefPtr<JSONValue> element = v8ToJSONValue(isolate, value, maxDepth);
787 if (!element)
788 return nullptr;
789 inspectorArray->pushValue(element);
790 }
791 return inspectorArray;
792 }
793 if (value->IsObject()) {
794 RefPtr<JSONObject> jsonObject = JSONObject::create();
795 v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value);
796 v8::Local<v8::Array> propertyNames = object->GetPropertyNames();
797 uint32_t length = propertyNames->Length();
798 for (uint32_t i = 0; i < length; i++) {
799 v8::Local<v8::Value> name = propertyNames->Get(v8::Int32::New(isolat e, i));
800 // FIXME(yurys): v8::Object should support GetOwnPropertyNames
801 if (name->IsString() && !object->HasRealNamedProperty(v8::Handle<v8: :String>::Cast(name)))
802 continue;
803 RefPtr<JSONValue> propertyValue = v8ToJSONValue(isolate, object->Get (name), maxDepth);
804 if (!propertyValue)
805 return nullptr;
806 TOSTRING_DEFAULT(V8StringResource<TreatNullAsNullString>, nameString , name, nullptr);
807 jsonObject->setValue(nameString, propertyValue);
808 }
809 return jsonObject;
810 }
811 ASSERT_NOT_REACHED();
812 return nullptr;
813 }
814
815 V8TestingScope::V8TestingScope(v8::Isolate* isolate)
816 : m_handleScope(isolate)
817 , m_contextScope(v8::Context::New(isolate))
818 , m_scriptState(ScriptStateForTesting::create(isolate->GetCurrentContext(), DOMWrapperWorld::create(FakeWorld)))
819 {
820 }
821
822 V8TestingScope::~V8TestingScope()
823 {
824 m_scriptState->disposePerContextData();
825 }
826
827 ScriptState* V8TestingScope::scriptState() const
828 {
829 return m_scriptState.get();
830 }
831
832 v8::Isolate* V8TestingScope::isolate() const
833 {
834 return m_scriptState->isolate();
835 }
836
837 } // namespace blink
OLDNEW
« no previous file with comments | « sky/engine/bindings/core/v8/V8Binding.h ('k') | sky/engine/bindings/core/v8/V8BindingMacros.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698