| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 /** | 5 /** |
| 6 * Support for interoperating with JavaScript. | 6 * Support for interoperating with JavaScript. |
| 7 * | 7 * |
| 8 * This library provides access to JavaScript objects from Dart, allowing | 8 * This library provides access to JavaScript objects from Dart, allowing |
| 9 * Dart code to get and set properties, and call methods of JavaScript objects | 9 * Dart code to get and set properties, and call methods of JavaScript objects |
| 10 * and invoke JavaScript functions. The library takes care of converting | 10 * and invoke JavaScript functions. The library takes care of converting |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 53 * | 53 * |
| 54 * Functions and closures are proxied in such a way that they are callable. A | 54 * Functions and closures are proxied in such a way that they are callable. A |
| 55 * Dart closure assigned to a JavaScript property is proxied by a function in | 55 * Dart closure assigned to a JavaScript property is proxied by a function in |
| 56 * JavaScript. A JavaScript function accessed from Dart is proxied by a | 56 * JavaScript. A JavaScript function accessed from Dart is proxied by a |
| 57 * [JsFunction], which has a [apply] method to invoke it. | 57 * [JsFunction], which has a [apply] method to invoke it. |
| 58 * | 58 * |
| 59 * The following types are transferred directly and not proxied: | 59 * The following types are transferred directly and not proxied: |
| 60 * | 60 * |
| 61 * * "Basic" types: `null`, `bool`, `num`, `String`, `DateTime` | 61 * * "Basic" types: `null`, `bool`, `num`, `String`, `DateTime` |
| 62 * * `Blob` | 62 * * `Blob` |
| 63 * * `Event` |
| 64 * * `HtmlCollection` |
| 65 * * `ImageData` |
| 63 * * `KeyRange` | 66 * * `KeyRange` |
| 64 * * `ImageData` | 67 * * `Node` |
| 68 * * `NodeList` |
| 65 * * `TypedData`, including its subclasses like `Int32List`, but _not_ | 69 * * `TypedData`, including its subclasses like `Int32List`, but _not_ |
| 66 * `ByteBuffer` | 70 * `ByteBuffer` |
| 67 * * `Node` | 71 * * `Window` |
| 68 * | 72 * |
| 69 * ## Converting collections with JsObject.jsify() | 73 * ## Converting collections with JsObject.jsify() |
| 70 * | 74 * |
| 71 * To create a JavaScript collection from a Dart collection use the | 75 * To create a JavaScript collection from a Dart collection use the |
| 72 * [JsObject.jsify] constructor, which converts Dart [Map]s and [Iterable]s | 76 * [JsObject.jsify] constructor, which converts Dart [Map]s and [Iterable]s |
| 73 * into JavaScript Objects and Arrays. | 77 * into JavaScript Objects and Arrays. |
| 74 * | 78 * |
| 75 * The following expression creats a new JavaScript object with the properties | 79 * The following expression creats a new JavaScript object with the properties |
| 76 * `a` and `b` defined: | 80 * `a` and `b` defined: |
| 77 * | 81 * |
| 78 * var jsMap = new JsObject.jsify({'a': 1, 'b': 2}); | 82 * var jsMap = new JsObject.jsify({'a': 1, 'b': 2}); |
| 79 * | 83 * |
| 80 * This expression creates a JavaScript array: | 84 * This expression creates a JavaScript array: |
| 81 * | 85 * |
| 82 * var jsArray = new JsObject.jsify([1, 2, 3]); | 86 * var jsArray = new JsObject.jsify([1, 2, 3]); |
| 83 */ | 87 */ |
| 84 library dart.js; | 88 library dart.js; |
| 85 | 89 |
| 86 import 'dart:html' show Blob, ImageData, Node; | 90 import 'dart:html' show Blob, Event, ImageData, Node, Window; |
| 87 import 'dart:collection' show HashMap, ListMixin; | 91 import 'dart:collection' show HashMap, ListMixin; |
| 88 import 'dart:indexed_db' show KeyRange; | 92 import 'dart:indexed_db' show KeyRange; |
| 89 import 'dart:typed_data' show TypedData; | 93 import 'dart:typed_data' show TypedData; |
| 90 | 94 |
| 91 import 'dart:_foreign_helper' show JS, DART_CLOSURE_TO_JS; | 95 import 'dart:_foreign_helper' show JS, DART_CLOSURE_TO_JS; |
| 92 import 'dart:_interceptors' show JavaScriptObject, UnknownJavaScriptObject; | 96 import 'dart:_interceptors' show JavaScriptObject, UnknownJavaScriptObject; |
| 93 import 'dart:_js_helper' show Primitives, convertDartClosureToJS; | 97 import 'dart:_js_helper' show Primitives, convertDartClosureToJS; |
| 94 | 98 |
| 95 final JsObject context = _wrapToDart(Primitives.computeGlobalThis()); | 99 final JsObject context = _wrapToDart(Primitives.computeGlobalThis()); |
| 96 | 100 |
| (...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 460 JS('void', 'Object.defineProperty(#, #, { value: #})', o, name, value); | 464 JS('void', 'Object.defineProperty(#, #, { value: #})', o, name, value); |
| 461 return true; | 465 return true; |
| 462 } catch(e) { | 466 } catch(e) { |
| 463 // object is native and lies about being extensible | 467 // object is native and lies about being extensible |
| 464 // see https://bugzilla.mozilla.org/show_bug.cgi?id=775185 | 468 // see https://bugzilla.mozilla.org/show_bug.cgi?id=775185 |
| 465 } | 469 } |
| 466 } | 470 } |
| 467 return false; | 471 return false; |
| 468 } | 472 } |
| 469 | 473 |
| 474 bool _isLocalObject(o) => JS('bool', '# instanceof Object', o); |
| 475 |
| 470 dynamic _convertToJS(dynamic o) { | 476 dynamic _convertToJS(dynamic o) { |
| 471 if (o == null) { | 477 if (o == null) { |
| 472 return null; | 478 return null; |
| 473 } else if (o is String || o is num || o is bool | 479 } else if (o is String || o is num || o is bool |
| 474 || o is Blob || o is KeyRange || o is ImageData || o is Node | 480 || o is Blob || o is Event || o is KeyRange || o is ImageData |
| 475 || o is TypedData) { | 481 || o is Node || o is TypedData || o is Window) { |
| 476 return o; | 482 return o; |
| 477 } else if (o is DateTime) { | 483 } else if (o is DateTime) { |
| 478 return Primitives.lazyAsJsDate(o); | 484 return Primitives.lazyAsJsDate(o); |
| 479 } else if (o is JsObject) { | 485 } else if (o is JsObject) { |
| 480 return o._jsObject; | 486 return o._jsObject; |
| 481 } else if (o is Function) { | 487 } else if (o is Function) { |
| 482 return _getJsProxy(o, _JS_FUNCTION_PROPERTY_NAME, (o) { | 488 return _getJsProxy(o, _JS_FUNCTION_PROPERTY_NAME, (o) { |
| 483 var jsFunction = _convertDartFunction(o); | 489 var jsFunction = _convertDartFunction(o); |
| 484 // set a property on the JS closure referencing the Dart closure | 490 // set a property on the JS closure referencing the Dart closure |
| 485 _defineProperty(jsFunction, _DART_CLOSURE_PROPERTY_NAME, o); | 491 _defineProperty(jsFunction, _DART_CLOSURE_PROPERTY_NAME, o); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 496 if (jsProxy == null) { | 502 if (jsProxy == null) { |
| 497 jsProxy = createProxy(o); | 503 jsProxy = createProxy(o); |
| 498 _defineProperty(o, propertyName, jsProxy); | 504 _defineProperty(o, propertyName, jsProxy); |
| 499 } | 505 } |
| 500 return jsProxy; | 506 return jsProxy; |
| 501 } | 507 } |
| 502 | 508 |
| 503 // converts a Dart object to a reference to a native JS object | 509 // converts a Dart object to a reference to a native JS object |
| 504 // which might be a DartObject JS->Dart proxy | 510 // which might be a DartObject JS->Dart proxy |
| 505 Object _convertToDart(o) { | 511 Object _convertToDart(o) { |
| 506 var isArray = JS('bool', '# instanceof Array', o); | |
| 507 if (JS('bool', '# == null', o) || | 512 if (JS('bool', '# == null', o) || |
| 508 JS('bool', 'typeof # == "string"', o) || | 513 JS('bool', 'typeof # == "string"', o) || |
| 509 JS('bool', 'typeof # == "number"', o) || | 514 JS('bool', 'typeof # == "number"', o) || |
| 510 JS('bool', 'typeof # == "boolean"', o)) { | 515 JS('bool', 'typeof # == "boolean"', o)) { |
| 511 return o; | 516 return o; |
| 512 } else if (o is Blob || o is KeyRange || o is ImageData || o is Node | 517 } else if (_isLocalObject(o) |
| 513 || o is TypedData) { | 518 && (o is Blob || o is Event || o is KeyRange || o is ImageData |
| 514 return JS('Blob|KeyRange|ImageData|Node|TypedData', '#', o); | 519 || o is Node || o is TypedData || o is Window)) { |
| 520 // long line: dart2js doesn't allow string concatenation in the JS() form |
| 521 return JS('Blob|Event|KeyRange|ImageData|Node|TypedData|Window', '#', o); |
| 515 } else if (JS('bool', '# instanceof Date', o)) { | 522 } else if (JS('bool', '# instanceof Date', o)) { |
| 516 var ms = JS('num', '#.getMilliseconds()', o); | 523 var ms = JS('num', '#.getMilliseconds()', o); |
| 517 return new DateTime.fromMillisecondsSinceEpoch(ms); | 524 return new DateTime.fromMillisecondsSinceEpoch(ms); |
| 518 } else if (JS('bool', '#.constructor === DartObject', o)) { | 525 } else if (JS('bool', '#.constructor === DartObject', o)) { |
| 519 return JS('', '#.o', o); | 526 return JS('', '#.o', o); |
| 520 } else { | 527 } else { |
| 521 return _wrapToDart(o); | 528 return _wrapToDart(o); |
| 522 } | 529 } |
| 523 } | 530 } |
| 524 | 531 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 536 } | 543 } |
| 537 | 544 |
| 538 Object _getDartProxy(o, String propertyName, createProxy(o)) { | 545 Object _getDartProxy(o, String propertyName, createProxy(o)) { |
| 539 var dartProxy = JS('', '#[#]', o, propertyName); | 546 var dartProxy = JS('', '#[#]', o, propertyName); |
| 540 if (dartProxy == null) { | 547 if (dartProxy == null) { |
| 541 dartProxy = createProxy(o); | 548 dartProxy = createProxy(o); |
| 542 _defineProperty(o, propertyName, dartProxy); | 549 _defineProperty(o, propertyName, dartProxy); |
| 543 } | 550 } |
| 544 return dartProxy; | 551 return dartProxy; |
| 545 } | 552 } |
| OLD | NEW |