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

Side by Side Diff: Source/bindings/v8/V8Binding.cpp

Issue 351423002: Moved files under Source/bindings/v8 to Source/bindings/core/v8. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 5 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 | Annotate | Revision Log
« no previous file with comments | « Source/bindings/v8/V8Binding.h ('k') | Source/bindings/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 "config.h"
32 #include "bindings/v8/V8Binding.h"
33
34 #include "bindings/core/v8/V8Element.h"
35 #include "bindings/core/v8/V8NodeFilter.h"
36 #include "bindings/core/v8/V8Window.h"
37 #include "bindings/core/v8/V8WorkerGlobalScope.h"
38 #include "bindings/core/v8/V8XPathNSResolver.h"
39 #include "bindings/core/v8/custom/V8CustomXPathNSResolver.h"
40 #include "bindings/v8/ScriptController.h"
41 #include "bindings/v8/V8AbstractEventListener.h"
42 #include "bindings/v8/V8BindingMacros.h"
43 #include "bindings/v8/V8NodeFilterCondition.h"
44 #include "bindings/v8/V8ObjectConstructor.h"
45 #include "bindings/v8/V8WindowShell.h"
46 #include "bindings/v8/WorkerScriptController.h"
47 #include "core/dom/Document.h"
48 #include "core/dom/Element.h"
49 #include "core/dom/NodeFilter.h"
50 #include "core/dom/QualifiedName.h"
51 #include "core/frame/LocalFrame.h"
52 #include "core/frame/Settings.h"
53 #include "core/inspector/BindingVisitors.h"
54 #include "core/inspector/InspectorTraceEvents.h"
55 #include "core/loader/FrameLoader.h"
56 #include "core/loader/FrameLoaderClient.h"
57 #include "core/workers/WorkerGlobalScope.h"
58 #include "core/xml/XPathNSResolver.h"
59 #include "platform/EventTracer.h"
60 #include "platform/JSONValues.h"
61 #include "wtf/ArrayBufferContents.h"
62 #include "wtf/MainThread.h"
63 #include "wtf/MathExtras.h"
64 #include "wtf/StdLibExtras.h"
65 #include "wtf/Threading.h"
66 #include "wtf/text/AtomicString.h"
67 #include "wtf/text/CString.h"
68 #include "wtf/text/StringBuffer.h"
69 #include "wtf/text/StringHash.h"
70 #include "wtf/text/WTFString.h"
71 #include "wtf/unicode/CharacterNames.h"
72 #include "wtf/unicode/Unicode.h"
73
74 namespace WebCore {
75
76 v8::Handle<v8::Value> throwError(V8ErrorType errorType, const String& message, v 8::Isolate* isolate)
77 {
78 return V8ThrowException::throwError(errorType, message, isolate);
79 }
80
81 v8::Handle<v8::Value> throwError(v8::Handle<v8::Value> exception, v8::Isolate* i solate)
82 {
83 return V8ThrowException::throwError(exception, isolate);
84 }
85
86 v8::Handle<v8::Value> throwTypeError(const String& message, v8::Isolate* isolate )
87 {
88 return V8ThrowException::throwTypeError(message, isolate);
89 }
90
91 void throwArityTypeErrorForMethod(const char* method, const char* type, const ch ar* valid, unsigned provided, v8::Isolate* isolate)
92 {
93 throwTypeError(ExceptionMessages::failedToExecute(method, type, ExceptionMes sages::invalidArity(valid, provided)), isolate);
94 }
95
96 void throwArityTypeErrorForConstructor(const char* type, const char* valid, unsi gned provided, v8::Isolate* isolate)
97 {
98 throwTypeError(ExceptionMessages::failedToConstruct(type, ExceptionMessages: :invalidArity(valid, provided)), isolate);
99 }
100
101 void throwArityTypeError(ExceptionState& exceptionState, const char* valid, unsi gned provided)
102 {
103 exceptionState.throwTypeError(ExceptionMessages::invalidArity(valid, provide d));
104 exceptionState.throwIfNeeded();
105 }
106
107 void throwMinimumArityTypeErrorForMethod(const char* method, const char* type, u nsigned expected, unsigned providedLeastNumMandatoryParams, v8::Isolate* isolate )
108 {
109 throwTypeError(ExceptionMessages::failedToExecute(method, type, ExceptionMes sages::notEnoughArguments(expected, providedLeastNumMandatoryParams)), isolate);
110 }
111
112 void throwMinimumArityTypeErrorForConstructor(const char* type, unsigned expecte d, unsigned providedLeastNumMandatoryParams, v8::Isolate* isolate)
113 {
114 throwTypeError(ExceptionMessages::failedToConstruct(type, ExceptionMessages: :notEnoughArguments(expected, providedLeastNumMandatoryParams)), isolate);
115 }
116
117 void throwMinimumArityTypeError(ExceptionState& exceptionState, unsigned expecte d, unsigned providedLeastNumMandatoryParams)
118 {
119 exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(expected , providedLeastNumMandatoryParams));
120 exceptionState.throwIfNeeded();
121 }
122
123 class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
124 virtual void* Allocate(size_t size) OVERRIDE
125 {
126 void* data;
127 WTF::ArrayBufferContents::allocateMemory(size, WTF::ArrayBufferContents: :ZeroInitialize, data);
128 return data;
129 }
130
131 virtual void* AllocateUninitialized(size_t size) OVERRIDE
132 {
133 void* data;
134 WTF::ArrayBufferContents::allocateMemory(size, WTF::ArrayBufferContents: :DontInitialize, data);
135 return data;
136 }
137
138 virtual void Free(void* data, size_t size) OVERRIDE
139 {
140 WTF::ArrayBufferContents::freeMemory(data, size);
141 }
142 };
143
144 v8::ArrayBuffer::Allocator* v8ArrayBufferAllocator()
145 {
146 DEFINE_STATIC_LOCAL(ArrayBufferAllocator, arrayBufferAllocator, ());
147 return &arrayBufferAllocator;
148 }
149
150 PassRefPtrWillBeRawPtr<NodeFilter> toNodeFilter(v8::Handle<v8::Value> callback, v8::Handle<v8::Object> creationContext, ScriptState* scriptState)
151 {
152 RefPtrWillBeRawPtr<NodeFilter> filter = NodeFilter::create();
153
154 v8::Handle<v8::Object> filterWrapper = toV8(filter, creationContext, scriptS tate->isolate()).As<v8::Object>();
155
156 RefPtrWillBeRawPtr<NodeFilterCondition> condition = V8NodeFilterCondition::c reate(callback, filterWrapper, scriptState);
157 filter->setCondition(condition.release());
158
159 return filter.release();
160 }
161
162 const int32_t kMaxInt32 = 0x7fffffff;
163 const int32_t kMinInt32 = -kMaxInt32 - 1;
164 const uint32_t kMaxUInt32 = 0xffffffff;
165 const int64_t kJSMaxInteger = 0x20000000000000LL - 1; // 2^53 - 1, maximum uniqu ely representable integer in ECMAScript.
166
167 static double enforceRange(double x, double minimum, double maximum, const char* typeName, ExceptionState& exceptionState)
168 {
169 if (std::isnan(x) || std::isinf(x)) {
170 exceptionState.throwTypeError("Value is" + String(std::isinf(x) ? " infi nite and" : "") + " not of type '" + String(typeName) + "'.");
171 return 0;
172 }
173 x = trunc(x);
174 if (x < minimum || x > maximum) {
175 exceptionState.throwTypeError("Value is outside the '" + String(typeName ) + "' value range.");
176 return 0;
177 }
178 return x;
179 }
180
181 template <typename T>
182 struct IntTypeLimits {
183 };
184
185 template <>
186 struct IntTypeLimits<int8_t> {
187 static const int8_t minValue = -128;
188 static const int8_t maxValue = 127;
189 static const unsigned numberOfValues = 256; // 2^8
190 };
191
192 template <>
193 struct IntTypeLimits<uint8_t> {
194 static const uint8_t maxValue = 255;
195 static const unsigned numberOfValues = 256; // 2^8
196 };
197
198 template <>
199 struct IntTypeLimits<int16_t> {
200 static const short minValue = -32768;
201 static const short maxValue = 32767;
202 static const unsigned numberOfValues = 65536; // 2^16
203 };
204
205 template <>
206 struct IntTypeLimits<uint16_t> {
207 static const unsigned short maxValue = 65535;
208 static const unsigned numberOfValues = 65536; // 2^16
209 };
210
211 template <typename T>
212 static inline T toSmallerInt(v8::Handle<v8::Value> value, IntegerConversionConfi guration configuration, const char* typeName, ExceptionState& exceptionState)
213 {
214 typedef IntTypeLimits<T> LimitsTrait;
215
216 // Fast case. The value is already a 32-bit integer in the right range.
217 if (value->IsInt32()) {
218 int32_t result = value->Int32Value();
219 if (result >= LimitsTrait::minValue && result <= LimitsTrait::maxValue)
220 return static_cast<T>(result);
221 if (configuration == EnforceRange) {
222 exceptionState.throwTypeError("Value is outside the '" + String(type Name) + "' value range.");
223 return 0;
224 }
225 result %= LimitsTrait::numberOfValues;
226 return static_cast<T>(result > LimitsTrait::maxValue ? result - LimitsTr ait::numberOfValues : result);
227 }
228
229 // Can the value be converted to a number?
230 TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::Number>, numberObject, value-> ToNumber(), exceptionState, 0);
231 if (numberObject.IsEmpty()) {
232 exceptionState.throwTypeError("Not convertible to a number value (of typ e '" + String(typeName) + "'.");
233 return 0;
234 }
235
236 if (configuration == EnforceRange)
237 return enforceRange(numberObject->Value(), LimitsTrait::minValue, Limits Trait::maxValue, typeName, exceptionState);
238
239 double numberValue = numberObject->Value();
240 if (std::isnan(numberValue) || std::isinf(numberValue) || !numberValue)
241 return 0;
242
243 numberValue = numberValue < 0 ? -floor(fabs(numberValue)) : floor(fabs(numbe rValue));
244 numberValue = fmod(numberValue, LimitsTrait::numberOfValues);
245
246 return static_cast<T>(numberValue > LimitsTrait::maxValue ? numberValue - Li mitsTrait::numberOfValues : numberValue);
247 }
248
249 template <typename T>
250 static inline T toSmallerUInt(v8::Handle<v8::Value> value, IntegerConversionConf iguration configuration, const char* typeName, ExceptionState& exceptionState)
251 {
252 typedef IntTypeLimits<T> LimitsTrait;
253
254 // Fast case. The value is a 32-bit signed integer - possibly positive?
255 if (value->IsInt32()) {
256 int32_t result = value->Int32Value();
257 if (result >= 0 && result <= LimitsTrait::maxValue)
258 return static_cast<T>(result);
259 if (configuration == EnforceRange) {
260 exceptionState.throwTypeError("Value is outside the '" + String(type Name) + "' value range.");
261 return 0;
262 }
263 return static_cast<T>(result);
264 }
265
266 // Can the value be converted to a number?
267 TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::Number>, numberObject, value-> ToNumber(), exceptionState, 0);
268 if (numberObject.IsEmpty()) {
269 exceptionState.throwTypeError("Not convertible to a number value (of typ e '" + String(typeName) + "'.");
270 return 0;
271 }
272
273 if (configuration == EnforceRange)
274 return enforceRange(numberObject->Value(), 0, LimitsTrait::maxValue, typ eName, exceptionState);
275
276 // Does the value convert to nan or to an infinity?
277 double numberValue = numberObject->Value();
278 if (std::isnan(numberValue) || std::isinf(numberValue) || !numberValue)
279 return 0;
280
281 if (configuration == Clamp)
282 return clampTo<T>(numberObject->Value());
283
284 numberValue = numberValue < 0 ? -floor(fabs(numberValue)) : floor(fabs(numbe rValue));
285 return static_cast<T>(fmod(numberValue, LimitsTrait::numberOfValues));
286 }
287
288 int8_t toInt8(v8::Handle<v8::Value> value, IntegerConversionConfiguration config uration, ExceptionState& exceptionState)
289 {
290 return toSmallerInt<int8_t>(value, configuration, "byte", exceptionState);
291 }
292
293 int8_t toInt8(v8::Handle<v8::Value> value)
294 {
295 NonThrowableExceptionState exceptionState;
296 return toInt8(value, NormalConversion, exceptionState);
297 }
298
299 uint8_t toUInt8(v8::Handle<v8::Value> value, IntegerConversionConfiguration conf iguration, ExceptionState& exceptionState)
300 {
301 return toSmallerUInt<uint8_t>(value, configuration, "octet", exceptionState) ;
302 }
303
304 uint8_t toUInt8(v8::Handle<v8::Value> value)
305 {
306 NonThrowableExceptionState exceptionState;
307 return toUInt8(value, NormalConversion, exceptionState);
308 }
309
310 int16_t toInt16(v8::Handle<v8::Value> value, IntegerConversionConfiguration conf iguration, ExceptionState& exceptionState)
311 {
312 return toSmallerInt<int16_t>(value, configuration, "short", exceptionState);
313 }
314
315 int16_t toInt16(v8::Handle<v8::Value> value)
316 {
317 NonThrowableExceptionState exceptionState;
318 return toInt16(value, NormalConversion, exceptionState);
319 }
320
321 uint16_t toUInt16(v8::Handle<v8::Value> value, IntegerConversionConfiguration co nfiguration, ExceptionState& exceptionState)
322 {
323 return toSmallerUInt<uint16_t>(value, configuration, "unsigned short", excep tionState);
324 }
325
326 uint16_t toUInt16(v8::Handle<v8::Value> value)
327 {
328 NonThrowableExceptionState exceptionState;
329 return toUInt16(value, NormalConversion, exceptionState);
330 }
331
332 int32_t toInt32(v8::Handle<v8::Value> value, IntegerConversionConfiguration conf iguration, ExceptionState& exceptionState)
333 {
334 // Fast case. The value is already a 32-bit integer.
335 if (value->IsInt32())
336 return value->Int32Value();
337
338 // Can the value be converted to a number?
339 TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::Number>, numberObject, value-> ToNumber(), exceptionState, 0);
340 if (numberObject.IsEmpty()) {
341 exceptionState.throwTypeError("Not convertible to a number value (of typ e 'long'.)");
342 return 0;
343 }
344
345 if (configuration == EnforceRange)
346 return enforceRange(numberObject->Value(), kMinInt32, kMaxInt32, "long", exceptionState);
347
348 // Does the value convert to nan or to an infinity?
349 double numberValue = numberObject->Value();
350 if (std::isnan(numberValue) || std::isinf(numberValue))
351 return 0;
352
353 if (configuration == Clamp)
354 return clampTo<int32_t>(numberObject->Value());
355
356 TONATIVE_DEFAULT_EXCEPTIONSTATE(int32_t, result, numberObject->Int32Value(), exceptionState, 0);
357 return result;
358 }
359
360 int32_t toInt32(v8::Handle<v8::Value> value)
361 {
362 NonThrowableExceptionState exceptionState;
363 return toInt32(value, NormalConversion, exceptionState);
364 }
365
366 uint32_t toUInt32(v8::Handle<v8::Value> value, IntegerConversionConfiguration co nfiguration, ExceptionState& exceptionState)
367 {
368 // Fast case. The value is already a 32-bit unsigned integer.
369 if (value->IsUint32())
370 return value->Uint32Value();
371
372 // Fast case. The value is a 32-bit signed integer - possibly positive?
373 if (value->IsInt32()) {
374 int32_t result = value->Int32Value();
375 if (result >= 0)
376 return result;
377 if (configuration == EnforceRange) {
378 exceptionState.throwTypeError("Value is outside the 'unsigned long' value range.");
379 return 0;
380 }
381 return result;
382 }
383
384 // Can the value be converted to a number?
385 TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::Number>, numberObject, value-> ToNumber(), exceptionState, 0);
386 if (numberObject.IsEmpty()) {
387 exceptionState.throwTypeError("Not convertible to a number value (of typ e 'unsigned long'.)");
388 return 0;
389 }
390
391 if (configuration == EnforceRange)
392 return enforceRange(numberObject->Value(), 0, kMaxUInt32, "unsigned long ", exceptionState);
393
394 // Does the value convert to nan or to an infinity?
395 double numberValue = numberObject->Value();
396 if (std::isnan(numberValue) || std::isinf(numberValue))
397 return 0;
398
399 if (configuration == Clamp)
400 return clampTo<uint32_t>(numberObject->Value());
401
402 TONATIVE_DEFAULT(uint32_t, result, numberObject->Uint32Value(), 0);
403 return result;
404 }
405
406 uint32_t toUInt32(v8::Handle<v8::Value> value)
407 {
408 NonThrowableExceptionState exceptionState;
409 return toUInt32(value, NormalConversion, exceptionState);
410 }
411
412 int64_t toInt64(v8::Handle<v8::Value> value, IntegerConversionConfiguration conf iguration, ExceptionState& exceptionState)
413 {
414 // Fast case. The value is a 32-bit integer.
415 if (value->IsInt32())
416 return value->Int32Value();
417
418 // Can the value be converted to a number?
419 TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::Number>, numberObject, value-> ToNumber(), exceptionState, 0);
420 if (numberObject.IsEmpty()) {
421 exceptionState.throwTypeError("Not convertible to a number value (of typ e 'long long'.)");
422 return 0;
423 }
424
425 double x = numberObject->Value();
426
427 if (configuration == EnforceRange)
428 return enforceRange(x, -kJSMaxInteger, kJSMaxInteger, "long long", excep tionState);
429
430 // Does the value convert to nan or to an infinity?
431 if (std::isnan(x) || std::isinf(x))
432 return 0;
433
434 // NaNs and +/-Infinity should be 0, otherwise modulo 2^64.
435 unsigned long long integer;
436 doubleToInteger(x, integer);
437 return integer;
438 }
439
440 int64_t toInt64(v8::Handle<v8::Value> value)
441 {
442 NonThrowableExceptionState exceptionState;
443 return toInt64(value, NormalConversion, exceptionState);
444 }
445
446 uint64_t toUInt64(v8::Handle<v8::Value> value, IntegerConversionConfiguration co nfiguration, ExceptionState& exceptionState)
447 {
448 // Fast case. The value is a 32-bit unsigned integer.
449 if (value->IsUint32())
450 return value->Uint32Value();
451
452 // Fast case. The value is a 32-bit integer.
453 if (value->IsInt32()) {
454 int32_t result = value->Int32Value();
455 if (result >= 0)
456 return result;
457 if (configuration == EnforceRange) {
458 exceptionState.throwTypeError("Value is outside the 'unsigned long l ong' value range.");
459 return 0;
460 }
461 return result;
462 }
463
464 // Can the value be converted to a number?
465 TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::Number>, numberObject, value-> ToNumber(), exceptionState, 0);
466 if (numberObject.IsEmpty()) {
467 exceptionState.throwTypeError("Not convertible to a number value (of typ e 'unsigned long long'.)");
468 return 0;
469 }
470
471 double x = numberObject->Value();
472
473 if (configuration == EnforceRange)
474 return enforceRange(x, 0, kJSMaxInteger, "unsigned long long", exception State);
475
476 // Does the value convert to nan or to an infinity?
477 if (std::isnan(x) || std::isinf(x))
478 return 0;
479
480 // NaNs and +/-Infinity should be 0, otherwise modulo 2^64.
481 unsigned long long integer;
482 doubleToInteger(x, integer);
483 return integer;
484 }
485
486 uint64_t toUInt64(v8::Handle<v8::Value> value)
487 {
488 NonThrowableExceptionState exceptionState;
489 return toUInt64(value, NormalConversion, exceptionState);
490 }
491
492 float toFloat(v8::Handle<v8::Value> value, ExceptionState& exceptionState)
493 {
494 TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::Number>, numberObject, value-> ToNumber(), exceptionState, 0);
495 return numberObject->NumberValue();
496 }
497
498 String toByteString(v8::Handle<v8::Value> value, ExceptionState& exceptionState)
499 {
500 // Handle null default value.
501 if (value.IsEmpty())
502 return String();
503
504 // From the Web IDL spec: http://heycam.github.io/webidl/#es-ByteString
505 if (value.IsEmpty())
506 return String();
507
508 // 1. Let x be ToString(v)
509 TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::String>, stringObject, value-> ToString(), exceptionState, String());
510 String x = toCoreString(stringObject);
511
512 // 2. If the value of any element of x is greater than 255, then throw a Typ eError.
513 if (!x.containsOnlyLatin1()) {
514 exceptionState.throwTypeError("Value is not a valid ByteString.");
515 return String();
516 }
517
518 // 3. Return an IDL ByteString value whose length is the length of x, and wh ere the
519 // value of each element is the value of the corresponding element of x.
520 // Blink: A ByteString is simply a String with a range constrained per the a bove, so
521 // this is the identity operation.
522 return x;
523 }
524
525 static bool hasUnmatchedSurrogates(const String& string)
526 {
527 // By definition, 8-bit strings are confined to the Latin-1 code page and
528 // have no surrogates, matched or otherwise.
529 if (string.is8Bit())
530 return false;
531
532 const UChar* characters = string.characters16();
533 const unsigned length = string.length();
534
535 for (unsigned i = 0; i < length; ++i) {
536 UChar c = characters[i];
537 if (U16_IS_SINGLE(c))
538 continue;
539 if (U16_IS_TRAIL(c))
540 return true;
541 ASSERT(U16_IS_LEAD(c));
542 if (i == length - 1)
543 return true;
544 UChar d = characters[i + 1];
545 if (!U16_IS_TRAIL(d))
546 return true;
547 ++i;
548 }
549 return false;
550 }
551
552 // Replace unmatched surrogates with REPLACEMENT CHARACTER U+FFFD.
553 static String replaceUnmatchedSurrogates(const String& string)
554 {
555 // This roughly implements http://heycam.github.io/webidl/#dfn-obtain-unicod e
556 // but since Blink strings are 16-bits internally, the output is simply
557 // re-encoded to UTF-16.
558
559 // The concept of surrogate pairs is explained at:
560 // http://www.unicode.org/versions/Unicode6.2.0/ch03.pdf#G2630
561
562 // Blink-specific optimization to avoid making an unnecessary copy.
563 if (!hasUnmatchedSurrogates(string))
564 return string;
565 ASSERT(!string.is8Bit());
566
567 // 1. Let S be the DOMString value.
568 const UChar* s = string.characters16();
569
570 // 2. Let n be the length of S.
571 const unsigned n = string.length();
572
573 // 3. Initialize i to 0.
574 unsigned i = 0;
575
576 // 4. Initialize U to be an empty sequence of Unicode characters.
577 StringBuilder u;
578 u.reserveCapacity(n);
579
580 // 5. While i < n:
581 while (i < n) {
582 // 1. Let c be the code unit in S at index i.
583 UChar c = s[i];
584 // 2. Depending on the value of c:
585 if (U16_IS_SINGLE(c)) {
586 // c < 0xD800 or c > 0xDFFF
587 // Append to U the Unicode character with code point c.
588 u.append(c);
589 } else if (U16_IS_TRAIL(c)) {
590 // 0xDC00 <= c <= 0xDFFF
591 // Append to U a U+FFFD REPLACEMENT CHARACTER.
592 u.append(WTF::Unicode::replacementCharacter);
593 } else {
594 // 0xD800 <= c <= 0xDBFF
595 ASSERT(U16_IS_LEAD(c));
596 if (i == n - 1) {
597 // 1. If i = n−1, then append to U a U+FFFD REPLACEMENT CHARACTE R.
598 u.append(WTF::Unicode::replacementCharacter);
599 } else {
600 // 2. Otherwise, i < n−1:
601 ASSERT(i < n - 1);
602 // ....1. Let d be the code unit in S at index i+1.
603 UChar d = s[i + 1];
604 if (U16_IS_TRAIL(d)) {
605 // 2. If 0xDC00 <= d <= 0xDFFF, then:
606 // ..1. Let a be c & 0x3FF.
607 // ..2. Let b be d & 0x3FF.
608 // ..3. Append to U the Unicode character with code point 2^ 16+2^10*a+b.
609 u.append(U16_GET_SUPPLEMENTARY(c, d));
610 // Blink: This is equivalent to u.append(c); u.append(d);
611 ++i;
612 } else {
613 // 3. Otherwise, d < 0xDC00 or d > 0xDFFF. Append to U a U+F FFD REPLACEMENT CHARACTER.
614 u.append(WTF::Unicode::replacementCharacter);
615 }
616 }
617 }
618 // 3. Set i to i+1.
619 ++i;
620 }
621
622 // 6. Return U.
623 ASSERT(u.length() == string.length());
624 return u.toString();
625 }
626
627 String toScalarValueString(v8::Handle<v8::Value> value, ExceptionState& exceptio nState)
628 {
629 // From the Encoding standard (with a TODO to move to Web IDL):
630 // http://encoding.spec.whatwg.org/#type-scalarvaluestring
631 if (value.IsEmpty())
632 return String();
633 TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::String>, stringObject, value-> ToString(), exceptionState, String());
634
635 // ScalarValueString is identical to DOMString except that "convert a
636 // DOMString to a sequence of Unicode characters" is used subsequently
637 // when converting to an IDL value
638 String x = toCoreString(stringObject);
639 return replaceUnmatchedSurrogates(x);
640 }
641
642 PassRefPtrWillBeRawPtr<XPathNSResolver> toXPathNSResolver(v8::Handle<v8::Value> value, v8::Isolate* isolate)
643 {
644 RefPtrWillBeRawPtr<XPathNSResolver> resolver = nullptr;
645 if (V8XPathNSResolver::hasInstance(value, isolate))
646 resolver = V8XPathNSResolver::toNative(v8::Handle<v8::Object>::Cast(valu e));
647 else if (value->IsObject())
648 resolver = V8CustomXPathNSResolver::create(value->ToObject(), isolate);
649 return resolver;
650 }
651
652 LocalDOMWindow* toDOMWindow(v8::Handle<v8::Value> value, v8::Isolate* isolate)
653 {
654 if (value.IsEmpty() || !value->IsObject())
655 return 0;
656
657 v8::Handle<v8::Object> windowWrapper = V8Window::findInstanceInPrototypeChai n(v8::Handle<v8::Object>::Cast(value), isolate);
658 if (!windowWrapper.IsEmpty())
659 return V8Window::toNative(windowWrapper);
660 return 0;
661 }
662
663 LocalDOMWindow* toDOMWindow(v8::Handle<v8::Context> context)
664 {
665 if (context.IsEmpty())
666 return 0;
667 return toDOMWindow(context->Global(), context->GetIsolate());
668 }
669
670 LocalDOMWindow* enteredDOMWindow(v8::Isolate* isolate)
671 {
672 LocalDOMWindow* window = toDOMWindow(isolate->GetEnteredContext());
673 if (!window) {
674 // We don't always have an entered DOM window, for example during microt ask callbacks from V8
675 // (where the entered context may be the DOM-in-JS context). In that cas e, we fall back
676 // to the current context.
677 window = currentDOMWindow(isolate);
678 ASSERT(window);
679 }
680 return window;
681 }
682
683 LocalDOMWindow* currentDOMWindow(v8::Isolate* isolate)
684 {
685 return toDOMWindow(isolate->GetCurrentContext());
686 }
687
688 LocalDOMWindow* callingDOMWindow(v8::Isolate* isolate)
689 {
690 v8::Handle<v8::Context> context = isolate->GetCallingContext();
691 if (context.IsEmpty()) {
692 // Unfortunately, when processing script from a plug-in, we might not
693 // have a calling context. In those cases, we fall back to the
694 // entered context.
695 context = isolate->GetEnteredContext();
696 }
697 return toDOMWindow(context);
698 }
699
700 ExecutionContext* toExecutionContext(v8::Handle<v8::Context> context)
701 {
702 v8::Handle<v8::Object> global = context->Global();
703 v8::Handle<v8::Object> windowWrapper = V8Window::findInstanceInPrototypeChai n(global, context->GetIsolate());
704 if (!windowWrapper.IsEmpty())
705 return V8Window::toNative(windowWrapper)->executionContext();
706 v8::Handle<v8::Object> workerWrapper = V8WorkerGlobalScope::findInstanceInPr ototypeChain(global, context->GetIsolate());
707 if (!workerWrapper.IsEmpty())
708 return V8WorkerGlobalScope::toNative(workerWrapper)->executionContext();
709 // FIXME: Is this line of code reachable?
710 return 0;
711 }
712
713 ExecutionContext* currentExecutionContext(v8::Isolate* isolate)
714 {
715 return toExecutionContext(isolate->GetCurrentContext());
716 }
717
718 ExecutionContext* callingExecutionContext(v8::Isolate* isolate)
719 {
720 v8::Handle<v8::Context> context = isolate->GetCallingContext();
721 if (context.IsEmpty()) {
722 // Unfortunately, when processing script from a plug-in, we might not
723 // have a calling context. In those cases, we fall back to the
724 // entered context.
725 context = isolate->GetEnteredContext();
726 }
727 return toExecutionContext(context);
728 }
729
730 LocalFrame* toFrameIfNotDetached(v8::Handle<v8::Context> context)
731 {
732 LocalDOMWindow* window = toDOMWindow(context);
733 if (window && window->isCurrentlyDisplayedInFrame())
734 return window->frame();
735 // We return 0 here because |context| is detached from the LocalFrame. If we
736 // did return |frame| we could get in trouble because the frame could be
737 // navigated to another security origin.
738 return 0;
739 }
740
741 v8::Local<v8::Context> toV8Context(ExecutionContext* context, DOMWrapperWorld& w orld)
742 {
743 ASSERT(context);
744 if (context->isDocument()) {
745 if (LocalFrame* frame = toDocument(context)->frame())
746 return frame->script().windowShell(world)->context();
747 } else if (context->isWorkerGlobalScope()) {
748 if (WorkerScriptController* script = toWorkerGlobalScope(context)->scrip t())
749 return script->context();
750 }
751 return v8::Local<v8::Context>();
752 }
753
754 v8::Local<v8::Context> toV8Context(LocalFrame* frame, DOMWrapperWorld& world)
755 {
756 if (!frame)
757 return v8::Local<v8::Context>();
758 v8::Local<v8::Context> context = frame->script().windowShell(world)->context ();
759 if (context.IsEmpty())
760 return v8::Local<v8::Context>();
761 LocalFrame* attachedFrame= toFrameIfNotDetached(context);
762 return frame == attachedFrame ? context : v8::Local<v8::Context>();
763 }
764
765 v8::Local<v8::Value> handleMaxRecursionDepthExceeded(v8::Isolate* isolate)
766 {
767 throwError(v8RangeError, "Maximum call stack size exceeded.", isolate);
768 return v8::Local<v8::Value>();
769 }
770
771 void crashIfV8IsDead()
772 {
773 if (v8::V8::IsDead()) {
774 // FIXME: We temporarily deal with V8 internal error situations
775 // such as out-of-memory by crashing the renderer.
776 CRASH();
777 }
778 }
779
780 v8::Handle<v8::Function> getBoundFunction(v8::Handle<v8::Function> function)
781 {
782 v8::Handle<v8::Value> boundFunction = function->GetBoundFunction();
783 return boundFunction->IsFunction() ? v8::Handle<v8::Function>::Cast(boundFun ction) : function;
784 }
785
786 void addHiddenValueToArray(v8::Handle<v8::Object> object, v8::Local<v8::Value> v alue, int arrayIndex, v8::Isolate* isolate)
787 {
788 v8::Local<v8::Value> arrayValue = object->GetInternalField(arrayIndex);
789 if (arrayValue->IsNull() || arrayValue->IsUndefined()) {
790 arrayValue = v8::Array::New(isolate);
791 object->SetInternalField(arrayIndex, arrayValue);
792 }
793
794 v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(arrayValue);
795 array->Set(v8::Integer::New(isolate, array->Length()), value);
796 }
797
798 void removeHiddenValueFromArray(v8::Handle<v8::Object> object, v8::Local<v8::Val ue> value, int arrayIndex, v8::Isolate* isolate)
799 {
800 v8::Local<v8::Value> arrayValue = object->GetInternalField(arrayIndex);
801 if (!arrayValue->IsArray())
802 return;
803 v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(arrayValue);
804 for (int i = array->Length() - 1; i >= 0; --i) {
805 v8::Local<v8::Value> item = array->Get(v8::Integer::New(isolate, i));
806 if (item->StrictEquals(value)) {
807 array->Delete(i);
808 return;
809 }
810 }
811 }
812
813 void moveEventListenerToNewWrapper(v8::Handle<v8::Object> object, EventListener* oldValue, v8::Local<v8::Value> newValue, int arrayIndex, v8::Isolate* isolate)
814 {
815 if (oldValue) {
816 V8AbstractEventListener* oldListener = V8AbstractEventListener::cast(old Value);
817 if (oldListener) {
818 v8::Local<v8::Object> oldListenerObject = oldListener->getExistingLi stenerObject();
819 if (!oldListenerObject.IsEmpty())
820 removeHiddenValueFromArray(object, oldListenerObject, arrayIndex , isolate);
821 }
822 }
823 // Non-callable input is treated as null and ignored
824 if (newValue->IsFunction())
825 addHiddenValueToArray(object, newValue, arrayIndex, isolate);
826 }
827
828 v8::Isolate* toIsolate(ExecutionContext* context)
829 {
830 if (context && context->isDocument())
831 return V8PerIsolateData::mainThreadIsolate();
832 return v8::Isolate::GetCurrent();
833 }
834
835 v8::Isolate* toIsolate(LocalFrame* frame)
836 {
837 ASSERT(frame);
838 return frame->script().isolate();
839 }
840
841 PassRefPtr<JSONValue> v8ToJSONValue(v8::Isolate* isolate, v8::Handle<v8::Value> value, int maxDepth)
842 {
843 if (value.IsEmpty()) {
844 ASSERT_NOT_REACHED();
845 return nullptr;
846 }
847
848 if (!maxDepth)
849 return nullptr;
850 maxDepth--;
851
852 if (value->IsNull() || value->IsUndefined())
853 return JSONValue::null();
854 if (value->IsBoolean())
855 return JSONBasicValue::create(value->BooleanValue());
856 if (value->IsNumber())
857 return JSONBasicValue::create(value->NumberValue());
858 if (value->IsString())
859 return JSONString::create(toCoreString(value.As<v8::String>()));
860 if (value->IsArray()) {
861 v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(value);
862 RefPtr<JSONArray> inspectorArray = JSONArray::create();
863 uint32_t length = array->Length();
864 for (uint32_t i = 0; i < length; i++) {
865 v8::Local<v8::Value> value = array->Get(v8::Int32::New(isolate, i));
866 RefPtr<JSONValue> element = v8ToJSONValue(isolate, value, maxDepth);
867 if (!element)
868 return nullptr;
869 inspectorArray->pushValue(element);
870 }
871 return inspectorArray;
872 }
873 if (value->IsObject()) {
874 RefPtr<JSONObject> jsonObject = JSONObject::create();
875 v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value);
876 v8::Local<v8::Array> propertyNames = object->GetPropertyNames();
877 uint32_t length = propertyNames->Length();
878 for (uint32_t i = 0; i < length; i++) {
879 v8::Local<v8::Value> name = propertyNames->Get(v8::Int32::New(isolat e, i));
880 // FIXME(yurys): v8::Object should support GetOwnPropertyNames
881 if (name->IsString() && !object->HasRealNamedProperty(v8::Handle<v8: :String>::Cast(name)))
882 continue;
883 RefPtr<JSONValue> propertyValue = v8ToJSONValue(isolate, object->Get (name), maxDepth);
884 if (!propertyValue)
885 return nullptr;
886 TOSTRING_DEFAULT(V8StringResource<WithNullCheck>, nameString, name, nullptr);
887 jsonObject->setValue(nameString, propertyValue);
888 }
889 return jsonObject;
890 }
891 ASSERT_NOT_REACHED();
892 return nullptr;
893 }
894
895 V8TestingScope::V8TestingScope(v8::Isolate* isolate)
896 : m_handleScope(isolate)
897 , m_contextScope(v8::Context::New(isolate))
898 , m_scriptState(ScriptStateForTesting::create(isolate->GetCurrentContext(), DOMWrapperWorld::create()))
899 {
900 }
901
902 V8TestingScope::~V8TestingScope()
903 {
904 m_scriptState->disposePerContextData();
905 }
906
907 ScriptState* V8TestingScope::scriptState() const
908 {
909 return m_scriptState.get();
910 }
911
912 v8::Isolate* V8TestingScope::isolate() const
913 {
914 return m_scriptState->isolate();
915 }
916
917 void GetDevToolsFunctionInfo(v8::Handle<v8::Function> function, v8::Isolate* iso late, int& scriptId, String& resourceName, int& lineNumber)
918 {
919 v8::Handle<v8::Function> originalFunction = getBoundFunction(function);
920 scriptId = originalFunction->ScriptId();
921 v8::ScriptOrigin origin = originalFunction->GetScriptOrigin();
922 if (!origin.ResourceName().IsEmpty()) {
923 resourceName = NativeValueTraits<String>::nativeValue(origin.ResourceNam e(), isolate);
924 lineNumber = originalFunction->GetScriptLineNumber() + 1;
925 }
926 if (resourceName.isEmpty()) {
927 resourceName = "undefined";
928 lineNumber = 1;
929 }
930 }
931
932 PassRefPtr<TraceEvent::ConvertableToTraceFormat> devToolsTraceEventData(Executio nContext* context, v8::Handle<v8::Function> function, v8::Isolate* isolate)
933 {
934 int scriptId = 0;
935 String resourceName;
936 int lineNumber = 1;
937 GetDevToolsFunctionInfo(function, isolate, scriptId, resourceName, lineNumbe r);
938 return InspectorFunctionCallEvent::data(context, scriptId, resourceName, lin eNumber);
939 }
940
941 } // namespace WebCore
OLDNEW
« no previous file with comments | « Source/bindings/v8/V8Binding.h ('k') | Source/bindings/v8/V8BindingMacros.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698