Vats is a project mainly written in JavaScript, it's free.
Prototype implementation of vats for Jetpack
Currently access to a chrome module from add-on process requires boilerplate / wrapper code in both (chrome, add-on) processes, this is specially painful for a tests that use raw chrome access to an APIs that were never exposed through low level modules that will have to be build from scratch.
Module vats will simplify E10S integration by providing de-sugared, low-level access to all existing modules (from add-on process) without any wrapping code, on top of which high level modules in add-on process could be build (most likely high level modules will just be ported to the add-on process).
Proposal is based on well researched work that has being implemented and well tested in other languages like E, C# and also being implemented as a libraries in JavaScript: Q-comm, web-send.
To address existing E10S integration issues module vats must provide mechanics for:
detroy
method on it).Optionally:
de-usgared | sync | async |
---|---|---|
Q.get(promise, 'bar') | promise.bar | promise['! bar'] |
Q.put(promise, 'bar', 'foo') | promise.bar = 'foo' | promise['! bar'] = 'foo' |
Q.post(promise, 'foo', a, b) | promise.foo(a, b) | promise['! foo'](a, b) |
Generator may be used to add further syntax sugar for saving continuations on promise resolution / rejections. This was prototyped in an actor lib and would map de-sugared API as follows:
Q.when(promise, function resolved(value) { callback(null, data + foo); }, function rejected(reason) { callback(new Error(reason)); })
try { callback(null, (yield promise) + foo); } catch(exception) { callback(exception); }
Vats could be exposed for a content workers, that will allow similar wrappers (likely by third parties) in content context for a sugared access to a high-level APIs.
API can be implemented as module accessible from the add-on process. Following example uses vat to get raw access to the chrome API:
const { Vat } = require("vats");
const { Q } = require("q");
// Returns promise for the `exports` object in the vat context.
let vat = Vat({
source: "new " + function Worker() {
const { Cc, Ci } = require("chrome");
exports.WM = Cc["@mozilla.org/appshell/window-mediator;1"].
getService(Ci.nsIWindowMediator);
}
});
// Getting remote promise for `exports.WM`.
let pWM = Q.get(vat, "WM");
// Remote promise for `exports.WM.getMostRecentWindow("navigator:browser");
let pActiveWindow = Q.post(pWM, "getMostRecentWindow", "navigator:browser");
// Sets a property on the remote object (that returns promise that will
// be fulfilled / get broken once operation in the chrome process is
// performed.
let onSet = Q.put(pActiveWindow, "location", "data:text/html,Hello Vat!");
// Setting a callback to log a message when `location` property of the
// active window will change and an errorback to be notified if race
// condition occurred. Please note that failure will propagate across the
// whole chain, meaning that Q.post failure, will be caught by onFailure.
Q.when(onSet, function onFulfill() console.log("done"),
function onFailure(error) console.log("failed: " + error));
Also vats can be created out of chrome modules. Following example creates a high-level "notifications" module using a vat wrapper:
const { Vat } = require("vats");
const { Q } = require("q");
pNotifications = Vat({ module: "notifications" });
exports.notify = function notify(options) {
Q.post(pNotifications, "notify", options);
}
In order to try this demo implementation you will have to do following steps:
cd {{addon-sdk}}/packages
git clone git://github.com/Gozala/vats.git
git clone git://github.com/Gozala/q.git
git clone git://github.com/Gozala/q-comm.git
cd q-comm
git fetch origin
git checkout -b origin/jetpack jetpack
cd ../vats
cfx run --e10s