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 // THIS FILE IS AUTO GENERATED. PLEASE DO NOT EDIT. | 5 // THIS FILE IS AUTO GENERATED. PLEASE DO NOT EDIT. |
6 | 6 |
7 // TODO(vsm): Move this file once we determine where assets should go. See | 7 // TODO(vsm): Move this file once we determine where assets should go. See |
8 // http://dartbug.com/6101. | 8 // http://dartbug.com/6101. |
9 | 9 |
10 (function() { | 10 (function() { |
11 // Proxy support for js.dart. | 11 // Proxy support for js.dart. |
12 | 12 |
13 var globalContext = window; | 13 var globalContext = window; |
14 | 14 |
| 15 // Support for binding the receiver (this) in proxied functions. |
| 16 function bindIfFunction(f, _this) { |
| 17 if (typeof(f) != "function") { |
| 18 return f; |
| 19 } else { |
| 20 return new BoundFunction(_this, f); |
| 21 } |
| 22 } |
| 23 |
| 24 function unbind(obj) { |
| 25 if (obj instanceof BoundFunction) { |
| 26 return obj.object; |
| 27 } else { |
| 28 return obj; |
| 29 } |
| 30 } |
| 31 |
| 32 function getBoundThis(obj) { |
| 33 if (obj instanceof BoundFunction) { |
| 34 return obj._this; |
| 35 } else { |
| 36 return globalContext; |
| 37 } |
| 38 } |
| 39 |
| 40 function BoundFunction(_this, object) { |
| 41 this._this = _this; |
| 42 this.object = object; |
| 43 } |
| 44 |
15 // Table for local objects and functions that are proxied. | 45 // Table for local objects and functions that are proxied. |
16 function ProxiedObjectTable() { | 46 function ProxiedObjectTable() { |
17 // Name for debugging. | 47 // Name for debugging. |
18 this.name = 'js-ref'; | 48 this.name = 'js-ref'; |
19 | 49 |
20 // Table from IDs to JS objects. | 50 // Table from IDs to JS objects. |
21 this.map = {}; | 51 this.map = {}; |
22 | 52 |
23 // Generator for new IDs. | 53 // Generator for new IDs. |
24 this._nextId = 0; | 54 this._nextId = 0; |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
120 } | 150 } |
121 | 151 |
122 ProxiedObjectTable.prototype._initialize = function () { | 152 ProxiedObjectTable.prototype._initialize = function () { |
123 // Configure this table's port to forward methods, getters, and setters | 153 // Configure this table's port to forward methods, getters, and setters |
124 // from the remote proxy to the local object. | 154 // from the remote proxy to the local object. |
125 var table = this; | 155 var table = this; |
126 | 156 |
127 this.port.receive(function (message) { | 157 this.port.receive(function (message) { |
128 // TODO(vsm): Support a mechanism to register a handler here. | 158 // TODO(vsm): Support a mechanism to register a handler here. |
129 try { | 159 try { |
130 var receiver = table.get(message[0]); | 160 var object = table.get(message[0]); |
| 161 var receiver = unbind(object); |
131 var member = message[1]; | 162 var member = message[1]; |
132 var kind = message[2]; | 163 var kind = message[2]; |
133 var args = message[3].map(deserialize); | 164 var args = message[3].map(deserialize); |
134 if (kind == 'get') { | 165 if (kind == 'get') { |
135 // Getter. | 166 // Getter. |
136 var field = member; | 167 var field = member; |
137 if (field in receiver && args.length == 0) { | 168 if (field in receiver && args.length == 0) { |
138 return [ 'return', serialize(receiver[field]) ]; | 169 var result = bindIfFunction(receiver[field], receiver); |
| 170 return [ 'return', serialize(result) ]; |
139 } | 171 } |
140 } else if (kind == 'set') { | 172 } else if (kind == 'set') { |
141 // Setter. | 173 // Setter. |
142 var field = member; | 174 var field = member; |
143 if (args.length == 1) { | 175 if (args.length == 1) { |
144 return [ 'return', serialize(receiver[field] = args[0]) ]; | 176 return [ 'return', serialize(receiver[field] = args[0]) ]; |
145 } | 177 } |
146 } else if (kind == 'apply') { | 178 } else if (kind == 'apply') { |
147 // Direct function invocation. | 179 // Direct function invocation. |
148 // TODO(vsm): Should we capture _this_ automatically? | 180 var _this = getBoundThis(object); |
149 return [ 'return', serialize(receiver.apply(null, args)) ]; | 181 return [ 'return', serialize(receiver.apply(_this, args)) ]; |
150 } else if (member == '[]' && args.length == 1) { | 182 } else if (member == '[]' && args.length == 1) { |
151 // Index getter. | 183 // Index getter. |
152 return [ 'return', serialize(receiver[args[0]]) ]; | 184 var result = bindIfFunction(receiver[args[0]], receiver); |
| 185 return [ 'return', serialize(result) ]; |
153 } else if (member == '[]=' && args.length == 2) { | 186 } else if (member == '[]=' && args.length == 2) { |
154 // Index setter. | 187 // Index setter. |
155 return [ 'return', serialize(receiver[args[0]] = args[1]) ]; | 188 return [ 'return', serialize(receiver[args[0]] = args[1]) ]; |
156 } else { | 189 } else { |
| 190 // Member function invocation. |
157 var f = receiver[member]; | 191 var f = receiver[member]; |
158 if (f) { | 192 if (f) { |
159 var result = f.apply(receiver, args); | 193 var result = f.apply(receiver, args); |
160 return [ 'return', serialize(result) ]; | 194 return [ 'return', serialize(result) ]; |
161 } | 195 } |
162 } | 196 } |
163 return [ 'none' ]; | 197 return [ 'none' ]; |
164 } catch (e) { | 198 } catch (e) { |
165 return [ 'throws', e.toString() ]; | 199 return [ 'throws', e.toString() ]; |
166 } | 200 } |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
269 typeof(message) == 'number' || | 303 typeof(message) == 'number' || |
270 typeof(message) == 'boolean') { | 304 typeof(message) == 'boolean') { |
271 // Primitives are passed directly through. | 305 // Primitives are passed directly through. |
272 return message; | 306 return message; |
273 } else if (message instanceof SendPortSync) { | 307 } else if (message instanceof SendPortSync) { |
274 // Non-proxied objects are serialized. | 308 // Non-proxied objects are serialized. |
275 return message; | 309 return message; |
276 } else if (message instanceof Element && | 310 } else if (message instanceof Element && |
277 (message.ownerDocument == null || message.ownerDocument == document)) { | 311 (message.ownerDocument == null || message.ownerDocument == document)) { |
278 return [ 'domref', serializeElement(message) ]; | 312 return [ 'domref', serializeElement(message) ]; |
| 313 } else if (message instanceof BoundFunction && |
| 314 typeof(message.object) == 'function') { |
| 315 // Local function proxy. |
| 316 return [ 'funcref', |
| 317 proxiedObjectTable.add(message), |
| 318 proxiedObjectTable.sendPort ]; |
279 } else if (typeof(message) == 'function') { | 319 } else if (typeof(message) == 'function') { |
280 if ('_dart_id' in message) { | 320 if ('_dart_id' in message) { |
281 // Remote function proxy. | 321 // Remote function proxy. |
282 var remoteId = message._dart_id; | 322 var remoteId = message._dart_id; |
283 var remoteSendPort = message._dart_port; | 323 var remoteSendPort = message._dart_port; |
284 return [ 'funcref', remoteId, remoteSendPort ]; | 324 return [ 'funcref', remoteId, remoteSendPort ]; |
285 } else { | 325 } else { |
286 // Local function proxy. | 326 // Local function proxy. |
287 return [ 'funcref', | 327 return [ 'funcref', |
288 proxiedObjectTable.add(message), | 328 proxiedObjectTable.add(message), |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
359 } else { | 399 } else { |
360 // Remote object. | 400 // Remote object. |
361 return new DartProxy(id, port); | 401 return new DartProxy(id, port); |
362 } | 402 } |
363 } | 403 } |
364 | 404 |
365 // Remote handler to construct a new JavaScript object given its | 405 // Remote handler to construct a new JavaScript object given its |
366 // serialized constructor and arguments. | 406 // serialized constructor and arguments. |
367 function construct(args) { | 407 function construct(args) { |
368 args = args.map(deserialize); | 408 args = args.map(deserialize); |
369 var constructor = args[0]; | 409 var constructor = unbind(args[0]); |
370 args = Array.prototype.slice.call(args, 1); | 410 args = Array.prototype.slice.call(args, 1); |
371 | 411 |
372 // Until 10 args, the 'new' operator is used. With more arguments we use a | 412 // Until 10 args, the 'new' operator is used. With more arguments we use a |
373 // generic way that may not work, particulary when the constructor does not | 413 // generic way that may not work, particulary when the constructor does not |
374 // have an "apply" method. | 414 // have an "apply" method. |
375 var ret = null; | 415 var ret = null; |
376 if (args.length === 0) { | 416 if (args.length === 0) { |
377 ret = new constructor(); | 417 ret = new constructor(); |
378 } else if (args.length === 1) { | 418 } else if (args.length === 1) { |
379 ret = new constructor(args[0]); | 419 ret = new constructor(args[0]); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
428 ' (out of ' + total + ' ever allocated).'; | 468 ' (out of ' + total + ' ever allocated).'; |
429 } | 469 } |
430 | 470 |
431 // Return true if two JavaScript proxies are equal (==). | 471 // Return true if two JavaScript proxies are equal (==). |
432 function proxyEquals(args) { | 472 function proxyEquals(args) { |
433 return deserialize(args[0]) == deserialize(args[1]); | 473 return deserialize(args[0]) == deserialize(args[1]); |
434 } | 474 } |
435 | 475 |
436 // Return true if a JavaScript proxy is instance of a given type (instanceof). | 476 // Return true if a JavaScript proxy is instance of a given type (instanceof). |
437 function proxyInstanceof(args) { | 477 function proxyInstanceof(args) { |
438 return deserialize(args[0]) instanceof deserialize(args[1]); | 478 var obj = unbind(deserialize(args[0])); |
| 479 var type = unbind(deserialize(args[1])); |
| 480 return obj instanceof type; |
439 } | 481 } |
440 | 482 |
441 // Return true if a JavaScript proxy is instance of a given type (instanceof). | 483 // Return true if a JavaScript proxy is instance of a given type (instanceof). |
442 function proxyDeleteProperty(args) { | 484 function proxyDeleteProperty(args) { |
443 delete deserialize(args[0])[deserialize(args[1])]; | 485 var obj = unbind(deserialize(args[0])); |
| 486 var member = unbind(deserialize(args[1])); |
| 487 delete obj[member]; |
444 } | 488 } |
445 | 489 |
446 function proxyConvert(args) { | 490 function proxyConvert(args) { |
447 return serialize(deserializeDataTree(args)); | 491 return serialize(deserializeDataTree(args)); |
448 } | 492 } |
449 | 493 |
450 function deserializeDataTree(data) { | 494 function deserializeDataTree(data) { |
451 var type = data[0]; | 495 var type = data[0]; |
452 var value = data[1]; | 496 var value = data[1]; |
453 if (type === 'map') { | 497 if (type === 'map') { |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
517 if (data[0] == "objref") return proxiedObjectTable.globalize(data[1]); | 561 if (data[0] == "objref") return proxiedObjectTable.globalize(data[1]); |
518 // TODO(vsm): Do we ever need to globalize functions? | 562 // TODO(vsm): Do we ever need to globalize functions? |
519 throw 'Illegal type: ' + data[0]; | 563 throw 'Illegal type: ' + data[0]; |
520 }); | 564 }); |
521 makeGlobalPort('dart-js-invalidate', function(data) { | 565 makeGlobalPort('dart-js-invalidate', function(data) { |
522 if (data[0] == "objref") return proxiedObjectTable.invalidate(data[1]); | 566 if (data[0] == "objref") return proxiedObjectTable.invalidate(data[1]); |
523 // TODO(vsm): Do we ever need to globalize functions? | 567 // TODO(vsm): Do we ever need to globalize functions? |
524 throw 'Illegal type: ' + data[0]; | 568 throw 'Illegal type: ' + data[0]; |
525 }); | 569 }); |
526 })(); | 570 })(); |
OLD | NEW |