OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library _interceptors; | 5 library _interceptors; |
6 | 6 |
7 import 'dart:_js_embedded_names' show | 7 import 'dart:_js_embedded_names' show |
8 DISPATCH_PROPERTY_NAME, | 8 DISPATCH_PROPERTY_NAME, |
9 TYPE_TO_INTERCEPTOR_MAP; | 9 TYPE_TO_INTERCEPTOR_MAP; |
10 | 10 |
11 import 'dart:collection'; | 11 import 'dart:collection'; |
12 import 'dart:_internal' hide Symbol; | 12 import 'dart:_internal' hide Symbol; |
13 import "dart:_internal" as _symbol_dev show Symbol; | 13 import "dart:_internal" as _symbol_dev show Symbol; |
14 import 'dart:_js_helper' show allMatchesInStringUnchecked, | 14 import 'dart:_js_helper' show allMatchesInStringUnchecked, |
15 Null, | 15 Null, |
16 JSSyntaxRegExp, | 16 JSSyntaxRegExp, |
17 Primitives, | 17 Primitives, |
18 argumentErrorValue, | 18 argumentErrorValue, |
19 checkInt, | 19 checkInt, |
20 checkNull, | 20 checkNull, |
21 checkNum, | 21 checkNum, |
22 checkString, | 22 checkString, |
23 defineProperty, | 23 defineProperty, |
24 diagnoseIndexError, | 24 diagnoseIndexError, |
| 25 getIsolateAffinityTag, |
25 getRuntimeType, | 26 getRuntimeType, |
26 initNativeDispatch, | 27 initNativeDispatch, |
27 initNativeDispatchFlag, | 28 initNativeDispatchFlag, |
28 regExpGetNative, | 29 regExpGetNative, |
29 regExpCaptureCount, | 30 regExpCaptureCount, |
30 stringContainsUnchecked, | 31 stringContainsUnchecked, |
31 stringIndexOfStringUnchecked, | 32 stringIndexOfStringUnchecked, |
32 stringLastIndexOfUnchecked, | 33 stringLastIndexOfUnchecked, |
33 stringReplaceAllFuncUnchecked, | 34 stringReplaceAllFuncUnchecked, |
34 stringReplaceAllUnchecked, | 35 stringReplaceAllUnchecked, |
35 stringReplaceFirstUnchecked, | 36 stringReplaceFirstUnchecked, |
36 stringReplaceFirstMappedUnchecked, | 37 stringReplaceFirstMappedUnchecked, |
37 stringReplaceRangeUnchecked, | 38 stringReplaceRangeUnchecked, |
38 lookupAndCacheInterceptor, | 39 lookupAndCacheInterceptor, |
39 lookupDispatchRecord, | 40 lookupDispatchRecord, |
40 StringMatch, | 41 StringMatch, |
41 firstMatchAfter, | 42 firstMatchAfter, |
42 NoInline; | 43 NoInline; |
| 44 import 'dart:js' show JsNative; |
| 45 |
43 import 'dart:_foreign_helper' show | 46 import 'dart:_foreign_helper' show |
44 JS, | 47 JS, |
45 JS_EFFECT, | 48 JS_EFFECT, |
46 JS_EMBEDDED_GLOBAL, | 49 JS_EMBEDDED_GLOBAL, |
47 JS_INTERCEPTOR_CONSTANT, | 50 JS_INTERCEPTOR_CONSTANT, |
48 JS_STRING_CONCAT; | 51 JS_STRING_CONCAT; |
49 import 'dart:math' show Random; | 52 import 'dart:math' show Random; |
50 | 53 |
51 part 'js_array.dart'; | 54 part 'js_array.dart'; |
52 part 'js_number.dart'; | 55 part 'js_number.dart'; |
53 part 'js_string.dart'; | 56 part 'js_string.dart'; |
54 | 57 |
| 58 final String DART_CLOSURE_PROPERTY_NAME = |
| 59 getIsolateAffinityTag(r'_$dart_dartClosure'); |
| 60 |
55 String _symbolToString(Symbol symbol) => _symbol_dev.Symbol.getName(symbol); | 61 String _symbolToString(Symbol symbol) => _symbol_dev.Symbol.getName(symbol); |
56 | 62 |
57 _symbolMapToStringMap(Map<Symbol, dynamic> map) { | 63 _symbolMapToStringMap(Map<Symbol, dynamic> map) { |
58 if (map == null) return null; | 64 if (map == null) return null; |
59 var result = new Map<String, dynamic>(); | 65 var result = new Map<String, dynamic>(); |
60 map.forEach((Symbol key, value) { | 66 map.forEach((Symbol key, value) { |
61 result[_symbolToString(key)] = value; | 67 result[_symbolToString(key)] = value; |
62 }); | 68 }); |
63 return result; | 69 return result; |
64 } | 70 } |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
163 throw new UnimplementedError('Return interceptor for $discriminatedTag'); | 169 throw new UnimplementedError('Return interceptor for $discriminatedTag'); |
164 } | 170 } |
165 } | 171 } |
166 | 172 |
167 var interceptor = lookupAndCacheInterceptor(object); | 173 var interceptor = lookupAndCacheInterceptor(object); |
168 if (interceptor == null) { | 174 if (interceptor == null) { |
169 // JavaScript Objects created via object literals and `Object.create(null)` | 175 // JavaScript Objects created via object literals and `Object.create(null)` |
170 // are 'plain' Objects. This test could be simplified and the dispatch path | 176 // are 'plain' Objects. This test could be simplified and the dispatch path |
171 // be faster if Object.prototype was pre-patched with a non-leaf dispatch | 177 // be faster if Object.prototype was pre-patched with a non-leaf dispatch |
172 // record. | 178 // record. |
| 179 if (JS('bool', 'typeof # == "function"', object)) { |
| 180 return JS_INTERCEPTOR_CONSTANT(JavaScriptFunction); |
| 181 } |
173 var proto = JS('', 'Object.getPrototypeOf(#)', object); | 182 var proto = JS('', 'Object.getPrototypeOf(#)', object); |
174 if (JS('bool', '# == null || # === Object.prototype', proto, proto)) { | 183 if (JS('bool', '# == null || # === Object.prototype', proto, proto)) { |
175 return JS_INTERCEPTOR_CONSTANT(PlainJavaScriptObject); | 184 return JS_INTERCEPTOR_CONSTANT(PlainJavaScriptObject); |
176 } else { | 185 } else { |
177 return JS_INTERCEPTOR_CONSTANT(UnknownJavaScriptObject); | 186 return JS_INTERCEPTOR_CONSTANT(UnknownJavaScriptObject); |
178 } | 187 } |
179 } | 188 } |
180 | 189 |
181 return interceptor; | 190 return interceptor; |
182 } | 191 } |
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
387 * This is the type that should be exported by a JavaScript interop library. | 396 * This is the type that should be exported by a JavaScript interop library. |
388 */ | 397 */ |
389 abstract class JSObject { | 398 abstract class JSObject { |
390 } | 399 } |
391 | 400 |
392 | 401 |
393 /** | 402 /** |
394 * Interceptor base class for JavaScript objects not recognized as some more | 403 * Interceptor base class for JavaScript objects not recognized as some more |
395 * specific native type. | 404 * specific native type. |
396 */ | 405 */ |
397 abstract class JavaScriptObject extends Interceptor implements JSObject { | 406 class JavaScriptObject extends Interceptor implements JSObject { |
398 const JavaScriptObject(); | 407 const JavaScriptObject(); |
399 | 408 |
400 // It would be impolite to stash a property on the object. | 409 // It would be impolite to stash a property on the object. |
401 int get hashCode => 0; | 410 int get hashCode => 0; |
402 | 411 |
403 Type get runtimeType => JSObject; | 412 Type get runtimeType => JSObject; |
| 413 |
| 414 /** |
| 415 * Returns the result of the JavaScript objects `toString` method. |
| 416 */ |
| 417 String toString() { |
| 418 try { |
| 419 return JS('String', 'String(#)', this); |
| 420 } catch(e) { |
| 421 return super.toString(); |
| 422 } |
| 423 } |
404 } | 424 } |
405 | 425 |
406 | 426 |
407 /** | 427 /** |
408 * Interceptor for plain JavaScript objects created as JavaScript object | 428 * Interceptor for plain JavaScript objects created as JavaScript object |
409 * literals or `new Object()`. | 429 * literals or `new Object()`. |
410 */ | 430 */ |
411 class PlainJavaScriptObject extends JavaScriptObject { | 431 class PlainJavaScriptObject extends JavaScriptObject { |
412 const PlainJavaScriptObject(); | 432 const PlainJavaScriptObject(); |
413 } | 433 } |
414 | 434 |
415 | 435 |
416 /** | 436 /** |
417 * Interceptor for unclassified JavaScript objects, typically objects with a | 437 * Interceptor for unclassified JavaScript objects, typically objects with a |
418 * non-trivial prototype chain. | 438 * non-trivial prototype chain. |
419 * | 439 * |
420 * This class also serves as a fallback for unknown JavaScript exceptions. | 440 * This class also serves as a fallback for unknown JavaScript exceptions. |
421 */ | 441 */ |
422 class UnknownJavaScriptObject extends JavaScriptObject { | 442 class UnknownJavaScriptObject extends JavaScriptObject { |
423 const UnknownJavaScriptObject(); | 443 const UnknownJavaScriptObject(); |
424 | 444 |
425 String toString() => JS('String', 'String(#)', this); | 445 String toString() => JS('String', 'String(#)', this); |
426 } | 446 } |
| 447 |
| 448 /** |
| 449 * Interceptor for JavaScript function objects and Dart functions that have |
| 450 * been converted to JavaScript functions. |
| 451 * These interceptor methods are not always used as the JavaScript function |
| 452 * object has also been mangled to support Dart function calling conventions. |
| 453 */ |
| 454 class JavaScriptFunction extends JavaScriptObject implements Function { |
| 455 const JavaScriptFunction(); |
| 456 |
| 457 String toString() { |
| 458 var dartClosure = JsNative.getProperty(this, DART_CLOSURE_PROPERTY_NAME); |
| 459 return dartClosure == null ? super.toString() : dartClosure.toString(); |
| 460 } |
| 461 } |
OLD | NEW |