Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(503)

Unified Diff: extension/dart_proxy.js

Issue 11305009: Fix dwc extension with latest js-interop, small fix to dwc, and updates to (Closed) Base URL: git@github.com:dart-lang/dart-web-components.git@master
Patch Set: Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: extension/dart_proxy.js
diff --git a/extension/dart_proxy.js b/extension/dart_proxy.js
deleted file mode 100644
index 8669347a2b0292210a276445dc3daad841efc013..0000000000000000000000000000000000000000
--- a/extension/dart_proxy.js
+++ /dev/null
@@ -1,482 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// We have to add this manually due to Chrome extension restrictions injecting arbitrary JS.
-// TODO(jacobr): modify the jsinterop library so this is not required.
-(function() {
- // Proxy support
-
- // Table for local objects and functions that are proxied.
- // TODO(vsm): Merge into one.
- function ProxiedReferenceTable(name) {
- // Name for debugging.
- this.name = name;
-
- // Table from IDs to JS objects.
- this.map = {};
-
- // Generator for new IDs.
- this._nextId = 0;
-
- // Counter for deleted proxies.
- this._deletedCount = 0;
-
- // Flag for one-time initialization.
- this._initialized = false;
-
- // Ports for managing communication to proxies.
- this.port = new ReceivePortSync();
- this.sendPort = this.port.toSendPort();
-
- // Set of IDs that are global.
- // These will not be freed on an exitScope().
- this.globalIds = {};
-
- // Stack of scoped handles.
- this.handleStack = [];
-
- // Stack of active scopes where each value is represented by the size of
- // the handleStack at the beginning of the scope. When an active scope
- // is popped, the handleStack is restored to where it was when the
- // scope was entered.
- this.scopeIndices = [];
- }
-
- // Number of valid IDs. This is the number of objects (global and local)
- // kept alive by this table.
- ProxiedReferenceTable.prototype.count = function () {
- return Object.keys(this.map).length;
- }
-
- // Number of total IDs ever allocated.
- ProxiedReferenceTable.prototype.total = function () {
- return this.count() + this._deletedCount;
- }
-
- // Adds an object to the table and return an ID for serialization.
- ProxiedReferenceTable.prototype.add = function (obj) {
- if (this.scopeIndices.length == 0) {
- throw "Cannot allocate a proxy outside of a scope.";
- }
- // TODO(vsm): Cache refs for each obj?
- var ref = this.name + '-' + this._nextId++;
- this.handleStack.push(ref);
- this.map[ref] = obj;
- return ref;
- }
-
- ProxiedReferenceTable.prototype._initializeOnce = function () {
- if (!this._initialized) {
- this._initialize();
- }
- this._initialized = true;
- }
-
- // Overridable initialization on first use hook.
- ProxiedReferenceTable.prototype._initialize = function () {}
-
- // Enters a new scope for this table.
- ProxiedReferenceTable.prototype.enterScope = function() {
- this._initializeOnce();
- this.scopeIndices.push(this.handleStack.length);
- }
-
- // Invalidates all non-global IDs in the current scope and
- // exit the current scope.
- ProxiedReferenceTable.prototype.exitScope = function() {
- var start = this.scopeIndices.pop();
- for (var i = start; i < this.handleStack.length; ++i) {
- var key = this.handleStack[i];
- if (!this.globalIds.hasOwnProperty(key)) {
- delete this.map[this.handleStack[i]];
- this._deletedCount++;
- }
- }
- this.handleStack = this.handleStack.splice(0, start);
- }
-
- // Makes this ID globally scope. It must be explicitly invalidated.
- ProxiedReferenceTable.prototype.globalize = function(id) {
- this.globalIds[id] = true;
- }
-
- // Invalidates this ID, potentially freeing its corresponding object.
- ProxiedReferenceTable.prototype.invalidate = function(id) {
- var old = this.get(id);
- delete this.globalIds[id];
- delete this.map[id];
- this._deletedCount++;
- return old;
- }
-
- // Gets the object or function corresponding to this ID.
- ProxiedReferenceTable.prototype.get = function (id) {
- if (!this.map.hasOwnProperty(id)) {
- throw 'Proxy ' + id + ' has been invalidated.'
- }
- return this.map[id];
- }
-
- // Subtype for managing function proxies.
- function ProxiedFunctionTable() {}
-
- ProxiedFunctionTable.prototype = new ProxiedReferenceTable('func-ref');
-
- ProxiedFunctionTable.prototype._initialize = function () {
- // Configure this table's port to invoke the corresponding function given
- // its ID.
- // TODO(vsm): Should we enter / exit a scope?
- var table = this;
-
- this.port.receive(function (message) {
- try {
- var id = message[0];
- var args = message[1].map(deserialize);
- var f = table.get(id);
- // TODO(vsm): Should we capture _this_ automatically?
- return [ 'return', serialize(f.apply(null, args)) ];
- } catch (e) {
- return [ 'throws', e.toString() ];
- }
- });
- }
-
- // The singleton table for proxied local functions.
- var proxiedFunctionTable = new ProxiedFunctionTable();
-
- // Subtype for proxied local objects.
- function ProxiedObjectTable() {}
-
- ProxiedObjectTable.prototype = new ProxiedReferenceTable('js-ref');
-
- ProxiedObjectTable.prototype._initialize = function () {
- // Configure this table's port to forward methods, getters, and setters
- // from the remote proxy to the local object.
- var table = this;
-
- this.port.receive(function (message) {
- // TODO(vsm): Support a mechanism to register a handler here.
- try {
- var receiver = table.get(message[0]);
- var method = message[1];
- var args = message[2].map(deserialize);
- if (method.indexOf("get:") == 0) {
- // Getter.
- var field = method.substring(4);
- if (field in receiver && args.length == 0) {
- return [ 'return', serialize(receiver[field]) ];
- }
- } else if (method.indexOf("set:") == 0) {
- // Setter.
- var field = method.substring(4);
- if (args.length == 1) {
- return [ 'return', serialize(receiver[field] = args[0]) ];
- }
- } else if (method == '[]' && args.length == 1) {
- // Index getter.
- return [ 'return', serialize(receiver[args[0]]) ];
- } else {
- var f = receiver[method];
- if (f) {
- var result = f.apply(receiver, args);
- return [ 'return', serialize(result) ];
- }
- }
- return [ 'none' ];
- } catch (e) {
- return [ 'throws', e.toString() ];
- }
- });
- }
-
- // Singleton for local proxied objects.
- var proxiedObjectTable = new ProxiedObjectTable();
-
- // DOM element serialization code.
- var _localNextElementId = 0;
- var _DART_ID = 'data-dart_id';
- var _DART_TEMPORARY_ATTACHED = 'data-dart_temporary_attached';
-
- function serializeElement(e) {
- // TODO(vsm): Use an isolate-specific id.
- var id;
- if (e.hasAttribute(_DART_ID)) {
- id = e.getAttribute(_DART_ID);
- } else {
- id = (_localNextElementId++).toString();
- e.setAttribute(_DART_ID, id);
- }
- if (e !== document.documentElement) {
- // Element must be attached to DOM to be retrieve in js part.
- // Attach top unattached parent to avoid detaching parent of "e" when
- // appending "e" directly to document. We keep count of elements
- // temporarily attached to prevent detaching top unattached parent to
- // early. This count is equals to the length of _DART_TEMPORARY_ATTACHED
- // attribute. There could be other elements to serialize having the same
- // top unattached parent.
- var top = e;
- while (true) {
- if (top.hasAttribute(_DART_TEMPORARY_ATTACHED)) {
- var oldValue = top.getAttribute(_DART_TEMPORARY_ATTACHED);
- var newValue = oldValue + "a";
- top.setAttribute(_DART_TEMPORARY_ATTACHED, newValue);
- break;
- }
- if (top.parentNode == null) {
- top.setAttribute(_DART_TEMPORARY_ATTACHED, "a");
- document.documentElement.appendChild(top);
- break;
- }
- if (top.parentNode === document.documentElement) {
- // e was already attached to dom
- break;
- }
- top = top.parentNode;
- }
- }
- return id;
- }
-
- function deserializeElement(id) {
- // TODO(vsm): Clear the attribute.
- var list = document.querySelectorAll('[' + _DART_ID + '="' + id + '"]');
-
- if (list.length > 1) throw 'Non unique ID: ' + id;
- if (list.length == 0) {
- throw 'Element must be attached to the document: ' + id;
- }
- var e = list[0];
- if (e !== document.documentElement) {
- // detach temporary attached element
- var top = e;
- while (true) {
- if (top.hasAttribute(_DART_TEMPORARY_ATTACHED)) {
- var oldValue = top.getAttribute(_DART_TEMPORARY_ATTACHED);
- var newValue = oldValue.substring(1);
- top.setAttribute(_DART_TEMPORARY_ATTACHED, newValue);
- // detach top only if no more elements have to be unserialized
- if (top.getAttribute(_DART_TEMPORARY_ATTACHED).length === 0) {
- top.removeAttribute(_DART_TEMPORARY_ATTACHED);
- document.documentElement.removeChild(top);
- }
- break;
- }
- if (top.parentNode === document.documentElement) {
- // e was already attached to dom
- break;
- }
- top = top.parentNode;
- }
- }
- return e;
- }
-
-
- // Type for remote proxies to Dart objects.
- function DartProxy(id, sendPort) {
- this.id = id;
- this.port = sendPort;
- }
-
- // Serializes JS types to SendPortSync format:
- // - primitives -> primitives
- // - sendport -> sendport
- // - DOM element -> [ 'domref', element-id ]
- // - Function -> [ 'funcref', function-id, sendport ]
- // - Object -> [ 'objref', object-id, sendport ]
- function serialize(message) {
- if (message == null) {
- return null; // Convert undefined to null.
- } else if (typeof(message) == 'string' ||
- typeof(message) == 'number' ||
- typeof(message) == 'boolean') {
- // Primitives are passed directly through.
- return message;
- } else if (message instanceof SendPortSync) {
- // Non-proxied objects are serialized.
- return message;
- } else if (message instanceof Element) {
- return [ 'domref', serializeElement(message) ];
- } else if (typeof(message) == 'function') {
- if ('_dart_id' in message) {
- // Remote function proxy.
- var remoteId = message._dart_id;
- var remoteSendPort = message._dart_port;
- return [ 'funcref', remoteId, remoteSendPort ];
- } else {
- // Local function proxy.
- return [ 'funcref',
- proxiedFunctionTable.add(message),
- proxiedFunctionTable.sendPort ];
- }
- } else if (message instanceof DartProxy) {
- // Remote object proxy.
- return [ 'objref', message.id, message.port ];
- } else {
- // Local object proxy.
- return [ 'objref',
- proxiedObjectTable.add(message),
- proxiedObjectTable.sendPort ];
- }
- }
-
- function deserialize(message) {
- if (message == null) {
- return null; // Convert undefined to null.
- } else if (typeof(message) == 'string' ||
- typeof(message) == 'number' ||
- typeof(message) == 'boolean') {
- // Primitives are passed directly through.
- return message;
- } else if (message instanceof SendPortSync) {
- // Serialized type.
- return message;
- }
- var tag = message[0];
- switch (tag) {
- case 'funcref': return deserializeFunction(message);
- case 'objref': return deserializeObject(message);
- case 'domref': return deserializeElement(message[1]);
- }
- throw 'Unsupported serialized data: ' + message;
- }
-
- // Create a local function that forwards to the remote function.
- function deserializeFunction(message) {
- var id = message[1];
- var port = message[2];
- // TODO(vsm): Add a more robust check for a local SendPortSync.
- if ("receivePort" in port) {
- // Local function.
- return proxiedFunctionTable.get(id);
- } else {
- // Remote function. Forward to its port.
- var f = function () {
- var depth = enterScope();
- try {
- var args = Array.prototype.slice.apply(arguments).map(serialize);
- var result = port.callSync([id, args]);
- if (result[0] == 'throws') throw deserialize(result[1]);
- return deserialize(result[1]);
- } finally {
- exitScope(depth);
- }
- };
- // Cache the remote id and port.
- f._dart_id = id;
- f._dart_port = port;
- return f;
- }
- }
-
- // Creates a DartProxy to forwards to the remote object.
- function deserializeObject(message) {
- var id = message[1];
- var port = message[2];
- // TODO(vsm): Add a more robust check for a local SendPortSync.
- if ("receivePort" in port) {
- // Local object.
- return proxiedObjectTable.get(id);
- } else {
- // Remote object.
- return new DartProxy(id, port);
- }
- }
-
- // Remote handler to construct a new JavaScript object given its
- // serialized constructor and arguments.
- function construct(args) {
- args = args.map(deserialize);
- var constructor = args[0];
- args = Array.prototype.slice.call(args, 1);
-
- // Dummy Type with correct constructor.
- var Type = function(){};
- Type.prototype = constructor.prototype;
-
- // Create a new instance
- var instance = new Type();
-
- // Call the original constructor.
- var ret = constructor.apply(instance, args);
-
- return serialize(Object(ret) === ret ? ret : instance);
- }
-
- // Remote handler to evaluate a string in JavaScript and return a serialized
- // result.
- function evaluate(data) {
- return serialize(eval(deserialize(data)));
- }
-
- // Remote handler for debugging.
- function debug() {
- var live = proxiedObjectTable.count() + proxiedFunctionTable.count();
- var total = proxiedObjectTable.total() + proxiedFunctionTable.total();
- return 'JS objects Live : ' + live +
- ' (out of ' + total + ' ever allocated).';
- }
-
- // Return true iff two JavaScript proxies are equal (==).
- function proxyEquals(args) {
- return deserialize(args[0]) ==
- deserialize(args[1]);
- }
-
- function makeGlobalPort(name, f) {
- var port = new ReceivePortSync();
- port.receive(f);
- window.registerPort(name, port.toSendPort());
- }
-
- // Enters a new scope in the JavaScript context.
- function enterJavaScriptScope() {
- proxiedObjectTable.enterScope();
- proxiedFunctionTable.enterScope();
- }
-
- // Enters a new scope in both the JavaScript and Dart context.
- var _dartEnterScopePort = null;
- function enterScope() {
- enterJavaScriptScope();
- if (!_dartEnterScopePort) {
- _dartEnterScopePort = window.lookupPort('js-dart-enter-scope');
- }
- return _dartEnterScopePort.callSync([]);
- }
-
- // Exits the current scope (and invalidate local IDs) in the JavaScript
- // context.
- function exitJavaScriptScope() {
- proxiedFunctionTable.exitScope();
- proxiedObjectTable.exitScope();
- }
-
- // Exits the current scope in both the JavaScript and Dart context.
- var _dartExitScopePort = null;
- function exitScope(depth) {
- exitJavaScriptScope();
- if (!_dartExitScopePort) {
- _dartExitScopePort = window.lookupPort('js-dart-exit-scope');
- }
- return _dartExitScopePort.callSync([ depth ]);
- }
-
- makeGlobalPort('dart-js-evaluate', evaluate);
- makeGlobalPort('dart-js-create', construct);
- makeGlobalPort('dart-js-debug', debug);
- makeGlobalPort('dart-js-equals', proxyEquals);
- makeGlobalPort('dart-js-enter-scope', enterJavaScriptScope);
- makeGlobalPort('dart-js-exit-scope', exitJavaScriptScope);
- makeGlobalPort('dart-js-globalize', function(data) {
- if (data[0] == "objref") return proxiedObjectTable.globalize(data[1]);
- // TODO(vsm): Do we ever need to globalize functions?
- throw 'Illegal type: ' + data[0];
- });
- makeGlobalPort('dart-js-invalidate', function(data) {
- if (data[0] == "objref") return proxiedObjectTable.invalidate(data[1]);
- // TODO(vsm): Do we ever need to globalize functions?
- throw 'Illegal type: ' + data[0];
- });
-})();

Powered by Google App Engine
This is Rietveld 408576698