| 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 JS interoperability | 6 // Support for JS interoperability |
| 7 // --------------------------------------------------------------------------- | 7 // --------------------------------------------------------------------------- |
| 8 function SendPortSync() { | 8 function SendPortSync() { |
| 9 } | 9 } |
| 10 | 10 |
| 11 function ReceivePortSync() { | 11 function ReceivePortSync() { |
| 12 this.id = ReceivePortSync.id++; | 12 this.id = ReceivePortSync.id++; |
| 13 ReceivePortSync.map[this.id] = this; | 13 ReceivePortSync.map[this.id] = this; |
| 14 } | 14 } |
| 15 | 15 |
| 16 // Type for remote proxies to Dart objects with dart2js. | 16 // Type for remote proxies to Dart objects with dart2js. |
| 17 function DartObject(o) { | 17 function DartProxy(o) { |
| 18 this.o = o; | 18 this.o = o; |
| 19 } | 19 } |
| 20 | 20 |
| 21 (function() { | 21 (function() { |
| 22 // Serialize the following types as follows: | 22 // Serialize the following types as follows: |
| 23 // - primitives / null: unchanged | 23 // - primitives / null: unchanged |
| 24 // - lists: [ 'list', internal id, list of recursively serialized elements ] | 24 // - lists: [ 'list', internal id, list of recursively serialized elements ] |
| 25 // - maps: [ 'map', internal id, map of keys and recursively serialized value
s ] | 25 // - maps: [ 'map', internal id, map of keys and recursively serialized value
s ] |
| 26 // - send ports: [ 'sendport', type, isolate id, port id ] | 26 // - send ports: [ 'sendport', type, isolate id, port id ] |
| 27 // | 27 // |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 243 this.port = new ReceivePortSync(); | 243 this.port = new ReceivePortSync(); |
| 244 this.sendPort = this.port.toSendPort(); | 244 this.sendPort = this.port.toSendPort(); |
| 245 } | 245 } |
| 246 | 246 |
| 247 // Number of valid IDs. This is the number of objects (global and local) | 247 // Number of valid IDs. This is the number of objects (global and local) |
| 248 // kept alive by this table. | 248 // kept alive by this table. |
| 249 ProxiedObjectTable.prototype.count = function () { | 249 ProxiedObjectTable.prototype.count = function () { |
| 250 return Object.keys(this.map).length; | 250 return Object.keys(this.map).length; |
| 251 } | 251 } |
| 252 | 252 |
| 253 var _dartRefPropertyName = "_$dart_ref"; | |
| 254 | |
| 255 // Adds an object to the table and return an ID for serialization. | 253 // Adds an object to the table and return an ID for serialization. |
| 256 ProxiedObjectTable.prototype.add = function (obj, id) { | 254 ProxiedObjectTable.prototype.add = function (obj) { |
| 257 if (id != null) { | 255 for (var ref in this.map) { |
| 258 this.map[id] = obj; | 256 var o = this.map[ref]; |
| 259 return id; | 257 if (o === obj) { |
| 260 } else { | 258 return ref; |
| 261 var ref = obj[_dartRefPropertyName]; | |
| 262 if (ref == null) { | |
| 263 ref = this.name + '-' + this._nextId++; | |
| 264 this.map[ref] = obj; | |
| 265 Object.defineProperty(obj, _dartRefPropertyName, { value: ref }); | |
| 266 } | 259 } |
| 267 return ref; | |
| 268 } | 260 } |
| 261 var ref = this.name + '-' + this._nextId++; |
| 262 this.map[ref] = obj; |
| 263 return ref; |
| 269 } | 264 } |
| 270 | 265 |
| 271 // Gets the object or function corresponding to this ID. | 266 // Gets the object or function corresponding to this ID. |
| 272 ProxiedObjectTable.prototype.contains = function (id) { | |
| 273 return this.map.hasOwnProperty(id); | |
| 274 } | |
| 275 | |
| 276 // Gets the object or function corresponding to this ID. | |
| 277 ProxiedObjectTable.prototype.get = function (id) { | 267 ProxiedObjectTable.prototype.get = function (id) { |
| 278 if (!this.map.hasOwnProperty(id)) { | 268 if (!this.map.hasOwnProperty(id)) { |
| 279 throw 'Proxy ' + id + ' has been invalidated.' | 269 throw 'Proxy ' + id + ' has been invalidated.' |
| 280 } | 270 } |
| 281 return this.map[id]; | 271 return this.map[id]; |
| 282 } | 272 } |
| 283 | 273 |
| 284 ProxiedObjectTable.prototype._initialize = function () { | 274 ProxiedObjectTable.prototype._initialize = function () { |
| 285 // Configure this table's port to forward methods, getters, and setters | 275 // Configure this table's port to forward methods, getters, and setters |
| 286 // from the remote proxy to the local object. | 276 // from the remote proxy to the local object. |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 331 return [ 'throws', e.toString() ]; | 321 return [ 'throws', e.toString() ]; |
| 332 } | 322 } |
| 333 }); | 323 }); |
| 334 } | 324 } |
| 335 | 325 |
| 336 // Singleton for local proxied objects. | 326 // Singleton for local proxied objects. |
| 337 var proxiedObjectTable = new ProxiedObjectTable(); | 327 var proxiedObjectTable = new ProxiedObjectTable(); |
| 338 proxiedObjectTable._initialize() | 328 proxiedObjectTable._initialize() |
| 339 | 329 |
| 340 // Type for remote proxies to Dart objects. | 330 // Type for remote proxies to Dart objects. |
| 341 function DartObject(id, sendPort) { | 331 function DartProxy(id, sendPort) { |
| 342 this.id = id; | 332 this.id = id; |
| 343 this.port = sendPort; | 333 this.port = sendPort; |
| 344 } | 334 } |
| 345 | 335 |
| 346 // Serializes JS types to SendPortSync format: | 336 // Serializes JS types to SendPortSync format: |
| 347 // - primitives -> primitives | 337 // - primitives -> primitives |
| 348 // - sendport -> sendport | 338 // - sendport -> sendport |
| 349 // - Function -> [ 'funcref', function-id, sendport ] | 339 // - Function -> [ 'funcref', function-id, sendport ] |
| 350 // - Object -> [ 'objref', object-id, sendport ] | 340 // - Object -> [ 'objref', object-id, sendport ] |
| 351 function serialize(message) { | 341 function serialize(message) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 364 // Remote function proxy. | 354 // Remote function proxy. |
| 365 var remoteId = message._dart_id; | 355 var remoteId = message._dart_id; |
| 366 var remoteSendPort = message._dart_port; | 356 var remoteSendPort = message._dart_port; |
| 367 return [ 'funcref', remoteId, remoteSendPort ]; | 357 return [ 'funcref', remoteId, remoteSendPort ]; |
| 368 } else { | 358 } else { |
| 369 // Local function proxy. | 359 // Local function proxy. |
| 370 return [ 'funcref', | 360 return [ 'funcref', |
| 371 proxiedObjectTable.add(message), | 361 proxiedObjectTable.add(message), |
| 372 proxiedObjectTable.sendPort ]; | 362 proxiedObjectTable.sendPort ]; |
| 373 } | 363 } |
| 374 } else if (message instanceof DartObject) { | 364 } else if (message instanceof DartProxy) { |
| 375 // Remote object proxy. | 365 // Remote object proxy. |
| 376 return [ 'objref', message.id, message.port ]; | 366 return [ 'objref', message.id, message.port ]; |
| 377 } else { | 367 } else { |
| 378 // Local object proxy. | 368 // Local object proxy. |
| 379 return [ 'objref', | 369 return [ 'objref', |
| 380 proxiedObjectTable.add(message), | 370 proxiedObjectTable.add(message), |
| 381 proxiedObjectTable.sendPort ]; | 371 proxiedObjectTable.sendPort ]; |
| 382 } | 372 } |
| 383 } | 373 } |
| 384 | 374 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 405 // Create a local function that forwards to the remote function. | 395 // Create a local function that forwards to the remote function. |
| 406 function deserializeFunction(message) { | 396 function deserializeFunction(message) { |
| 407 var id = message[1]; | 397 var id = message[1]; |
| 408 var port = message[2]; | 398 var port = message[2]; |
| 409 // TODO(vsm): Add a more robust check for a local SendPortSync. | 399 // TODO(vsm): Add a more robust check for a local SendPortSync. |
| 410 if ("receivePort" in port) { | 400 if ("receivePort" in port) { |
| 411 // Local function. | 401 // Local function. |
| 412 return proxiedObjectTable.get(id); | 402 return proxiedObjectTable.get(id); |
| 413 } else { | 403 } else { |
| 414 // Remote function. Forward to its port. | 404 // Remote function. Forward to its port. |
| 415 if (proxiedObjectTable.contains(id)) { | |
| 416 return proxiedObjectTable.get(id); | |
| 417 } | |
| 418 var f = function () { | 405 var f = function () { |
| 419 var args = Array.prototype.slice.apply(arguments); | 406 var args = Array.prototype.slice.apply(arguments); |
| 420 args.splice(0, 0, this); | 407 args.splice(0, 0, this); |
| 421 args = args.map(serialize); | 408 args = args.map(serialize); |
| 422 var result = port.callSync([id, '#call', args]); | 409 var result = port.callSync([id, '#call', args]); |
| 423 if (result[0] == 'throws') throw deserialize(result[1]); | 410 if (result[0] == 'throws') throw deserialize(result[1]); |
| 424 return deserialize(result[1]); | 411 return deserialize(result[1]); |
| 425 }; | 412 }; |
| 426 // Cache the remote id and port. | 413 // Cache the remote id and port. |
| 427 f._dart_id = id; | 414 f._dart_id = id; |
| 428 f._dart_port = port; | 415 f._dart_port = port; |
| 429 proxiedObjectTable.add(f, id); | |
| 430 return f; | 416 return f; |
| 431 } | 417 } |
| 432 } | 418 } |
| 433 | 419 |
| 434 // Creates a DartObject to forwards to the remote object. | 420 // Creates a DartProxy to forwards to the remote object. |
| 435 function deserializeObject(message) { | 421 function deserializeObject(message) { |
| 436 var id = message[1]; | 422 var id = message[1]; |
| 437 var port = message[2]; | 423 var port = message[2]; |
| 438 // TODO(vsm): Add a more robust check for a local SendPortSync. | 424 // TODO(vsm): Add a more robust check for a local SendPortSync. |
| 439 if ("receivePort" in port) { | 425 if ("receivePort" in port) { |
| 440 // Local object. | 426 // Local object. |
| 441 return proxiedObjectTable.get(id); | 427 return proxiedObjectTable.get(id); |
| 442 } else { | 428 } else { |
| 443 // Remote object. | 429 // Remote object. |
| 444 if (proxiedObjectTable.contains(id)) { | 430 return new DartProxy(id, port); |
| 445 return proxiedObjectTable.get(id); | |
| 446 } | |
| 447 proxy = new DartObject(id, port); | |
| 448 proxiedObjectTable.add(proxy, id); | |
| 449 return proxy; | |
| 450 } | 431 } |
| 451 } | 432 } |
| 452 | 433 |
| 453 // Remote handler to construct a new JavaScript object given its | 434 // Remote handler to construct a new JavaScript object given its |
| 454 // serialized constructor and arguments. | 435 // serialized constructor and arguments. |
| 455 function construct(args) { | 436 function construct(args) { |
| 456 args = args.map(deserialize); | 437 args = args.map(deserialize); |
| 457 var constructor = args[0]; | 438 var constructor = args[0]; |
| 458 args = Array.prototype.slice.call(args, 1); | 439 args = Array.prototype.slice.call(args, 1); |
| 459 | 440 |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 551 port.receive(f); | 532 port.receive(f); |
| 552 window.registerPort(name, port.toSendPort()); | 533 window.registerPort(name, port.toSendPort()); |
| 553 } | 534 } |
| 554 | 535 |
| 555 makeGlobalPort('dart-js-context', context); | 536 makeGlobalPort('dart-js-context', context); |
| 556 makeGlobalPort('dart-js-create', construct); | 537 makeGlobalPort('dart-js-create', construct); |
| 557 makeGlobalPort('dart-js-instanceof', proxyInstanceof); | 538 makeGlobalPort('dart-js-instanceof', proxyInstanceof); |
| 558 makeGlobalPort('dart-js-delete-property', proxyDeleteProperty); | 539 makeGlobalPort('dart-js-delete-property', proxyDeleteProperty); |
| 559 makeGlobalPort('dart-js-convert', proxyConvert); | 540 makeGlobalPort('dart-js-convert', proxyConvert); |
| 560 })(); | 541 })(); |
| OLD | NEW |