From b8c37a26efb46819b42d63777ba8f5415979c3d9 Mon Sep 17 00:00:00 2001 From: natecain Date: Fri, 11 Oct 2013 11:32:58 -0400 Subject: [PATCH] Additional improvement to CommonJS Modules support Now implements (and mostly follows) requirements of Modules/1.1 spec implementes only the required "secure sandbox" subset of the spec `module` free variable changed from the `moduleInfo` to an id container `require` free variable given a "main" property boot module scope closed and exported this also changes the interface between boot and bootprefix slightly (should now be able to create multiple TW instances under node) BREAKING CHANGES: The tiddlywiki module itself now exports a single constructor function Modules which depended on `module` referring to `moduleInfo` will break Modules which don't conform to Modules/1.1 will break (by attempting to modify require.main or module.id) --- boot/boot.js | 53 ++++++++++++++++++++++++++++++++++------------ boot/bootprefix.js | 26 +++++++++++++++++------ tiddlywiki.js | 2 +- 3 files changed, 60 insertions(+), 21 deletions(-) diff --git a/boot/boot.js b/boot/boot.js index ac312c39c..5719b0183 100644 --- a/boot/boot.js +++ b/boot/boot.js @@ -20,23 +20,16 @@ The module definitions on the browser look like this: In practice, each module is wrapped in a separate script block. \*/ -(function() { + +var _boot = (function($tw) { /*jslint node: true, browser: true */ /*global modules: false, $tw: false */ "use strict"; -/////////////////////////// Setting up $tw - -// Set up $tw global for the server (set up for browser is in bootprefix.js) -if(typeof(window) === "undefined") { - global.$tw = global.$tw || {}; // No `browser` member for the server - exports.$tw = $tw; // Export $tw for when boot.js is required directly in node.js -} - -// Include bootprefix if we're on the server -if(!$tw.browser) { - require("./bootprefix.js"); +// Include bootprefix if we're not given module data +if(!$tw) { + $tw = require("./bootprefix.js").bootprefix(); } $tw.utils = $tw.utils || {}; @@ -548,7 +541,8 @@ $tw.modules.execute = function(moduleName,moduleRoot) { tiddler = $tw.wiki.getTiddler(name) || $tw.wiki.getTiddler(name + ".js") || $tw.wiki.getTiddler(moduleName) || $tw.wiki.getTiddler(moduleName + ".js") , _exports = {}, sandbox = { - module: moduleInfo, + module: {}, + //moduleInfo: moduleInfo, exports: _exports, console: console, setInterval: setInterval, @@ -560,10 +554,30 @@ $tw.modules.execute = function(moduleName,moduleRoot) { return $tw.modules.execute(title, name); } }; + + Object.defineProperty(sandbox.module, "id", { + value: name, + writable: false, + enumerable: true, + configurable: false + }); + if(!$tw.browser) { $tw.utils.extend(sandbox,{ process: process }); + } else { + /* + CommonJS optional require.main property: + In a browser we offer a fake main module which points back to the boot function + (Theoretically, this may allow TW to eventually load itself as a module in the browser) + */ + Object.defineProperty(sandbox.require, "main", { + value: (typeof(require) !== "undefined") ? require.main : {TiddlyWiki: _boot}, + writable: false, + enumerable: true, + configurable: false + }); } if(!moduleInfo) { // We could not find the module on this path @@ -1417,4 +1431,15 @@ if($tw.browser) { $tw.boot.boot(); } -})(); +return $tw; + +}); + +if(typeof(exports) !== "undefined") { + exports.TiddlyWiki = _boot; +} else { + _boot(window.$tw); +} + + + diff --git a/boot/bootprefix.js b/boot/bootprefix.js index 90e30a80c..7de3309cd 100644 --- a/boot/bootprefix.js +++ b/boot/bootprefix.js @@ -12,12 +12,11 @@ See Boot.js for further details of the boot process. \*/ -// Set up $tw global for the browser -if(typeof(window) === "undefined") { - global.$tw = global.$tw || {}; // No `browser` member for the server -} else { - window.$tw = window.$tw || {browser: {}}; -} +var _bootprefix = (function($tw) { + +"use strict"; + +$tw = $tw || {browser: typeof(window) !== "undefined" ? {} : null}; /* Information about each module is kept in an object with these members: @@ -81,3 +80,18 @@ Convenience function for pushing a tiddler onto the preloading array $tw.preloadTiddler = function(fields) { $tw.preloadTiddlers.push(fields); }; + +return $tw + +}); + +if(typeof(exports) === "undefined") { + // Set up $tw global for the browser + window.$tw = _bootprefix(); +} else { + // Export functionality as a module + exports.bootprefix = _bootprefix; +} + + + diff --git a/tiddlywiki.js b/tiddlywiki.js index 0d8704810..3bbb7f567 100755 --- a/tiddlywiki.js +++ b/tiddlywiki.js @@ -4,7 +4,7 @@ This is invoked as a shell script by NPM when the `tiddlywiki` command is typed */ -var $tw = require("./boot/boot.js").$tw; +var $tw = require("./boot/boot.js").TiddlyWiki(); // Pass the command line arguments to the boot kernel $tw.boot.argv = Array.prototype.slice.call(process.argv,2);