Chrome Workers, now with modules!

July 17, 2013 § 3 Comments

One of the main objectives of Project Async is to encourage Firefox developers and Firefox add-on developers to use Chrome Workers to ensure that whatever they do doesn’t block Firefox’ UI thread. The main obstacle, for the moment, is that Chrome Workers have access to very few features, so one the tasks of Project Async is to add features to Chrome Workers.

Today, let me introduce the Module Loader for Chrome Workers.

This module loader should not surprise developers familiar with CommonJS, as it implements a minimal CommonJS require().

Loading modules

Loading a module is trivial.
Firstly, import the module loader:


// Import the module loader.
 // You only need to do this once per worker, but doing it several times is ok.
 importScripts("resource://gre/modules/workers/require.js");

This defines a global value require(), that you may now use as follows:


// Import the module
 // (here, we import the core of OS.File)
 let Core = require("resource://gre/modules/osfile/osfile_shared_allthreads.jsm");

// We may now use module osfile_shared_allthreads. Since it exports a value |declareFFI|, let's try it:
 Core.declareFFI(...)

Note that, for the moment, require() only accepts absolute URIs. If the your module URI ends with “.js”, you can omit the extension.

Creating modules

Creating a module is just as trivial.

A module is a file, whose filename generally ends with either “.js” or “.jsm”, and designed to be opened through require(). Any value you define in that file is private by default. To make the value public, you just have to add it to either global value exports, as follows:


/* File myModule.js */
 let secretKey = "this is a secret";
 let publicKey = "this is public";
 exports.key = publicKey;
 // secretKey is not exported
 // publicKey is exported with name "key"

Alternatively, if you prefer that style, you may write


// variable |module| is a special global introduced by require()
 module.exports = {
key: publicKey
 };

Once this is done, we may load the module and use the values that have been exported


// Assuming that myModule.js is installed to resource://gre/modules/myModule.js
 let Module = require("resource://gre/modules/myModule.js")

foo(Module.key); // Module.key == "this is public";
 // However, secretKey is not exported and cannot be used

Stack traces

Unfortunately, the module loader doesn’t play nicely with error stack traces. That is, the following will not show human-readable stacks:


try {
MyModule.foo();
 } catch (ex) {
log("Exception raised at " + ex.fileName)
log("Stack: " + ex.stack);
 }

Rather, you should use properties moduleName and moduleStack, as follows:

try {
  MyModule.foo();
} catch (ex) {
  log("Exception raised at " + ex.moduleName)
  log("Stack: " + ex.moduleStack);
}

This is all you need to know to use the module loader. Have fun!

Subtleties

You shouldn’t mix both styles exports.foo = bar and module.exports = {foo: bar}. If you do, know that any call to module.exports will overwrite all calls to `exports.foo = bar.

You should not modify exports or module.exports once your module initialization is complete.

The module loader supports cyclic calls to require(). However, if you have cyclic requirements, some of the modules involved in the cyclic requirements may become visible by the other modules before they are fully evaluated.

No attempt is made to fully isolate modules from each other. In particular, globals (String, Math, Object, self) and the worker global scope itself (this) are shared between workers. In other words, the true isolation unit is the worker itself, not the module.

Tagged: , , , , , , , , , ,

§ 3 Responses to Chrome Workers, now with modules!

  • George Smitt says:

    Thanks for posting. When will the require.js feature be available to ChromeWorkers, in what official Firefox release is it scheduled to be included?

    Since ChromeWorkers is supposed to give access to js-ctype is it possible to actually load and execute a function from a library/DLL in a ChromeWorker without the ability the load modules? If yes, do you have any sample code or a link to where I can see any? I haven’t found any examples online of someone showing actual working code of a ChromeWorker loading a function using js-ctype from a library/DLL and executing.

    Thanks in advance.

  • yoric says:

    The module loader has landed in Firefox 25 (currently Nightly) and is available to all ChromeWorkers.

    You can definitely use js-ctypes without this module loader – I have been doing it for ~1 year. The source of OS.File is somewhat complex, as it is probably the largest use of js-ctypes at the moment, but you can find it here: http://mxr.mozilla.org/mozilla-central/source/toolkit/components/osfile/

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

What’s this?

You are currently reading Chrome Workers, now with modules! at Il y a du thé renversé au bord de la table.

meta

Follow

Get every new post delivered to your Inbox.

Join 25 other followers

%d bloggers like this: