diff options
Diffstat (limited to 'toolkit/jetpack/dev/ports.js')
-rw-r--r-- | toolkit/jetpack/dev/ports.js | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/toolkit/jetpack/dev/ports.js b/toolkit/jetpack/dev/ports.js new file mode 100644 index 000000000..a41f59eb7 --- /dev/null +++ b/toolkit/jetpack/dev/ports.js @@ -0,0 +1,64 @@ +/* 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"; + +module.metadata = { + "stability": "experimental" +}; + +// This module provides `marshal` and `demarshal` functions +// that can be used to send MessagePort's over `nsIFrameMessageManager` +// until Bug 914974 is fixed. + +const { add, iterator } = require("../sdk/lang/weak-set"); +const { curry } = require("../sdk/lang/functional"); + +var id = 0; +const ports = new WeakMap(); + +// Takes `nsIFrameMessageManager` and `MessagePort` instances +// and returns a handle representing given `port`. Messages +// received on given `port` will be forwarded to a message +// manager under `sdk/port/message` and messages like: +// { port: { type: "MessagePort", id: 2}, data: data } +// Where id is an identifier associated with a given `port` +// and `data` is an `event.data` received on port. +const marshal = curry((manager, port) => { + if (!ports.has(port)) { + id = id + 1; + const handle = {type: "MessagePort", id: id}; + // Bind id to the given port + ports.set(port, handle); + + // Obtain a weak reference to a port. + add(exports, port); + + port.onmessage = event => { + manager.sendAsyncMessage("sdk/port/message", { + port: handle, + message: event.data + }); + }; + + return handle; + } + return ports.get(port); +}); +exports.marshal = marshal; + +// Takes `nsIFrameMessageManager` instance and a handle returned +// `marshal(manager, port)` returning a `port` that was passed +// to it. Note that `port` may be GC-ed in which case returned +// value will be `null`. +const demarshal = curry((manager, {type, id}) => { + if (type === "MessagePort") { + for (let port of iterator(exports)) { + if (id === ports.get(port).id) + return port; + } + } + return null; +}); +exports.demarshal = demarshal; |