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

Side by Side Diff: sdk/lib/js/dart2js/js_dart2js.dart

Issue 1318043005: Support user generated custom native JS classes. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: about to land Created 5 years, 2 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
OLDNEW
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 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
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:html' show Blob, Event, ImageData, Node, Window; 90 import 'dart:html' show Blob, Event, ImageData, Node, Window;
91 import 'dart:collection' show HashMap, ListMixin; 91 import 'dart:collection' show HashMap, ListMixin;
92 import 'dart:indexed_db' show KeyRange; 92 import 'dart:indexed_db' show KeyRange;
93 import 'dart:typed_data' show TypedData; 93 import 'dart:typed_data' show TypedData;
94 94
95 import 'dart:_foreign_helper' show JS, DART_CLOSURE_TO_JS; 95 import 'dart:_foreign_helper' show JS, JS_CONST, DART_CLOSURE_TO_JS;
96 import 'dart:_interceptors' show JavaScriptObject, UnknownJavaScriptObject; 96 import 'dart:_interceptors'
97 import 'dart:_js_helper' show Primitives, convertDartClosureToJS, 97 show JavaScriptObject, UnknownJavaScriptObject, DART_CLOSURE_PROPERTY_NAME;
98 getIsolateAffinityTag; 98 import 'dart:_js_helper'
99 show Primitives, convertDartClosureToJS, getIsolateAffinityTag;
100
101 export 'dart:_interceptors' show JavaScriptObject;
99 102
100 final JsObject context = _wrapToDart(JS('', 'self')); 103 final JsObject context = _wrapToDart(JS('', 'self'));
101 104
102 _convertDartFunction(Function f, {bool captureThis: false}) { 105 _convertDartFunction(Function f, {bool captureThis: false}) {
103 return JS('', 106 return JS(
104 'function(_call, f, captureThis) {' 107 '',
105 'return function() {' 108 '''
106 'return _call(f, captureThis, this, ' 109 function(_call, f, captureThis) {
107 'Array.prototype.slice.apply(arguments));' 110 return function() {
108 '}' 111 return _call(f, captureThis, this,
109 '}(#, #, #)', DART_CLOSURE_TO_JS(_callDartFunction), f, captureThis); 112 Array.prototype.slice.apply(arguments));
113 }
114 }(#, #, #)
115 ''',
116 DART_CLOSURE_TO_JS(_callDartFunction),
117 f,
118 captureThis);
110 } 119 }
111 120
112 _callDartFunction(callback, bool captureThis, self, List arguments) { 121 _callDartFunction(callback, bool captureThis, self, List arguments) {
113 if (captureThis) { 122 if (captureThis) {
114 arguments = [self]..addAll(arguments); 123 arguments = [self]..addAll(arguments);
115 } 124 }
116 var dartArgs = new List.from(arguments.map(_convertToDart)); 125 var dartArgs = new List.from(arguments.map(_convertToDart));
117 return _convertToJS(Function.apply(callback, dartArgs)); 126 return _convertToJS(Function.apply(callback, dartArgs));
118 } 127 }
119 128
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
205 * 214 *
206 * Use this constructor only if you wish to get access to JavaScript 215 * Use this constructor only if you wish to get access to JavaScript
207 * properties attached to a browser host object, such as a Node or Blob, that 216 * properties attached to a browser host object, such as a Node or Blob, that
208 * is normally automatically converted into a native Dart object. 217 * is normally automatically converted into a native Dart object.
209 * 218 *
210 * An exception will be thrown if [object] either is `null` or has the type 219 * An exception will be thrown if [object] either is `null` or has the type
211 * `bool`, `num`, or `String`. 220 * `bool`, `num`, or `String`.
212 */ 221 */
213 factory JsObject.fromBrowserObject(object) { 222 factory JsObject.fromBrowserObject(object) {
214 if (object is num || object is String || object is bool || object == null) { 223 if (object is num || object is String || object is bool || object == null) {
215 throw new ArgumentError( 224 throw new ArgumentError("object cannot be a num, string, bool, or null");
216 "object cannot be a num, string, bool, or null");
217 } 225 }
218 return _wrapToDart(_convertToJS(object)); 226 return _wrapToDart(_convertToJS(object));
219 } 227 }
220 228
221 /** 229 /**
222 * Recursively converts a JSON-like collection of Dart objects to a 230 * Recursively converts a JSON-like collection of Dart objects to a
223 * collection of JavaScript objects and returns a [JsObject] proxy to it. 231 * collection of JavaScript objects and returns a [JsObject] proxy to it.
224 * 232 *
225 * [object] must be a [Map] or [Iterable], the contents of which are also 233 * [object] must be a [Map] or [Iterable], the contents of which are also
226 * converted. Maps and Iterables are copied to a new JavaScript object. 234 * converted. Maps and Iterables are copied to a new JavaScript object.
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
260 268
261 return _convert(data); 269 return _convert(data);
262 } 270 }
263 271
264 /** 272 /**
265 * Returns the value associated with [property] from the proxied JavaScript 273 * Returns the value associated with [property] from the proxied JavaScript
266 * object. 274 * object.
267 * 275 *
268 * The type of [property] must be either [String] or [num]. 276 * The type of [property] must be either [String] or [num].
269 */ 277 */
270 dynamic operator[](property) { 278 dynamic operator [](property) {
271 if (property is! String && property is! num) { 279 if (property is! String && property is! num) {
272 throw new ArgumentError("property is not a String or num"); 280 throw new ArgumentError("property is not a String or num");
273 } 281 }
274 return _convertToDart(JS('', '#[#]', _jsObject, property)); 282 return _convertToDart(JS('', '#[#]', _jsObject, property));
275 } 283 }
276 284
277 /** 285 /**
278 * Sets the value associated with [property] on the proxied JavaScript 286 * Sets the value associated with [property] on the proxied JavaScript
279 * object. 287 * object.
280 * 288 *
281 * The type of [property] must be either [String] or [num]. 289 * The type of [property] must be either [String] or [num].
282 */ 290 */
283 operator[]=(property, value) { 291 operator []=(property, value) {
284 if (property is! String && property is! num) { 292 if (property is! String && property is! num) {
285 throw new ArgumentError("property is not a String or num"); 293 throw new ArgumentError("property is not a String or num");
286 } 294 }
287 JS('', '#[#]=#', _jsObject, property, _convertToJS(value)); 295 JS('', '#[#]=#', _jsObject, property, _convertToJS(value));
288 } 296 }
289 297
290 int get hashCode => 0; 298 int get hashCode => 0;
291 299
292 bool operator==(other) => other is JsObject && 300 bool operator ==(other) =>
293 JS('bool', '# === #', _jsObject, other._jsObject); 301 other is JsObject && JS('bool', '# === #', _jsObject, other._jsObject);
294 302
295 /** 303 /**
296 * Returns `true` if the JavaScript object contains the specified property 304 * Returns `true` if the JavaScript object contains the specified property
297 * either directly or though its prototype chain. 305 * either directly or though its prototype chain.
298 * 306 *
299 * This is the equivalent of the `in` operator in JavaScript. 307 * This is the equivalent of the `in` operator in JavaScript.
300 */ 308 */
301 bool hasProperty(property) { 309 bool hasProperty(property) {
302 if (property is! String && property is! num) { 310 if (property is! String && property is! num) {
303 throw new ArgumentError("property is not a String or num"); 311 throw new ArgumentError("property is not a String or num");
(...skipping 21 matching lines...) Expand all
325 bool instanceof(JsFunction type) { 333 bool instanceof(JsFunction type) {
326 return JS('bool', '# instanceof #', _jsObject, _convertToJS(type)); 334 return JS('bool', '# instanceof #', _jsObject, _convertToJS(type));
327 } 335 }
328 336
329 /** 337 /**
330 * Returns the result of the JavaScript objects `toString` method. 338 * Returns the result of the JavaScript objects `toString` method.
331 */ 339 */
332 String toString() { 340 String toString() {
333 try { 341 try {
334 return JS('String', 'String(#)', _jsObject); 342 return JS('String', 'String(#)', _jsObject);
335 } catch(e) { 343 } catch (e) {
336 return super.toString(); 344 return super.toString();
337 } 345 }
338 } 346 }
339 347
340 /** 348 /**
341 * Calls [method] on the JavaScript object with the arguments [args] and 349 * Calls [method] on the JavaScript object with the arguments [args] and
342 * returns the result. 350 * returns the result.
343 * 351 *
344 * The type of [method] must be either [String] or [num]. 352 * The type of [method] must be either [String] or [num].
345 */ 353 */
346 dynamic callMethod(method, [List args]) { 354 dynamic callMethod(method, [List args]) {
347 if (method is! String && method is! num) { 355 if (method is! String && method is! num) {
348 throw new ArgumentError("method is not a String or num"); 356 throw new ArgumentError("method is not a String or num");
349 } 357 }
350 return _convertToDart(JS('', '#[#].apply(#, #)', _jsObject, method, 358 return _convertToDart(JS(
359 '',
360 '#[#].apply(#, #)',
361 _jsObject,
362 method,
351 _jsObject, 363 _jsObject,
352 args == null ? null : new List.from(args.map(_convertToJS)))); 364 args == null ? null : new List.from(args.map(_convertToJS))));
353 } 365 }
354 } 366 }
355 367
356 /** 368 /**
357 * Proxies a JavaScript Function object. 369 * Proxies a JavaScript Function object.
358 */ 370 */
359 class JsFunction extends JsObject { 371 class JsFunction extends JsObject {
360
361 /** 372 /**
362 * Returns a [JsFunction] that captures its 'this' binding and calls [f] 373 * Returns a [JsFunction] that captures its 'this' binding and calls [f]
363 * with the value of this passed as the first argument. 374 * with the value of this passed as the first argument.
364 */ 375 */
365 factory JsFunction.withThis(Function f) { 376 factory JsFunction.withThis(Function f) {
366 var jsFunc = _convertDartFunction(f, captureThis: true); 377 var jsFunc = _convertDartFunction(f, captureThis: true);
367 return new JsFunction._fromJs(jsFunc); 378 return new JsFunction._fromJs(jsFunc);
368 } 379 }
369 380
370 JsFunction._fromJs(jsObject) : super._fromJs(jsObject); 381 JsFunction._fromJs(jsObject) : super._fromJs(jsObject);
371 382
372 /** 383 /**
373 * Invokes the JavaScript function with arguments [args]. If [thisArg] is 384 * Invokes the JavaScript function with arguments [args]. If [thisArg] is
374 * supplied it is the value of `this` for the invocation. 385 * supplied it is the value of `this` for the invocation.
375 */ 386 */
376 dynamic apply(List args, { thisArg }) => 387 dynamic apply(List args, {thisArg}) => _convertToDart(JS(
377 _convertToDart(JS('', '#.apply(#, #)', _jsObject, 388 '',
378 _convertToJS(thisArg), 389 '#.apply(#, #)',
379 args == null ? null : new List.from(args.map(_convertToJS)))); 390 _jsObject,
391 _convertToJS(thisArg),
392 args == null ? null : new List.from(args.map(_convertToJS))));
380 } 393 }
381 394
382 /** 395 /**
383 * A [List] that proxies a JavaScript array. 396 * A [List] that proxies a JavaScript array.
384 */ 397 */
385 class JsArray<E> extends JsObject with ListMixin<E> { 398 class JsArray<E> extends JsObject with ListMixin<E> {
386
387 /** 399 /**
388 * Creates a new JavaScript array. 400 * Creates a new JavaScript array.
389 */ 401 */
390 JsArray() : super._fromJs([]); 402 JsArray() : super._fromJs([]);
391 403
392 /** 404 /**
393 * Creates a new JavaScript array and initializes it to the contents of 405 * Creates a new JavaScript array and initializes it to the contents of
394 * [other]. 406 * [other].
395 */ 407 */
396 JsArray.from(Iterable<E> other) 408 JsArray.from(Iterable<E> other)
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
442 int get length { 454 int get length {
443 // Check the length honours the List contract. 455 // Check the length honours the List contract.
444 var len = JS('', '#.length', _jsObject); 456 var len = JS('', '#.length', _jsObject);
445 // JavaScript arrays have lengths which are unsigned 32-bit integers. 457 // JavaScript arrays have lengths which are unsigned 32-bit integers.
446 if (JS('bool', 'typeof # === "number" && (# >>> 0) === #', len, len, len)) { 458 if (JS('bool', 'typeof # === "number" && (# >>> 0) === #', len, len, len)) {
447 return JS('int', '#', len); 459 return JS('int', '#', len);
448 } 460 }
449 throw new StateError('Bad JsArray length'); 461 throw new StateError('Bad JsArray length');
450 } 462 }
451 463
452 set length(int length) { super['length'] = length; } 464 void set length(int length) {
453 465 super['length'] = length;
466 }
454 467
455 // Methods overriden for better performance 468 // Methods overriden for better performance
456 469
457 void add(E value) { 470 void add(E value) {
458 callMethod('push', [value]); 471 callMethod('push', [value]);
459 } 472 }
460 473
461 void addAll(Iterable<E> iterable) { 474 void addAll(Iterable<E> iterable) {
462 var list = (JS('bool', '# instanceof Array', iterable)) 475 var list = (JS('bool', '# instanceof Array', iterable))
463 ? iterable 476 ? iterable
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
496 509
497 void sort([int compare(E a, E b)]) { 510 void sort([int compare(E a, E b)]) {
498 // Note: arr.sort(null) is a type error in FF 511 // Note: arr.sort(null) is a type error in FF
499 callMethod('sort', compare == null ? [] : [compare]); 512 callMethod('sort', compare == null ? [] : [compare]);
500 } 513 }
501 } 514 }
502 515
503 // property added to a Dart object referencing its JS-side DartObject proxy 516 // property added to a Dart object referencing its JS-side DartObject proxy
504 final String _DART_OBJECT_PROPERTY_NAME = 517 final String _DART_OBJECT_PROPERTY_NAME =
505 getIsolateAffinityTag(r'_$dart_dartObject'); 518 getIsolateAffinityTag(r'_$dart_dartObject');
506 final String _DART_CLOSURE_PROPERTY_NAME =
507 getIsolateAffinityTag(r'_$dart_dartClosure');
508 519
509 // property added to a JS object referencing its Dart-side JsObject proxy 520 // property added to a JS object referencing its Dart-side JsObject proxy
510 const _JS_OBJECT_PROPERTY_NAME = r'_$dart_jsObject'; 521 const _JS_OBJECT_PROPERTY_NAME = r'_$dart_jsObject';
511 const _JS_FUNCTION_PROPERTY_NAME = r'$dart_jsFunction'; 522 const _JS_FUNCTION_PROPERTY_NAME = r'$dart_jsFunction';
523 const _JS_FUNCTION_PROPERTY_NAME_CAPTURE_THIS = r'_$dart_jsFunctionCaptureThis';
512 524
513 bool _defineProperty(o, String name, value) { 525 bool _defineProperty(o, String name, value) {
514 try { 526 try {
515 if (_isExtensible(o) && 527 if (_isExtensible(o) &&
516 // TODO(ahe): Calling _hasOwnProperty to work around 528 // TODO(ahe): Calling _hasOwnProperty to work around
517 // https://code.google.com/p/dart/issues/detail?id=21331. 529 // https://code.google.com/p/dart/issues/detail?id=21331.
518 !_hasOwnProperty(o, name)) { 530 !_hasOwnProperty(o, name)) {
519 JS('void', 'Object.defineProperty(#, #, { value: #})', o, name, value); 531 JS('void', 'Object.defineProperty(#, #, { value: #})', o, name, value);
520 return true; 532 return true;
521 } 533 }
522 } catch (e) { 534 } catch (e) {
523 // object is native and lies about being extensible 535 // object is native and lies about being extensible
524 // see https://bugzilla.mozilla.org/show_bug.cgi?id=775185 536 // see https://bugzilla.mozilla.org/show_bug.cgi?id=775185
525 // Or, isExtensible throws for this object. 537 // Or, isExtensible throws for this object.
526 } 538 }
527 return false; 539 return false;
528 } 540 }
529 541
530 bool _hasOwnProperty(o, String name) { 542 bool _hasOwnProperty(o, String name) {
531 return JS('bool', 'Object.prototype.hasOwnProperty.call(#, #)', o, name); 543 return JS('bool', 'Object.prototype.hasOwnProperty.call(#, #)', o, name);
532 } 544 }
533 545
534 bool _isExtensible(o) => JS('bool', 'Object.isExtensible(#)', o); 546 bool _isExtensible(o) => JS('bool', 'Object.isExtensible(#)', o);
535 547
(...skipping 12 matching lines...) Expand all
548 dynamic _convertToJS(dynamic o) { 560 dynamic _convertToJS(dynamic o) {
549 // Note: we don't write `if (o == null) return null;` to make sure dart2js 561 // Note: we don't write `if (o == null) return null;` to make sure dart2js
550 // doesn't convert `return null;` into `return;` (which would make `null` be 562 // doesn't convert `return null;` into `return;` (which would make `null` be
551 // `undefined` in Javascprit). See dartbug.com/20305 for details. 563 // `undefined` in Javascprit). See dartbug.com/20305 for details.
552 if (o == null || o is String || o is num || o is bool) { 564 if (o == null || o is String || o is num || o is bool) {
553 return o; 565 return o;
554 } 566 }
555 if (o is JsObject) { 567 if (o is JsObject) {
556 return o._jsObject; 568 return o._jsObject;
557 } 569 }
558 if (o is Blob || o is Event || o is KeyRange || o is ImageData || o is Node || 570 if (o is Blob ||
559 o is TypedData || o is Window) { 571 o is Event ||
572 o is KeyRange ||
573 o is ImageData ||
574 o is Node ||
575 o is TypedData ||
576 o is Window) {
560 return o; 577 return o;
561 } 578 }
562 if (o is DateTime) { 579 if (o is DateTime) {
563 return Primitives.lazyAsJsDate(o); 580 return Primitives.lazyAsJsDate(o);
564 } 581 }
565 if (o is Function) { 582 if (o is Function) {
566 return _getJsProxy(o, _JS_FUNCTION_PROPERTY_NAME, (o) { 583 return _getJsProxy(o, _JS_FUNCTION_PROPERTY_NAME, (o) {
567 var jsFunction = _convertDartFunction(o); 584 var jsFunction = _convertDartFunction(o);
568 // set a property on the JS closure referencing the Dart closure 585 // set a property on the JS closure referencing the Dart closure
569 _defineProperty(jsFunction, _DART_CLOSURE_PROPERTY_NAME, o); 586 _defineProperty(jsFunction, DART_CLOSURE_PROPERTY_NAME, o);
570 return jsFunction; 587 return jsFunction;
571 }); 588 });
572 } 589 }
573 var ctor = _dartProxyCtor; 590 var ctor = _dartProxyCtor;
574 return _getJsProxy(o, _JS_OBJECT_PROPERTY_NAME, 591 return _getJsProxy(
575 (o) => JS('', 'new #(#)', ctor, o)); 592 o, _JS_OBJECT_PROPERTY_NAME, (o) => JS('', 'new #(#)', ctor, o));
576 } 593 }
577 594
578 Object _getJsProxy(o, String propertyName, createProxy(o)) { 595 Object _getJsProxy(o, String propertyName, createProxy(o)) {
579 var jsProxy = _getOwnProperty(o, propertyName); 596 var jsProxy = _getOwnProperty(o, propertyName);
580 if (jsProxy == null) { 597 if (jsProxy == null) {
581 jsProxy = createProxy(o); 598 jsProxy = createProxy(o);
582 _defineProperty(o, propertyName, jsProxy); 599 _defineProperty(o, propertyName, jsProxy);
583 } 600 }
584 return jsProxy; 601 return jsProxy;
585 } 602 }
586 603
587 // converts a Dart object to a reference to a native JS object 604 // converts a Dart object to a reference to a native JS object
588 // which might be a DartObject JS->Dart proxy 605 // which might be a DartObject JS->Dart proxy
589 Object _convertToDart(o) { 606 Object _convertToDart(o) {
590 if (JS('bool', '# == null', o) || 607 if (JS('bool', '# == null', o) ||
591 JS('bool', 'typeof # == "string"', o) || 608 JS('bool', 'typeof # == "string"', o) ||
592 JS('bool', 'typeof # == "number"', o) || 609 JS('bool', 'typeof # == "number"', o) ||
593 JS('bool', 'typeof # == "boolean"', o)) { 610 JS('bool', 'typeof # == "boolean"', o)) {
594 return o; 611 return o;
595 } else if (_isLocalObject(o) 612 } else if (_isLocalObject(o) &&
596 && (o is Blob || o is Event || o is KeyRange || o is ImageData 613 (o is Blob ||
597 || o is Node || o is TypedData || o is Window)) { 614 o is Event ||
615 o is KeyRange ||
616 o is ImageData ||
617 o is Node ||
618 o is TypedData ||
619 o is Window)) {
598 // long line: dart2js doesn't allow string concatenation in the JS() form 620 // long line: dart2js doesn't allow string concatenation in the JS() form
599 return JS('Blob|Event|KeyRange|ImageData|Node|TypedData|Window', '#', o); 621 return JS('Blob|Event|KeyRange|ImageData|Node|TypedData|Window', '#', o);
600 } else if (JS('bool', '# instanceof Date', o)) { 622 } else if (JS('bool', '# instanceof Date', o)) {
601 var ms = JS('num', '#.getTime()', o); 623 var ms = JS('num', '#.getTime()', o);
602 return new DateTime.fromMillisecondsSinceEpoch(ms); 624 return new DateTime.fromMillisecondsSinceEpoch(ms);
603 } else if (JS('bool', '#.constructor === #', o, _dartProxyCtor)) { 625 } else if (JS('bool', '#.constructor === #', o, _dartProxyCtor)) {
604 return JS('', '#.o', o); 626 return JS('', '#.o', o);
605 } else { 627 } else {
606 return _wrapToDart(o); 628 return _wrapToDart(o);
607 } 629 }
608 } 630 }
609 631
610 JsObject _wrapToDart(o) { 632 JsObject _wrapToDart(o) {
611 if (JS('bool', 'typeof # == "function"', o)) { 633 if (JS('bool', 'typeof # == "function"', o)) {
612 return _getDartProxy(o, _DART_CLOSURE_PROPERTY_NAME, 634 return _getDartProxy(
613 (o) => new JsFunction._fromJs(o)); 635 o, DART_CLOSURE_PROPERTY_NAME, (o) => new JsFunction._fromJs(o));
614 } 636 }
615 if (JS('bool', '# instanceof Array', o)) { 637 if (JS('bool', '# instanceof Array', o)) {
616 return _getDartProxy(o, _DART_OBJECT_PROPERTY_NAME, 638 return _getDartProxy(
617 (o) => new JsArray._fromJs(o)); 639 o, _DART_OBJECT_PROPERTY_NAME, (o) => new JsArray._fromJs(o));
618 } 640 }
619 return _getDartProxy(o, _DART_OBJECT_PROPERTY_NAME, 641 return _getDartProxy(
620 (o) => new JsObject._fromJs(o)); 642 o, _DART_OBJECT_PROPERTY_NAME, (o) => new JsObject._fromJs(o));
621 } 643 }
622 644
623 Object _getDartProxy(o, String propertyName, createProxy(o)) { 645 Object _getDartProxy(o, String propertyName, createProxy(o)) {
624 var dartProxy = _getOwnProperty(o, propertyName); 646 var dartProxy = _getOwnProperty(o, propertyName);
625 // Temporary fix for dartbug.com/15193 647 // Temporary fix for dartbug.com/15193
626 // In some cases it's possible to see a JavaScript object that 648 // In some cases it's possible to see a JavaScript object that
627 // came from a different context and was previously proxied to 649 // came from a different context and was previously proxied to
628 // Dart in that context. The JS object will have a cached proxy 650 // Dart in that context. The JS object will have a cached proxy
629 // but it won't be a valid Dart object in this context. 651 // but it won't be a valid Dart object in this context.
630 // For now we throw away the cached proxy, but we should be able 652 // For now we throw away the cached proxy, but we should be able
631 // to cache proxies from multiple JS contexts and Dart isolates. 653 // to cache proxies from multiple JS contexts and Dart isolates.
632 if (dartProxy == null || !_isLocalObject(o)) { 654 if (dartProxy == null || !_isLocalObject(o)) {
633 dartProxy = createProxy(o); 655 dartProxy = createProxy(o);
634 _defineProperty(o, propertyName, dartProxy); 656 _defineProperty(o, propertyName, dartProxy);
635 } 657 }
636 return dartProxy; 658 return dartProxy;
637 } 659 }
660
661 // ---------------------------------------------------------------------------
662 // Start of methods for new style Dart-JS interop.
663
664 _convertDartFunctionFast(Function f) {
665 var existing = JS('', '#.#', f, _JS_FUNCTION_PROPERTY_NAME);
666 if (existing != null) return existing;
667 var ret = JS(
668 '',
669 '''
670 function(_call, f) {
671 return function() {
672 return _call(f, Array.prototype.slice.apply(arguments));
673 }
674 }(#, #)
675 ''',
676 DART_CLOSURE_TO_JS(_callDartFunctionFast),
677 f);
678 JS('', '#.# = #', ret, DART_CLOSURE_PROPERTY_NAME, f);
679 JS('', '#.# = #', f, _JS_FUNCTION_PROPERTY_NAME, ret);
680 return ret;
681 }
682
683 _convertDartFunctionFastCaptureThis(Function f) {
684 var existing = JS('', '#.#', f, _JS_FUNCTION_PROPERTY_NAME_CAPTURE_THIS);
685 if (existing != null) return existing;
686 var ret = JS(
687 '',
688 '''
689 function(_call, f) {
690 return function() {
691 return _call(f, this,Array.prototype.slice.apply(arguments));
692 }
693 }(#, #)
694 ''',
695 DART_CLOSURE_TO_JS(_callDartFunctionFastCaptureThis),
696 f);
697 JS('', '#.# = #', ret, DART_CLOSURE_PROPERTY_NAME, f);
698 JS('', '#.# = #', f, _JS_FUNCTION_PROPERTY_NAME_CAPTURE_THIS, ret);
699 return ret;
700 }
701
702 _callDartFunctionFast(callback, List arguments) {
703 return Function.apply(callback, arguments);
704 }
705
706 _callDartFunctionFastCaptureThis(callback, self, List arguments) {
707 return _convertToJS(Function.apply(callback, [self]..addAll(arguments)));
708 }
709
710 Function allowInterop(Function f) {
711 if (JS('bool', 'typeof(#) == "function"', f)) {
712 // Already supports interop, just use the existing function.
713 return f;
714 } else {
715 return _convertDartFunctionFast(f);
716 }
717 }
718
719 Function allowInteropCaptureThis(Function f) {
720 if (JS('bool', 'typeof(#) == "function"', f)) {
721 // Behavior when the function is already a JS function is unspecified.
722 throw new ArgumentError(
723 "Function is already a JS function so cannot capture this.");
724 return f;
725 } else {
726 return _convertDartFunctionFastCaptureThis(f);
727 }
728 }
OLDNEW
« no previous file with comments | « sdk/lib/_internal/js_runtime/lib/interceptors.dart ('k') | tests/compiler/dart2js/mock_libraries.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698