addon-sdk/source/lib/sdk/output/system.js

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/addon-sdk/source/lib/sdk/output/system.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,71 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +"use strict";
     1.8 +
     1.9 +const { Cc, Ci, Cr } = require("chrome");
    1.10 +const { Input, start, stop, receive, outputs } = require("../event/utils");
    1.11 +const { id: addonID } = require("../self");
    1.12 +const { setImmediate } = require("../timers");
    1.13 +const { notifyObservers } = Cc['@mozilla.org/observer-service;1'].
    1.14 +                             getService(Ci.nsIObserverService);
    1.15 +
    1.16 +const NOT_AN_INPUT = "OutputPort can be used only for sending messages";
    1.17 +
    1.18 +// `OutputPort` creates a port to which messages can be send. Those
    1.19 +// messages are actually disptached as `subject`'s of the observer
    1.20 +// notifications. This is handy for communicating between different
    1.21 +// components of the SDK. By default messages are dispatched
    1.22 +// asynchronously, although `options.sync` can be used to make them
    1.23 +// synchronous. If `options.id` is given `topic` for observer
    1.24 +// notifications is generated by namespacing it, to avoid spamming
    1.25 +// other SDK add-ons. It's also possible to provide `options.topic`
    1.26 +// to use excat `topic` without namespacing it.
    1.27 +//
    1.28 +// Note: Symmetric `new InputPort({ id: "x" })` instances can be used to
    1.29 +// receive messages send to the instances of `new OutputPort({ id: "x" })`.
    1.30 +const OutputPort = function({id, topic, sync}) {
    1.31 +  this.id = id || topic;
    1.32 +  this.sync = !!sync;
    1.33 +  this.topic = topic || "sdk:" + addonID + ":" + id;
    1.34 +};
    1.35 +// OutputPort extends base signal type to implement same message
    1.36 +// receiving interface.
    1.37 +OutputPort.prototype = new Input();
    1.38 +OutputPort.constructor = OutputPort;
    1.39 +
    1.40 +// OutputPort can not be consumed there for starting or stopping it
    1.41 +// is not supported.
    1.42 +OutputPort.prototype[start] = _ => { throw TypeError(NOT_AN_INPUT); };
    1.43 +OutputPort.prototype[stop] = _ => { throw TypeError(NOT_AN_INPUT); };
    1.44 +
    1.45 +// Port reecives message send to it, which will be dispatched via
    1.46 +// observer notification service.
    1.47 +OutputPort.receive = ({topic, sync}, message) => {
    1.48 +  const type = typeof(message);
    1.49 +  const supported = message === null ||
    1.50 +                    type === "object" ||
    1.51 +                    type === "function";
    1.52 +
    1.53 +  // There is no sensible way to wrap JS primitives that would make sense
    1.54 +  // for general observer notification users. It's also probably not very
    1.55 +  // useful to dispatch JS primitives as subject of observer service, there
    1.56 +  // for we do not support those use cases.
    1.57 +  if (!supported)
    1.58 +    throw new TypeError("Unsupproted message type: `" + type + "`");
    1.59 +
    1.60 +  // Normalize `message` to create a valid observer notification `subject`.
    1.61 +  // If `message` is `null`, implements `nsISupports` interface or already
    1.62 +  // represents wrapped JS object use it as is. Otherwise create a wrapped
    1.63 +  // object so that observers could receive it.
    1.64 +  const subject = message === null ? null :
    1.65 +                  message instanceof Ci.nsISupports ? message :
    1.66 +                  message.wrappedJSObject ? message :
    1.67 +                  {wrappedJSObject: message};
    1.68 +  if (sync)
    1.69 +    notifyObservers(subject, topic, null);
    1.70 +  else
    1.71 +    setImmediate(notifyObservers, subject, topic, null);
    1.72 +};
    1.73 +OutputPort.prototype[receive] = OutputPort.receive;
    1.74 +exports.OutputPort = OutputPort;

mercurial