Chromium Code Reviews| 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 /** | 5 /** |
| 6 * The js.dart library provides simple JavaScript invocation from Dart that | 6 * The js.dart library provides simple JavaScript invocation from Dart that |
| 7 * works on both Dartium and on other modern browsers via Dart2JS. | 7 * works on both Dartium and on other modern browsers via Dart2JS. |
| 8 * | 8 * |
| 9 * It provides a model based on scoped [Proxy] objects. Proxies give Dart | 9 * It provides a model based on scoped [Proxy] objects. Proxies give Dart |
| 10 * code access to JavaScript objects, fields, and functions as well as the | 10 * code access to JavaScript objects, fields, and functions as well as the |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 82 // one. | 82 // one. |
| 83 | 83 |
| 84 // NOTE: Please re-run tools/create_bootstrap.dart on any modification of | 84 // NOTE: Please re-run tools/create_bootstrap.dart on any modification of |
| 85 // this bootstrap string. | 85 // this bootstrap string. |
| 86 final _JS_BOOTSTRAP = r""" | 86 final _JS_BOOTSTRAP = r""" |
| 87 (function() { | 87 (function() { |
| 88 // Proxy support for js.dart. | 88 // Proxy support for js.dart. |
| 89 | 89 |
| 90 var globalContext = window; | 90 var globalContext = window; |
| 91 | 91 |
| 92 // Support for binding the receiver (this) in proxied functions. | |
| 93 function bindIfFunction(f, _this) { | |
| 94 if (typeof(f) != "function") { | |
| 95 return f; | |
| 96 } else { | |
| 97 return new BoundFunction(_this, f); | |
| 98 } | |
| 99 } | |
| 100 | |
| 101 function unbind(obj) { | |
| 102 if (obj instanceof BoundFunction) { | |
| 103 return obj.object; | |
| 104 } else { | |
| 105 return obj; | |
| 106 } | |
| 107 } | |
| 108 | |
| 109 function getBoundThis(obj) { | |
| 110 if (obj instanceof BoundFunction) { | |
| 111 return obj._this; | |
| 112 } else { | |
| 113 return globalContext; | |
| 114 } | |
| 115 } | |
| 116 | |
| 117 function BoundFunction(_this, object) { | |
| 118 this._this = _this; | |
| 119 this.object = object; | |
| 120 } | |
| 121 | |
| 92 // Table for local objects and functions that are proxied. | 122 // Table for local objects and functions that are proxied. |
| 93 function ProxiedObjectTable() { | 123 function ProxiedObjectTable() { |
| 94 // Name for debugging. | 124 // Name for debugging. |
| 95 this.name = 'js-ref'; | 125 this.name = 'js-ref'; |
| 96 | 126 |
| 97 // Table from IDs to JS objects. | 127 // Table from IDs to JS objects. |
| 98 this.map = {}; | 128 this.map = {}; |
| 99 | 129 |
| 100 // Generator for new IDs. | 130 // Generator for new IDs. |
| 101 this._nextId = 0; | 131 this._nextId = 0; |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 197 } | 227 } |
| 198 | 228 |
| 199 ProxiedObjectTable.prototype._initialize = function () { | 229 ProxiedObjectTable.prototype._initialize = function () { |
| 200 // Configure this table's port to forward methods, getters, and setters | 230 // Configure this table's port to forward methods, getters, and setters |
| 201 // from the remote proxy to the local object. | 231 // from the remote proxy to the local object. |
| 202 var table = this; | 232 var table = this; |
| 203 | 233 |
| 204 this.port.receive(function (message) { | 234 this.port.receive(function (message) { |
| 205 // TODO(vsm): Support a mechanism to register a handler here. | 235 // TODO(vsm): Support a mechanism to register a handler here. |
| 206 try { | 236 try { |
| 207 var receiver = table.get(message[0]); | 237 var object = table.get(message[0]); |
| 238 var receiver = unbind(object); | |
| 208 var member = message[1]; | 239 var member = message[1]; |
| 209 var kind = message[2]; | 240 var kind = message[2]; |
| 210 var args = message[3].map(deserialize); | 241 var args = message[3].map(deserialize); |
| 211 if (kind == 'get') { | 242 if (kind == 'get') { |
| 212 // Getter. | 243 // Getter. |
| 213 var field = member; | 244 var field = member; |
| 214 if (field in receiver && args.length == 0) { | 245 if (field in receiver && args.length == 0) { |
| 215 return [ 'return', serialize(receiver[field]) ]; | 246 var result = bindIfFunction(receiver[field], receiver); |
| 247 return [ 'return', serialize(result) ]; | |
| 216 } | 248 } |
| 217 } else if (kind == 'set') { | 249 } else if (kind == 'set') { |
| 218 // Setter. | 250 // Setter. |
| 219 var field = member; | 251 var field = member; |
| 220 if (args.length == 1) { | 252 if (args.length == 1) { |
| 221 return [ 'return', serialize(receiver[field] = args[0]) ]; | 253 return [ 'return', serialize(receiver[field] = args[0]) ]; |
| 222 } | 254 } |
| 223 } else if (kind == 'apply') { | 255 } else if (kind == 'apply') { |
| 224 // Direct function invocation. | 256 // Direct function invocation. |
| 225 // TODO(vsm): Should we capture _this_ automatically? | 257 var _this = getBoundThis(object); |
| 226 return [ 'return', serialize(receiver.apply(null, args)) ]; | 258 return [ 'return', serialize(receiver.apply(_this, args)) ]; |
| 227 } else if (member == '[]' && args.length == 1) { | 259 } else if (member == '[]' && args.length == 1) { |
| 228 // Index getter. | 260 // Index getter. |
| 229 return [ 'return', serialize(receiver[args[0]]) ]; | 261 var result = bindIfFunction(receiver[args[0]], receiver); |
| 262 return [ 'return', serialize(result) ]; | |
| 230 } else if (member == '[]=' && args.length == 2) { | 263 } else if (member == '[]=' && args.length == 2) { |
| 231 // Index setter. | 264 // Index setter. |
| 232 return [ 'return', serialize(receiver[args[0]] = args[1]) ]; | 265 return [ 'return', serialize(receiver[args[0]] = args[1]) ]; |
| 233 } else { | 266 } else { |
| 267 // Member function invocation. | |
| 234 var f = receiver[member]; | 268 var f = receiver[member]; |
| 235 if (f) { | 269 if (f) { |
| 236 var result = f.apply(receiver, args); | 270 var result = f.apply(receiver, args); |
| 237 return [ 'return', serialize(result) ]; | 271 return [ 'return', serialize(result) ]; |
| 238 } | 272 } |
| 239 } | 273 } |
| 240 return [ 'none' ]; | 274 return [ 'none' ]; |
| 241 } catch (e) { | 275 } catch (e) { |
| 242 return [ 'throws', e.toString() ]; | 276 return [ 'throws', e.toString() ]; |
| 243 } | 277 } |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 346 typeof(message) == 'number' || | 380 typeof(message) == 'number' || |
| 347 typeof(message) == 'boolean') { | 381 typeof(message) == 'boolean') { |
| 348 // Primitives are passed directly through. | 382 // Primitives are passed directly through. |
| 349 return message; | 383 return message; |
| 350 } else if (message instanceof SendPortSync) { | 384 } else if (message instanceof SendPortSync) { |
| 351 // Non-proxied objects are serialized. | 385 // Non-proxied objects are serialized. |
| 352 return message; | 386 return message; |
| 353 } else if (message instanceof Element && | 387 } else if (message instanceof Element && |
| 354 (message.ownerDocument == null || message.ownerDocument == document)) { | 388 (message.ownerDocument == null || message.ownerDocument == document)) { |
| 355 return [ 'domref', serializeElement(message) ]; | 389 return [ 'domref', serializeElement(message) ]; |
| 390 } else if (message instanceof BoundFunction && | |
| 391 typeof(message.object) == 'function') { | |
|
alexandre.ardhuin
2013/04/07 21:20:20
Could typeof(message.object) be something else tha
vsm
2013/04/07 21:37:36
It shouldn't. I'll change this to assert that.
O
| |
| 392 // Local function proxy. | |
| 393 return [ 'funcref', | |
| 394 proxiedObjectTable.add(message), | |
| 395 proxiedObjectTable.sendPort ]; | |
| 356 } else if (typeof(message) == 'function') { | 396 } else if (typeof(message) == 'function') { |
| 357 if ('_dart_id' in message) { | 397 if ('_dart_id' in message) { |
| 358 // Remote function proxy. | 398 // Remote function proxy. |
| 359 var remoteId = message._dart_id; | 399 var remoteId = message._dart_id; |
| 360 var remoteSendPort = message._dart_port; | 400 var remoteSendPort = message._dart_port; |
| 361 return [ 'funcref', remoteId, remoteSendPort ]; | 401 return [ 'funcref', remoteId, remoteSendPort ]; |
| 362 } else { | 402 } else { |
| 363 // Local function proxy. | 403 // Local function proxy. |
| 364 return [ 'funcref', | 404 return [ 'funcref', |
| 365 proxiedObjectTable.add(message), | 405 proxiedObjectTable.add(message), |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 436 } else { | 476 } else { |
| 437 // Remote object. | 477 // Remote object. |
| 438 return new DartProxy(id, port); | 478 return new DartProxy(id, port); |
| 439 } | 479 } |
| 440 } | 480 } |
| 441 | 481 |
| 442 // Remote handler to construct a new JavaScript object given its | 482 // Remote handler to construct a new JavaScript object given its |
| 443 // serialized constructor and arguments. | 483 // serialized constructor and arguments. |
| 444 function construct(args) { | 484 function construct(args) { |
| 445 args = args.map(deserialize); | 485 args = args.map(deserialize); |
| 446 var constructor = args[0]; | 486 var constructor = unbind(args[0]); |
| 447 args = Array.prototype.slice.call(args, 1); | 487 args = Array.prototype.slice.call(args, 1); |
| 448 | 488 |
| 449 // Until 10 args, the 'new' operator is used. With more arguments we use a | 489 // Until 10 args, the 'new' operator is used. With more arguments we use a |
| 450 // generic way that may not work, particulary when the constructor does not | 490 // generic way that may not work, particulary when the constructor does not |
| 451 // have an "apply" method. | 491 // have an "apply" method. |
| 452 var ret = null; | 492 var ret = null; |
| 453 if (args.length === 0) { | 493 if (args.length === 0) { |
| 454 ret = new constructor(); | 494 ret = new constructor(); |
| 455 } else if (args.length === 1) { | 495 } else if (args.length === 1) { |
| 456 ret = new constructor(args[0]); | 496 ret = new constructor(args[0]); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 505 ' (out of ' + total + ' ever allocated).'; | 545 ' (out of ' + total + ' ever allocated).'; |
| 506 } | 546 } |
| 507 | 547 |
| 508 // Return true if two JavaScript proxies are equal (==). | 548 // Return true if two JavaScript proxies are equal (==). |
| 509 function proxyEquals(args) { | 549 function proxyEquals(args) { |
| 510 return deserialize(args[0]) == deserialize(args[1]); | 550 return deserialize(args[0]) == deserialize(args[1]); |
| 511 } | 551 } |
| 512 | 552 |
| 513 // Return true if a JavaScript proxy is instance of a given type (instanceof). | 553 // Return true if a JavaScript proxy is instance of a given type (instanceof). |
| 514 function proxyInstanceof(args) { | 554 function proxyInstanceof(args) { |
| 515 return deserialize(args[0]) instanceof deserialize(args[1]); | 555 var obj = unbind(deserialize(args[0])); |
| 556 var type = unbind(deserialize(args[1])); | |
| 557 return obj instanceof type; | |
| 516 } | 558 } |
| 517 | 559 |
| 518 // Return true if a JavaScript proxy is instance of a given type (instanceof). | 560 // Return true if a JavaScript proxy is instance of a given type (instanceof). |
| 519 function proxyDeleteProperty(args) { | 561 function proxyDeleteProperty(args) { |
| 520 delete deserialize(args[0])[deserialize(args[1])]; | 562 var obj = unbind(deserialize(args[0])); |
| 563 var member = unbind(deserialize(args[1])); | |
| 564 delete obj[member]; | |
| 521 } | 565 } |
| 522 | 566 |
| 523 function proxyConvert(args) { | 567 function proxyConvert(args) { |
| 524 return serialize(deserializeDataTree(args)); | 568 return serialize(deserializeDataTree(args)); |
| 525 } | 569 } |
| 526 | 570 |
| 527 function deserializeDataTree(data) { | 571 function deserializeDataTree(data) { |
| 528 var type = data[0]; | 572 var type = data[0]; |
| 529 var value = data[1]; | 573 var value = data[1]; |
| 530 if (type === 'map') { | 574 if (type === 'map') { |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 818 /** | 862 /** |
| 819 * Creates a multi-fire [Callback] that invokes [f]. The callback must be | 863 * Creates a multi-fire [Callback] that invokes [f]. The callback must be |
| 820 * explicitly disposed to avoid memory leaks. | 864 * explicitly disposed to avoid memory leaks. |
| 821 */ | 865 */ |
| 822 Callback.many(Function f) { | 866 Callback.many(Function f) { |
| 823 _callback = (args) => Function.apply(f, args); | 867 _callback = (args) => Function.apply(f, args); |
| 824 _initialize(true); | 868 _initialize(true); |
| 825 } | 869 } |
| 826 } | 870 } |
| 827 | 871 |
| 872 // Detect unspecified arguments. | |
| 873 class _Undefined { | |
| 874 const _Undefined(); | |
| 875 } | |
| 876 const _undefined = const _Undefined(); | |
| 877 List _pruneUndefined(arg1, arg2, arg3, arg4, arg5, arg6) { | |
| 878 // This assumes no argument | |
| 879 final args = [arg1, arg2, arg3, arg4, arg5, arg6]; | |
| 880 final index = args.indexOf(_undefined); | |
| 881 if (index < 0) return args; | |
| 882 return args.sublist(0, index); | |
| 883 } | |
| 884 | |
| 828 /** | 885 /** |
| 829 * Proxies to JavaScript objects. | 886 * Proxies to JavaScript objects. |
| 830 */ | 887 */ |
| 831 class Proxy implements Serializable<Proxy> { | 888 class Proxy implements Serializable<Proxy> { |
| 832 SendPortSync _port; | 889 SendPortSync _port; |
| 833 final _id; | 890 final _id; |
| 834 | 891 |
| 835 /** | 892 /** |
| 836 * Constructs a [Proxy] to a new JavaScript object by invoking a (proxy to a) | 893 * Constructs a [Proxy] to a new JavaScript object by invoking a (proxy to a) |
| 837 * JavaScript [constructor]. The arguments should be either | 894 * JavaScript [constructor]. The arguments should be either |
| 838 * primitive values, DOM elements, or Proxies. | 895 * primitive values, DOM elements, or Proxies. |
| 839 */ | 896 */ |
| 840 factory Proxy(FunctionProxy constructor, [arg1, arg2, arg3, arg4]) { | 897 factory Proxy(FunctionProxy constructor, |
| 841 var arguments; | 898 [arg1 = _undefined, |
| 842 if (?arg4) { | 899 arg2 = _undefined, |
| 843 arguments = [arg1, arg2, arg3, arg4]; | 900 arg3 = _undefined, |
| 844 } else if (?arg3) { | 901 arg4 = _undefined, |
| 845 arguments = [arg1, arg2, arg3]; | 902 arg5 = _undefined, |
| 846 } else if (?arg2) { | 903 arg6 = _undefined]) { |
| 847 arguments = [arg1, arg2]; | 904 var arguments = _pruneUndefined(arg1, arg2, arg3, arg4, arg5, arg6); |
| 848 } else if (?arg1) { | |
| 849 arguments = [arg1]; | |
| 850 } else { | |
| 851 arguments = []; | |
| 852 } | |
| 853 return new Proxy.withArgList(constructor, arguments); | 905 return new Proxy.withArgList(constructor, arguments); |
| 854 } | 906 } |
| 855 | 907 |
| 856 /** | 908 /** |
| 857 * Constructs a [Proxy] to a new JavaScript object by invoking a (proxy to a) | 909 * Constructs a [Proxy] to a new JavaScript object by invoking a (proxy to a) |
| 858 * JavaScript [constructor]. The [arguments] list should contain either | 910 * JavaScript [constructor]. The [arguments] list should contain either |
| 859 * primitive values, DOM elements, or Proxies. | 911 * primitive values, DOM elements, or Proxies. |
| 860 */ | 912 */ |
| 861 factory Proxy.withArgList(FunctionProxy constructor, List arguments) { | 913 factory Proxy.withArgList(FunctionProxy constructor, List arguments) { |
| 862 if (_depth == 0) throw 'Cannot create Proxy out of scope.'; | 914 if (_depth == 0) throw 'Cannot create Proxy out of scope.'; |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 890 return ['list', data.map((e) => _serializeDataTree(e)).toList()]; | 942 return ['list', data.map((e) => _serializeDataTree(e)).toList()]; |
| 891 } else { | 943 } else { |
| 892 return ['simple', _serialize(data)]; | 944 return ['simple', _serialize(data)]; |
| 893 } | 945 } |
| 894 } | 946 } |
| 895 | 947 |
| 896 Proxy._internal(this._port, this._id); | 948 Proxy._internal(this._port, this._id); |
| 897 | 949 |
| 898 Proxy toJs() => this; | 950 Proxy toJs() => this; |
| 899 | 951 |
| 900 // TODO(vsm): This is not required in Dartium, but | |
| 901 // it is in Dart2JS. | |
| 902 // Resolve whether this is needed. | 952 // Resolve whether this is needed. |
| 903 operator[](arg) => _forward(this, '[]', 'method', [ arg ]); | 953 operator[](arg) => _forward(this, '[]', 'method', [ arg ]); |
| 904 | 954 |
| 905 // TODO(vsm): This is not required in Dartium, but | |
| 906 // it is in Dart2JS. | |
| 907 // Resolve whether this is needed. | 955 // Resolve whether this is needed. |
| 908 operator[]=(key, value) => _forward(this, '[]=', 'method', [ key, value ]); | 956 operator[]=(key, value) => _forward(this, '[]=', 'method', [ key, value ]); |
| 909 | 957 |
| 910 // Test if this is equivalent to another Proxy. This essentially | 958 // Test if this is equivalent to another Proxy. This essentially |
| 911 // maps to JavaScript's == operator. | 959 // maps to JavaScript's == operator. |
| 912 // TODO(vsm): Can we avoid forwarding to JS? | 960 // TODO(vsm): Can we avoid forwarding to JS? |
| 913 operator==(Proxy other) => identical(this, other) | 961 operator==(other) => identical(this, other) |
| 914 ? true | 962 ? true |
| 915 : (other is Proxy && | 963 : (other is Proxy && |
| 916 _jsPortEquals.callSync([_serialize(this), _serialize(other)])); | 964 _jsPortEquals.callSync([_serialize(this), _serialize(other)])); |
| 917 | 965 |
| 918 // Forward member accesses to the backing JavaScript object. | 966 // Forward member accesses to the backing JavaScript object. |
| 919 noSuchMethod(InvocationMirror invocation) { | 967 noSuchMethod(InvocationMirror invocation) { |
| 920 String member = invocation.memberName; | 968 String member = invocation.memberName; |
| 921 // If trying to access a JavaScript field/variable that starts with | 969 // If trying to access a JavaScript field/variable that starts with |
| 922 // _ (underscore), Dart treats it a library private and member name | 970 // _ (underscore), Dart treats it a library private and member name |
| 923 // it suffixed with '@internalLibraryIdentifier' which we have to | 971 // it suffixed with '@internalLibraryIdentifier' which we have to |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 943 } | 991 } |
| 944 if (member.startsWith('set:')) { | 992 if (member.startsWith('set:')) { |
| 945 member = member.substring(4); | 993 member = member.substring(4); |
| 946 } | 994 } |
| 947 } else if (member.startsWith('get:')) { | 995 } else if (member.startsWith('get:')) { |
| 948 kind = 'get'; | 996 kind = 'get'; |
| 949 member = member.substring(4); | 997 member = member.substring(4); |
| 950 } else if (member.startsWith('set:')) { | 998 } else if (member.startsWith('set:')) { |
| 951 kind = 'set'; | 999 kind = 'set'; |
| 952 member = member.substring(4); | 1000 member = member.substring(4); |
| 1001 } else if (member == 'call') { | |
|
alexandre.ardhuin
2013/04/07 21:20:20
If what I have observed on minification of call is
vsm
2013/04/07 21:37:36
I'm uncomfortable making an assumptions on minifie
| |
| 1002 // A 'call' (probably) means that this proxy was invoked directly | |
| 1003 // as if it was a function. Map this to JS function application. | |
| 1004 kind = 'apply'; | |
| 953 } else { | 1005 } else { |
| 954 kind = 'method'; | 1006 kind = 'method'; |
| 955 } | 1007 } |
| 956 return _forward(this, member, kind, args); | 1008 return _forward(this, member, kind, args); |
| 957 } | 1009 } |
| 958 | 1010 |
| 959 // Forward member accesses to the backing JavaScript object. | 1011 // Forward member accesses to the backing JavaScript object. |
| 960 static _forward(Proxy receiver, String member, String kind, List args) { | 1012 static _forward(Proxy receiver, String member, String kind, List args) { |
| 961 if (_depth == 0) throw 'Cannot access a JavaScript proxy out of scope.'; | 1013 if (_depth == 0) throw 'Cannot access a JavaScript proxy out of scope.'; |
| 962 var result = receiver._port.callSync([receiver._id, member, kind, | 1014 var result = receiver._port.callSync([receiver._id, member, kind, |
| 963 args.map(_serialize).toList()]); | 1015 args.map(_serialize).toList()]); |
| 964 switch (result[0]) { | 1016 switch (result[0]) { |
| 965 case 'return': return _deserialize(result[1]); | 1017 case 'return': return _deserialize(result[1]); |
| 966 case 'throws': throw _deserialize(result[1]); | 1018 case 'throws': throw _deserialize(result[1]); |
| 967 case 'none': throw new NoSuchMethodError(receiver, member, args, {}); | 1019 case 'none': throw new NoSuchMethodError(receiver, member, args, {}); |
| 968 default: throw 'Invalid return value'; | 1020 default: throw 'Invalid return value'; |
| 969 } | 1021 } |
| 970 } | 1022 } |
| 971 } | 1023 } |
| 972 | 1024 |
| 973 // TODO(aa) make FunctionProxy implements Function once it is allowed | 1025 // TODO(aa) make FunctionProxy implements Function once it is allowed |
| 974 /// A [Proxy] subtype to JavaScript functions. | 1026 /// A [Proxy] subtype to JavaScript functions. |
| 975 class FunctionProxy extends Proxy /*implements Function*/ { | 1027 class FunctionProxy extends Proxy /*implements Function*/ { |
| 976 FunctionProxy._internal(port, id) : super._internal(port, id); | 1028 FunctionProxy._internal(port, id) : super._internal(port, id); |
| 977 | 1029 |
| 978 noSuchMethod(InvocationMirror invocation) { | 1030 // TODO(vsm): This allows calls with a limited number of arguments |
| 979 if (invocation.isMethod && invocation.memberName == 'call') { | 1031 // in the context of dartbug.com/9283. Eliminate pending the resolution |
| 980 var message = [_id, '', 'apply', | 1032 // of this bug. Note, if this Proxy is called with more arguments then |
| 981 invocation.positionalArguments.map(_serialize).toList()]; | 1033 // allowed below, it will trigger the 'call' path in Proxy.noSuchMethod |
| 982 var result = _port.callSync(message); | 1034 // - and still work correctly in unminified mode. |
| 983 if (result[0] == 'throws') throw result[1]; | 1035 call([arg1 = _undefined, arg2 = _undefined, |
| 984 return _deserialize(result[1]); | 1036 arg3 = _undefined, arg4 = _undefined, |
| 985 } else { | 1037 arg5 = _undefined, arg6 = _undefined]) { |
| 986 return super.noSuchMethod(invocation); | 1038 var arguments = _pruneUndefined(arg1, arg2, arg3, arg4, arg5, arg6); |
| 987 } | 1039 return Proxy._forward(this, '', 'apply', arguments); |
| 988 } | 1040 } |
| 989 } | 1041 } |
| 990 | 1042 |
| 991 /// Marker class used to indicate it is serializable to js. If a class is a | 1043 /// Marker class used to indicate it is serializable to js. If a class is a |
| 992 /// [Serializable] the "toJs" method will be called and the result will be used | 1044 /// [Serializable] the "toJs" method will be called and the result will be used |
| 993 /// as value. | 1045 /// as value. |
| 994 abstract class Serializable<T> { | 1046 abstract class Serializable<T> { |
| 995 T toJs(); | 1047 T toJs(); |
| 996 } | 1048 } |
| 997 | 1049 |
| (...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1280 * Prints the number of live handles in Dart and JavaScript. This is for | 1332 * Prints the number of live handles in Dart and JavaScript. This is for |
| 1281 * debugging / profiling purposes. | 1333 * debugging / profiling purposes. |
| 1282 */ | 1334 */ |
| 1283 void proxyDebug([String message = '']) { | 1335 void proxyDebug([String message = '']) { |
| 1284 print('Proxy status $message:'); | 1336 print('Proxy status $message:'); |
| 1285 var live = _proxiedObjectTable.count; | 1337 var live = _proxiedObjectTable.count; |
| 1286 var total = _proxiedObjectTable.total; | 1338 var total = _proxiedObjectTable.total; |
| 1287 print(' Dart objects Live : $live (out of $total ever allocated).'); | 1339 print(' Dart objects Live : $live (out of $total ever allocated).'); |
| 1288 print(' ${_jsPortDebug.callSync([])}'); | 1340 print(' ${_jsPortDebug.callSync([])}'); |
| 1289 } | 1341 } |
| OLD | NEW |