mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
72 lines
3.2 KiB
JavaScript
72 lines
3.2 KiB
JavaScript
/* 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/. */
|
|
"use strict";
|
|
|
|
const { Cc, Ci, Cr } = require("chrome");
|
|
const { Input, start, stop, receive, outputs } = require("../event/utils");
|
|
const { id: addonID } = require("../self");
|
|
const { setImmediate } = require("../timers");
|
|
const { notifyObservers } = Cc['@mozilla.org/observer-service;1'].
|
|
getService(Ci.nsIObserverService);
|
|
|
|
const NOT_AN_INPUT = "OutputPort can be used only for sending messages";
|
|
|
|
// `OutputPort` creates a port to which messages can be send. Those
|
|
// messages are actually disptached as `subject`'s of the observer
|
|
// notifications. This is handy for communicating between different
|
|
// components of the SDK. By default messages are dispatched
|
|
// asynchronously, although `options.sync` can be used to make them
|
|
// synchronous. If `options.id` is given `topic` for observer
|
|
// notifications is generated by namespacing it, to avoid spamming
|
|
// other SDK add-ons. It's also possible to provide `options.topic`
|
|
// to use excat `topic` without namespacing it.
|
|
//
|
|
// Note: Symmetric `new InputPort({ id: "x" })` instances can be used to
|
|
// receive messages send to the instances of `new OutputPort({ id: "x" })`.
|
|
const OutputPort = function({id, topic, sync}) {
|
|
this.id = id || topic;
|
|
this.sync = !!sync;
|
|
this.topic = topic || "sdk:" + addonID + ":" + id;
|
|
};
|
|
// OutputPort extends base signal type to implement same message
|
|
// receiving interface.
|
|
OutputPort.prototype = new Input();
|
|
OutputPort.constructor = OutputPort;
|
|
|
|
// OutputPort can not be consumed there for starting or stopping it
|
|
// is not supported.
|
|
OutputPort.prototype[start] = _ => { throw TypeError(NOT_AN_INPUT); };
|
|
OutputPort.prototype[stop] = _ => { throw TypeError(NOT_AN_INPUT); };
|
|
|
|
// Port reecives message send to it, which will be dispatched via
|
|
// observer notification service.
|
|
OutputPort.receive = ({topic, sync}, message) => {
|
|
const type = typeof(message);
|
|
const supported = message === null ||
|
|
type === "object" ||
|
|
type === "function";
|
|
|
|
// There is no sensible way to wrap JS primitives that would make sense
|
|
// for general observer notification users. It's also probably not very
|
|
// useful to dispatch JS primitives as subject of observer service, there
|
|
// for we do not support those use cases.
|
|
if (!supported)
|
|
throw new TypeError("Unsupproted message type: `" + type + "`");
|
|
|
|
// Normalize `message` to create a valid observer notification `subject`.
|
|
// If `message` is `null`, implements `nsISupports` interface or already
|
|
// represents wrapped JS object use it as is. Otherwise create a wrapped
|
|
// object so that observers could receive it.
|
|
const subject = message === null ? null :
|
|
message instanceof Ci.nsISupports ? message :
|
|
message.wrappedJSObject ? message :
|
|
{wrappedJSObject: message};
|
|
if (sync)
|
|
notifyObservers(subject, topic, null);
|
|
else
|
|
setImmediate(notifyObservers, subject, topic, null);
|
|
};
|
|
OutputPort.prototype[receive] = OutputPort.receive;
|
|
exports.OutputPort = OutputPort;
|