Monday, December 20, 2010

Wrapped modules with GPSEE 0.2 / GSR 1.0

There has been some discussion on the CommonJS mailing list lately about experimenting with wrapped modules in a move toward a new CommonJS module standard which works better with browser-side environments.

One of these suggestions has been to wrap modules in a module.declare statement, which looks something like this:
module.declare([/* optional dependencies */],
function (require, exports, module) {
/*
* Regular Modules/1.1 module goes here
*/
})
It is possible to retrofit this style of module declaration -- without breaking Modules 1.0 -- into a system based on GSR 1.0 and GPSEE 0.2. (GSR is the script runner which ships with GPSEE)

To add this feature, simply link your gsr binary to another file name -- say, /usr/bin/gsr2 -- and create a preload file (e.g. /usr/bin/.gsr2_preload) containing the following code:
module.constructor.prototype.declare = function(deps, factory) {
if (typeof deps === 'function')
factory = deps;

const ffi = require("gffi");
const JS_GetGlobalObject = new ffi.CFunction(ffi.pointer, "JS_GetGlobalObject", ffi.pointer);
JS_GetGlobalObject.jsapiCall = true;
const gptr = JS_GetGlobalObject(require("vm").cx);
const g = require("vm").objectPtrValue(gptr);

factory(g.require, g.exports, this);
};

With this simple patch, any scripts invoked with #! /usr/bin/gsr2 will be able to use modules written in the current CommonJS Modules/1.1 idiom, or with new the proposed module.declare() syntax.

Of course, when CommonJS blesses a new module format, we will add support for the new format, without breaking your current modules.