| 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 * 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 [JsObject] objects. Proxies give Dart | 9 * It provides a model based on scoped [JsObject] 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 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 235 } | 235 } |
| 236 } | 236 } |
| 237 | 237 |
| 238 /// Marker class used to indicate it is serializable to js. If a class is a | 238 /// Marker class used to indicate it is serializable to js. If a class is a |
| 239 /// [Serializable] the "toJs" method will be called and the result will be used | 239 /// [Serializable] the "toJs" method will be called and the result will be used |
| 240 /// as value. | 240 /// as value. |
| 241 abstract class Serializable<T> { | 241 abstract class Serializable<T> { |
| 242 T toJs(); | 242 T toJs(); |
| 243 } | 243 } |
| 244 | 244 |
| 245 // A table to managed local Dart objects that are proxied in JavaScript. | 245 // A table to managed local Dart objects that are proxied in JavaScript, |
| 246 // or proxies to JavaScript objects. |
| 246 class _ProxiedObjectTable { | 247 class _ProxiedObjectTable { |
| 247 // Debugging name. | 248 // Debugging name. |
| 248 final String _name; | 249 final String _name; |
| 249 | 250 |
| 250 // Generator for unique IDs. | 251 // Generator for unique IDs. |
| 251 int _nextId; | 252 int _nextId; |
| 252 | 253 |
| 253 // Table of IDs to Dart objects. | 254 // Table of IDs to Dart objects. |
| 254 final Map<String, Object> _registry; | 255 final Map<String, Object> _registry; |
| 255 | 256 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 276 throw 'Invocation unsupported on non-function Dart proxies'; | 277 throw 'Invocation unsupported on non-function Dart proxies'; |
| 277 } | 278 } |
| 278 } catch (e) { | 279 } catch (e) { |
| 279 // TODO(vsm): callSync should just handle exceptions itself. | 280 // TODO(vsm): callSync should just handle exceptions itself. |
| 280 return ['throws', '$e']; | 281 return ['throws', '$e']; |
| 281 } | 282 } |
| 282 }); | 283 }); |
| 283 } | 284 } |
| 284 | 285 |
| 285 // Adds a new object to the table and return a new ID for it. | 286 // Adds a new object to the table and return a new ID for it. |
| 286 String add(x) { | 287 String add(x, {String id}) { |
| 287 // TODO(vsm): Cache x and reuse id. | 288 // TODO(vsm): Cache x and reuse id. |
| 288 final id = '$_name-${_nextId++}'; | 289 id = (id != null) ? id : '$_name-${_nextId++}'; |
| 289 _registry[id] = x; | 290 _registry[id] = x; |
| 290 return id; | 291 return id; |
| 291 } | 292 } |
| 292 | 293 |
| 293 // Gets an object by ID. | 294 // Gets an object by ID. |
| 294 Object get(String id) { | 295 Object get(String id) { |
| 295 return _registry[id]; | 296 return _registry[id]; |
| 296 } | 297 } |
| 297 | 298 |
| 298 // Gets the current number of objects kept alive by this table. | 299 // Gets the current number of objects kept alive by this table. |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 340 } | 341 } |
| 341 | 342 |
| 342 _deserialize(var message) { | 343 _deserialize(var message) { |
| 343 deserializeFunction(message) { | 344 deserializeFunction(message) { |
| 344 var id = message[1]; | 345 var id = message[1]; |
| 345 var port = message[2]; | 346 var port = message[2]; |
| 346 if (port == _proxiedObjectTable.sendPort) { | 347 if (port == _proxiedObjectTable.sendPort) { |
| 347 // Local function. | 348 // Local function. |
| 348 return _proxiedObjectTable.get(id); | 349 return _proxiedObjectTable.get(id); |
| 349 } else { | 350 } else { |
| 350 // Remote function. Forward to its port. | 351 // Remote function. |
| 351 return new JsFunction._internal(port, id); | 352 var jsFunction = _proxiedObjectTable.get(id); |
| 353 if (jsFunction == null) { |
| 354 jsFunction = new JsFunction._internal(port, id); |
| 355 _proxiedObjectTable.add(jsFunction, id: id); |
| 356 } |
| 357 return jsFunction; |
| 352 } | 358 } |
| 353 } | 359 } |
| 354 | 360 |
| 355 deserializeObject(message) { | 361 deserializeObject(message) { |
| 356 var id = message[1]; | 362 var id = message[1]; |
| 357 var port = message[2]; | 363 var port = message[2]; |
| 358 if (port == _proxiedObjectTable.sendPort) { | 364 if (port == _proxiedObjectTable.sendPort) { |
| 359 // Local object. | 365 // Local object. |
| 360 return _proxiedObjectTable.get(id); | 366 return _proxiedObjectTable.get(id); |
| 361 } else { | 367 } else { |
| 362 // Remote object. | 368 // Remote object. |
| 363 return new JsObject._internal(port, id); | 369 var jsObject = _proxiedObjectTable.get(id); |
| 370 if (jsObject == null) { |
| 371 jsObject = new JsObject._internal(port, id); |
| 372 _proxiedObjectTable.add(jsObject, id: id); |
| 373 } |
| 374 return jsObject; |
| 364 } | 375 } |
| 365 } | 376 } |
| 366 | 377 |
| 367 if (message == null) { | 378 if (message == null) { |
| 368 return null; // Convert undefined to null. | 379 return null; // Convert undefined to null. |
| 369 } else if (message is String || | 380 } else if (message is String || |
| 370 message is num || | 381 message is num || |
| 371 message is bool) { | 382 message is bool) { |
| 372 // Primitives are passed directly through. | 383 // Primitives are passed directly through. |
| 373 return message; | 384 return message; |
| 374 } else if (message is SendPortSync) { | 385 } else if (message is SendPortSync) { |
| 375 // Serialized type. | 386 // Serialized type. |
| 376 return message; | 387 return message; |
| 377 } | 388 } |
| 378 var tag = message[0]; | 389 var tag = message[0]; |
| 379 switch (tag) { | 390 switch (tag) { |
| 380 case 'funcref': return deserializeFunction(message); | 391 case 'funcref': return deserializeFunction(message); |
| 381 case 'objref': return deserializeObject(message); | 392 case 'objref': return deserializeObject(message); |
| 382 } | 393 } |
| 383 throw 'Unsupported serialized data: $message'; | 394 throw 'Unsupported serialized data: $message'; |
| 384 } | 395 } |
| OLD | NEW |