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 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
80 * `a` and `b` defined: | 80 * `a` and `b` defined: |
81 * | 81 * |
82 * var jsMap = new JsObject.jsify({'a': 1, 'b': 2}); | 82 * var jsMap = new JsObject.jsify({'a': 1, 'b': 2}); |
83 * | 83 * |
84 * This expression creates a JavaScript array: | 84 * This expression creates a JavaScript array: |
85 * | 85 * |
86 * var jsArray = new JsObject.jsify([1, 2, 3]); | 86 * var jsArray = new JsObject.jsify([1, 2, 3]); |
87 */ | 87 */ |
88 library dart.js; | 88 library dart.js; |
89 | 89 |
| 90 import 'dart:async' show Zone; |
90 import 'dart:html' show Blob, Event, ImageData, Node, Window; | 91 import 'dart:html' show Blob, Event, ImageData, Node, Window; |
91 import 'dart:collection' show HashMap, ListMixin; | 92 import 'dart:collection' show HashMap, ListMixin; |
92 import 'dart:indexed_db' show KeyRange; | 93 import 'dart:indexed_db' show KeyRange; |
93 import 'dart:typed_data' show TypedData; | 94 import 'dart:typed_data' show TypedData; |
94 | 95 |
95 import 'dart:_foreign_helper' show JS, DART_CLOSURE_TO_JS; | 96 import 'dart:_foreign_helper' show JS, DART_CLOSURE_TO_JS; |
96 import 'dart:_interceptors' show JavaScriptObject, UnknownJavaScriptObject; | 97 import 'dart:_interceptors' show JavaScriptObject, UnknownJavaScriptObject; |
97 import 'dart:_js_helper' show Primitives, convertDartClosureToJS, | 98 import 'dart:_js_helper' show Primitives, convertDartClosureToJS, |
98 getIsolateAffinityTag; | 99 getIsolateAffinityTag; |
99 | 100 |
100 final JsObject context = _wrapToDart(Primitives.computeGlobalThis()); | 101 final JsObject context = _wrapToDart(Primitives.computeGlobalThis()); |
101 | 102 |
102 _convertDartFunction(Function f, {bool captureThis: false}) { | 103 _convertDartFunction(Function f) { |
103 return JS('', | 104 return JS('', |
104 'function(_call, f, captureThis) {' | 105 'function(_call, f) {' |
105 'return function() {' | 106 'return function() {' |
106 'return _call(f, captureThis, this, ' | 107 'return _call(f, Array.prototype.slice.apply(arguments));' |
107 'Array.prototype.slice.apply(arguments));' | |
108 '}' | 108 '}' |
109 '}(#, #, #)', DART_CLOSURE_TO_JS(_callDartFunction), f, captureThis); | 109 '}(#, #)', DART_CLOSURE_TO_JS(_callDartFunction), _applyZoned(f)); |
110 } | 110 } |
111 | 111 |
112 _callDartFunction(callback, bool captureThis, self, List arguments) { | 112 _convertDartFunctionWithThis(Function f) { |
113 if (captureThis) { | 113 return JS('', |
114 arguments = [self]..addAll(arguments); | 114 'function(_call, f) {' |
115 } | 115 'return function() {' |
116 var dartArgs = new List.from(arguments.map(_convertToDart)); | 116 'var args = Array.prototype.slice.apply(arguments);' |
117 return _convertToJS(Function.apply(callback, dartArgs)); | 117 'args.unshift(this);' |
| 118 'return _call(f, args);' |
| 119 '}' |
| 120 '}(#, #)', DART_CLOSURE_TO_JS(_callDartFunction), _applyZoned(f)); |
| 121 } |
| 122 |
| 123 _callDartFunction(f, List arguments) => f(arguments); |
| 124 |
| 125 _applyZoned(f) { |
| 126 var callDart = (List arguments) { |
| 127 var dartArgs = new List.from(arguments.map(_convertToDart)); |
| 128 return _convertToJS(Function.apply(f, dartArgs)); |
| 129 }; |
| 130 if (Zone.current == Zone.ROOT) return callDart; |
| 131 return Zone.current.bindUnaryCallback(callDart); |
118 } | 132 } |
119 | 133 |
120 /** | 134 /** |
121 * Proxies a JavaScript object to Dart. | 135 * Proxies a JavaScript object to Dart. |
122 * | 136 * |
123 * The properties of the JavaScript object are accessible via the `[]` and | 137 * The properties of the JavaScript object are accessible via the `[]` and |
124 * `[]=` operators. Methods are callable via [callMethod]. | 138 * `[]=` operators. Methods are callable via [callMethod]. |
125 */ | 139 */ |
126 class JsObject { | 140 class JsObject { |
127 // The wrapped JS object. | 141 // The wrapped JS object. |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
316 /** | 330 /** |
317 * Proxies a JavaScript Function object. | 331 * Proxies a JavaScript Function object. |
318 */ | 332 */ |
319 class JsFunction extends JsObject { | 333 class JsFunction extends JsObject { |
320 | 334 |
321 /** | 335 /** |
322 * Returns a [JsFunction] that captures its 'this' binding and calls [f] | 336 * Returns a [JsFunction] that captures its 'this' binding and calls [f] |
323 * with the value of this passed as the first argument. | 337 * with the value of this passed as the first argument. |
324 */ | 338 */ |
325 factory JsFunction.withThis(Function f) { | 339 factory JsFunction.withThis(Function f) { |
326 var jsFunc = _convertDartFunction(f, captureThis: true); | 340 var jsFunc = _convertDartFunctionWithThis(f); |
327 return new JsFunction._fromJs(jsFunc); | 341 return new JsFunction._fromJs(jsFunc); |
328 } | 342 } |
329 | 343 |
330 JsFunction._fromJs(jsObject) : super._fromJs(jsObject); | 344 JsFunction._fromJs(jsObject) : super._fromJs(jsObject); |
331 | 345 |
332 /** | 346 /** |
333 * Invokes the JavaScript function with arguments [args]. If [thisArg] is | 347 * Invokes the JavaScript function with arguments [args]. If [thisArg] is |
334 * supplied it is the value of `this` for the invocation. | 348 * supplied it is the value of `this` for the invocation. |
335 */ | 349 */ |
336 dynamic apply(List args, { thisArg }) => | 350 dynamic apply(List args, { thisArg }) => |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
573 // Dart in that context. The JS object will have a cached proxy | 587 // Dart in that context. The JS object will have a cached proxy |
574 // but it won't be a valid Dart object in this context. | 588 // but it won't be a valid Dart object in this context. |
575 // For now we throw away the cached proxy, but we should be able | 589 // For now we throw away the cached proxy, but we should be able |
576 // to cache proxies from multiple JS contexts and Dart isolates. | 590 // to cache proxies from multiple JS contexts and Dart isolates. |
577 if (dartProxy == null || !_isLocalObject(o)) { | 591 if (dartProxy == null || !_isLocalObject(o)) { |
578 dartProxy = createProxy(o); | 592 dartProxy = createProxy(o); |
579 _defineProperty(o, propertyName, dartProxy); | 593 _defineProperty(o, propertyName, dartProxy); |
580 } | 594 } |
581 return dartProxy; | 595 return dartProxy; |
582 } | 596 } |
OLD | NEW |