diff options
Diffstat (limited to 'addon-sdk/source/examples/debug-client/data/client.js')
-rw-r--r-- | addon-sdk/source/examples/debug-client/data/client.js | 816 |
1 files changed, 0 insertions, 816 deletions
diff --git a/addon-sdk/source/examples/debug-client/data/client.js b/addon-sdk/source/examples/debug-client/data/client.js deleted file mode 100644 index 022f9a1c35..0000000000 --- a/addon-sdk/source/examples/debug-client/data/client.js +++ /dev/null @@ -1,816 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -(function(exports) { -"use strict"; - - -var describe = Object.getOwnPropertyDescriptor; -var Class = fields => { - var constructor = fields.constructor || function() {}; - var ancestor = fields.extends || Object; - - - - var descriptor = {}; - for (var key of Object.keys(fields)) - descriptor[key] = describe(fields, key); - - var prototype = Object.create(ancestor.prototype, descriptor); - - constructor.prototype = prototype; - prototype.constructor = constructor; - - return constructor; -}; - - -var bus = function Bus() { - var parser = new DOMParser(); - return parser.parseFromString("<EventTarget/>", "application/xml").documentElement; -}(); - -var GUID = new WeakMap(); -GUID.id = 0; -var guid = x => GUID.get(x); -var setGUID = x => { - GUID.set(x, ++ GUID.id); -}; - -var Emitter = Class({ - extends: EventTarget, - constructor: function() { - this.setupEmitter(); - }, - setupEmitter: function() { - setGUID(this); - }, - addEventListener: function(type, listener, capture) { - bus.addEventListener(type + "@" + guid(this), - listener, capture); - }, - removeEventListener: function(type, listener, capture) { - bus.removeEventListener(type + "@" + guid(this), - listener, capture); - } -}); - -function dispatch(target, type, data) { - var event = new MessageEvent(type + "@" + guid(target), { - bubbles: true, - cancelable: false, - data: data - }); - bus.dispatchEvent(event); -} - -var supervisedWorkers = new WeakMap(); -var supervised = supervisor => { - if (!supervisedWorkers.has(supervisor)) { - supervisedWorkers.set(supervisor, new Map()); - supervisor.connection.addActorPool(supervisor); - } - return supervisedWorkers.get(supervisor); -}; - -var Supervisor = Class({ - extends: Emitter, - constructor: function(...params) { - this.setupEmitter(...params); - this.setupSupervisor(...params); - }, - Supervisor: function(connection) { - this.connection = connection; - }, - /** - * Return the parent pool for this client. - */ - supervisor: function() { - return this.connection.poolFor(this.actorID); - }, - /** - * Override this if you want actors returned by this actor - * to belong to a different actor by default. - */ - marshallPool: function() { return this; }, - /** - * Add an actor as a child of this pool. - */ - supervise: function(actor) { - if (!actor.actorID) - actor.actorID = this.connection.allocID(actor.actorPrefix || - actor.typeName); - - supervised(this).set(actor.actorID, actor); - return actor; - }, - /** - * Remove an actor as a child of this pool. - */ - abandon: function(actor) { - supervised(this).delete(actor.actorID); - }, - // true if the given actor ID exists in the pool. - has: function(actorID) { - return supervised(this).has(actorID); - }, - // Same as actor, should update debugger connection to use 'actor' - // and then remove this. - get: function(actorID) { - return supervised(this).get(actorID); - }, - actor: function(actorID) { - return supervised(this).get(actorID); - }, - isEmpty: function() { - return supervised(this).size === 0; - }, - /** - * For getting along with the debugger server pools, should be removable - * eventually. - */ - cleanup: function() { - this.destroy(); - }, - destroy: function() { - var supervisor = this.supervisor(); - if (supervisor) - supervisor.abandon(this); - - for (var actor of supervised(this).values()) { - if (actor !== this) { - var destroy = actor.destroy; - // Disconnect destroy while we're destroying in case of (misbehaving) - // circular ownership. - if (destroy) { - actor.destroy = null; - destroy.call(actor); - actor.destroy = destroy; - } - } - } - - this.connection.removeActorPool(this); - supervised(this).clear(); - } - -}); - - - - -var mailbox = new WeakMap(); -var clientRequests = new WeakMap(); - -var inbox = client => mailbox.get(client).inbox; -var outbox = client => mailbox.get(client).outbox; -var requests = client => clientRequests.get(client); - - -var Receiver = Class({ - receive: function(packet) { - if (packet.error) - this.reject(packet.error); - else - this.resolve(this.read(packet)); - } -}); - -var Connection = Class({ - constructor: function() { - // Queue of the outgoing messages. - this.outbox = []; - // Map of pending requests. - this.pending = new Map(); - this.pools = new Set(); - }, - isConnected: function() { - return !!this.port - }, - connect: function(port) { - this.port = port; - port.addEventListener("message", this); - port.start(); - - this.flush(); - }, - addPool: function(pool) { - this.pools.add(pool); - }, - removePool: function(pool) { - this.pools.delete(pool); - }, - poolFor: function(id) { - for (let pool of this.pools.values()) { - if (pool.has(id)) - return pool; - } - }, - get: function(id) { - var pool = this.poolFor(id); - return pool && pool.get(id); - }, - disconnect: function() { - this.port.stop(); - this.port = null; - for (var request of this.pending.values()) { - request.catch(new Error("Connection closed")); - } - this.pending.clear(); - - var requests = this.outbox.splice(0); - for (var request of request) { - requests.catch(new Error("Connection closed")); - } - }, - handleEvent: function(event) { - this.receive(event.data); - }, - flush: function() { - if (this.isConnected()) { - for (var request of this.outbox) { - if (!this.pending.has(request.to)) { - this.outbox.splice(this.outbox.indexOf(request), 1); - this.pending.set(request.to, request); - this.send(request.packet); - } - } - } - }, - send: function(packet) { - this.port.postMessage(packet); - }, - request: function(packet) { - return new Promise(function(resolve, reject) { - this.outbox.push({ - to: packet.to, - packet: packet, - receive: resolve, - catch: reject - }); - this.flush(); - }); - }, - receive: function(packet) { - var { from, type, why } = packet; - var receiver = this.pending.get(from); - if (!receiver) { - console.warn("Unable to handle received packet", data); - } else { - this.pending.delete(from); - if (packet.error) - receiver.catch(packet.error); - else - receiver.receive(packet); - } - this.flush(); - }, -}); - -/** - * Base class for client-side actor fronts. - */ -var Client = Class({ - extends: Supervisor, - constructor: function(from=null, detail=null, connection=null) { - this.Client(from, detail, connection); - }, - Client: function(form, detail, connection) { - this.Supervisor(connection); - - if (form) { - this.actorID = form.actor; - this.from(form, detail); - } - }, - connect: function(port) { - this.connection = new Connection(port); - }, - actorID: null, - actor: function() { - return this.actorID; - }, - /** - * Update the actor from its representation. - * Subclasses should override this. - */ - form: function(form) { - }, - /** - * Method is invokeid when packet received constitutes an - * event. By default such packets are demarshalled and - * dispatched on the client instance. - */ - dispatch: function(packet) { - }, - /** - * Method is invoked when packet is returned in response to - * a request. By default respond delivers response to a first - * request in a queue. - */ - read: function(input) { - throw new TypeError("Subclass must implement read method"); - }, - write: function(input) { - throw new TypeError("Subclass must implement write method"); - }, - respond: function(packet) { - var [resolve, reject] = requests(this).shift(); - if (packet.error) - reject(packet.error); - else - resolve(this.read(packet)); - }, - receive: function(packet) { - if (this.isEventPacket(packet)) { - this.dispatch(packet); - } - else if (requests(this).length) { - this.respond(packet); - } - else { - this.catch(packet); - } - }, - send: function(packet) { - Promise.cast(packet.to || this.actor()).then(id => { - packet.to = id; - this.connection.send(packet); - }) - }, - request: function(packet) { - return this.connection.request(packet); - } -}); - - -var Destructor = method => { - return function(...args) { - return method.apply(this, args).then(result => { - this.destroy(); - return result; - }); - }; -}; - -var Profiled = (method, id) => { - return function(...args) { - var start = new Date(); - return method.apply(this, args).then(result => { - var end = new Date(); - this.telemetry.add(id, +end - start); - return result; - }); - }; -}; - -var Method = (request, response) => { - return response ? new BidirectionalMethod(request, response) : - new UnidirecationalMethod(request); -}; - -var UnidirecationalMethod = request => { - return function(...args) { - var packet = request.write(args, this); - this.connection.send(packet); - return Promise.resolve(void(0)); - }; -}; - -var BidirectionalMethod = (request, response) => { - return function(...args) { - var packet = request.write(args, this); - return this.connection.request(packet).then(packet => { - return response.read(packet, this); - }); - }; -}; - - -Client.from = ({category, typeName, methods, events}) => { - var proto = { - constructor: function(...args) { - this.Client(...args); - }, - extends: Client, - name: typeName - }; - - methods.forEach(({telemetry, request, response, name, oneway, release}) => { - var [reader, writer] = oneway ? [, new Request(request)] : - [new Request(request), new Response(response)]; - var method = new Method(request, response); - var profiler = telemetry ? new Profiler(method) : method; - var destructor = release ? new Destructor(profiler) : profiler; - proto[name] = destructor; - }); - - return Class(proto); -}; - - -var defineType = (client, descriptor) => { - var type = void(0) - if (typeof(descriptor) === "string") { - if (name.indexOf(":") > 0) - type = makeCompoundType(descriptor); - else if (name.indexOf("#") > 0) - type = new ActorDetail(descriptor); - else if (client.specification[descriptor]) - type = makeCategoryType(client.specification[descriptor]); - } else { - type = makeCategoryType(descriptor); - } - - if (type) - client.types.set(type.name, type); - else - throw TypeError("Invalid type: " + descriptor); -}; - - -var makeCompoundType = name => { - var index = name.indexOf(":"); - var [baseType, subType] = [name.slice(0, index), parts.slice(1)]; - return baseType === "array" ? new ArrayOf(subType) : - baseType === "nullable" ? new Maybe(subType) : - null; -}; - -var makeCategoryType = (descriptor) => { - var { category } = descriptor; - return category === "dict" ? new Dictionary(descriptor) : - category === "actor" ? new Actor(descriptor) : - null; -}; - - -var typeFor = (client, type="primitive") => { - if (!client.types.has(type)) - defineType(client, type); - - return client.types.get(type); -}; - - -var Client = Class({ - constructor: function() { - }, - setupTypes: function(specification) { - this.specification = specification; - this.types = new Map(); - }, - read: function(input, type) { - return typeFor(this, type).read(input, this); - }, - write: function(input, type) { - return typeFor(this, type).write(input, this); - } -}); - - -var Type = Class({ - get name() { - return this.category ? this.category + ":" + this.type : - this.type; - }, - read: function(input, client) { - throw new TypeError("`Type` subclass must implement `read`"); - }, - write: function(input, client) { - throw new TypeError("`Type` subclass must implement `write`"); - } -}); - - -var Primitve = Class({ - extends: Type, - constuctor: function(type) { - this.type = type; - }, - read: function(input, client) { - return input; - }, - write: function(input, client) { - return input; - } -}); - -var Maybe = Class({ - extends: Type, - category: "nullable", - constructor: function(type) { - this.type = type; - }, - read: function(input, client) { - return input === null ? null : - input === void(0) ? void(0) : - client.read(input, this.type); - }, - write: function(input, client) { - return input === null ? null : - input === void(0) ? void(0) : - client.write(input, this.type); - } -}); - -var ArrayOf = Class({ - extends: Type, - category: "array", - constructor: function(type) { - this.type = type; - }, - read: function(input, client) { - return input.map($ => client.read($, this.type)); - }, - write: function(input, client) { - return input.map($ => client.write($, this.type)); - } -}); - -var Dictionary = Class({ - exteds: Type, - category: "dict", - get name() { return this.type; }, - constructor: function({typeName, specializations}) { - this.type = typeName; - this.types = specifications; - }, - read: function(input, client) { - var output = {}; - for (var key in input) { - output[key] = client.read(input[key], this.types[key]); - } - return output; - }, - write: function(input, client) { - var output = {}; - for (var key in input) { - output[key] = client.write(value, this.types[key]); - } - return output; - } -}); - -var Actor = Class({ - exteds: Type, - category: "actor", - get name() { return this.type; }, - constructor: function({typeName}) { - this.type = typeName; - }, - read: function(input, client, detail) { - var id = value.actor; - var actor = void(0); - if (client.connection.has(id)) { - return client.connection.get(id).form(input, detail, client); - } else { - actor = Client.from(detail, client); - actor.actorID = id; - client.supervise(actor); - } - }, - write: function(input, client, detail) { - if (input instanceof Actor) { - if (!input.actorID) { - client.supervise(input); - } - return input.from(detail); - } - return input.actorID; - } -}); - -var Root = Client.from({ - "category": "actor", - "typeName": "root", - "methods": [ - {"name": "listTabs", - "request": {}, - "response": { - } - }, - {"name": "listAddons" - }, - {"name": "echo", - - }, - {"name": "protocolDescription", - - } - ] -}); - - -var ActorDetail = Class({ - extends: Actor, - constructor: function(name, actor, detail) { - this.detail = detail; - this.actor = actor; - }, - read: function(input, client) { - this.actor.read(input, client, this.detail); - }, - write: function(input, client) { - this.actor.write(input, client, this.detail); - } -}); - -var registeredLifetimes = new Map(); -var LifeTime = Class({ - extends: Type, - category: "lifetime", - constructor: function(lifetime, type) { - this.name = lifetime + ":" + type.name; - this.field = registeredLifetimes.get(lifetime); - }, - read: function(input, client) { - return this.type.read(input, client[this.field]); - }, - write: function(input, client) { - return this.type.write(input, client[this.field]); - } -}); - -var primitive = new Primitve("primitive"); -var string = new Primitve("string"); -var number = new Primitve("number"); -var boolean = new Primitve("boolean"); -var json = new Primitve("json"); -var array = new Primitve("array"); - - -var TypedValue = Class({ - extends: Type, - constructor: function(name, type) { - this.TypedValue(name, type); - }, - TypedValue: function(name, type) { - this.name = name; - this.type = type; - }, - read: function(input, client) { - return this.client.read(input, this.type); - }, - write: function(input, client) { - return this.client.write(input, this.type); - } -}); - -var Return = Class({ - extends: TypedValue, - constructor: function(type) { - this.type = type - } -}); - -var Argument = Class({ - extends: TypedValue, - constructor: function(...args) { - this.Argument(...args); - }, - Argument: function(index, type) { - this.index = index; - this.TypedValue("argument[" + index + "]", type); - }, - read: function(input, client, target) { - return target[this.index] = client.read(input, this.type); - } -}); - -var Option = Class({ - extends: Argument, - constructor: function(...args) { - return this.Argument(...args); - }, - read: function(input, client, target, name) { - var param = target[this.index] || (target[this.index] = {}); - param[name] = input === void(0) ? input : client.read(input, this.type); - }, - write: function(input, client, name) { - var value = input && input[name]; - return value === void(0) ? value : client.write(value, this.type); - } -}); - -var Request = Class({ - extends: Type, - constructor: function(template={}) { - this.type = template.type; - this.template = template; - this.params = findPlaceholders(template, Argument); - }, - read: function(packet, client) { - var args = []; - for (var param of this.params) { - var {placeholder, path} = param; - var name = path[path.length - 1]; - placeholder.read(getPath(packet, path), client, args, name); - // TODO: - // args[placeholder.index] = placeholder.read(query(packet, path), client); - } - return args; - }, - write: function(input, client) { - return JSON.parse(JSON.stringify(this.template, (key, value) => { - return value instanceof Argument ? value.write(input[value.index], - client, key) : - value; - })); - } -}); - -var Response = Class({ - extends: Type, - constructor: function(template={}) { - this.template = template; - var [x] = findPlaceholders(template, Return); - var {placeholder, path} = x; - this.return = placeholder; - this.path = path; - }, - read: function(packet, client) { - var value = query(packet, this.path); - return this.return.read(value, client); - }, - write: function(input, client) { - return JSON.parse(JSON.stringify(this.template, (key, value) => { - return value instanceof Return ? value.write(input) : - input - })); - } -}); - -// Returns array of values for the given object. -var values = object => Object.keys(object).map(key => object[key]); -// Returns [key, value] pairs for the given object. -var pairs = object => Object.keys(object).map(key => [key, object[key]]); -// Queries an object for the field nested with in it. -var query = (object, path) => path.reduce((object, entry) => object && object[entry], - object); - - -var Root = Client.from({ - "category": "actor", - "typeName": "root", - "methods": [ - { - "name": "echo", - "request": { - "string": { "_arg": 0, "type": "string" } - }, - "response": { - "string": { "_retval": "string" } - } - }, - { - "name": "listTabs", - "request": {}, - "response": { "_retval": "tablist" } - }, - { - "name": "actorDescriptions", - "request": {}, - "response": { "_retval": "json" } - } - ], - "events": { - "tabListChanged": {} - } -}); - -var Tab = Client.from({ - "category": "dict", - "typeName": "tab", - "specifications": { - "title": "string", - "url": "string", - "outerWindowID": "number", - "console": "console", - "inspectorActor": "inspector", - "callWatcherActor": "call-watcher", - "canvasActor": "canvas", - "webglActor": "webgl", - "webaudioActor": "webaudio", - "styleSheetsActor": "stylesheets", - "styleEditorActor": "styleeditor", - "storageActor": "storage", - "gcliActor": "gcli", - "memoryActor": "memory", - "eventLoopLag": "eventLoopLag", - - "trace": "trace", // missing - } -}); - -var tablist = Client.from({ - "category": "dict", - "typeName": "tablist", - "specializations": { - "selected": "number", - "tabs": "array:tab" - } -}); - -})(this); - |