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.

Wednesday, July 14, 2010

GPSEE, Valgrind and MacPorts

Running Valgrind in recent versions of TraceMonkey -- in particular versions since the addition of the conservative stack-scanning garbage collector -- requires special code to quiesce spurious noise from Valgrind.

This special code includes valgrind/valgrind.h, which in turn requires that the MacPorts include directory, /opt/local/include, be included in the path searched by the C precompiler.

Unfortunately, simply tweaking the global CFLAGS or CPPFLAGS on a project-wide basis doesn't work well with GPSEE, as we use the system iconv library. Including the header for GNU iconv, via MacPorts, will cause GPSEE to crash whenever we load a module which uses iconv, such as Binary/B or GFFI.

So, we need to include the MacPorts include directory when building TraceMonkey, but not GPSEE. We also need to pass the --enable-valgrind option to TraceMonkey's autoconf script. Here's how you do it:

# cd gpsee
# ./configure --prefix=/opt/local/gpsee --with-jsapi-build=DEBUG --with-jsapi-options=--enable-valgrind --with-jsapi-cppflags=-I/opt/local/include --with-build=DEBUG

# make build
# sudo make install


Presumably something very similar will also need to be done for users running Leopard+Homebrew or Solaris. Linux users are in the clear because they should not have iconv library/header conflicts.