| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 // THIS FILE IS AUTO GENERATED. PLEASE DO NOT EDIT. | |
| 6 | |
| 7 // TODO(vsm): Move this file once we determine where assets should go. See | |
| 8 // http://dartbug.com/6101. | |
| 9 | |
| 10 (function() { | |
| 11 // Proxy support for js.dart. | |
| 12 | |
| 13 var globalContext = window; | |
| 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 | |
| 45 // Table for local objects and functions that are proxied. | |
| 46 function ProxiedObjectTable() { | |
| 47 // Name for debugging. | |
| 48 this.name = 'js-ref'; | |
| 49 | |
| 50 // Table from IDs to JS objects. | |
| 51 this.map = {}; | |
| 52 | |
| 53 // Generator for new IDs. | |
| 54 this._nextId = 0; | |
| 55 | |
| 56 // Counter for deleted proxies. | |
| 57 this._deletedCount = 0; | |
| 58 | |
| 59 // Flag for one-time initialization. | |
| 60 this._initialized = false; | |
| 61 | |
| 62 // Ports for managing communication to proxies. | |
| 63 this.port = new ReceivePortSync(); | |
| 64 this.sendPort = this.port.toSendPort(); | |
| 65 | |
| 66 // Set of IDs that are global. | |
| 67 // These will not be freed on an exitScope(). | |
| 68 this.globalIds = {}; | |
| 69 | |
| 70 // Stack of scoped handles. | |
| 71 this.handleStack = []; | |
| 72 | |
| 73 // Stack of active scopes where each value is represented by the size of | |
| 74 // the handleStack at the beginning of the scope. When an active scope | |
| 75 // is popped, the handleStack is restored to where it was when the | |
| 76 // scope was entered. | |
| 77 this.scopeIndices = []; | |
| 78 } | |
| 79 | |
| 80 // Number of valid IDs. This is the number of objects (global and local) | |
| 81 // kept alive by this table. | |
| 82 ProxiedObjectTable.prototype.count = function () { | |
| 83 return Object.keys(this.map).length; | |
| 84 } | |
| 85 | |
| 86 // Number of total IDs ever allocated. | |
| 87 ProxiedObjectTable.prototype.total = function () { | |
| 88 return this.count() + this._deletedCount; | |
| 89 } | |
| 90 | |
| 91 // Adds an object to the table and return an ID for serialization. | |
| 92 ProxiedObjectTable.prototype.add = function (obj) { | |
| 93 if (this.scopeIndices.length == 0) { | |
| 94 throw "Cannot allocate a proxy outside of a scope."; | |
| 95 } | |
| 96 // TODO(vsm): Cache refs for each obj? | |
| 97 var ref = this.name + '-' + this._nextId++; | |
| 98 this.handleStack.push(ref); | |
| 99 this.map[ref] = obj; | |
| 100 return ref; | |
| 101 } | |
| 102 | |
| 103 ProxiedObjectTable.prototype._initializeOnce = function () { | |
| 104 if (!this._initialized) { | |
| 105 this._initialize(); | |
| 106 this._initialized = true; | |
| 107 } | |
| 108 } | |
| 109 | |
| 110 // Enters a new scope for this table. | |
| 111 ProxiedObjectTable.prototype.enterScope = function() { | |
| 112 this._initializeOnce(); | |
| 113 this.scopeIndices.push(this.handleStack.length); | |
| 114 } | |
| 115 | |
| 116 // Invalidates all non-global IDs in the current scope and | |
| 117 // exit the current scope. | |
| 118 ProxiedObjectTable.prototype.exitScope = function() { | |
| 119 var start = this.scopeIndices.pop(); | |
| 120 for (var i = start; i < this.handleStack.length; ++i) { | |
| 121 var key = this.handleStack[i]; | |
| 122 if (!this.globalIds.hasOwnProperty(key)) { | |
| 123 delete this.map[this.handleStack[i]]; | |
| 124 this._deletedCount++; | |
| 125 } | |
| 126 } | |
| 127 this.handleStack = this.handleStack.splice(0, start); | |
| 128 } | |
| 129 | |
| 130 // Makes this ID globally scope. It must be explicitly invalidated. | |
| 131 ProxiedObjectTable.prototype.globalize = function(id) { | |
| 132 this.globalIds[id] = true; | |
| 133 } | |
| 134 | |
| 135 // Invalidates this ID, potentially freeing its corresponding object. | |
| 136 ProxiedObjectTable.prototype.invalidate = function(id) { | |
| 137 var old = this.get(id); | |
| 138 delete this.globalIds[id]; | |
| 139 delete this.map[id]; | |
| 140 this._deletedCount++; | |
| 141 } | |
| 142 | |
| 143 // Gets the object or function corresponding to this ID. | |
| 144 ProxiedObjectTable.prototype.get = function (id) { | |
| 145 if (!this.map.hasOwnProperty(id)) { | |
| 146 throw 'Proxy ' + id + ' has been invalidated.' | |
| 147 } | |
| 148 return this.map[id]; | |
| 149 } | |
| 150 | |
| 151 ProxiedObjectTable.prototype._initialize = function () { | |
| 152 // Configure this table's port to forward methods, getters, and setters | |
| 153 // from the remote proxy to the local object. | |
| 154 var table = this; | |
| 155 | |
| 156 this.port.receive(function (message) { | |
| 157 // TODO(vsm): Support a mechanism to register a handler here. | |
| 158 try { | |
| 159 var object = table.get(message[0]); | |
| 160 var receiver = unbind(object); | |
| 161 var member = message[1]; | |
| 162 var kind = message[2]; | |
| 163 var args = message[3].map(deserialize); | |
| 164 if (kind == 'get') { | |
| 165 // Getter. | |
| 166 var field = member; | |
| 167 if (field in receiver && args.length == 0) { | |
| 168 var result = bindIfFunction(receiver[field], receiver); | |
| 169 return [ 'return', serialize(result) ]; | |
| 170 } | |
| 171 } else if (kind == 'set') { | |
| 172 // Setter. | |
| 173 var field = member; | |
| 174 if (args.length == 1) { | |
| 175 return [ 'return', serialize(receiver[field] = args[0]) ]; | |
| 176 } | |
| 177 } else if (kind == 'apply') { | |
| 178 // Direct function invocation. | |
| 179 var _this = getBoundThis(object); | |
| 180 return [ 'return', serialize(receiver.apply(_this, args)) ]; | |
| 181 } else if (member == '[]' && args.length == 1) { | |
| 182 // Index getter. | |
| 183 var result = bindIfFunction(receiver[args[0]], receiver); | |
| 184 return [ 'return', serialize(result) ]; | |
| 185 } else if (member == '[]=' && args.length == 2) { | |
| 186 // Index setter. | |
| 187 return [ 'return', serialize(receiver[args[0]] = args[1]) ]; | |
| 188 } else { | |
| 189 // Member function invocation. | |
| 190 var f = receiver[member]; | |
| 191 if (f) { | |
| 192 var result = f.apply(receiver, args); | |
| 193 return [ 'return', serialize(result) ]; | |
| 194 } | |
| 195 } | |
| 196 return [ 'none' ]; | |
| 197 } catch (e) { | |
| 198 return [ 'throws', e.toString() ]; | |
| 199 } | |
| 200 }); | |
| 201 } | |
| 202 | |
| 203 // Singleton for local proxied objects. | |
| 204 var proxiedObjectTable = new ProxiedObjectTable(); | |
| 205 | |
| 206 // DOM element serialization code. | |
| 207 var _localNextElementId = 0; | |
| 208 var _DART_ID = 'data-dart_id'; | |
| 209 var _DART_TEMPORARY_ATTACHED = 'data-dart_temporary_attached'; | |
| 210 | |
| 211 function serializeElement(e) { | |
| 212 // TODO(vsm): Use an isolate-specific id. | |
| 213 var id; | |
| 214 if (e.hasAttribute(_DART_ID)) { | |
| 215 id = e.getAttribute(_DART_ID); | |
| 216 } else { | |
| 217 id = (_localNextElementId++).toString(); | |
| 218 e.setAttribute(_DART_ID, id); | |
| 219 } | |
| 220 if (e !== document.documentElement) { | |
| 221 // Element must be attached to DOM to be retrieve in js part. | |
| 222 // Attach top unattached parent to avoid detaching parent of "e" when | |
| 223 // appending "e" directly to document. We keep count of elements | |
| 224 // temporarily attached to prevent detaching top unattached parent to | |
| 225 // early. This count is equals to the length of _DART_TEMPORARY_ATTACHED | |
| 226 // attribute. There could be other elements to serialize having the same | |
| 227 // top unattached parent. | |
| 228 var top = e; | |
| 229 while (true) { | |
| 230 if (top.hasAttribute(_DART_TEMPORARY_ATTACHED)) { | |
| 231 var oldValue = top.getAttribute(_DART_TEMPORARY_ATTACHED); | |
| 232 var newValue = oldValue + "a"; | |
| 233 top.setAttribute(_DART_TEMPORARY_ATTACHED, newValue); | |
| 234 break; | |
| 235 } | |
| 236 if (top.parentNode == null) { | |
| 237 top.setAttribute(_DART_TEMPORARY_ATTACHED, "a"); | |
| 238 document.documentElement.appendChild(top); | |
| 239 break; | |
| 240 } | |
| 241 if (top.parentNode === document.documentElement) { | |
| 242 // e was already attached to dom | |
| 243 break; | |
| 244 } | |
| 245 top = top.parentNode; | |
| 246 } | |
| 247 } | |
| 248 return id; | |
| 249 } | |
| 250 | |
| 251 function deserializeElement(id) { | |
| 252 // TODO(vsm): Clear the attribute. | |
| 253 var list = document.querySelectorAll('[' + _DART_ID + '="' + id + '"]'); | |
| 254 | |
| 255 if (list.length > 1) throw 'Non unique ID: ' + id; | |
| 256 if (list.length == 0) { | |
| 257 throw 'Element must be attached to the document: ' + id; | |
| 258 } | |
| 259 var e = list[0]; | |
| 260 if (e !== document.documentElement) { | |
| 261 // detach temporary attached element | |
| 262 var top = e; | |
| 263 while (true) { | |
| 264 if (top.hasAttribute(_DART_TEMPORARY_ATTACHED)) { | |
| 265 var oldValue = top.getAttribute(_DART_TEMPORARY_ATTACHED); | |
| 266 var newValue = oldValue.substring(1); | |
| 267 top.setAttribute(_DART_TEMPORARY_ATTACHED, newValue); | |
| 268 // detach top only if no more elements have to be unserialized | |
| 269 if (top.getAttribute(_DART_TEMPORARY_ATTACHED).length === 0) { | |
| 270 top.removeAttribute(_DART_TEMPORARY_ATTACHED); | |
| 271 document.documentElement.removeChild(top); | |
| 272 } | |
| 273 break; | |
| 274 } | |
| 275 if (top.parentNode === document.documentElement) { | |
| 276 // e was already attached to dom | |
| 277 break; | |
| 278 } | |
| 279 top = top.parentNode; | |
| 280 } | |
| 281 } | |
| 282 return e; | |
| 283 } | |
| 284 | |
| 285 | |
| 286 // Type for remote proxies to Dart objects. | |
| 287 function DartProxy(id, sendPort) { | |
| 288 this.id = id; | |
| 289 this.port = sendPort; | |
| 290 } | |
| 291 | |
| 292 // Serializes JS types to SendPortSync format: | |
| 293 // - primitives -> primitives | |
| 294 // - sendport -> sendport | |
| 295 // - DOM element -> [ 'domref', element-id ] | |
| 296 // - Function -> [ 'funcref', function-id, sendport ] | |
| 297 // - Object -> [ 'objref', object-id, sendport ] | |
| 298 function serialize(message) { | |
| 299 if (message == null) { | |
| 300 return null; // Convert undefined to null. | |
| 301 } else if (typeof(message) == 'string' || | |
| 302 typeof(message) == 'number' || | |
| 303 typeof(message) == 'boolean') { | |
| 304 // Primitives are passed directly through. | |
| 305 return message; | |
| 306 } else if (message instanceof SendPortSync) { | |
| 307 // Non-proxied objects are serialized. | |
| 308 return message; | |
| 309 } else if (message instanceof Element && | |
| 310 (message.ownerDocument == null || message.ownerDocument == document)) { | |
| 311 return [ 'domref', serializeElement(message) ]; | |
| 312 } else if (message instanceof BoundFunction && | |
| 313 typeof(message.object) == 'function') { | |
| 314 // Local function proxy. | |
| 315 return [ 'funcref', | |
| 316 proxiedObjectTable.add(message), | |
| 317 proxiedObjectTable.sendPort ]; | |
| 318 } else if (typeof(message) == 'function') { | |
| 319 if ('_dart_id' in message) { | |
| 320 // Remote function proxy. | |
| 321 var remoteId = message._dart_id; | |
| 322 var remoteSendPort = message._dart_port; | |
| 323 return [ 'funcref', remoteId, remoteSendPort ]; | |
| 324 } else { | |
| 325 // Local function proxy. | |
| 326 return [ 'funcref', | |
| 327 proxiedObjectTable.add(message), | |
| 328 proxiedObjectTable.sendPort ]; | |
| 329 } | |
| 330 } else if (message instanceof DartProxy) { | |
| 331 // Remote object proxy. | |
| 332 return [ 'objref', message.id, message.port ]; | |
| 333 } else { | |
| 334 // Local object proxy. | |
| 335 return [ 'objref', | |
| 336 proxiedObjectTable.add(message), | |
| 337 proxiedObjectTable.sendPort ]; | |
| 338 } | |
| 339 } | |
| 340 | |
| 341 function deserialize(message) { | |
| 342 if (message == null) { | |
| 343 return null; // Convert undefined to null. | |
| 344 } else if (typeof(message) == 'string' || | |
| 345 typeof(message) == 'number' || | |
| 346 typeof(message) == 'boolean') { | |
| 347 // Primitives are passed directly through. | |
| 348 return message; | |
| 349 } else if (message instanceof SendPortSync) { | |
| 350 // Serialized type. | |
| 351 return message; | |
| 352 } | |
| 353 var tag = message[0]; | |
| 354 switch (tag) { | |
| 355 case 'funcref': return deserializeFunction(message); | |
| 356 case 'objref': return deserializeObject(message); | |
| 357 case 'domref': return deserializeElement(message[1]); | |
| 358 } | |
| 359 throw 'Unsupported serialized data: ' + message; | |
| 360 } | |
| 361 | |
| 362 // Create a local function that forwards to the remote function. | |
| 363 function deserializeFunction(message) { | |
| 364 var id = message[1]; | |
| 365 var port = message[2]; | |
| 366 // TODO(vsm): Add a more robust check for a local SendPortSync. | |
| 367 if ("receivePort" in port) { | |
| 368 // Local function. | |
| 369 return unbind(proxiedObjectTable.get(id)); | |
| 370 } else { | |
| 371 // Remote function. Forward to its port. | |
| 372 var f = function () { | |
| 373 var depth = enterScope(); | |
| 374 try { | |
| 375 var args = Array.prototype.slice.apply(arguments); | |
| 376 args.splice(0, 0, this); | |
| 377 args = args.map(serialize); | |
| 378 var result = port.callSync([id, '#call', args]); | |
| 379 if (result[0] == 'throws') throw deserialize(result[1]); | |
| 380 return deserialize(result[1]); | |
| 381 } finally { | |
| 382 exitScope(depth); | |
| 383 } | |
| 384 }; | |
| 385 // Cache the remote id and port. | |
| 386 f._dart_id = id; | |
| 387 f._dart_port = port; | |
| 388 return f; | |
| 389 } | |
| 390 } | |
| 391 | |
| 392 // Creates a DartProxy to forwards to the remote object. | |
| 393 function deserializeObject(message) { | |
| 394 var id = message[1]; | |
| 395 var port = message[2]; | |
| 396 // TODO(vsm): Add a more robust check for a local SendPortSync. | |
| 397 if ("receivePort" in port) { | |
| 398 // Local object. | |
| 399 return proxiedObjectTable.get(id); | |
| 400 } else { | |
| 401 // Remote object. | |
| 402 return new DartProxy(id, port); | |
| 403 } | |
| 404 } | |
| 405 | |
| 406 // Remote handler to construct a new JavaScript object given its | |
| 407 // serialized constructor and arguments. | |
| 408 function construct(args) { | |
| 409 args = args.map(deserialize); | |
| 410 var constructor = unbind(args[0]); | |
| 411 args = Array.prototype.slice.call(args, 1); | |
| 412 | |
| 413 // Until 10 args, the 'new' operator is used. With more arguments we use a | |
| 414 // generic way that may not work, particulary when the constructor does not | |
| 415 // have an "apply" method. | |
| 416 var ret = null; | |
| 417 if (args.length === 0) { | |
| 418 ret = new constructor(); | |
| 419 } else if (args.length === 1) { | |
| 420 ret = new constructor(args[0]); | |
| 421 } else if (args.length === 2) { | |
| 422 ret = new constructor(args[0], args[1]); | |
| 423 } else if (args.length === 3) { | |
| 424 ret = new constructor(args[0], args[1], args[2]); | |
| 425 } else if (args.length === 4) { | |
| 426 ret = new constructor(args[0], args[1], args[2], args[3]); | |
| 427 } else if (args.length === 5) { | |
| 428 ret = new constructor(args[0], args[1], args[2], args[3], args[4]); | |
| 429 } else if (args.length === 6) { | |
| 430 ret = new constructor(args[0], args[1], args[2], args[3], args[4], | |
| 431 args[5]); | |
| 432 } else if (args.length === 7) { | |
| 433 ret = new constructor(args[0], args[1], args[2], args[3], args[4], | |
| 434 args[5], args[6]); | |
| 435 } else if (args.length === 8) { | |
| 436 ret = new constructor(args[0], args[1], args[2], args[3], args[4], | |
| 437 args[5], args[6], args[7]); | |
| 438 } else if (args.length === 9) { | |
| 439 ret = new constructor(args[0], args[1], args[2], args[3], args[4], | |
| 440 args[5], args[6], args[7], args[8]); | |
| 441 } else if (args.length === 10) { | |
| 442 ret = new constructor(args[0], args[1], args[2], args[3], args[4], | |
| 443 args[5], args[6], args[7], args[8], args[9]); | |
| 444 } else { | |
| 445 // Dummy Type with correct constructor. | |
| 446 var Type = function(){}; | |
| 447 Type.prototype = constructor.prototype; | |
| 448 | |
| 449 // Create a new instance | |
| 450 var instance = new Type(); | |
| 451 | |
| 452 // Call the original constructor. | |
| 453 ret = constructor.apply(instance, args); | |
| 454 ret = Object(ret) === ret ? ret : instance; | |
| 455 } | |
| 456 return serialize(ret); | |
| 457 } | |
| 458 | |
| 459 // Remote handler to return the top-level JavaScript context. | |
| 460 function context(data) { | |
| 461 return serialize(globalContext); | |
| 462 } | |
| 463 | |
| 464 // Remote handler to track number of live / allocated proxies. | |
| 465 function proxyCount() { | |
| 466 var live = proxiedObjectTable.count(); | |
| 467 var total = proxiedObjectTable.total(); | |
| 468 return [live, total]; | |
| 469 } | |
| 470 | |
| 471 // Return true if two JavaScript proxies are equal (==). | |
| 472 function proxyEquals(args) { | |
| 473 return deserialize(args[0]) == deserialize(args[1]); | |
| 474 } | |
| 475 | |
| 476 // Return true if a JavaScript proxy is instance of a given type (instanceof). | |
| 477 function proxyInstanceof(args) { | |
| 478 var obj = unbind(deserialize(args[0])); | |
| 479 var type = unbind(deserialize(args[1])); | |
| 480 return obj instanceof type; | |
| 481 } | |
| 482 | |
| 483 // Return true if a JavaScript proxy has a given property. | |
| 484 function proxyHasProperty(args) { | |
| 485 var obj = unbind(deserialize(args[0])); | |
| 486 var member = unbind(deserialize(args[1])); | |
| 487 return member in obj; | |
| 488 } | |
| 489 | |
| 490 // Delete a given property of object. | |
| 491 function proxyDeleteProperty(args) { | |
| 492 var obj = unbind(deserialize(args[0])); | |
| 493 var member = unbind(deserialize(args[1])); | |
| 494 delete obj[member]; | |
| 495 } | |
| 496 | |
| 497 function proxyConvert(args) { | |
| 498 return serialize(deserializeDataTree(args)); | |
| 499 } | |
| 500 | |
| 501 function deserializeDataTree(data) { | |
| 502 var type = data[0]; | |
| 503 var value = data[1]; | |
| 504 if (type === 'map') { | |
| 505 var obj = {}; | |
| 506 for (var i = 0; i < value.length; i++) { | |
| 507 obj[value[i][0]] = deserializeDataTree(value[i][1]); | |
| 508 } | |
| 509 return obj; | |
| 510 } else if (type === 'list') { | |
| 511 var list = []; | |
| 512 for (var i = 0; i < value.length; i++) { | |
| 513 list.push(deserializeDataTree(value[i])); | |
| 514 } | |
| 515 return list; | |
| 516 } else /* 'simple' */ { | |
| 517 return deserialize(value); | |
| 518 } | |
| 519 } | |
| 520 | |
| 521 function makeGlobalPort(name, f) { | |
| 522 var port = new ReceivePortSync(); | |
| 523 port.receive(f); | |
| 524 window.registerPort(name, port.toSendPort()); | |
| 525 } | |
| 526 | |
| 527 // Enters a new scope in the JavaScript context. | |
| 528 function enterJavaScriptScope() { | |
| 529 proxiedObjectTable.enterScope(); | |
| 530 } | |
| 531 | |
| 532 // Enters a new scope in both the JavaScript and Dart context. | |
| 533 var _dartEnterScopePort = null; | |
| 534 function enterScope() { | |
| 535 enterJavaScriptScope(); | |
| 536 if (!_dartEnterScopePort) { | |
| 537 _dartEnterScopePort = window.lookupPort('js-dart-interop-enter-scope'); | |
| 538 } | |
| 539 return _dartEnterScopePort.callSync([]); | |
| 540 } | |
| 541 | |
| 542 // Exits the current scope (and invalidate local IDs) in the JavaScript | |
| 543 // context. | |
| 544 function exitJavaScriptScope() { | |
| 545 proxiedObjectTable.exitScope(); | |
| 546 } | |
| 547 | |
| 548 // Exits the current scope in both the JavaScript and Dart context. | |
| 549 var _dartExitScopePort = null; | |
| 550 function exitScope(depth) { | |
| 551 exitJavaScriptScope(); | |
| 552 if (!_dartExitScopePort) { | |
| 553 _dartExitScopePort = window.lookupPort('js-dart-interop-exit-scope'); | |
| 554 } | |
| 555 return _dartExitScopePort.callSync([ depth ]); | |
| 556 } | |
| 557 | |
| 558 makeGlobalPort('dart-js-interop-context', context); | |
| 559 makeGlobalPort('dart-js-interop-create', construct); | |
| 560 makeGlobalPort('dart-js-interop-proxy-count', proxyCount); | |
| 561 makeGlobalPort('dart-js-interop-equals', proxyEquals); | |
| 562 makeGlobalPort('dart-js-interop-instanceof', proxyInstanceof); | |
| 563 makeGlobalPort('dart-js-interop-has-property', proxyHasProperty); | |
| 564 makeGlobalPort('dart-js-interop-delete-property', proxyDeleteProperty); | |
| 565 makeGlobalPort('dart-js-interop-convert', proxyConvert); | |
| 566 makeGlobalPort('dart-js-interop-enter-scope', enterJavaScriptScope); | |
| 567 makeGlobalPort('dart-js-interop-exit-scope', exitJavaScriptScope); | |
| 568 makeGlobalPort('dart-js-interop-globalize', function(data) { | |
| 569 if (data[0] == "objref" || data[0] == "funcref") return proxiedObjectTable.g
lobalize(data[1]); | |
| 570 throw 'Illegal type: ' + data[0]; | |
| 571 }); | |
| 572 makeGlobalPort('dart-js-interop-invalidate', function(data) { | |
| 573 if (data[0] == "objref" || data[0] == "funcref") return proxiedObjectTable.i
nvalidate(data[1]); | |
| 574 throw 'Illegal type: ' + data[0]; | |
| 575 }); | |
| 576 })(); | |
| OLD | NEW |