diff --git a/UnitTests/Makefile.unittests b/UnitTests/Makefile.unittests index 2e0d6ead29..cb84e3c380 100755 --- a/UnitTests/Makefile.unittests +++ b/UnitTests/Makefile.unittests @@ -80,6 +80,7 @@ SERVER_OPT := \ --javascript.action-directory @top_srcdir@/js/actions/system \ --javascript.gc-interval 1 \ --javascript.modules-path @top_srcdir@/js/server/modules:@top_srcdir@/js/common/modules \ + --javascript.package-path @top_srcdir@/js/common/test-data/modules \ --javascript.startup-directory @top_srcdir@/js \ --ruby.action-directory @top_srcdir@/mr/actions/system \ --ruby.modules-path @top_srcdir@/mr/server/modules:@top_srcdir@/mr/common/modules \ @@ -91,6 +92,7 @@ CLIENT_OPT := \ --configuration none \ --javascript.startup-directory @top_srcdir@/js \ --javascript.modules-path @top_srcdir@/js/client/modules:@top_srcdir@/js/common/modules \ + --javascript.package-path @top_srcdir@/js/common/test-data/modules \ --no-colors \ --quiet @@ -206,7 +208,8 @@ endif ### @brief SHELL SERVER TESTS (BASICS) ################################################################################ -SHELL_COMMON = @top_srcdir@/js/common/tests/shell-document.js \ +SHELL_COMMON = @top_srcdir@/js/common/tests/shell-require.js \ + @top_srcdir@/js/common/tests/shell-document.js \ @top_srcdir@/js/common/tests/shell-edge.js \ @top_srcdir@/js/common/tests/shell-database.js \ @top_srcdir@/js/common/tests/shell-collection.js \ diff --git a/arangod/V8Server/ApplicationV8.cpp b/arangod/V8Server/ApplicationV8.cpp index cde0bb233d..0609d5e292 100644 --- a/arangod/V8Server/ApplicationV8.cpp +++ b/arangod/V8Server/ApplicationV8.cpp @@ -169,6 +169,7 @@ ApplicationV8::ApplicationV8 (string const& binaryPath) : ApplicationFeature("V8"), _startupPath(), _startupModules(), + _startupNodeModules(), _actionPath(), _useActions(true), _performUpgrade(false), @@ -511,6 +512,7 @@ void ApplicationV8::setupOptions (map ("javascript.gc-frequency", &_gcFrequency, "JavaScript time-based garbage collection frequency (each x seconds)") ("javascript.action-directory", &_actionPath, "path to the JavaScript action directory") ("javascript.modules-path", &_startupModules, "one or more directories separated by (semi-) colons") + ("javascript.package-path", &_startupNodeModules, "one or more directories separated by (semi-) colons") ("javascript.startup-directory", &_startupPath, "path to the directory containing alternate JavaScript startup scripts") ("javascript.v8-options", &_v8Options, "options to pass to v8") ; @@ -536,6 +538,10 @@ bool ApplicationV8::prepare () { LOGGER_INFO("using JavaScript modules path '" << _startupModules << "'"); } + if (! _startupNodeModules.empty()) { + LOGGER_INFO("using Node modules path '" << _startupNodeModules << "'"); + } + // set up the startup loader if (_startupPath.empty()) { LOGGER_FATAL_AND_EXIT("no 'javascript.startup-directory' has been supplied, giving up"); @@ -678,7 +684,7 @@ bool ApplicationV8::prepareV8Instance (const size_t i) { } TRI_InitV8Conversions(context->_context); - TRI_InitV8Utils(context->_context, _startupModules); + TRI_InitV8Utils(context->_context, _startupModules, _startupNodeModules); TRI_InitV8Shell(context->_context); // set global flag before loading system files diff --git a/arangod/V8Server/ApplicationV8.h b/arangod/V8Server/ApplicationV8.h index 950872c783..84ff3299a8 100644 --- a/arangod/V8Server/ApplicationV8.h +++ b/arangod/V8Server/ApplicationV8.h @@ -357,6 +357,17 @@ namespace triagens { string _startupModules; +//////////////////////////////////////////////////////////////////////////////// +/// @brief semicolon separated list of module directories +/// +/// @CMDOPT{\--javascript.package-path @CA{directory}} +/// +/// Specifies the @CA{directory} path with user defined Node modules. +/// Multiple paths can be specified separated with commas. +//////////////////////////////////////////////////////////////////////////////// + + string _startupNodeModules; + //////////////////////////////////////////////////////////////////////////////// /// @brief path to the system action directory /// diff --git a/arangosh/V8Client/arangosh.cpp b/arangosh/V8Client/arangosh.cpp index 6e83a5689a..4ac043b8d3 100755 --- a/arangosh/V8Client/arangosh.cpp +++ b/arangosh/V8Client/arangosh.cpp @@ -109,6 +109,12 @@ static JSLoader StartupLoader; static string StartupModules = ""; +//////////////////////////////////////////////////////////////////////////////// +/// @brief path for Node modules files +//////////////////////////////////////////////////////////////////////////////// + +static string StartupNodeModules = ""; + //////////////////////////////////////////////////////////////////////////////// /// @brief path for JavaScript bootstrap files //////////////////////////////////////////////////////////////////////////////// @@ -427,6 +433,7 @@ static void ParseProgramOptions (int argc, char* argv[]) { ("javascript.execute", &ExecuteScripts, "execute Javascript code from file") ("javascript.check", &CheckScripts, "syntax check code Javascript code from file") ("javascript.modules-path", &StartupModules, "one or more directories separated by cola") + ("javascript.package-path", &StartupNodeModules, "one or more directories separated by cola") ("javascript.startup-directory", &StartupPath, "startup paths containing the JavaScript files; multiple directories can be separated by cola") ("javascript.unit-tests", &UnitTests, "do not start as shell, run unit tests instead") ("jslint", &JsLint, "do not start as shell, run jslint instead") @@ -1395,7 +1402,7 @@ int main (int argc, char* argv[]) { v8::FunctionTemplate::New(JS_PagerOutput)->GetFunction(), v8::ReadOnly); - TRI_InitV8Utils(context, StartupModules); + TRI_InitV8Utils(context, StartupModules, StartupNodeModules); TRI_InitV8Shell(context); // reset the prompt error flag (will determine prompt colors) diff --git a/js/common/bootstrap/module-internal.js b/js/common/bootstrap/module-internal.js index e968d06832..69b0d6f521 100644 --- a/js/common/bootstrap/module-internal.js +++ b/js/common/bootstrap/module-internal.js @@ -2,7 +2,7 @@ /*global require, module, Module, FS_MOVE, FS_REMOVE, FS_EXISTS, FS_IS_DIRECTORY, FS_LIST_TREE, SYS_EXECUTE, SYS_LOAD, SYS_LOG, SYS_LOG_LEVEL, SYS_MD5, SYS_OUTPUT, SYS_PROCESS_STAT, SYS_RAND, SYS_READ, SYS_SPRINTF, SYS_TIME, SYS_START_PAGER, SYS_STOP_PAGER, SYS_SHA256, SYS_WAIT, - SYS_GETLINE, SYS_PARSE, SYS_SAVE, SYS_IMPORT_CSV_FILE, SYS_IMPORT_JSON_FILE, + SYS_GETLINE, SYS_PARSE, SYS_SAVE, SYS_IMPORT_CSV_FILE, SYS_IMPORT_JSON_FILE, PACKAGE_PATH, SYS_PROCESS_CSV_FILE, SYS_PROCESS_JSON_FILE, ARANGO_QUIET, MODULES_PATH, COLORS, COLOR_OUTPUT, COLOR_OUTPUT_RESET, COLOR_BRIGHT, COLOR_BLACK, COLOR_BOLD_BLACK, COLOR_BLINK, COLOR_BLUE, COLOR_BOLD_BLUE, COLOR_BOLD_GREEN, COLOR_RED, COLOR_BOLD_RED, COLOR_GREEN, COLOR_WHITE, @@ -203,6 +203,17 @@ delete MODULES_PATH; } +//////////////////////////////////////////////////////////////////////////////// +/// @brief node modules path +//////////////////////////////////////////////////////////////////////////////// + + internal.PACKAGE_PATH = ""; + + if (typeof PACKAGE_PATH !== "undefined") { + internal.PACKAGE_PATH = PACKAGE_PATH; + delete PACKAGE_PATH; + } + //////////////////////////////////////////////////////////////////////////////// /// @brief quiet flag //////////////////////////////////////////////////////////////////////////////// @@ -823,63 +834,6 @@ return target; }; -//////////////////////////////////////////////////////////////////////////////// -/// @brief reads a file from the module path or the database -//////////////////////////////////////////////////////////////////////////////// - - internal.loadDatabaseFile = function (path) { - var i; - var mc; - var n; - - // try to load the file - var paths = internal.MODULES_PATH; - - for (i = 0; i < paths.length; ++i) { - var p = paths[i]; - - if (p === "") { - n = "." + path + ".js"; - } - else { - n = p + "/" + path + ".js"; - } - - if (internal.exists(n)) { - module.ModuleExistsCache[path] = true; - return { path : n, content : internal.read(n) }; - } - } - - // try to load the module from the database - if (internal.db !== undefined) { - mc = internal.db._collection("_modules"); - - if (mc !== null && typeof mc.firstExample === "function") { - n = mc.firstExample({ path: path }); - - if (n !== null) { - if (n.hasOwnProperty('content')) { - module.ModuleExistsCache[path] = true; - return { path : "_collection/" + path, content : n.content }; - } - - if (module.ModuleExistsCache.hasOwnProperty("/console")) { - var console = module.ModuleExistsCache["/console"]; - console.error("found empty content in '%s'", JSON.stringify(n)); - } - } - } - } - - module.ModuleExistsCache[path] = false; - - throw "cannot find a file named '" - + path - + "' using the module path(s) '" - + internal.MODULES_PATH + "'"; - }; - //////////////////////////////////////////////////////////////////////////////// /// @brief loads a file from the file-system //////////////////////////////////////////////////////////////////////////////// @@ -929,7 +883,7 @@ mc = internal.db._create("_modules", { isSystem: true }); } - path = module.normalise(path); + path = module.normalize(path); m = mc.firstExample({ path: path }); if (m === null) { diff --git a/js/common/bootstrap/modules.js b/js/common/bootstrap/modules.js index 7886e46f86..46f6a8855a 100644 --- a/js/common/bootstrap/modules.js +++ b/js/common/bootstrap/modules.js @@ -1,5 +1,5 @@ /*jslint indent: 2, nomen: true, maxlen: 100, sloppy: true, vars: true, white: true, plusplus: true */ -/*global require, module: true */ +/*global require, module: true, PACKAGE_PATH */ //////////////////////////////////////////////////////////////////////////////// /// @brief JavaScript server functions @@ -179,13 +179,71 @@ function stop_color_print () { /// @brief module constructor //////////////////////////////////////////////////////////////////////////////// - function Module (id) { - this.id = id; // commonjs Module/1.1.1 - this.exports = {}; // commonjs Module/1.1.1 + function Module (id, type, pkg) { + this.id = id; // commonjs Module/1.1.1 + this.exports = {}; // commonjs Module/1.1.1 - this._normalized = {}; + this._type = type; // module type: 'system', 'user' + this._origin = 'unknown'; // 'file:///{path}' + // 'database:///_document/{collection}/{key}' + + this._package = pkg; // package to which this module belongs } +//////////////////////////////////////////////////////////////////////////////// +/// @brief package constructor +//////////////////////////////////////////////////////////////////////////////// + + function Package (id, description, parent, paths) { + var i; + + this.id = id; // same of the corresponding module + this._description = description; // the package.json file + this._parent = parent; // parent package + this._moduleCache = {}; // module cache for package modules + + this._paths = paths; // path to the package + } + + var GlobalPackage = new Package("/", {name: "ArangoDB"}, undefined, PACKAGE_PATH); + + Package.prototype.defineSystemModule = function (path) { + var result = this._moduleCache[path] = new Module(path, 'system', GlobalPackage); + + return result; + }; + + Package.prototype.defineModule = function (path, module) { + this._moduleCache[path] = module; + + return module; + }; + + Package.prototype.clearModule = function (path) { + delete this._moduleCache[path]; + }; + + Package.prototype.module = function (path) { + if (this._moduleCache.hasOwnProperty(path)) { + return this._moduleCache[path]; + } + + return null; + }; + + Package.prototype.moduleNames = function () { + var name; + var names = []; + + for (name in this._moduleCache) { + if (this._moduleCache.hasOwnProperty(name)) { + names.push(name); + } + } + + return names; + }; + //////////////////////////////////////////////////////////////////////////////// /// @} //////////////////////////////////////////////////////////////////////////////// @@ -200,28 +258,21 @@ function stop_color_print () { //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// -/// @brief module cache +/// @brief global module cache //////////////////////////////////////////////////////////////////////////////// - var ModuleCache = {}; + var ModuleExistsCache = {}; - ModuleCache["/"] = new Module("/"); - ModuleCache["/internal"] = new Module("/internal"); - ModuleCache["/fs"] = new Module("/fs"); - ModuleCache["/console"] = new Module("/console"); - -//////////////////////////////////////////////////////////////////////////////// -/// @brief file exists cache -//////////////////////////////////////////////////////////////////////////////// - - Module.prototype.ModuleExistsCache = {}; + GlobalPackage.defineSystemModule("/"); + GlobalPackage.defineSystemModule("/internal"); + GlobalPackage.defineSystemModule("/fs"); + GlobalPackage.defineSystemModule("/console"); //////////////////////////////////////////////////////////////////////////////// /// @brief top-level-module //////////////////////////////////////////////////////////////////////////////// - Module.prototype.root = ModuleCache["/"]; - module = Module.prototype.root; + module = Module.prototype.root = GlobalPackage.module("/"); //////////////////////////////////////////////////////////////////////////////// /// @} @@ -236,86 +287,24 @@ function stop_color_print () { /// @{ //////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -/// @brief loads a file and creates a new module descriptor -//////////////////////////////////////////////////////////////////////////////// + var internal = GlobalPackage.module("/internal").exports; + var console = GlobalPackage.module("/console").exports; - Module.prototype.require = function (unormalizedPath) { - var content; - var f; - var internal; - var module; - var path; - var paths; - var raw; - var sandbox; - - internal = ModuleCache["/internal"].exports; - - // check if you already know the module - if (this._normalized.hasOwnProperty(unormalizedPath)) { - return this._normalized[unormalizedPath]; - } - - // first get rid of any ".." and "." - path = this.normalise(unormalizedPath); - - // check if you already know the module, return the exports - if (ModuleCache.hasOwnProperty(path)) { - module = ModuleCache[path]; - this._normalized[unormalizedPath] = module.exports; - return module.exports; - } - - // locate file and read content - raw = internal.loadDatabaseFile(path); - - // test for parse errors first and fail early if a parse error detected - if (! internal.parse(raw.content, path)) { - throw "Javascript parse error in file '" + path + "'"; - } - - // create a new sandbox and execute - module = ModuleCache[path] = new Module(path); - - content = "(function (module, exports, require, print) {" - + raw.content - + "\n});"; - - f = internal.execute(content, undefined, path); - - if (f === undefined) { - throw "cannot create context function"; - } - - try { - f(module, - module.exports, - function(path) { return module.require(path); }, - ModuleCache["/internal"].exports.print); - } - catch (err) { - delete ModuleCache[path]; - throw "Javascript exception in file '" + path + "': " + err + " - " + err.stack; - } - - this._normalized[unormalizedPath] = module.exports; - return module.exports; - }; + internal.GlobalPackage = GlobalPackage; //////////////////////////////////////////////////////////////////////////////// -/// @brief returns true if require found a file +/// @brief normalizes a module name +/// +/// If @FA{path} starts with "." or "..", then it is a relative path. +/// Otherwise it is an absolute path. +/// +/// @FA{prefix} must not end in `/` unless it is equal to `"/"`. +/// +/// The normalized name will start with a `/`, but not end in `/' unless it +/// is equal to `"/"`. //////////////////////////////////////////////////////////////////////////////// - Module.prototype.exists = function (path) { - return this.ModuleExistsCache[path]; - }; - -//////////////////////////////////////////////////////////////////////////////// -/// @brief normalises a path -//////////////////////////////////////////////////////////////////////////////// - - Module.prototype.normalise = function (path) { + internal.normalizeModuleName = function (prefix, path) { var i; var n; var p; @@ -323,14 +312,14 @@ function stop_color_print () { var x; if (path === "") { - return this.id; + return prefix; } p = path.split('/'); // relative path if (p[0] === "." || p[0] === "..") { - q = this.id.split('/'); + q = prefix.split('/'); q.pop(); q = q.concat(p); } @@ -348,7 +337,7 @@ function stop_color_print () { if (x === "..") { if (n.length === 0) { - throw "cannot cross module top"; + throw "cannot use '..' to escape top-level-directory"; } n.pop(); @@ -361,6 +350,376 @@ function stop_color_print () { return "/" + n.join('/'); }; +//////////////////////////////////////////////////////////////////////////////// +/// @brief reads a module package description file +//////////////////////////////////////////////////////////////////////////////// + + internal.loadPackageDescription = function (main, pkg) { + var paths; + var i; + + paths = pkg._paths; + + for (i = 0; i < paths.length; ++i) { + var p = paths[i]; + var n; + var m; + + if (p === "") { + m = "./node_modules" + main; + } + else if (p[p.length - 1] === '/') { + m = p + "node_modules" + main; + } + else { + m = p + "/node_modules" + main; + } + + n = m + "/package.json"; + + if (internal.exists(n)) { + try { + var desc = JSON.parse(internal.read(n)); + var mainfile = m + internal.normalizeModuleName("", desc.main) + ".js"; + + if (internal.exists(mainfile)) { + var content = internal.read(mainfile); + + return { name: main, + description: desc, + packagePath: m, + path: 'file://' + mainfile, + content: content }; + } + } + catch (err) { + if ('error' in console) { + console.error("cannot load package '%s': %s - %s", main, String(err), String(err.stack)); + } + } + } + } + + return null; + }; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief reads a file from the package path +//////////////////////////////////////////////////////////////////////////////// + + internal.loadPackageFile = function (main, pkg) { + var n; + var i; + var mc; + var paths; + + paths = pkg._paths; + + // ----------------------------------------------------------------------------- + // normal modules, file based + // ----------------------------------------------------------------------------- + + // try to load the file + for (i = 0; i < paths.length; ++i) { + var p = paths[i]; + + if (p === "") { + n = "." + main + ".js"; + } + else if (p[p.length - 1] === '/') { + n = p + main.substr(1) + ".js"; + } + else { + n = p + main + ".js"; + } + + if (internal.exists(n)) { + return { name: main, + path: 'file://' + n, + content: internal.read(n) }; + } + } + + return null; + } + +//////////////////////////////////////////////////////////////////////////////// +/// @brief reads a file from the module path or the database +//////////////////////////////////////////////////////////////////////////////// + + internal.loadModuleFile = function (main) { + var n; + var i; + var mc; + var paths; + + paths = internal.MODULES_PATH; + + // ----------------------------------------------------------------------------- + // normal modules, file based + // ----------------------------------------------------------------------------- + + // try to load the file + for (i = 0; i < paths.length; ++i) { + var p = paths[i]; + + if (p === "") { + n = "." + main + ".js"; + } + else if (p[p.length - 1] === '/') { + n = p + main.substr(1) + ".js"; + } + else { + n = p + main + ".js"; + } + + if (internal.exists(n)) { + return { name: main, + path: 'file://' + n, + content: internal.read(n) }; + } + } + + // ----------------------------------------------------------------------------- + // normal modules, database based + // ----------------------------------------------------------------------------- + + if (internal.db !== undefined) { + mc = internal.db._collection("_modules"); + + if (mc !== null && typeof mc.firstExample === "function") { + n = mc.firstExample({ path: main }); + + if (n !== null) { + if (n.hasOwnProperty('content')) { + return { name: main, + path: "database:///_document/" + n._id, + content: n.content }; + } + + if ('error' in console) { + console.error("found empty content in '%s'", JSON.stringify(n)); + } + } + } + } + + return null; + }; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief loads a module +//////////////////////////////////////////////////////////////////////////////// + + Module.prototype.createModule = function (description, type, pkg) { + var content; + var fun; + var module; + + // mark that we have seen the definition, used for debugging only + ModuleExistsCache[description.name] = true; + + // test for parse errors first and fail early if a parse error detected + if (! internal.parse(description.content)) { + throw "Javascript parse error in file '" + description.path + "'"; + } + + // create a new sandbox and execute + module = new Module(description.name, type, pkg); + module._origin = description.path; + + pkg.defineModule(description.name, module); + + // try to execute the module source code + content = "(function (module, exports, require, print) {" + + description.content + + "\n});"; + + fun = internal.execute(content, undefined, description.name); + + if (fun === undefined) { + pkg.clearModule(description.name); + throw "cannot create context function"; + } + + try { + fun(module, + module.exports, + function(path) { return module.require(path); }, + internal.print); + } + catch (err) { + pkg.clearModule(description.name); + throw "Javascript exception in file '" + description.name + "': " + err + " - " + err.stack; + } + + return module; + }; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief loads a package +//////////////////////////////////////////////////////////////////////////////// + + Module.prototype.createPackage = function (parent, description) { + var path; + var module; + var pkg; + + path = description.name; + + pkg = new Package(path, + description.description, + parent, + [description.packagePath]); + + module = this.createModule(description, 'package', pkg); + + if (module !== null) { + parent.defineModule(path, module); + } + + return module; + }; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief requires a package +//////////////////////////////////////////////////////////////////////////////// + + Module.prototype.requirePackage = function (unormalizedPath) { + var current; + var module; + var path; + + // first get rid of any ".." and "." + path = this.normalize(unormalizedPath); + + if (this._package.id === "/" && path === "/internal") { + return null; + } + + // try to locate the package file starting with the current package + current = this._package; + + while (current !== undefined) { + + // check if already know a package with that name + module = current.module(path); + + if (module !== null && module._type === 'package') { + return module; + } + + var description = internal.loadPackageDescription(path, current); + + if (description !== null) { + module = this.createPackage(current, description); + + if (module !== null) { + return module; + } + } + + current = current._parent; + } + + return null; + }; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief requires a module +//////////////////////////////////////////////////////////////////////////////// + + Module.prototype.requireModule = function (unormalizedPath) { + var description; + var module; + var path; + + // first get rid of any ".." and "." + path = this.normalize(unormalizedPath); + + // check if already know a module with that name + module = this._package.module(path); + + if (module) { + if (module.type !== 'package') { + return module; + } + else { + return null; + } + } + + // first check: we are talking about module within a package + description = internal.loadPackageFile(path, this._package); + + if (description !== null) { + module = this.createModule(description, 'module', this._package); + + if (module !== null) { + this._package.defineModule(path, module); + return module; + } + } + + // second check: we are talking about a global module + description = internal.loadModuleFile(path); + + if (description !== null) { + module = this.createModule(description, 'module', GlobalPackage); + + if (module !== null) { + this._package.defineModule(path, module); + return module; + } + } + + return null; + }; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief loads a file and creates a new module descriptor +//////////////////////////////////////////////////////////////////////////////// + + Module.prototype.require = function (unormalizedPath) { + var module; + var path; + + // check if path points to a package or a module in a package + module = this.requirePackage(unormalizedPath); + + if (module !== null) { + return module.exports; + } + + // try to load a global module into the current package + module = this.requireModule(unormalizedPath); + + if (module !== null) { + return module.exports; + } + + throw "cannot locate module '" + unormalizedPath + "'" + + " for package '" + this._package.id + "'" + + " using module path '" + internal.MODULES_PATH + "'" + + " and package path '" + this._package._paths + "'"; + }; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns true if require found a file +//////////////////////////////////////////////////////////////////////////////// + + Module.prototype.exists = function (path) { + return ModuleExistsCache[path]; + }; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief normalizes a path +//////////////////////////////////////////////////////////////////////////////// + + Module.prototype.normalize = function (path) { + return internal.normalizeModuleName(this.id, path); + }; + //////////////////////////////////////////////////////////////////////////////// /// @brief unloads module //////////////////////////////////////////////////////////////////////////////// @@ -370,13 +729,18 @@ function stop_color_print () { return; } - var norm = module.normalise(path); + var norm = module.normalize(path); + var m = GlobalPackage.module(norm); - if ( norm === "/" - || norm === "/console" - || norm === "/fs" - || norm === "/internal" - || norm === "/org/arangodb" + if (m === null) { + return; + } + + if (m._type === 'system') { + return; + } + + if ( norm === "/org/arangodb" || norm === "/org/arangodb/actions" || norm === "/org/arangodb/arango-collection" || norm === "/org/arangodb/arango-database" @@ -386,7 +750,7 @@ function stop_color_print () { return; } - delete ModuleCache[norm]; + GlobalPackage.clearModule(norm); }; //////////////////////////////////////////////////////////////////////////////// @@ -395,18 +759,12 @@ function stop_color_print () { Module.prototype.unloadAll = function () { var i; - var path; - var unload = []; + var names; - for (path in ModuleCache) { - if (ModuleCache.hasOwnProperty(path)) { - unload.push(path); - ModuleCache[path]._normalized = {}; - } - } + names = GlobalPackage.moduleNames(); - for (i = 0; i < unload.length; ++i) { - this.unload(unload[i]); + for (i = 0; i < names.length; ++i) { + this.unload(names[i]); } }; @@ -415,8 +773,35 @@ function stop_color_print () { //////////////////////////////////////////////////////////////////////////////// Module.prototype._PRINT = function () { - var internal = require("internal"); - internal.output('[module "' + this.id + '"]'); + var parent = ""; + + if (this._package._parent !== undefined) { + parent = ', parent package "' + this._package._parent.id + '"'; + } + + internal.output('[module "' + this.id + '"' + + ', type "' + this._type + '"' + + ', package "' + this._package.id + '"' + + parent + + ', origin "' + this._origin + '"' + + ']'); + }; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief prints a package +//////////////////////////////////////////////////////////////////////////////// + + Package.prototype._PRINT = function () { + var parent = ""; + + if (this._parent !== undefined) { + parent = ', parent "' + this._package._parent.id + '"'; + } + + internal.output('[module "' + this.id + '"' + + ', path "' + this._path + '"' + + parent + + ']'); }; //////////////////////////////////////////////////////////////////////////////// diff --git a/js/common/test-data/modules/commonjs/.gitignore b/js/common/test-data/modules/commonjs/.gitignore new file mode 100644 index 0000000000..5dbf9b7977 --- /dev/null +++ b/js/common/test-data/modules/commonjs/.gitignore @@ -0,0 +1,7 @@ +lib +_site +include +bin +src +.Python + diff --git a/js/common/test-data/modules/commonjs/README.txt b/js/common/test-data/modules/commonjs/README.txt new file mode 100644 index 0000000000..dfa3fce78f --- /dev/null +++ b/js/common/test-data/modules/commonjs/README.txt @@ -0,0 +1 @@ +The Official Specs for CommonJS diff --git a/js/common/test-data/modules/commonjs/bootstrap.py b/js/common/test-data/modules/commonjs/bootstrap.py new file mode 100644 index 0000000000..49012e352f --- /dev/null +++ b/js/common/test-data/modules/commonjs/bootstrap.py @@ -0,0 +1,1268 @@ +#!/usr/bin/env python +## WARNING: This file is generated +#!/usr/bin/env python +"""Create a "virtual" Python installation +""" + +import sys +import os +import optparse +import shutil +import logging +import distutils.sysconfig +try: + import subprocess +except ImportError, e: + if sys.version_info <= (2, 3): + print 'ERROR: %s' % e + print 'ERROR: this script requires Python 2.4 or greater; or at least the subprocess module.' + print 'If you copy subprocess.py from a newer version of Python this script will probably work' + sys.exit(101) + else: + raise +try: + set +except NameError: + from sets import Set as set + +join = os.path.join +py_version = 'python%s.%s' % (sys.version_info[0], sys.version_info[1]) +is_jython = sys.platform.startswith('java') +expected_exe = is_jython and 'jython' or 'python' + +REQUIRED_MODULES = ['os', 'posix', 'posixpath', 'ntpath', 'genericpath', + 'fnmatch', 'locale', 'encodings', 'codecs', + 'stat', 'UserDict', 'readline', 'copy_reg', 'types', + 're', 'sre', 'sre_parse', 'sre_constants', 'sre_compile', + 'lib-dynload', 'config', 'zlib'] + +if sys.version_info[:2] == (2, 6): + REQUIRED_MODULES.extend(['warnings', 'linecache', '_abcoll', 'abc']) +if sys.version_info[:2] <= (2, 3): + REQUIRED_MODULES.extend(['sets', '__future__']) + +class Logger(object): + + """ + Logging object for use in command-line script. Allows ranges of + levels, to avoid some redundancy of displayed information. + """ + + DEBUG = logging.DEBUG + INFO = logging.INFO + NOTIFY = (logging.INFO+logging.WARN)/2 + WARN = WARNING = logging.WARN + ERROR = logging.ERROR + FATAL = logging.FATAL + + LEVELS = [DEBUG, INFO, NOTIFY, WARN, ERROR, FATAL] + + def __init__(self, consumers): + self.consumers = consumers + self.indent = 0 + self.in_progress = None + self.in_progress_hanging = False + + def debug(self, msg, *args, **kw): + self.log(self.DEBUG, msg, *args, **kw) + def info(self, msg, *args, **kw): + self.log(self.INFO, msg, *args, **kw) + def notify(self, msg, *args, **kw): + self.log(self.NOTIFY, msg, *args, **kw) + def warn(self, msg, *args, **kw): + self.log(self.WARN, msg, *args, **kw) + def error(self, msg, *args, **kw): + self.log(self.WARN, msg, *args, **kw) + def fatal(self, msg, *args, **kw): + self.log(self.FATAL, msg, *args, **kw) + def log(self, level, msg, *args, **kw): + if args: + if kw: + raise TypeError( + "You may give positional or keyword arguments, not both") + args = args or kw + rendered = None + for consumer_level, consumer in self.consumers: + if self.level_matches(level, consumer_level): + if (self.in_progress_hanging + and consumer in (sys.stdout, sys.stderr)): + self.in_progress_hanging = False + sys.stdout.write('\n') + sys.stdout.flush() + if rendered is None: + if args: + rendered = msg % args + else: + rendered = msg + rendered = ' '*self.indent + rendered + if hasattr(consumer, 'write'): + consumer.write(rendered+'\n') + else: + consumer(rendered) + + def start_progress(self, msg): + assert not self.in_progress, ( + "Tried to start_progress(%r) while in_progress %r" + % (msg, self.in_progress)) + if self.level_matches(self.NOTIFY, self._stdout_level()): + sys.stdout.write(msg) + sys.stdout.flush() + self.in_progress_hanging = True + else: + self.in_progress_hanging = False + self.in_progress = msg + + def end_progress(self, msg='done.'): + assert self.in_progress, ( + "Tried to end_progress without start_progress") + if self.stdout_level_matches(self.NOTIFY): + if not self.in_progress_hanging: + # Some message has been printed out since start_progress + sys.stdout.write('...' + self.in_progress + msg + '\n') + sys.stdout.flush() + else: + sys.stdout.write(msg + '\n') + sys.stdout.flush() + self.in_progress = None + self.in_progress_hanging = False + + def show_progress(self): + """If we are in a progress scope, and no log messages have been + shown, write out another '.'""" + if self.in_progress_hanging: + sys.stdout.write('.') + sys.stdout.flush() + + def stdout_level_matches(self, level): + """Returns true if a message at this level will go to stdout""" + return self.level_matches(level, self._stdout_level()) + + def _stdout_level(self): + """Returns the level that stdout runs at""" + for level, consumer in self.consumers: + if consumer is sys.stdout: + return level + return self.FATAL + + def level_matches(self, level, consumer_level): + """ + >>> l = Logger() + >>> l.level_matches(3, 4) + False + >>> l.level_matches(3, 2) + True + >>> l.level_matches(slice(None, 3), 3) + False + >>> l.level_matches(slice(None, 3), 2) + True + >>> l.level_matches(slice(1, 3), 1) + True + >>> l.level_matches(slice(2, 3), 1) + False + """ + if isinstance(level, slice): + start, stop = level.start, level.stop + if start is not None and start > consumer_level: + return False + if stop is not None or stop <= consumer_level: + return False + return True + else: + return level >= consumer_level + + #@classmethod + def level_for_integer(cls, level): + levels = cls.LEVELS + if level < 0: + return levels[0] + if level >= len(levels): + return levels[-1] + return levels[level] + + level_for_integer = classmethod(level_for_integer) + +def mkdir(path): + if not os.path.exists(path): + logger.info('Creating %s', path) + os.makedirs(path) + else: + logger.info('Directory %s already exists', path) + +def copyfile(src, dest, symlink=True): + if not os.path.exists(src): + # Some bad symlink in the src + logger.warn('Cannot find file %s (bad symlink)', src) + return + if os.path.exists(dest): + logger.debug('File %s already exists', dest) + return + if not os.path.exists(os.path.dirname(dest)): + logger.info('Creating parent directories for %s' % os.path.dirname(dest)) + os.makedirs(os.path.dirname(dest)) + if symlink and hasattr(os, 'symlink'): + logger.info('Symlinking %s', dest) + os.symlink(os.path.abspath(src), dest) + else: + logger.info('Copying to %s', dest) + if os.path.isdir(src): + shutil.copytree(src, dest, True) + else: + shutil.copy2(src, dest) + +def writefile(dest, content, overwrite=True): + if not os.path.exists(dest): + logger.info('Writing %s', dest) + f = open(dest, 'wb') + f.write(content) + f.close() + return + else: + f = open(dest, 'rb') + c = f.read() + f.close() + if c != content: + if not overwrite: + logger.notify('File %s exists with different content; not overwriting', dest) + return + logger.notify('Overwriting %s with new content', dest) + f = open(dest, 'wb') + f.write(content) + f.close() + else: + logger.info('Content %s already in place', dest) + +def rmtree(dir): + if os.path.exists(dir): + logger.notify('Deleting tree %s', dir) + shutil.rmtree(dir) + else: + logger.info('Do not need to delete %s; already gone', dir) + +def make_exe(fn): + if hasattr(os, 'chmod'): + oldmode = os.stat(fn).st_mode & 07777 + newmode = (oldmode | 0555) & 07777 + os.chmod(fn, newmode) + logger.info('Changed mode of %s to %s', fn, oct(newmode)) + +def install_setuptools(py_executable, unzip=False): + setup_fn = 'setuptools-0.6c9-py%s.egg' % sys.version[:3] + search_dirs = ['.', os.path.dirname(__file__), join(os.path.dirname(__file__), 'support-files')] + if os.path.splitext(os.path.dirname(__file__))[0] != 'virtualenv': + # Probably some boot script; just in case virtualenv is installed... + try: + import virtualenv + except ImportError: + pass + else: + search_dirs.append(os.path.join(os.path.dirname(virtualenv.__file__), 'support-files')) + for dir in search_dirs: + if os.path.exists(join(dir, setup_fn)): + setup_fn = join(dir, setup_fn) + break + if is_jython and os._name == 'nt': + # Jython's .bat sys.executable can't handle a command line + # argument with newlines + import tempfile + fd, ez_setup = tempfile.mkstemp('.py') + os.write(fd, EZ_SETUP_PY) + os.close(fd) + cmd = [py_executable, ez_setup] + else: + cmd = [py_executable, '-c', EZ_SETUP_PY] + if unzip: + cmd.append('--always-unzip') + env = {} + if logger.stdout_level_matches(logger.DEBUG): + cmd.append('-v') + if os.path.exists(setup_fn): + logger.info('Using existing Setuptools egg: %s', setup_fn) + cmd.append(setup_fn) + if os.environ.get('PYTHONPATH'): + env['PYTHONPATH'] = setup_fn + os.path.pathsep + os.environ['PYTHONPATH'] + else: + env['PYTHONPATH'] = setup_fn + else: + logger.info('No Setuptools egg found; downloading') + cmd.extend(['--always-copy', '-U', 'setuptools']) + logger.start_progress('Installing setuptools...') + logger.indent += 2 + cwd = None + if not os.access(os.getcwd(), os.W_OK): + cwd = '/tmp' + try: + call_subprocess(cmd, show_stdout=False, + filter_stdout=filter_ez_setup, + extra_env=env, + cwd=cwd) + finally: + logger.indent -= 2 + logger.end_progress() + if is_jython and os._name == 'nt': + os.remove(ez_setup) + +def filter_ez_setup(line): + if not line.strip(): + return Logger.DEBUG + for prefix in ['Reading ', 'Best match', 'Processing setuptools', + 'Copying setuptools', 'Adding setuptools', + 'Installing ', 'Installed ']: + if line.startswith(prefix): + return Logger.DEBUG + return Logger.INFO + +def main(): + parser = optparse.OptionParser( + version="1.3.4dev", + usage="%prog [OPTIONS] DEST_DIR") + + parser.add_option( + '-v', '--verbose', + action='count', + dest='verbose', + default=0, + help="Increase verbosity") + + parser.add_option( + '-q', '--quiet', + action='count', + dest='quiet', + default=0, + help='Decrease verbosity') + + parser.add_option( + '-p', '--python', + dest='python', + metavar='PYTHON_EXE', + help='The Python interpreter to use, e.g., --python=python2.5 will use the python2.5 ' + 'interpreter to create the new environment. The default is the interpreter that ' + 'virtualenv was installed with (%s)' % sys.executable) + + parser.add_option( + '--clear', + dest='clear', + action='store_true', + help="Clear out the non-root install and start from scratch") + + parser.add_option( + '--no-site-packages', + dest='no_site_packages', + action='store_true', + help="Don't give access to the global site-packages dir to the " + "virtual environment") + + parser.add_option( + '--unzip-setuptools', + dest='unzip_setuptools', + action='store_true', + help="Unzip Setuptools when installing it") + + parser.add_option( + '--relocatable', + dest='relocatable', + action='store_true', + help='Make an EXISTING virtualenv environment relocatable. ' + 'This fixes up scripts and makes all .pth files relative') + + if 'extend_parser' in globals(): + extend_parser(parser) + + options, args = parser.parse_args() + + global logger + + if 'adjust_options' in globals(): + adjust_options(options, args) + + verbosity = options.verbose - options.quiet + logger = Logger([(Logger.level_for_integer(2-verbosity), sys.stdout)]) + + if options.python and not os.environ.get('VIRTUALENV_INTERPRETER_RUNNING'): + env = os.environ.copy() + interpreter = resolve_interpreter(options.python) + if interpreter == sys.executable: + logger.warn('Already using interpreter %s' % interpreter) + else: + logger.notify('Running virtualenv with interpreter %s' % interpreter) + env['VIRTUALENV_INTERPRETER_RUNNING'] = 'true' + file = __file__ + if file.endswith('.pyc'): + file = file[:-1] + os.execvpe(interpreter, [interpreter, file] + sys.argv[1:], env) + + if not args: + print 'You must provide a DEST_DIR' + parser.print_help() + sys.exit(2) + if len(args) > 1: + print 'There must be only one argument: DEST_DIR (you gave %s)' % ( + ' '.join(args)) + parser.print_help() + sys.exit(2) + + home_dir = args[0] + + if os.environ.get('WORKING_ENV'): + logger.fatal('ERROR: you cannot run virtualenv while in a workingenv') + logger.fatal('Please deactivate your workingenv, then re-run this script') + sys.exit(3) + + if os.environ.get('PYTHONHOME'): + if sys.platform == 'win32': + name = '%PYTHONHOME%' + else: + name = '$PYTHONHOME' + logger.warn('%s is set; this can cause problems creating environments' % name) + + if options.relocatable: + make_environment_relocatable(home_dir) + return + + create_environment(home_dir, site_packages=not options.no_site_packages, clear=options.clear, + unzip_setuptools=options.unzip_setuptools) + if 'after_install' in globals(): + after_install(options, home_dir) + +def call_subprocess(cmd, show_stdout=True, + filter_stdout=None, cwd=None, + raise_on_returncode=True, extra_env=None): + cmd_parts = [] + for part in cmd: + if len(part) > 40: + part = part[:30]+"..."+part[-5:] + if ' ' in part or '\n' in part or '"' in part or "'" in part: + part = '"%s"' % part.replace('"', '\\"') + cmd_parts.append(part) + cmd_desc = ' '.join(cmd_parts) + if show_stdout: + stdout = None + else: + stdout = subprocess.PIPE + logger.debug("Running command %s" % cmd_desc) + if extra_env: + env = os.environ.copy() + env.update(extra_env) + else: + env = None + try: + proc = subprocess.Popen( + cmd, stderr=subprocess.STDOUT, stdin=None, stdout=stdout, + cwd=cwd, env=env) + except Exception, e: + logger.fatal( + "Error %s while executing command %s" % (e, cmd_desc)) + raise + all_output = [] + if stdout is not None: + stdout = proc.stdout + while 1: + line = stdout.readline() + if not line: + break + line = line.rstrip() + all_output.append(line) + if filter_stdout: + level = filter_stdout(line) + if isinstance(level, tuple): + level, line = level + logger.log(level, line) + if not logger.stdout_level_matches(level): + logger.show_progress() + else: + logger.info(line) + else: + proc.communicate() + proc.wait() + if proc.returncode: + if raise_on_returncode: + if all_output: + logger.notify('Complete output from command %s:' % cmd_desc) + logger.notify('\n'.join(all_output) + '\n----------------------------------------') + raise OSError( + "Command %s failed with error code %s" + % (cmd_desc, proc.returncode)) + else: + logger.warn( + "Command %s had error code %s" + % (cmd_desc, proc.returncode)) + + +def create_environment(home_dir, site_packages=True, clear=False, + unzip_setuptools=False): + """ + Creates a new environment in ``home_dir``. + + If ``site_packages`` is true (the default) then the global + ``site-packages/`` directory will be on the path. + + If ``clear`` is true (default False) then the environment will + first be cleared. + """ + home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir) + + py_executable = install_python( + home_dir, lib_dir, inc_dir, bin_dir, + site_packages=site_packages, clear=clear) + + install_distutils(lib_dir, home_dir) + + install_setuptools(py_executable, unzip=unzip_setuptools) + + install_activate(home_dir, bin_dir) + +def path_locations(home_dir): + """Return the path locations for the environment (where libraries are, + where scripts go, etc)""" + # XXX: We'd use distutils.sysconfig.get_python_inc/lib but its + # prefix arg is broken: http://bugs.python.org/issue3386 + if sys.platform == 'win32': + # Windows has lots of problems with executables with spaces in + # the name; this function will remove them (using the ~1 + # format): + mkdir(home_dir) + if ' ' in home_dir: + try: + import win32api + except ImportError: + print 'Error: the path "%s" has a space in it' % home_dir + print 'To handle these kinds of paths, the win32api module must be installed:' + print ' http://sourceforge.net/projects/pywin32/' + sys.exit(3) + home_dir = win32api.GetShortPathName(home_dir) + lib_dir = join(home_dir, 'Lib') + inc_dir = join(home_dir, 'Include') + bin_dir = join(home_dir, 'Scripts') + elif is_jython: + lib_dir = join(home_dir, 'Lib') + inc_dir = join(home_dir, 'Include') + bin_dir = join(home_dir, 'bin') + else: + lib_dir = join(home_dir, 'lib', py_version) + inc_dir = join(home_dir, 'include', py_version) + bin_dir = join(home_dir, 'bin') + return home_dir, lib_dir, inc_dir, bin_dir + +def install_python(home_dir, lib_dir, inc_dir, bin_dir, site_packages, clear): + """Install just the base environment, no distutils patches etc""" + if sys.executable.startswith(bin_dir): + print 'Please use the *system* python to run this script' + return + + if clear: + rmtree(lib_dir) + ## FIXME: why not delete it? + ## Maybe it should delete everything with #!/path/to/venv/python in it + logger.notify('Not deleting %s', bin_dir) + + if hasattr(sys, 'real_prefix'): + logger.notify('Using real prefix %r' % sys.real_prefix) + prefix = sys.real_prefix + else: + prefix = sys.prefix + mkdir(lib_dir) + fix_lib64(lib_dir) + stdlib_dirs = [os.path.dirname(os.__file__)] + if sys.platform == 'win32': + stdlib_dirs.append(join(os.path.dirname(stdlib_dirs[0]), 'DLLs')) + elif sys.platform == 'darwin': + stdlib_dirs.append(join(stdlib_dirs[0], 'site-packages')) + for stdlib_dir in stdlib_dirs: + if not os.path.isdir(stdlib_dir): + continue + if hasattr(os, 'symlink'): + logger.info('Symlinking Python bootstrap modules') + else: + logger.info('Copying Python bootstrap modules') + logger.indent += 2 + try: + for fn in os.listdir(stdlib_dir): + if fn != 'site-packages' and os.path.splitext(fn)[0] in REQUIRED_MODULES: + copyfile(join(stdlib_dir, fn), join(lib_dir, fn)) + finally: + logger.indent -= 2 + mkdir(join(lib_dir, 'site-packages')) + writefile(join(lib_dir, 'site.py'), SITE_PY) + writefile(join(lib_dir, 'orig-prefix.txt'), prefix) + site_packages_filename = join(lib_dir, 'no-global-site-packages.txt') + if not site_packages: + writefile(site_packages_filename, '') + else: + if os.path.exists(site_packages_filename): + logger.info('Deleting %s' % site_packages_filename) + os.unlink(site_packages_filename) + + stdinc_dir = join(prefix, 'include', py_version) + if os.path.exists(stdinc_dir): + copyfile(stdinc_dir, inc_dir) + else: + logger.debug('No include dir %s' % stdinc_dir) + + if sys.exec_prefix != prefix: + if sys.platform == 'win32': + exec_dir = join(sys.exec_prefix, 'lib') + elif is_jython: + exec_dir = join(sys.exec_prefix, 'Lib') + else: + exec_dir = join(sys.exec_prefix, 'lib', py_version) + for fn in os.listdir(exec_dir): + copyfile(join(exec_dir, fn), join(lib_dir, fn)) + + if is_jython: + # Jython has either jython-dev.jar and javalib/ dir, or just + # jython.jar + for name in 'jython-dev.jar', 'javalib', 'jython.jar': + src = join(prefix, name) + if os.path.exists(src): + copyfile(src, join(home_dir, name)) + # XXX: registry should always exist after Jython 2.5rc1 + src = join(prefix, 'registry') + if os.path.exists(src): + copyfile(src, join(home_dir, 'registry'), symlink=False) + copyfile(join(prefix, 'cachedir'), join(home_dir, 'cachedir'), + symlink=False) + + mkdir(bin_dir) + py_executable = join(bin_dir, os.path.basename(sys.executable)) + if 'Python.framework' in prefix: + if py_executable.endswith('/Python'): + # The name of the python executable is not quite what + # we want, rename it. + py_executable = os.path.join( + os.path.dirname(py_executable), 'python') + + logger.notify('New %s executable in %s', expected_exe, py_executable) + if sys.executable != py_executable: + ## FIXME: could I just hard link? + executable = sys.executable + if sys.platform == 'cygwin' and os.path.exists(executable + '.exe'): + # Cygwin misreports sys.executable sometimes + executable += '.exe' + py_executable += '.exe' + logger.info('Executable actually exists in %s' % executable) + shutil.copyfile(executable, py_executable) + make_exe(py_executable) + if sys.platform == 'win32' or sys.platform == 'cygwin': + pythonw = os.path.join(os.path.dirname(sys.executable, 'pythonw.exe')) + if os.path.exists(pythonw): + logger.info('Also created pythonw.exe') + shutil.copyfile(pythonw, os.path.join(os.path.dirname(py_executable, 'pythonw.exe'))) + + if os.path.splitext(os.path.basename(py_executable))[0] != expected_exe: + secondary_exe = os.path.join(os.path.dirname(py_executable), + expected_exe) + py_executable_ext = os.path.splitext(py_executable)[1] + if py_executable_ext == '.exe': + # python2.4 gives an extension of '.4' :P + secondary_exe += py_executable_ext + if os.path.exists(secondary_exe): + logger.warn('Not overwriting existing %s script %s (you must use %s)' + % (expected_exe, secondary_exe, py_executable)) + else: + logger.notify('Also creating executable in %s' % secondary_exe) + shutil.copyfile(sys.executable, secondary_exe) + make_exe(secondary_exe) + + if 'Python.framework' in prefix: + logger.debug('MacOSX Python framework detected') + + # Copy the framework's dylib into the virtual + # environment + virtual_lib = os.path.join(home_dir, '.Python') + + if os.path.exists(virtual_lib): + os.unlink(virtual_lib) + copyfile( + os.path.join(prefix, 'Python'), + virtual_lib) + + # And then change the install_name of the copied python executable + try: + call_subprocess( + ["install_name_tool", "-change", + os.path.join(prefix, 'Python'), + '@executable_path/../.Python', + py_executable]) + except: + logger.fatal( + "Could not call install_name_tool -- you must have Apple's development tools installed") + raise + + # Some tools depend on pythonX.Y being present + pth = py_executable + '%s.%s' % ( + sys.version_info[0], sys.version_info[1]) + if os.path.exists(pth): + os.unlink(pth) + os.symlink('python', pth) + + if sys.platform == 'win32' and ' ' in py_executable: + # There's a bug with subprocess on Windows when using a first + # argument that has a space in it. Instead we have to quote + # the value: + py_executable = '"%s"' % py_executable + cmd = [py_executable, '-c', 'import sys; print sys.prefix'] + logger.info('Testing executable with %s %s "%s"' % tuple(cmd)) + proc = subprocess.Popen(cmd, + stdout=subprocess.PIPE) + proc_stdout, proc_stderr = proc.communicate() + proc_stdout = os.path.normcase(os.path.abspath(proc_stdout.strip())) + if proc_stdout != os.path.normcase(os.path.abspath(home_dir)): + logger.fatal( + 'ERROR: The executable %s is not functioning' % py_executable) + logger.fatal( + 'ERROR: It thinks sys.prefix is %r (should be %r)' + % (proc_stdout, os.path.normcase(os.path.abspath(home_dir)))) + logger.fatal( + 'ERROR: virtualenv is not compatible with this system or executable') + sys.exit(100) + else: + logger.info('Got sys.prefix result: %r' % proc_stdout) + + pydistutils = os.path.expanduser('~/.pydistutils.cfg') + if os.path.exists(pydistutils): + logger.notify('Please make sure you remove any previous custom paths from ' + 'your %s file.' % pydistutils) + ## FIXME: really this should be calculated earlier + return py_executable + +def install_activate(home_dir, bin_dir): + if sys.platform == 'win32' or is_jython and os._name == 'nt': + files = {'activate.bat': ACTIVATE_BAT, + 'deactivate.bat': DEACTIVATE_BAT} + if os.environ.get('OS') == 'Windows_NT' and os.environ.get('OSTYPE') == 'cygwin': + files['activate'] = ACTIVATE_SH + else: + files = {'activate': ACTIVATE_SH} + files['activate_this.py'] = ACTIVATE_THIS + for name, content in files.items(): + content = content.replace('__VIRTUAL_ENV__', os.path.abspath(home_dir)) + content = content.replace('__VIRTUAL_NAME__', os.path.basename(os.path.abspath(home_dir))) + content = content.replace('__BIN_NAME__', os.path.basename(bin_dir)) + writefile(os.path.join(bin_dir, name), content) + +def install_distutils(lib_dir, home_dir): + distutils_path = os.path.join(lib_dir, 'distutils') + mkdir(distutils_path) + ## FIXME: maybe this prefix setting should only be put in place if + ## there's a local distutils.cfg with a prefix setting? + home_dir = os.path.abspath(home_dir) + ## FIXME: this is breaking things, removing for now: + #distutils_cfg = DISTUTILS_CFG + "\n[install]\nprefix=%s\n" % home_dir + writefile(os.path.join(distutils_path, '__init__.py'), DISTUTILS_INIT) + writefile(os.path.join(distutils_path, 'distutils.cfg'), DISTUTILS_CFG, overwrite=False) + +def fix_lib64(lib_dir): + """ + Some platforms (particularly Gentoo on x64) put things in lib64/pythonX.Y + instead of lib/pythonX.Y. If this is such a platform we'll just create a + symlink so lib64 points to lib + """ + if [p for p in distutils.sysconfig.get_config_vars().values() + if isinstance(p, basestring) and 'lib64' in p]: + logger.debug('This system uses lib64; symlinking lib64 to lib') + assert os.path.basename(lib_dir) == 'python%s' % sys.version[:3], ( + "Unexpected python lib dir: %r" % lib_dir) + lib_parent = os.path.dirname(lib_dir) + assert os.path.basename(lib_parent) == 'lib', ( + "Unexpected parent dir: %r" % lib_parent) + copyfile(lib_parent, os.path.join(os.path.dirname(lib_parent), 'lib64')) + +def resolve_interpreter(exe): + """ + If the executable given isn't an absolute path, search $PATH for the interpreter + """ + if os.path.abspath(exe) != exe: + paths = os.environ.get('PATH', '').split(os.pathsep) + for path in paths: + if os.path.exists(os.path.join(path, exe)): + exe = os.path.join(path, exe) + break + if not os.path.exists(exe): + logger.fatal('The executable %s (from --python=%s) does not exist' % (exe, exe)) + sys.exit(3) + return exe + +############################################################ +## Relocating the environment: + +def make_environment_relocatable(home_dir): + """ + Makes the already-existing environment use relative paths, and takes out + the #!-based environment selection in scripts. + """ + activate_this = os.path.join(home_dir, 'bin', 'activate_this.py') + if not os.path.exists(activate_this): + logger.fatal( + 'The environment doesn\'t have a file %s -- please re-run virtualenv ' + 'on this environment to update it' % activate_this) + fixup_scripts(home_dir) + fixup_pth_and_egg_link(home_dir) + ## FIXME: need to fix up distutils.cfg + +OK_ABS_SCRIPTS = ['python', 'python%s' % sys.version[:3], + 'activate', 'activate.bat', 'activate_this.py'] + +def fixup_scripts(home_dir): + # This is what we expect at the top of scripts: + shebang = '#!%s/bin/python' % os.path.normcase(os.path.abspath(home_dir)) + # This is what we'll put: + new_shebang = '#!/usr/bin/env python%s' % sys.version[:3] + activate = "import os; activate_this=os.path.join(os.path.dirname(__file__), 'activate_this.py'); execfile(activate_this, dict(__file__=activate_this)); del os, activate_this" + bin_dir = os.path.join(home_dir, 'bin') + for filename in os.listdir(bin_dir): + filename = os.path.join(bin_dir, filename) + f = open(filename, 'rb') + lines = f.readlines() + f.close() + if not lines: + logger.warn('Script %s is an empty file' % filename) + continue + if lines[0].strip() != shebang: + if os.path.basename(filename) in OK_ABS_SCRIPTS: + logger.debug('Cannot make script %s relative' % filename) + elif lines[0].strip() == new_shebang: + logger.info('Script %s has already been made relative' % filename) + else: + logger.warn('Script %s cannot be made relative (it\'s not a normal script that starts with %s)' + % (filename, shebang)) + continue + logger.notify('Making script %s relative' % filename) + lines = [new_shebang+'\n', activate+'\n'] + lines[1:] + f = open(filename, 'wb') + f.writelines(lines) + f.close() + +def fixup_pth_and_egg_link(home_dir): + """Makes .pth and .egg-link files use relative paths""" + home_dir = os.path.normcase(os.path.abspath(home_dir)) + for path in sys.path: + if not path: + path = '.' + if not os.path.isdir(path): + continue + path = os.path.normcase(os.path.abspath(path)) + if not path.startswith(home_dir): + logger.debug('Skipping system (non-environment) directory %s' % path) + continue + for filename in os.listdir(path): + filename = os.path.join(path, filename) + if filename.endswith('.pth'): + if not os.access(filename, os.W_OK): + logger.warn('Cannot write .pth file %s, skipping' % filename) + else: + fixup_pth_file(filename) + if filename.endswith('.egg-link'): + if not os.access(filename, os.W_OK): + logger.warn('Cannot write .egg-link file %s, skipping' % filename) + else: + fixup_egg_link(filename) + +def fixup_pth_file(filename): + lines = [] + prev_lines = [] + f = open(filename) + prev_lines = f.readlines() + f.close() + for line in prev_lines: + line = line.strip() + if (not line or line.startswith('#') or line.startswith('import ') + or os.path.abspath(line) != line): + lines.append(line) + else: + new_value = make_relative_path(filename, line) + if line != new_value: + logger.debug('Rewriting path %s as %s (in %s)' % (line, new_value, filename)) + lines.append(new_value) + if lines == prev_lines: + logger.info('No changes to .pth file %s' % filename) + return + logger.notify('Making paths in .pth file %s relative' % filename) + f = open(filename, 'w') + f.write('\n'.join(lines) + '\n') + f.close() + +def fixup_egg_link(filename): + f = open(filename) + link = f.read().strip() + f.close() + if os.path.abspath(link) != link: + logger.debug('Link in %s already relative' % filename) + return + new_link = make_relative_path(filename, link) + logger.notify('Rewriting link %s in %s as %s' % (link, filename, new_link)) + f = open(filename, 'w') + f.write(new_link) + f.close() + +def make_relative_path(source, dest, dest_is_directory=True): + """ + Make a filename relative, where the filename is dest, and it is + being referred to from the filename source. + + >>> make_relative_path('/usr/share/something/a-file.pth', + ... '/usr/share/another-place/src/Directory') + '../another-place/src/Directory' + >>> make_relative_path('/usr/share/something/a-file.pth', + ... '/home/user/src/Directory') + '../../../home/user/src/Directory' + >>> make_relative_path('/usr/share/a-file.pth', '/usr/share/') + './' + """ + source = os.path.dirname(source) + if not dest_is_directory: + dest_filename = os.path.basename(dest) + dest = os.path.dirname(dest) + dest = os.path.normpath(os.path.abspath(dest)) + source = os.path.normpath(os.path.abspath(source)) + dest_parts = dest.strip(os.path.sep).split(os.path.sep) + source_parts = source.strip(os.path.sep).split(os.path.sep) + while dest_parts and source_parts and dest_parts[0] == source_parts[0]: + dest_parts.pop(0) + source_parts.pop(0) + full_parts = ['..']*len(source_parts) + dest_parts + if not dest_is_directory: + full_parts.append(dest_filename) + if not full_parts: + # Special case for the current directory (otherwise it'd be '') + return './' + return os.path.sep.join(full_parts) + + + +############################################################ +## Bootstrap script creation: + +def create_bootstrap_script(extra_text, python_version=''): + """ + Creates a bootstrap script, which is like this script but with + extend_parser, adjust_options, and after_install hooks. + + This returns a string that (written to disk of course) can be used + as a bootstrap script with your own customizations. The script + will be the standard virtualenv.py script, with your extra text + added (your extra text should be Python code). + + If you include these functions, they will be called: + + ``extend_parser(optparse_parser)``: + You can add or remove options from the parser here. + + ``adjust_options(options, args)``: + You can change options here, or change the args (if you accept + different kinds of arguments, be sure you modify ``args`` so it is + only ``[DEST_DIR]``). + + ``after_install(options, home_dir)``: + + After everything is installed, this function is called. This + is probably the function you are most likely to use. An + example would be:: + + def after_install(options, home_dir): + subprocess.call([join(home_dir, 'bin', 'easy_install'), + 'MyPackage']) + subprocess.call([join(home_dir, 'bin', 'my-package-script'), + 'setup', home_dir]) + + This example immediately installs a package, and runs a setup + script from that package. + + If you provide something like ``python_version='2.4'`` then the + script will start with ``#!/usr/bin/env python2.4`` instead of + ``#!/usr/bin/env python``. You can use this when the script must + be run with a particular Python version. + """ + filename = __file__ + if filename.endswith('.pyc'): + filename = filename[:-1] + f = open(filename, 'rb') + content = f.read() + f.close() + py_exe = 'python%s' % python_version + content = (('#!/usr/bin/env %s\n' % py_exe) + + '## WARNING: This file is generated\n' + + content) + return content.replace('##EXT' 'END##', extra_text) + +def adjust_options(options, args): + args[:] = ['.'] + +def after_install(options, home_dir): + if sys.platform == 'win32': + bin_dir = join(home_dir, 'Scripts') + else: + bin_dir = join(home_dir, 'bin') + subprocess.call([join(bin_dir, 'easy_install'), 'paver==1.0.1']) + subprocess.call([join(bin_dir, 'easy_install'), 'pip']) + subprocess.call([join(bin_dir, 'paver'),'initial']) + +##file site.py +SITE_PY = """ +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 ++D/cC/Pm +""".decode("base64").decode("zlib") + +##file ez_setup.py +EZ_SETUP_PY = """ +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 +woheJi7S138BSGV4QQ== +""".decode("base64").decode("zlib") + +##file activate.sh +ACTIVATE_SH = """ +eJytU99P2zAQfvdfcaQ8ABqN+srUh6IhUYmViXSdNECum1waS6ld2U6zgva/75ykNP0xpGnkIYl9 +n8/fffddB8aZtJDKHGFRWAczhMJiAqV0GQRWFyZGmEkVitjJlXAYwEVq9AJmwmYXrANrXUAslNIO +TKFAOkikwdjla8YS3JyCs3N4ZUCPTOERLhUEp/z+7gufDB/G3wd3/NtgfBvAM3wGl6GqkP7x2/1j +0DcE/lpq4yrg216hLDo4OFTFU8mqb6eu3Ga6yBNI0BHnqigQKoEXm32CMpNxBplYIQj6UCjWi4UP +u0y4Sq8mFakWizwn3ZyGOd1NMtBfqo1fLAUJ2xy1XYAfpK0uXBN2Us2bNDtALwScet4QZ0LN0UJJ +TRKJf63BC07XGrRLYo7JnrjXg4j0vNT16md0yyc3D9HwfnRE5Kq0S7Mjz9/aFPWOdSnqHTSJgAc9 +inrvtqgJbyjUkE30ZjTZEjshXkSkD4HSKkHrTOGNhnvcOhBhnsIGcLJ3+9aem3t/M3J0HZTGYE6t +Vw5Wwkgxy9G2Db17MWMtnv2A89aS84A1CrSLYQf+JA1rbzeLFjrk/Ho44qPB1xvOrxpY2/psX0qf +zPeg0iuYkrNRiQXC007ep2BayUgc96XzvpIiJ2Nb9FaFAe0o8t5cxs2MayNJlAaOCJlzy6swLMuy ++4KOnLrqkptDq1NXCoOh8BlC9maZxxatKaU8SvBpOn2GuhbMLW5Pn71T1Hl9gFra8h77oJn/gHn/ +z1n/9znfzDgp8gduuMqz +""".decode("base64").decode("zlib") + +##file activate.bat +ACTIVATE_BAT = """ +eJx9kMsOgjAQRfdN+g+zoAn8goZEDESJPBpEViSzkFbZ0IX8f+RRaVW0u5mee3PanbjeFSgpKXmI +Hqq4KC9BglFW+YjWhEgJJa2ETvXQCNl2ogFe5CkvwaUEhjPm543vcOdAiacjLxzzJFw6f2bZCsZ0 +2YitXPtswawi1zwgC9II0QPD/RELyuOb1jB/Sg0rNhM31Ss4n2I+7ibLb8epQGco2Rja1Fs/zeoa +cR9nWnprJaMspOQJdBR1/g== +""".decode("base64").decode("zlib") + +##file deactivate.bat +DEACTIVATE_BAT = """ +eJxzSE3OyFfIT0vj4spMU0hJTcvMS01RiPf3cYkP8wwKCXX0iQ8I8vcNCFHQ4FIAguLUEgWIgK0q +FlWqXJpcICVYpGzx2OAY4oFsPpCLbjpQCLvZILVcXFaufi5cACHzOrI= +""".decode("base64").decode("zlib") + +##file distutils-init.py +DISTUTILS_INIT = """ +eJytVl2r4zYQfdevGBKKbcia0r5dCPvQD7jQlkILLZRF6NpyrK4jGUm+SfrrO2M5tmQnbR9qSJCl +o9HMmZljqXNvrAfjmAojd5uHF2G10icH94lvjG7U6WdhnbSwT1+VA208CHhX1g+ik/odzqYeOnkA +Z+AioRIaBidBefAGGqVr8K0E5+tOvTFWK6vFWcIRnSl74dtymqEl5wevOsdpPkL8aZTOV/A8dqvk +vFGd5Lw4QDabyQqmmtmINvZMgzw9poDjxpV8s2e2X7wwwOfOWUmDfJyiZ/crRhoxMx8Fvag+i5ME +4eELB6LvJTpOBL0hUzowRLR0phJeGQ3Chcmb8/K8GPq4K5jsnAxu8DEEzkulkQWff3mAVXQjTF5l +BaaXC4kjoykUmeNcaeXRXH/LiqK0UtR5we5lQfCofKqRf8bYfo/R+aqFt0F1NZdXD4tpqI10OvPw +WZsLtPjDmE/Sj8FhQSBAWVl5Y2+ToRYw+guWjbk4+EBl1ApbV6aWgRGCIIPWDFNljYfLmnwqeysb +dSWfm/DeCd9gEinJGRr9+qssMNdYE7FaVuZ8FroulxCmQJcJTIjB4Twxmqk64dwCyhPEVCv01LKh +VhCd+kty01OGHeROdk0Eoof8xtkSqbHC3jiy46jpfjJapkh6ttAj/PEpgbF/xEeFk5QGcYfp73gg +9AC7HzBXu6JIzCXRluv4QnhbZx5T/5Dw+YUHjQkG1rNR1o7L4liYyzE0mkrFvTBGrpM28VDGY3sT +ewQrv8U/q94GCqPcoNiUzHQ2TmYz1uYRHh4S0RKamy/NspK8TYNGrDWnLBjZRxonrwhw+dru5NZ+ +9i1K+wY7J2wPv7ViFPFKdF1oNWk/DPQZCAEBBcSmskUfgrBjp/XGqWu21CvtGaOfpH+HCpPEsgs6 +NQvbw00P96xRmzK+V3ACLCKvR7hytJSnoMUX1BBUIhRi1OoOnchHGre9S5hS6tpdFH41spXHWbFt +4ZAPK8/mXea0vWDpEn0rdJ0/cN9KP1gdYOw/FC6ysy3mtEtmXV+1Cio272++NRo/ERUamoFlujQ2 +x7y42peTHHPXy0o1qjpi9YXkHEndJm6QxDC5Vb1pfjw8VqeYjK2z6aH3Iwv2zEm8S9Sm4nzq38eL +7Fn8MTWrvRsmUYifMUlXpadM4uKWSedRRPFDSatPmY1BQKL7P1K98Sr16V+IR8Rz4qPFx8SvmFzt +pRr//vX3H797gV9aM3Q1vE43ltTYtPmdbmYfqS/C80o3ELxx4N0Mb9BE4tA0B7z1uvH10iq0dL/m +OIkiEa512LF1yf4GZEHtwg== +""".decode("base64").decode("zlib") + +##file distutils.cfg +DISTUTILS_CFG = """ +eJxNj00KwkAMhfc9xYNuxe4Ft57AjYiUtDO1wXSmNJnK3N5pdSEEAu8nH6lxHVlRhtDHMPATA4uH +xJ4EFmGbvfJiicSHFRzUSISMY6hq3GLCRLnIvSTnEefN0FIjw5tF0Hkk9Q5dRunBsVoyFi24aaLg +9FDOlL0FPGluf4QjcInLlxd6f6rqkgPu/5nHLg0cXCscXoozRrP51DRT3j9QNl99AP53T2Q= +""".decode("base64").decode("zlib") + +##file activate_this.py +ACTIVATE_THIS = """ +eJx1UsGOnDAMvecrIlYriDRlKvU20h5aaY+teuilGo1QALO4CwlKAjP8fe1QGGalRoLEefbzs+Mk +Sb7NcvRo3iTcoGqwgyy06As+HWSNVciKaBTFywYoJWc7yit2ndBVwEkHkIzKCV0YdQdmkvShs6YH +E3IhfjFaaSNLoHxQy2sLJrL0ow98JQmEG/rAYn7OobVGogngBgf0P0hjgwgt7HOUaI5DdBVJkggR +3HwSktaqWcCtgiHIH7qHV+esW2CnkRJ+9R5cQGsikkWEV/J7leVGs9TV4TvcO5QOOrTHYI+xeCjY +JR/m9GPDHv2oSZunUokS2A/WBelnvx6tF6LUJO2FjjlH5zU6Q+Kz/9m69LxvSZVSwiOlGnT1rt/A +77j+WDQZ8x9k2mFJetOle88+lc8sJJ/AeerI+fTlQigTfVqJUiXoKaaC3AqmI+KOnivjMLbvBVFU +1JDruuadNGcPmkgiBTnQXUGUDd6IK9JEQ9yPdM96xZP8bieeMRqTuqbxIbbey2DjVUNzRs1rosFS +TsLAdS/0fBGNdTGKhuqD7mUmsFlgGjN2eSj1tM3GnjfXwwCmzjhMbR4rLZXXk+Z/6Hp7Pn2+kJ49 +jfgLHgI4Jg== +""".decode("base64").decode("zlib") + +if __name__ == '__main__': + main() + +## TODO: +## Copy python.exe.manifest +## Monkeypatch distutils.sysconfig diff --git a/js/common/test-data/modules/commonjs/docs/_hooks/extend_md.py b/js/common/test-data/modules/commonjs/docs/_hooks/extend_md.py new file mode 100644 index 0000000000..0b083dbaa1 --- /dev/null +++ b/js/common/test-data/modules/commonjs/docs/_hooks/extend_md.py @@ -0,0 +1,12 @@ +import markdown + +MARKDOWN_EXTENSIONS = ["def_list", "fenced_code", "codehilite", "tables"] + +def extended_markdown(text): + if isinstance(text, str): + text = text.decode("utf8") + return markdown.markdown(text, extensions=MARKDOWN_EXTENSIONS, + output_format="html") + +Config.transformers['markdown'] = extended_markdown + diff --git a/js/common/test-data/modules/commonjs/docs/_hooks/transformers.py b/js/common/test-data/modules/commonjs/docs/_hooks/transformers.py new file mode 100644 index 0000000000..b816a467f0 --- /dev/null +++ b/js/common/test-data/modules/commonjs/docs/_hooks/transformers.py @@ -0,0 +1 @@ +Config.transformers['noop'] = lambda source: source diff --git a/js/common/test-data/modules/commonjs/docs/_layout/default.html b/js/common/test-data/modules/commonjs/docs/_layout/default.html new file mode 100644 index 0000000000..d11ea6a64c --- /dev/null +++ b/js/common/test-data/modules/commonjs/docs/_layout/default.html @@ -0,0 +1,104 @@ + + + + +CommonJS: JavaScript Standard Library + + + + + + +
+
+ + +
javascript: not just for browsers any more!
+
+
+
+
+
+
+ {{content}} +
+
+
+

Site Updates

+
+
+
    +
  • // Work is ongoing in fleshing out the content and bringing in new CommonJS 0.5 specs.
  • +
  • // Formatting has been cleaned up around the site and on the Modules 1.0 page. +
  • +
+
+
+

CommonJS Links

+ +
+
+
 
+
+
+
+ + + diff --git a/js/common/test-data/modules/commonjs/docs/contributors.html.markdown b/js/common/test-data/modules/commonjs/docs/contributors.html.markdown new file mode 100644 index 0000000000..b9d3a62dff --- /dev/null +++ b/js/common/test-data/modules/commonjs/docs/contributors.html.markdown @@ -0,0 +1,35 @@ +--- +layout: default +title: CommonJS Contributors +--- + +The CommonJS Contributors +========================= + +Creating the CommonJS APIs has been a volunteer effort, and the people below have contributed their time and energy to creating a consensus around these APIs. Without working through the details and making compromises, we would never have standardized anything or seen any implementations come into existence. + +The following people have contributed substantially to the work of creating the CommonJS APIs: + +* Ihab Awad +* Ash Berlin +* Aristid Breitkreuz +* Kevin Dangoor +* Daniel Friesen +* Wes Garland +* Kris Kowal +* Dean Landolt +* Peter Michaux +* George Moschovitis +* Michael O'Brien +* Tom Robinson +* Hannes Wallnoefer +* Mike Wilson +* Ondrej Zara +* Chris Zumbrunn +* Kris Zyp + +My apologies to any contributor whose name was omitted. With thousands of messages of discussion during 2009, there are many people who have come and pitched in to the project with their ideas. + +Additionally, thanks are due to all of the people who have been involved in building the implementations of the CommonJS APIs. Many of the people on the list above are implementers, but there are many other people involved in their projects and many other projects that are not represented here. + +Thanks to you all for making this project a success! diff --git a/js/common/test-data/modules/commonjs/docs/css/colorful.css b/js/common/test-data/modules/commonjs/docs/css/colorful.css new file mode 100644 index 0000000000..72750df39d --- /dev/null +++ b/js/common/test-data/modules/commonjs/docs/css/colorful.css @@ -0,0 +1,61 @@ +.codehilite .hll { background-color: #ffffcc } +.codehilite .c { color: #808080 } /* Comment */ +.codehilite .err { color: #F00000; background-color: #F0A0A0 } /* Error */ +.codehilite .k { color: #008000; font-weight: bold } /* Keyword */ +.codehilite .o { color: #303030 } /* Operator */ +.codehilite .cm { color: #808080 } /* Comment.Multiline */ +.codehilite .cp { color: #507090 } /* Comment.Preproc */ +.codehilite .c1 { color: #808080 } /* Comment.Single */ +.codehilite .cs { color: #cc0000; font-weight: bold } /* Comment.Special */ +.codehilite .gd { color: #A00000 } /* Generic.Deleted */ +.codehilite .ge { font-style: italic } /* Generic.Emph */ +.codehilite .gr { color: #FF0000 } /* Generic.Error */ +.codehilite .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.codehilite .gi { color: #00A000 } /* Generic.Inserted */ +.codehilite .go { color: #808080 } /* Generic.Output */ +.codehilite .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */ +.codehilite .gs { font-weight: bold } /* Generic.Strong */ +.codehilite .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.codehilite .gt { color: #0040D0 } /* Generic.Traceback */ +.codehilite .kc { color: #008000; font-weight: bold } /* Keyword.Constant */ +.codehilite .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */ +.codehilite .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */ +.codehilite .kp { color: #003080; font-weight: bold } /* Keyword.Pseudo */ +.codehilite .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */ +.codehilite .kt { color: #303090; font-weight: bold } /* Keyword.Type */ +.codehilite .m { color: #6000E0; font-weight: bold } /* Literal.Number */ +.codehilite .s { background-color: #fff0f0 } /* Literal.String */ +.codehilite .na { color: #0000C0 } /* Name.Attribute */ +.codehilite .nb { color: #007020 } /* Name.Builtin */ +.codehilite .nc { color: #B00060; font-weight: bold } /* Name.Class */ +.codehilite .no { color: #003060; font-weight: bold } /* Name.Constant */ +.codehilite .nd { color: #505050; font-weight: bold } /* Name.Decorator */ +.codehilite .ni { color: #800000; font-weight: bold } /* Name.Entity */ +.codehilite .ne { color: #F00000; font-weight: bold } /* Name.Exception */ +.codehilite .nf { color: #0060B0; font-weight: bold } /* Name.Function */ +.codehilite .nl { color: #907000; font-weight: bold } /* Name.Label */ +.codehilite .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */ +.codehilite .nt { color: #007000 } /* Name.Tag */ +.codehilite .nv { color: #906030 } /* Name.Variable */ +.codehilite .ow { color: #000000; font-weight: bold } /* Operator.Word */ +.codehilite .w { color: #bbbbbb } /* Text.Whitespace */ +.codehilite .mf { color: #6000E0; font-weight: bold } /* Literal.Number.Float */ +.codehilite .mh { color: #005080; font-weight: bold } /* Literal.Number.Hex */ +.codehilite .mi { color: #0000D0; font-weight: bold } /* Literal.Number.Integer */ +.codehilite .mo { color: #4000E0; font-weight: bold } /* Literal.Number.Oct */ +.codehilite .sb { background-color: #fff0f0 } /* Literal.String.Backtick */ +.codehilite .sc { color: #0040D0 } /* Literal.String.Char */ +.codehilite .sd { color: #D04020 } /* Literal.String.Doc */ +.codehilite .s2 { background-color: #fff0f0 } /* Literal.String.Double */ +.codehilite .se { color: #606060; font-weight: bold; background-color: #fff0f0 } /* Literal.String.Escape */ +.codehilite .sh { background-color: #fff0f0 } /* Literal.String.Heredoc */ +.codehilite .si { background-color: #e0e0e0 } /* Literal.String.Interpol */ +.codehilite .sx { color: #D02000; background-color: #fff0f0 } /* Literal.String.Other */ +.codehilite .sr { color: #000000; background-color: #fff0ff } /* Literal.String.Regex */ +.codehilite .s1 { background-color: #fff0f0 } /* Literal.String.Single */ +.codehilite .ss { color: #A06000 } /* Literal.String.Symbol */ +.codehilite .bp { color: #007020 } /* Name.Builtin.Pseudo */ +.codehilite .vc { color: #306090 } /* Name.Variable.Class */ +.codehilite .vg { color: #d07000; font-weight: bold } /* Name.Variable.Global */ +.codehilite .vi { color: #3030B0 } /* Name.Variable.Instance */ +.codehilite .il { color: #0000D0; font-weight: bold } /* Literal.Number.Integer.Long */ diff --git a/js/common/test-data/modules/commonjs/docs/css/default.css b/js/common/test-data/modules/commonjs/docs/css/default.css new file mode 100644 index 0000000000..ef95359ffa --- /dev/null +++ b/js/common/test-data/modules/commonjs/docs/css/default.css @@ -0,0 +1,62 @@ +.codehilite .hll { background-color: #ffffcc } +.codehilite { background: #f8f8f8; } +.codehilite .c { color: #408080; font-style: italic } /* Comment */ +.codehilite .err { border: 1px solid #FF0000 } /* Error */ +.codehilite .k { color: #008000; font-weight: bold } /* Keyword */ +.codehilite .o { color: #666666 } /* Operator */ +.codehilite .cm { color: #408080; font-style: italic } /* Comment.Multiline */ +.codehilite .cp { color: #BC7A00 } /* Comment.Preproc */ +.codehilite .c1 { color: #408080; font-style: italic } /* Comment.Single */ +.codehilite .cs { color: #408080; font-style: italic } /* Comment.Special */ +.codehilite .gd { color: #A00000 } /* Generic.Deleted */ +.codehilite .ge { font-style: italic } /* Generic.Emph */ +.codehilite .gr { color: #FF0000 } /* Generic.Error */ +.codehilite .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.codehilite .gi { color: #00A000 } /* Generic.Inserted */ +.codehilite .go { color: #808080 } /* Generic.Output */ +.codehilite .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ +.codehilite .gs { font-weight: bold } /* Generic.Strong */ +.codehilite .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.codehilite .gt { color: #0040D0 } /* Generic.Traceback */ +.codehilite .kc { color: #008000; font-weight: bold } /* Keyword.Constant */ +.codehilite .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */ +.codehilite .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */ +.codehilite .kp { color: #008000 } /* Keyword.Pseudo */ +.codehilite .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */ +.codehilite .kt { color: #B00040 } /* Keyword.Type */ +.codehilite .m { color: #666666 } /* Literal.Number */ +.codehilite .s { color: #BA2121 } /* Literal.String */ +.codehilite .na { color: #7D9029 } /* Name.Attribute */ +.codehilite .nb { color: #008000 } /* Name.Builtin */ +.codehilite .nc { color: #0000FF; font-weight: bold } /* Name.Class */ +.codehilite .no { color: #880000 } /* Name.Constant */ +.codehilite .nd { color: #AA22FF } /* Name.Decorator */ +.codehilite .ni { color: #999999; font-weight: bold } /* Name.Entity */ +.codehilite .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ +.codehilite .nf { color: #0000FF } /* Name.Function */ +.codehilite .nl { color: #A0A000 } /* Name.Label */ +.codehilite .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ +.codehilite .nt { color: #008000; font-weight: bold } /* Name.Tag */ +.codehilite .nv { color: #19177C } /* Name.Variable */ +.codehilite .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ +.codehilite .w { color: #bbbbbb } /* Text.Whitespace */ +.codehilite .mf { color: #666666 } /* Literal.Number.Float */ +.codehilite .mh { color: #666666 } /* Literal.Number.Hex */ +.codehilite .mi { color: #666666 } /* Literal.Number.Integer */ +.codehilite .mo { color: #666666 } /* Literal.Number.Oct */ +.codehilite .sb { color: #BA2121 } /* Literal.String.Backtick */ +.codehilite .sc { color: #BA2121 } /* Literal.String.Char */ +.codehilite .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */ +.codehilite .s2 { color: #BA2121 } /* Literal.String.Double */ +.codehilite .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ +.codehilite .sh { color: #BA2121 } /* Literal.String.Heredoc */ +.codehilite .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ +.codehilite .sx { color: #008000 } /* Literal.String.Other */ +.codehilite .sr { color: #BB6688 } /* Literal.String.Regex */ +.codehilite .s1 { color: #BA2121 } /* Literal.String.Single */ +.codehilite .ss { color: #19177C } /* Literal.String.Symbol */ +.codehilite .bp { color: #008000 } /* Name.Builtin.Pseudo */ +.codehilite .vc { color: #19177C } /* Name.Variable.Class */ +.codehilite .vg { color: #19177C } /* Name.Variable.Global */ +.codehilite .vi { color: #19177C } /* Name.Variable.Instance */ +.codehilite .il { color: #666666 } /* Literal.Number.Integer.Long */ diff --git a/js/common/test-data/modules/commonjs/docs/css/styles.css b/js/common/test-data/modules/commonjs/docs/css/styles.css new file mode 100644 index 0000000000..5941e66eb0 --- /dev/null +++ b/js/common/test-data/modules/commonjs/docs/css/styles.css @@ -0,0 +1,209 @@ +@charset "UTF-8"; + +body { + background-color: #3c3c3c; + font-family: Helvetica, Arial, sans-serif; + margin: 0px; + padding: 0px; + font-size: 14px; + line-height: 18px; +} +.col_level { + font-size: 0px; + clear: both; + height: 1px; +} + + +/* PAGE HEADER */ + +.header_wrapper { + height: 107px; + background-image: url(../images/header_wrapper_bg.png); + background-repeat: repeat-x; +} +.header_bg { + width: 970px; + margin-right: auto; + margin-left: auto; + height: 107px; + background-image: url(../images/header_gradient.jpg); + background-repeat: no-repeat; + background-position: center; +} +.tagline { + float: left; + margin-left: 15px; + line-height: 107px; + font-size: 18px; + color: #9f9f9f; +} +img.logo { + float: left; + margin-top: 24px; + margin-left: 0px; +} +.nav_wrapper { + float: right; + height: 107px; +} +.nav_item { + float: right; + width: 125px; + color: #FFFFFF; + text-align: center; + padding-top: 60px; + height: 47px; + font-size: 22px; + font-weight: normal; +} +.nav_item a:link, .nav_item a:visited { + color: #FFFFFF; + text-decoration: none; +} +.nav_item a:hover { + color: #CCCCCC; +} +.nav1 { + background-image: url(../images/nav_js.png); + background-repeat: repeat-x; + background-position: bottom; +} +.nav2 { + background-image: url(../images/nav_commonjs.png); + background-repeat: repeat-x; + background-position: bottom; +} +.nav3 { + background-image: url(../images/nav_browsers.png); + background-repeat: repeat-x; + background-position: bottom; +} +.nav_div { + float: right; + background-image: url(../images/nav_div.png); + width: 1px; + background-position: bottom; + height: 107px; + background-repeat: no-repeat; +} + + + + +/* PAGE BODY */ + +.content_wrapper { + background-image: url(../images/content-wrapper_bg.png); + background-repeat: repeat-x; + background-color: #efefef; +} + +.content_bg { + width: 1000px; + margin-right: auto; + margin-left: auto; + background-image: url(../images/content_bg.png); + background-repeat: repeat-y; +} + +.content { + position: relative; + background-image: url(../images/banner_gray.jpg); + background-repeat: no-repeat; + background-position: center 11px; +} +.content-left { + width: 680px; + margin-left: 60px; + float: left; + margin-top: 60px; + padding-bottom: 20px; +} +.content-left h1 { + font-size: 28px; + color: #863e3e; + font-weight: normal; + margin-top: 0px; + margin-right: 0px; + margin-bottom: 6px; + margin-left: 0px; +} + + + + +/* NEWS */ + +.news_wrapper { + width: 219px; + right: 14px; + float: right; + margin-right: 27px; + margin-top: 70px; + font-size: 12px; + line-height: 13px; +} +.news-top { + background-image: url(../images/news_bg-top.png); + background-repeat: no-repeat; + height: 25px; + background-position: left top; + padding-left: 24px; + vertical-align: bottom; + padding-top: 20px; +} +.news_items { + background-image: url(../images/news_bg-btm.png); + background-repeat: no-repeat; + background-position: left bottom; + padding-left: 24px; + color: #9d9d9d; + padding-right: 12px; +} +.news_items ul { + list-style: none; + margin-left: 0; + padding-left: 1em; + text-indent: -.9em; + margin-top: 0px; +} +.news_items li { + margin-bottom: 8px; + margin-left: 8px; +} +.news_items a:link, .news_items a:visited { + color: #90d5ff; + text-decoration: none; +} +.news_items a:hover { + text-decoration: underline; +} +.news_wrapper h1 { + font-weight: normal; + font-size: 16px; + margin-bottom: 8px; + color: #636363; + margin-top: 0px; +} + + + + +/* PAGE FOOT */ + +.footer_wrapper { + font-size: 10px; + border-top-width: 10px; + border-top-style: solid; + border-top-color: #636363; + text-align: center; + padding-top: 10px; + padding-bottom: 10px; + color: #999999; +} +.footer_bg { + width: 970px; + margin-right: auto; + margin-left: auto; +} diff --git a/js/common/test-data/modules/commonjs/docs/history.html.markdown b/js/common/test-data/modules/commonjs/docs/history.html.markdown new file mode 100644 index 0000000000..dc4401ee16 --- /dev/null +++ b/js/common/test-data/modules/commonjs/docs/history.html.markdown @@ -0,0 +1,12 @@ +--- +layout: default +title: CommonJS Project History +--- + +CommonJS Project History +======================== + +* January 2009: the group was formed as "ServerJS" following a blog post on Kevin Dangoor's Blue Sky on Mars +* March 2009: the dust had settled around "securable modules" as the module style for the group. This is CommonJS API 0.1 +* April 2009: CommonJS modules were shown off with several implementations at the first JSConf in Washington, DC. +* August 2009: The group name was formally changed to CommonJS to reflect the broader applicability of the APIs. diff --git a/js/common/test-data/modules/commonjs/docs/images/banner_blue.jpg b/js/common/test-data/modules/commonjs/docs/images/banner_blue.jpg new file mode 100644 index 0000000000..476bd2ea05 Binary files /dev/null and b/js/common/test-data/modules/commonjs/docs/images/banner_blue.jpg differ diff --git a/js/common/test-data/modules/commonjs/docs/images/banner_gray.jpg b/js/common/test-data/modules/commonjs/docs/images/banner_gray.jpg new file mode 100644 index 0000000000..70c7c20739 Binary files /dev/null and b/js/common/test-data/modules/commonjs/docs/images/banner_gray.jpg differ diff --git a/js/common/test-data/modules/commonjs/docs/images/banner_green.jpg b/js/common/test-data/modules/commonjs/docs/images/banner_green.jpg new file mode 100644 index 0000000000..55c28c3e9a Binary files /dev/null and b/js/common/test-data/modules/commonjs/docs/images/banner_green.jpg differ diff --git a/js/common/test-data/modules/commonjs/docs/images/banner_home.jpg b/js/common/test-data/modules/commonjs/docs/images/banner_home.jpg new file mode 100644 index 0000000000..89f707eeca Binary files /dev/null and b/js/common/test-data/modules/commonjs/docs/images/banner_home.jpg differ diff --git a/js/common/test-data/modules/commonjs/docs/images/banner_orange.jpg b/js/common/test-data/modules/commonjs/docs/images/banner_orange.jpg new file mode 100644 index 0000000000..dd95ae0fe3 Binary files /dev/null and b/js/common/test-data/modules/commonjs/docs/images/banner_orange.jpg differ diff --git a/js/common/test-data/modules/commonjs/docs/images/banner_red.jpg b/js/common/test-data/modules/commonjs/docs/images/banner_red.jpg new file mode 100644 index 0000000000..b09c8486a7 Binary files /dev/null and b/js/common/test-data/modules/commonjs/docs/images/banner_red.jpg differ diff --git a/js/common/test-data/modules/commonjs/docs/images/content-wrapper_bg.png b/js/common/test-data/modules/commonjs/docs/images/content-wrapper_bg.png new file mode 100644 index 0000000000..fc7451b0fb Binary files /dev/null and b/js/common/test-data/modules/commonjs/docs/images/content-wrapper_bg.png differ diff --git a/js/common/test-data/modules/commonjs/docs/images/content_bg.png b/js/common/test-data/modules/commonjs/docs/images/content_bg.png new file mode 100644 index 0000000000..ef089c632e Binary files /dev/null and b/js/common/test-data/modules/commonjs/docs/images/content_bg.png differ diff --git a/js/common/test-data/modules/commonjs/docs/images/explosion.jpg b/js/common/test-data/modules/commonjs/docs/images/explosion.jpg new file mode 100644 index 0000000000..d85bccdfd5 Binary files /dev/null and b/js/common/test-data/modules/commonjs/docs/images/explosion.jpg differ diff --git a/js/common/test-data/modules/commonjs/docs/images/header_gradient.jpg b/js/common/test-data/modules/commonjs/docs/images/header_gradient.jpg new file mode 100644 index 0000000000..3202c3802d Binary files /dev/null and b/js/common/test-data/modules/commonjs/docs/images/header_gradient.jpg differ diff --git a/js/common/test-data/modules/commonjs/docs/images/header_wrapper_bg.png b/js/common/test-data/modules/commonjs/docs/images/header_wrapper_bg.png new file mode 100644 index 0000000000..49c5e8ad75 Binary files /dev/null and b/js/common/test-data/modules/commonjs/docs/images/header_wrapper_bg.png differ diff --git a/js/common/test-data/modules/commonjs/docs/images/logo.png b/js/common/test-data/modules/commonjs/docs/images/logo.png new file mode 100644 index 0000000000..90b43b4693 Binary files /dev/null and b/js/common/test-data/modules/commonjs/docs/images/logo.png differ diff --git a/js/common/test-data/modules/commonjs/docs/images/nav_browsers.png b/js/common/test-data/modules/commonjs/docs/images/nav_browsers.png new file mode 100644 index 0000000000..a3e8bc0bff Binary files /dev/null and b/js/common/test-data/modules/commonjs/docs/images/nav_browsers.png differ diff --git a/js/common/test-data/modules/commonjs/docs/images/nav_browsers_on.png b/js/common/test-data/modules/commonjs/docs/images/nav_browsers_on.png new file mode 100644 index 0000000000..30bf37cd21 Binary files /dev/null and b/js/common/test-data/modules/commonjs/docs/images/nav_browsers_on.png differ diff --git a/js/common/test-data/modules/commonjs/docs/images/nav_commonjs.png b/js/common/test-data/modules/commonjs/docs/images/nav_commonjs.png new file mode 100644 index 0000000000..9daddb62c4 Binary files /dev/null and b/js/common/test-data/modules/commonjs/docs/images/nav_commonjs.png differ diff --git a/js/common/test-data/modules/commonjs/docs/images/nav_commonjs_on.png b/js/common/test-data/modules/commonjs/docs/images/nav_commonjs_on.png new file mode 100644 index 0000000000..92933821a8 Binary files /dev/null and b/js/common/test-data/modules/commonjs/docs/images/nav_commonjs_on.png differ diff --git a/js/common/test-data/modules/commonjs/docs/images/nav_div.png b/js/common/test-data/modules/commonjs/docs/images/nav_div.png new file mode 100644 index 0000000000..063c76902f Binary files /dev/null and b/js/common/test-data/modules/commonjs/docs/images/nav_div.png differ diff --git a/js/common/test-data/modules/commonjs/docs/images/nav_js.png b/js/common/test-data/modules/commonjs/docs/images/nav_js.png new file mode 100644 index 0000000000..4ab2cbb60d Binary files /dev/null and b/js/common/test-data/modules/commonjs/docs/images/nav_js.png differ diff --git a/js/common/test-data/modules/commonjs/docs/images/nav_js_on.png b/js/common/test-data/modules/commonjs/docs/images/nav_js_on.png new file mode 100644 index 0000000000..668c2adeec Binary files /dev/null and b/js/common/test-data/modules/commonjs/docs/images/nav_js_on.png differ diff --git a/js/common/test-data/modules/commonjs/docs/images/news_bg-btm.png b/js/common/test-data/modules/commonjs/docs/images/news_bg-btm.png new file mode 100644 index 0000000000..14ccb2a6de Binary files /dev/null and b/js/common/test-data/modules/commonjs/docs/images/news_bg-btm.png differ diff --git a/js/common/test-data/modules/commonjs/docs/images/news_bg-top.png b/js/common/test-data/modules/commonjs/docs/images/news_bg-top.png new file mode 100644 index 0000000000..3aeed16ca9 Binary files /dev/null and b/js/common/test-data/modules/commonjs/docs/images/news_bg-top.png differ diff --git a/js/common/test-data/modules/commonjs/docs/impl/flusspferd.html.markdown b/js/common/test-data/modules/commonjs/docs/impl/flusspferd.html.markdown new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/common/test-data/modules/commonjs/docs/impl/gpsee.html.markdown b/js/common/test-data/modules/commonjs/docs/impl/gpsee.html.markdown new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/common/test-data/modules/commonjs/docs/impl/helma.html.markdown b/js/common/test-data/modules/commonjs/docs/impl/helma.html.markdown new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/common/test-data/modules/commonjs/docs/impl/index.html.markdown b/js/common/test-data/modules/commonjs/docs/impl/index.html.markdown new file mode 100644 index 0000000000..45ce4e7476 --- /dev/null +++ b/js/common/test-data/modules/commonjs/docs/impl/index.html.markdown @@ -0,0 +1,10 @@ +--- +layout: default +Title: Get CommonJS +--- + +Getting CommonJS +================ + +There are several implementations of the CommonJS standard, and you can choose the one that fits what you're trying to do. + diff --git a/js/common/test-data/modules/commonjs/docs/impl/narwhal.html.markdown b/js/common/test-data/modules/commonjs/docs/impl/narwhal.html.markdown new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/common/test-data/modules/commonjs/docs/impl/persevere.html.markdown b/js/common/test-data/modules/commonjs/docs/impl/persevere.html.markdown new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/common/test-data/modules/commonjs/docs/impl/v8cgi.html.markdown b/js/common/test-data/modules/commonjs/docs/impl/v8cgi.html.markdown new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/common/test-data/modules/commonjs/docs/index.html.markdown b/js/common/test-data/modules/commonjs/docs/index.html.markdown new file mode 100644 index 0000000000..301b785eca --- /dev/null +++ b/js/common/test-data/modules/commonjs/docs/index.html.markdown @@ -0,0 +1,45 @@ +--- +layout: default +title: CommonJS API +--- + +CommonJS +======== + +JavaScript is a powerful object oriented language with some of the fastest dynamic language interpreters around. The official JavaScript specification defines APIs for some objects that are useful for building browser-based applications. However, the spec does not define a standard library that is useful for building a broader range of applications. + +The CommonJS API will fill that gap by defining APIs that handle many common application needs, ultimately providing a standard library as rich as those of Python, Ruby and Java. The intention is that an application developer will be able to write an application using the CommonJS APIs and then run that application across different JavaScript interpreters and host environments. With CommonJS-compliant systems, you can use JavaScript to write: + +* Server-side JavaScript applications +* Command line tools +* Desktop GUI-based applications +* Hybrid applications (Titanium, Adobe AIR) + +Read an [additional introduction by Kris Kowal at Ars Technica](http://arstechnica.com/web/news/2009/12/commonjs-effort-sets-javascript-on-path-for-world-domination.ars). + +Current version: [0.1](specs/0.1.html) +In development: [0.5](specs/0.5.html) + +Implementations +--------------- + + + + + + + + + + + + + + +
ProjectAPI VersionInterpreter
Narwhal0.1+Rhino, Mozilla
v8cgi0.1+v8
Helma0.1+Rhino
Persevere0.1+Rhino
GPSEE0.1+SpiderMonkey
Flusspferd0.1+SpiderMonkey
MonkeyScript0.0Rhino
+ +More information about CommonJS +------------------------------- + +* [Group Process](process.html) +* [Project History](history.html) diff --git a/js/common/test-data/modules/commonjs/docs/interp/jsc.html.markdown b/js/common/test-data/modules/commonjs/docs/interp/jsc.html.markdown new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/common/test-data/modules/commonjs/docs/interp/mozilla.html.markdown b/js/common/test-data/modules/commonjs/docs/interp/mozilla.html.markdown new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/common/test-data/modules/commonjs/docs/interp/rhino.html.markdown b/js/common/test-data/modules/commonjs/docs/interp/rhino.html.markdown new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/common/test-data/modules/commonjs/docs/interp/spidermonkey.html.markdown b/js/common/test-data/modules/commonjs/docs/interp/spidermonkey.html.markdown new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/common/test-data/modules/commonjs/docs/interp/v8.html.markdown b/js/common/test-data/modules/commonjs/docs/interp/v8.html.markdown new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/common/test-data/modules/commonjs/docs/license.html.markdown b/js/common/test-data/modules/commonjs/docs/license.html.markdown new file mode 100644 index 0000000000..8c42f773fa --- /dev/null +++ b/js/common/test-data/modules/commonjs/docs/license.html.markdown @@ -0,0 +1,32 @@ +--- +layout: default +title: License +--- + +CommonJS Documentation and Code License +======================================= + +The output of the CommonJS group is protected under copyright laws, but is intended for the good of the JavaScript development community. CommonJS related projects are licensed under whatever terms the author(s) wish to apply, but the CommonJS specifications and test suites are all licensed under the MIT-style license presented below. + +Copyright 2009 Kevin Dangoor and many CommonJS contributors + +License +------- + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/js/common/test-data/modules/commonjs/docs/process.html.markdown b/js/common/test-data/modules/commonjs/docs/process.html.markdown new file mode 100644 index 0000000000..e7bfef0860 --- /dev/null +++ b/js/common/test-data/modules/commonjs/docs/process.html.markdown @@ -0,0 +1,34 @@ +--- +layout: default +title: CommonJS Process +--- + +CommonJS Process +================ + +The CommonJS group has, to date, operated in an informal manner. Our goal is to make meaningful progress toward these goals: + +1. Design reasonable APIs for common application needs +2. Document those designs +3. Implement those designs in different interpreters and environments + +The process followed through the development of CommonJS 0.5 has been: + +1. Discussion of an API area is started on the mailing list +2. A page is created [on the wiki][wiki] to collect proposals and prior art +3. Further discussion and iteration on the proposals +4. A rough consensus is reached +5. The proposal graduates from the wiki to this website + +So far, achieving rough consensus among the group has been a successful route to meeting these goals. Everyone involved has interoperability on their mind and interop necessarily involves compromise and minimal [bikeshedding][]. + +As applications built upon the CommonJS APIs start appearing, we will likely need more process to handle changes to the API. + +Further reading +--------------- + +For an interesting take on API design from a highly regarded master, take a look at [this tech talk by Josh Bloch][bloch]. + +[wiki]: http://wiki.commonjs.org/ "CommonJS Wiki" +[bikeshedding]: http://en.wikipedia.org/wiki/Parkinson%27s_Law_of_Triviality "Parkinson's Law of Triviality" +[bloch]: http://www.youtube.com/watch?v=aAb7hSCtvGw "Josh Bloch on API design" \ No newline at end of file diff --git a/js/common/test-data/modules/commonjs/docs/specs/0.1.html.markdown b/js/common/test-data/modules/commonjs/docs/specs/0.1.html.markdown new file mode 100644 index 0000000000..b93e596092 --- /dev/null +++ b/js/common/test-data/modules/commonjs/docs/specs/0.1.html.markdown @@ -0,0 +1,13 @@ +--- +layout: default +title: CommonJS API 0.1 +--- + +CommonJS API 0.1 +================ + +As an initial step to allowing code re-use between JavaScript interpreters and libraries, we have defined a common module format: + +* [Modules 1.0](modules/1.0.html) + +This format has gained broad acceptance in the community and had several implementations which were demonstrated at JSConf 2009 in Washington DC. diff --git a/js/common/test-data/modules/commonjs/docs/specs/0.5.html.markdown b/js/common/test-data/modules/commonjs/docs/specs/0.5.html.markdown new file mode 100644 index 0000000000..c492146246 --- /dev/null +++ b/js/common/test-data/modules/commonjs/docs/specs/0.5.html.markdown @@ -0,0 +1,21 @@ +--- +layout: default +title: CommonJS API 0.5 +--- + +CommonJS API 0.5 +================ + +CommonJS 0.5 is currently being developed. It will enable a much broader range of applications to be developed an run seamlessly in different environments. + +Here are the current specifications and discussions for 0.5: + +* [Modules 1.0](modules/1.0.html) +* [Binary Data Type](http://wiki.commonjs.org/wiki/Binary) +* [Encodings](http://wiki.commonjs.org/wiki/Encodings) +* [I/O Streams](http://wiki.commonjs.org/wiki/IO) +* [Filesystem](http://wiki.commonjs.org/wiki/Filesystem) +* [System interface](http://wiki.commonjs.org/wiki/System) +* [Unit Testing](http://wiki.commonjs.org/wiki/Unit_Testing) +* [Sockets](http://wiki.commonjs.org/wiki/Sockets) + diff --git a/js/common/test-data/modules/commonjs/docs/specs/modules/1.0.html.markdown b/js/common/test-data/modules/commonjs/docs/specs/modules/1.0.html.markdown new file mode 100644 index 0000000000..277de3bd0f --- /dev/null +++ b/js/common/test-data/modules/commonjs/docs/specs/modules/1.0.html.markdown @@ -0,0 +1,74 @@ +--- +layout: default +title: CommonJS Modules 1.0 +--- + +CommonJS Modules +================ + +This specification addresses how modules should be written in order to be interoperable among a class of module systems that can be both client and server side, secure or insecure, implemented today or supported by future systems with syntax extensions. These modules are offered privacy of their top scope, facility for importing singleton objects from other modules, and exporting their own API. By implication, this specification defines the minimum features that a module system must provide in order to support interoperable modules. + +Contract +-------- + +### Module Context ### + +1. In a module, there is a free variable "require", that is a function. + 1. The "require" function accepts a module identifier. + 2. "require" returns the exported API of the foreign module. + 3. If there is a dependency cycle, the foreign module may not have finished executing at the time it is required by one of its transitive dependencies; in this case, the object returned by "require" must contain at least the exports that the foreign module has prepared before the call to require that led to the current module's execution. + 4. If the requested module cannot be returned, "require" must throw an error. +2. In a module, there is a free variable called "exports", that is an object that the module may add its API to as it executes. +3. modules must use the "exports" object as the only means of exporting. + +### Module Identifiers ### + +1. A module identifier is a String of "terms" delimited by forward slashes. +2. A term must be a camelCase identifier, ".", or "..". +3. Module identifiers may not have file-name extensions like ".js". +4. Module identifiers may be "relative" or "top-level". A module identifier is "relative" if the first term is "." or "..". +5. Top-level identifiers are resolved off the conceptual module name space root. +6. Relative identifiers are resolved relative to the identifier of the module in which "require" is written and called. + +### Unspecified ### + +This specification leaves the following important points of interoperability unspecified: + +1. Whether modules are stored with a database, file system, or factory functions, or are interchangeable with link libraries. +2. Whether a PATH is supported by the module loader for resolving module identifiers. + +Sample Code +----------- + +*math.js:* + + :::js + exports.add = function() { + var sum = arguments[0]; + for (var i=1; i < arguments.length; i++) { + sum += arguments[i]; + } + return sum; + }; + +*increment.js:* + + :::js + var add = require('math').add; + + exports.increment = function(val) { + return add(val, 1); + }; + +*program.js:* + + :::js + var inc = require('increment').increment; + var a = 1; + inc(a); // 2 + +Related Documents +----------------- + +* Proposal to ECMA TC39: [Module System for ES-Harmony](http://docs.google.com/Doc?id=dfgxb7gk_34gpk37z9v&hl=en) +* Presentation to ECMA TC39: [Modules](http://docs.google.com/Presentation?docid=dcd8d5dk_0cs639jg8&hl=en) diff --git a/js/common/test-data/modules/commonjs/pavement.py b/js/common/test-data/modules/commonjs/pavement.py new file mode 100644 index 0000000000..83b45ef495 --- /dev/null +++ b/js/common/test-data/modules/commonjs/pavement.py @@ -0,0 +1,34 @@ +import sys + +from paver.easy import * +import paver.virtual + +options( + virtualenv=Bunch( + packages_to_install=['pip'], + paver_command_line="initial" + ) +) + +@task +def initial(): + """Initial setup help.""" + venv_command = "Scripts/activate.bat" if sys.platform == 'win32' \ + else "source bin/activate" + + print """This is the source for the CommonJS website. + +You can build the website, by running these two commands (the +result will be in _site): + +%s +paver build +""" % (venv_command) + +@task +def build(options): + """Builds the documentation.""" + if not path("src/growl").exists(): + sh("pip install -r requirements.txt") + sh("growl.py . ../_site", cwd="docs") + \ No newline at end of file diff --git a/js/common/test-data/modules/commonjs/requirements.txt b/js/common/test-data/modules/commonjs/requirements.txt new file mode 100644 index 0000000000..277c859580 --- /dev/null +++ b/js/common/test-data/modules/commonjs/requirements.txt @@ -0,0 +1,4 @@ +-e git://github.com/dangoor/growl.git#egg=growl +PyYAML +Jinja2 +Markdown \ No newline at end of file diff --git a/js/common/test-data/modules/commonjs/tests/modules/1.0/absolute/b.js b/js/common/test-data/modules/commonjs/tests/modules/1.0/absolute/b.js new file mode 100644 index 0000000000..da5bf4fd18 --- /dev/null +++ b/js/common/test-data/modules/commonjs/tests/modules/1.0/absolute/b.js @@ -0,0 +1 @@ +exports.foo = function() {}; diff --git a/js/common/test-data/modules/commonjs/tests/modules/1.0/absolute/program.js b/js/common/test-data/modules/commonjs/tests/modules/1.0/absolute/program.js new file mode 100644 index 0000000000..7980ecf143 --- /dev/null +++ b/js/common/test-data/modules/commonjs/tests/modules/1.0/absolute/program.js @@ -0,0 +1,5 @@ +var test = require('test'); +var a = require('submodule/a'); +var b = require('b'); +test.assert(a.foo().foo === b.foo, 'require works with absolute identifiers'); +test.print('DONE', 'info'); diff --git a/js/common/test-data/modules/commonjs/tests/modules/1.0/absolute/submodule/a.js b/js/common/test-data/modules/commonjs/tests/modules/1.0/absolute/submodule/a.js new file mode 100644 index 0000000000..bc138b87da --- /dev/null +++ b/js/common/test-data/modules/commonjs/tests/modules/1.0/absolute/submodule/a.js @@ -0,0 +1,3 @@ +exports.foo = function () { + return require('b'); +}; diff --git a/js/common/test-data/modules/commonjs/tests/modules/1.0/absolute/test.js b/js/common/test-data/modules/commonjs/tests/modules/1.0/absolute/test.js new file mode 100644 index 0000000000..5d0984eec8 --- /dev/null +++ b/js/common/test-data/modules/commonjs/tests/modules/1.0/absolute/test.js @@ -0,0 +1,15 @@ + +exports.print = typeof print !== "undefined" ? print : function () { + var system = require("system"); + var stdio = system.stdio; + stdio.print.apply(stdio, arguments); +}; + +exports.assert = function (guard, message) { + if (guard) { + exports.print('PASS ' + message, 'pass'); + } else { + exports.print('FAIL ' + message, 'fail'); + } +}; + diff --git a/js/common/test-data/modules/commonjs/tests/modules/1.0/cyclic/a.js b/js/common/test-data/modules/commonjs/tests/modules/1.0/cyclic/a.js new file mode 100644 index 0000000000..e0188fa08c --- /dev/null +++ b/js/common/test-data/modules/commonjs/tests/modules/1.0/cyclic/a.js @@ -0,0 +1,4 @@ +exports.a = function () { + return b; +}; +var b = require('b'); diff --git a/js/common/test-data/modules/commonjs/tests/modules/1.0/cyclic/b.js b/js/common/test-data/modules/commonjs/tests/modules/1.0/cyclic/b.js new file mode 100644 index 0000000000..873a305776 --- /dev/null +++ b/js/common/test-data/modules/commonjs/tests/modules/1.0/cyclic/b.js @@ -0,0 +1,4 @@ +var a = require('a'); +exports.b = function () { + return a; +}; diff --git a/js/common/test-data/modules/commonjs/tests/modules/1.0/cyclic/program.js b/js/common/test-data/modules/commonjs/tests/modules/1.0/cyclic/program.js new file mode 100644 index 0000000000..2ee4758dbe --- /dev/null +++ b/js/common/test-data/modules/commonjs/tests/modules/1.0/cyclic/program.js @@ -0,0 +1,10 @@ +var test = require('test'); +var a = require('a'); +var b = require('b'); + +test.assert(a.a, 'a exists'); +test.assert(b.b, 'b exists') +test.assert(a.a().b === b.b, 'a gets b'); +test.assert(b.b().a === a.a, 'b gets a'); + +test.print('DONE', 'info'); diff --git a/js/common/test-data/modules/commonjs/tests/modules/1.0/cyclic/test.js b/js/common/test-data/modules/commonjs/tests/modules/1.0/cyclic/test.js new file mode 100644 index 0000000000..5d0984eec8 --- /dev/null +++ b/js/common/test-data/modules/commonjs/tests/modules/1.0/cyclic/test.js @@ -0,0 +1,15 @@ + +exports.print = typeof print !== "undefined" ? print : function () { + var system = require("system"); + var stdio = system.stdio; + stdio.print.apply(stdio, arguments); +}; + +exports.assert = function (guard, message) { + if (guard) { + exports.print('PASS ' + message, 'pass'); + } else { + exports.print('FAIL ' + message, 'fail'); + } +}; + diff --git a/js/common/test-data/modules/commonjs/tests/modules/1.0/determinism/program.js b/js/common/test-data/modules/commonjs/tests/modules/1.0/determinism/program.js new file mode 100644 index 0000000000..7c0e50b0b1 --- /dev/null +++ b/js/common/test-data/modules/commonjs/tests/modules/1.0/determinism/program.js @@ -0,0 +1,3 @@ +var test = require('test'); +require('submodule/a'); +test.print('DONE', 'info'); diff --git a/js/common/test-data/modules/commonjs/tests/modules/1.0/determinism/submodule/a.js b/js/common/test-data/modules/commonjs/tests/modules/1.0/determinism/submodule/a.js new file mode 100644 index 0000000000..215ea1d9a7 --- /dev/null +++ b/js/common/test-data/modules/commonjs/tests/modules/1.0/determinism/submodule/a.js @@ -0,0 +1,9 @@ +var test = require('test'); +var pass = false; +var test = require('test'); +try { + require('a'); +} catch (exception) { + pass = true; +} +test.assert(pass, 'require does not fall back to relative modules when absolutes are not available.') diff --git a/js/common/test-data/modules/commonjs/tests/modules/1.0/determinism/submodule/b.js b/js/common/test-data/modules/commonjs/tests/modules/1.0/determinism/submodule/b.js new file mode 100644 index 0000000000..139597f9cb --- /dev/null +++ b/js/common/test-data/modules/commonjs/tests/modules/1.0/determinism/submodule/b.js @@ -0,0 +1,2 @@ + + diff --git a/js/common/test-data/modules/commonjs/tests/modules/1.0/determinism/test.js b/js/common/test-data/modules/commonjs/tests/modules/1.0/determinism/test.js new file mode 100644 index 0000000000..5d0984eec8 --- /dev/null +++ b/js/common/test-data/modules/commonjs/tests/modules/1.0/determinism/test.js @@ -0,0 +1,15 @@ + +exports.print = typeof print !== "undefined" ? print : function () { + var system = require("system"); + var stdio = system.stdio; + stdio.print.apply(stdio, arguments); +}; + +exports.assert = function (guard, message) { + if (guard) { + exports.print('PASS ' + message, 'pass'); + } else { + exports.print('FAIL ' + message, 'fail'); + } +}; + diff --git a/js/common/test-data/modules/commonjs/tests/modules/1.0/exactExports/a.js b/js/common/test-data/modules/commonjs/tests/modules/1.0/exactExports/a.js new file mode 100644 index 0000000000..99c929e44f --- /dev/null +++ b/js/common/test-data/modules/commonjs/tests/modules/1.0/exactExports/a.js @@ -0,0 +1,3 @@ +exports.program = function () { + return require('program'); +}; diff --git a/js/common/test-data/modules/commonjs/tests/modules/1.0/exactExports/program.js b/js/common/test-data/modules/commonjs/tests/modules/1.0/exactExports/program.js new file mode 100644 index 0000000000..e82bd6db2c --- /dev/null +++ b/js/common/test-data/modules/commonjs/tests/modules/1.0/exactExports/program.js @@ -0,0 +1,4 @@ +var test = require('test'); +var a = require('a'); +test.assert(a.program() === exports, 'exact exports'); +test.print('DONE', 'info'); diff --git a/js/common/test-data/modules/commonjs/tests/modules/1.0/exactExports/test.js b/js/common/test-data/modules/commonjs/tests/modules/1.0/exactExports/test.js new file mode 100644 index 0000000000..5d0984eec8 --- /dev/null +++ b/js/common/test-data/modules/commonjs/tests/modules/1.0/exactExports/test.js @@ -0,0 +1,15 @@ + +exports.print = typeof print !== "undefined" ? print : function () { + var system = require("system"); + var stdio = system.stdio; + stdio.print.apply(stdio, arguments); +}; + +exports.assert = function (guard, message) { + if (guard) { + exports.print('PASS ' + message, 'pass'); + } else { + exports.print('FAIL ' + message, 'fail'); + } +}; + diff --git a/js/common/test-data/modules/commonjs/tests/modules/1.0/hasOwnProperty/hasOwnProperty.js b/js/common/test-data/modules/commonjs/tests/modules/1.0/hasOwnProperty/hasOwnProperty.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/common/test-data/modules/commonjs/tests/modules/1.0/hasOwnProperty/program.js b/js/common/test-data/modules/commonjs/tests/modules/1.0/hasOwnProperty/program.js new file mode 100644 index 0000000000..1653f1b863 --- /dev/null +++ b/js/common/test-data/modules/commonjs/tests/modules/1.0/hasOwnProperty/program.js @@ -0,0 +1,4 @@ +var hasOwnProperty = require('hasOwnProperty'); +var toString = require('toString'); +var test = require('test'); +test.print('DONE', 'info'); diff --git a/js/common/test-data/modules/commonjs/tests/modules/1.0/hasOwnProperty/test.js b/js/common/test-data/modules/commonjs/tests/modules/1.0/hasOwnProperty/test.js new file mode 100644 index 0000000000..5d0984eec8 --- /dev/null +++ b/js/common/test-data/modules/commonjs/tests/modules/1.0/hasOwnProperty/test.js @@ -0,0 +1,15 @@ + +exports.print = typeof print !== "undefined" ? print : function () { + var system = require("system"); + var stdio = system.stdio; + stdio.print.apply(stdio, arguments); +}; + +exports.assert = function (guard, message) { + if (guard) { + exports.print('PASS ' + message, 'pass'); + } else { + exports.print('FAIL ' + message, 'fail'); + } +}; + diff --git a/js/common/test-data/modules/commonjs/tests/modules/1.0/hasOwnProperty/toString.js b/js/common/test-data/modules/commonjs/tests/modules/1.0/hasOwnProperty/toString.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/common/test-data/modules/commonjs/tests/modules/1.0/method/a.js b/js/common/test-data/modules/commonjs/tests/modules/1.0/method/a.js new file mode 100644 index 0000000000..69c48af67a --- /dev/null +++ b/js/common/test-data/modules/commonjs/tests/modules/1.0/method/a.js @@ -0,0 +1,12 @@ +exports.foo = function () { + return this; +}; +exports.set = function (x) { + this.x = x; +}; +exports.get = function () { + return this.x; +}; +exports.getClosed = function () { + return exports.x; +}; diff --git a/js/common/test-data/modules/commonjs/tests/modules/1.0/method/program.js b/js/common/test-data/modules/commonjs/tests/modules/1.0/method/program.js new file mode 100644 index 0000000000..192811c5a7 --- /dev/null +++ b/js/common/test-data/modules/commonjs/tests/modules/1.0/method/program.js @@ -0,0 +1,8 @@ +var test = require('test'); +var a = require('a'); +var foo = a.foo; +test.assert(a.foo() == a, 'calling a module member'); +test.assert(foo() == (function (){return this})(), 'members not implicitly bound'); +a.set(10); +test.assert(a.get() == 10, 'get and set') +test.print('DONE', 'info'); diff --git a/js/common/test-data/modules/commonjs/tests/modules/1.0/method/test.js b/js/common/test-data/modules/commonjs/tests/modules/1.0/method/test.js new file mode 100644 index 0000000000..5d0984eec8 --- /dev/null +++ b/js/common/test-data/modules/commonjs/tests/modules/1.0/method/test.js @@ -0,0 +1,15 @@ + +exports.print = typeof print !== "undefined" ? print : function () { + var system = require("system"); + var stdio = system.stdio; + stdio.print.apply(stdio, arguments); +}; + +exports.assert = function (guard, message) { + if (guard) { + exports.print('PASS ' + message, 'pass'); + } else { + exports.print('FAIL ' + message, 'fail'); + } +}; + diff --git a/js/common/test-data/modules/commonjs/tests/modules/1.0/missing/program.js b/js/common/test-data/modules/commonjs/tests/modules/1.0/missing/program.js new file mode 100644 index 0000000000..c6b03aa28f --- /dev/null +++ b/js/common/test-data/modules/commonjs/tests/modules/1.0/missing/program.js @@ -0,0 +1,8 @@ +var test = require('test'); +try { + require('bogus'); + test.print('FAIL require throws error when module missing', 'fail'); +} catch (exception) { + test.print('PASS require throws error when module missing', 'pass'); +} +test.print('DONE', 'info'); diff --git a/js/common/test-data/modules/commonjs/tests/modules/1.0/missing/test.js b/js/common/test-data/modules/commonjs/tests/modules/1.0/missing/test.js new file mode 100644 index 0000000000..5d0984eec8 --- /dev/null +++ b/js/common/test-data/modules/commonjs/tests/modules/1.0/missing/test.js @@ -0,0 +1,15 @@ + +exports.print = typeof print !== "undefined" ? print : function () { + var system = require("system"); + var stdio = system.stdio; + stdio.print.apply(stdio, arguments); +}; + +exports.assert = function (guard, message) { + if (guard) { + exports.print('PASS ' + message, 'pass'); + } else { + exports.print('FAIL ' + message, 'fail'); + } +}; + diff --git a/js/common/test-data/modules/commonjs/tests/modules/1.0/monkeys/a.js b/js/common/test-data/modules/commonjs/tests/modules/1.0/monkeys/a.js new file mode 100644 index 0000000000..a949e1dcf5 --- /dev/null +++ b/js/common/test-data/modules/commonjs/tests/modules/1.0/monkeys/a.js @@ -0,0 +1 @@ +require('program').monkey = 10; diff --git a/js/common/test-data/modules/commonjs/tests/modules/1.0/monkeys/program.js b/js/common/test-data/modules/commonjs/tests/modules/1.0/monkeys/program.js new file mode 100644 index 0000000000..42d67112ee --- /dev/null +++ b/js/common/test-data/modules/commonjs/tests/modules/1.0/monkeys/program.js @@ -0,0 +1,4 @@ +var a = require('a'); +var test = require('test'); +test.assert(exports.monkey == 10, 'monkeys permitted'); +test.print('DONE', 'info'); diff --git a/js/common/test-data/modules/commonjs/tests/modules/1.0/monkeys/test.js b/js/common/test-data/modules/commonjs/tests/modules/1.0/monkeys/test.js new file mode 100644 index 0000000000..5d0984eec8 --- /dev/null +++ b/js/common/test-data/modules/commonjs/tests/modules/1.0/monkeys/test.js @@ -0,0 +1,15 @@ + +exports.print = typeof print !== "undefined" ? print : function () { + var system = require("system"); + var stdio = system.stdio; + stdio.print.apply(stdio, arguments); +}; + +exports.assert = function (guard, message) { + if (guard) { + exports.print('PASS ' + message, 'pass'); + } else { + exports.print('FAIL ' + message, 'fail'); + } +}; + diff --git a/js/common/test-data/modules/commonjs/tests/modules/1.0/nested/a/b/c/d.js b/js/common/test-data/modules/commonjs/tests/modules/1.0/nested/a/b/c/d.js new file mode 100644 index 0000000000..69fd282283 --- /dev/null +++ b/js/common/test-data/modules/commonjs/tests/modules/1.0/nested/a/b/c/d.js @@ -0,0 +1,3 @@ +exports.foo = function () { + return 1; +}; diff --git a/js/common/test-data/modules/commonjs/tests/modules/1.0/nested/program.js b/js/common/test-data/modules/commonjs/tests/modules/1.0/nested/program.js new file mode 100644 index 0000000000..c014b57277 --- /dev/null +++ b/js/common/test-data/modules/commonjs/tests/modules/1.0/nested/program.js @@ -0,0 +1,3 @@ +var test = require('test'); +test.assert(require('a/b/c/d').foo() == 1, 'nested module identifier'); +test.print('DONE', 'info'); diff --git a/js/common/test-data/modules/commonjs/tests/modules/1.0/nested/test.js b/js/common/test-data/modules/commonjs/tests/modules/1.0/nested/test.js new file mode 100644 index 0000000000..5d0984eec8 --- /dev/null +++ b/js/common/test-data/modules/commonjs/tests/modules/1.0/nested/test.js @@ -0,0 +1,15 @@ + +exports.print = typeof print !== "undefined" ? print : function () { + var system = require("system"); + var stdio = system.stdio; + stdio.print.apply(stdio, arguments); +}; + +exports.assert = function (guard, message) { + if (guard) { + exports.print('PASS ' + message, 'pass'); + } else { + exports.print('FAIL ' + message, 'fail'); + } +}; + diff --git a/js/common/test-data/modules/commonjs/tests/modules/1.0/relative/program.js b/js/common/test-data/modules/commonjs/tests/modules/1.0/relative/program.js new file mode 100644 index 0000000000..b3e4b6ed7c --- /dev/null +++ b/js/common/test-data/modules/commonjs/tests/modules/1.0/relative/program.js @@ -0,0 +1,5 @@ +var test = require('test'); +var a = require('submodule/a'); +var b = require('submodule/b'); +test.assert(a.foo == b.foo, 'a and b share foo through a relative require'); +test.print('DONE', 'info'); diff --git a/js/common/test-data/modules/commonjs/tests/modules/1.0/relative/submodule/a.js b/js/common/test-data/modules/commonjs/tests/modules/1.0/relative/submodule/a.js new file mode 100644 index 0000000000..42e4ca0864 --- /dev/null +++ b/js/common/test-data/modules/commonjs/tests/modules/1.0/relative/submodule/a.js @@ -0,0 +1 @@ +exports.foo = require('./b').foo; diff --git a/js/common/test-data/modules/commonjs/tests/modules/1.0/relative/submodule/b.js b/js/common/test-data/modules/commonjs/tests/modules/1.0/relative/submodule/b.js new file mode 100644 index 0000000000..9042c16b5a --- /dev/null +++ b/js/common/test-data/modules/commonjs/tests/modules/1.0/relative/submodule/b.js @@ -0,0 +1,2 @@ +exports.foo = function () { +}; diff --git a/js/common/test-data/modules/commonjs/tests/modules/1.0/relative/test.js b/js/common/test-data/modules/commonjs/tests/modules/1.0/relative/test.js new file mode 100644 index 0000000000..5d0984eec8 --- /dev/null +++ b/js/common/test-data/modules/commonjs/tests/modules/1.0/relative/test.js @@ -0,0 +1,15 @@ + +exports.print = typeof print !== "undefined" ? print : function () { + var system = require("system"); + var stdio = system.stdio; + stdio.print.apply(stdio, arguments); +}; + +exports.assert = function (guard, message) { + if (guard) { + exports.print('PASS ' + message, 'pass'); + } else { + exports.print('FAIL ' + message, 'fail'); + } +}; + diff --git a/js/common/test-data/modules/commonjs/tests/modules/1.0/transitive/a.js b/js/common/test-data/modules/commonjs/tests/modules/1.0/transitive/a.js new file mode 100644 index 0000000000..4df7bb8d26 --- /dev/null +++ b/js/common/test-data/modules/commonjs/tests/modules/1.0/transitive/a.js @@ -0,0 +1 @@ +exports.foo = require('b').foo; diff --git a/js/common/test-data/modules/commonjs/tests/modules/1.0/transitive/b.js b/js/common/test-data/modules/commonjs/tests/modules/1.0/transitive/b.js new file mode 100644 index 0000000000..30ea70dd17 --- /dev/null +++ b/js/common/test-data/modules/commonjs/tests/modules/1.0/transitive/b.js @@ -0,0 +1 @@ +exports.foo = require('c').foo; diff --git a/js/common/test-data/modules/commonjs/tests/modules/1.0/transitive/c.js b/js/common/test-data/modules/commonjs/tests/modules/1.0/transitive/c.js new file mode 100644 index 0000000000..69fd282283 --- /dev/null +++ b/js/common/test-data/modules/commonjs/tests/modules/1.0/transitive/c.js @@ -0,0 +1,3 @@ +exports.foo = function () { + return 1; +}; diff --git a/js/common/test-data/modules/commonjs/tests/modules/1.0/transitive/program.js b/js/common/test-data/modules/commonjs/tests/modules/1.0/transitive/program.js new file mode 100644 index 0000000000..98bb996445 --- /dev/null +++ b/js/common/test-data/modules/commonjs/tests/modules/1.0/transitive/program.js @@ -0,0 +1,3 @@ +var test = require('test'); +test.assert(require('a').foo() == 1, 'transitive'); +test.print('DONE', 'info'); diff --git a/js/common/test-data/modules/commonjs/tests/modules/1.0/transitive/test.js b/js/common/test-data/modules/commonjs/tests/modules/1.0/transitive/test.js new file mode 100644 index 0000000000..5d0984eec8 --- /dev/null +++ b/js/common/test-data/modules/commonjs/tests/modules/1.0/transitive/test.js @@ -0,0 +1,15 @@ + +exports.print = typeof print !== "undefined" ? print : function () { + var system = require("system"); + var stdio = system.stdio; + stdio.print.apply(stdio, arguments); +}; + +exports.assert = function (guard, message) { + if (guard) { + exports.print('PASS ' + message, 'pass'); + } else { + exports.print('FAIL ' + message, 'fail'); + } +}; + diff --git a/js/common/test-data/modules/commonjs/tests/unit-testing/1.0/program.js b/js/common/test-data/modules/commonjs/tests/unit-testing/1.0/program.js new file mode 100644 index 0000000000..14ae2b9342 --- /dev/null +++ b/js/common/test-data/modules/commonjs/tests/unit-testing/1.0/program.js @@ -0,0 +1,162 @@ +// From Node.js test/mjsunit/test-assert.js +// Felix Geisendörfer (felixge), backported from NodeJS +// Karl Guertin (greyrest), backported from NodeJS +// Kris Kowal (kriskowal), conversion to CommonJS + +// strangely meta, no? + +var assert = require('assert'); + +function makeBlock(f) { + var args = Array.prototype.slice.call(arguments,1); + return function(){ + return f.apply(this, args); + } +} + +exports['test AssertionError instanceof Error'] = function () { + assert.ok(new assert.AssertionError({}) instanceof Error); +}; + +exports['test ok false'] = function () { + assert['throws'](makeBlock(assert.ok, false), assert.AssertionError); +}; + +exports['test ok(true)'] = makeBlock(assert.ok, true); +exports['test ok("test")'] = makeBlock(assert.ok, "test"); +exports['test equal true false'] = function () { + assert['throws'](makeBlock(assert.equal, true, false), assert.AssertionError, 'equal'); +}; + +exports['test equal null null'] = makeBlock(assert.equal, null, null); +exports['test equal undefined undefined'] = makeBlock(assert.equal, undefined, undefined); +exports['test equal null undefined'] = makeBlock(assert.equal, null, undefined); +exports['test equal 2 "2"'] = makeBlock(assert.equal, 2, "2"); +exports['test equal "2" 2'] = makeBlock(assert.equal, "2", 2); +exports['test equal true true'] = makeBlock(assert.equal, true, true); +exports['test notEqual true false'] = makeBlock(assert.notEqual, true, false); +exports['test notEqual true true'] = function () { + assert['throws'](makeBlock(assert.notEqual, true, true), assert.AssertionError, 'notEqual'); +}; +exports['test strictEqual 2 "2"'] = function () { + assert['throws'](makeBlock(assert.strictEqual, 2, "2"), assert.AssertionError, 'strictEqual'); +}; +exports['test strictEqual null undefined'] = function () { + assert['throws'](makeBlock(assert.strictEqual, null, undefined), assert.AssertionError, 'strictEqual'); +}; +exports['test notStrictEqual 2 "2"'] = makeBlock(assert.notStrictEqual, 2, "2"); + +//deepEquals + +//7.2 +exports['test 7.2 deepEqual date'] = makeBlock(assert.deepEqual, new Date(2000,3,14), new Date(2000,3,14)); +exports['test 7.2 deepEqual date negative'] = function () { + assert['throws'](makeBlock(assert.deepEqual, new Date(), new Date(2000,3,14)), assert.AssertionError, 'deepEqual date'); +}; + +//7.3 +exports['test 7.3 deepEqual 4 "4"'] = makeBlock(assert.deepEqual, 4, "4"); +exports['test 7.3 deepEqual "4" 4'] = makeBlock(assert.deepEqual, "4", 4); +exports['test 7.3 deepEqual true 1'] = makeBlock(assert.deepEqual, true, 1); +exports['test 7.3 deepEqual 4 "5"'] = function () { + assert['throws'](makeBlock(assert.deepEqual, 4, "5")); +}; + +//7.4 +// having the same number of owned properties && the same set of keys +exports['test 7.4 deepEqual {a:4} {a:4}'] = makeBlock(assert.deepEqual, {a:4}, {a:4}); +exports['test 7.4 deepEqual {a:4,b:"2"} {a:4,b:"2"}'] = makeBlock(assert.deepEqual, {a:4,b:"2"}, {a:4,b:"2"}); +exports['test 7.4 deepEqual [4] ["4"]'] = makeBlock(assert.deepEqual, [4], ["4"]); +exports['test 7.4 deepEqual {a:4} {a:4,b:true}'] = function () { + assert['throws'](makeBlock(assert.deepEqual, {a:4}, {a:4,b:true}), assert.AssertionError); +}; + +exports['test deepEqual ["a"], {0:"a"}'] = makeBlock(assert.deepEqual, ["a"], {0:"a"}); +//(although not necessarily the same order), +exports['test deepEqual {a:4,b:"1"} {b:"1",a:4}'] = makeBlock(assert.deepEqual, {a:4,b:"1"}, {b:"1",a:4}); + +exports['test deepEqual arrays with non-numeric properties'] = function () { + var a1 = [1,2,3]; + var a2 = [1,2,3]; + a1.a = "test"; + a1.b = true; + a2.b = true; + a2.a = "test" + assert['throws'](makeBlock(assert.deepEqual, Object.keys(a1), Object.keys(a2)), assert.AssertionError); + makeBlock(assert.deepEqual, a1, a2); +}; + +exports['test deepEqual identical prototype'] = function () { + // having an identical prototype property + var nbRoot = { + toString: function(){return this.first+' '+this.last;} + } + var nameBuilder = function(first,last){ + this.first = first; + this.last = last; + return this; + } + nameBuilder.prototype = nbRoot; + var nameBuilder2 = function(first,last){ + this.first = first; + this.last = last; + return this; + } + nameBuilder2.prototype = nbRoot; + var nb1 = new nameBuilder('Ryan', 'Dahl'); + var nb2 = new nameBuilder2('Ryan','Dahl'); + + assert.deepEqual(nb1, nb2); + + nameBuilder2.prototype = Object; + nb2 = new nameBuilder2('Ryan','Dahl'); + assert['throws'](makeBlock(assert.deepEqual, nb1, nb2), assert.AssertionError); + +}; + +exports['test deepEqual "a" {}'] = function () { + assert['throws'](makeBlock(assert.deepEqual, 'a', {}), assert.AssertionError); +}; + +exports['test deepEqual "" ""'] = function () { + assert.deepEqual("", ""); +}; + +exports['test deepEqual "" [""]'] = function () { + assert['throws'](makeBlock(assert.deepEqual, '', ['']), assert.AssertionError); +}; + +exports['test deepEqual [""] [""]'] = function () { + assert.deepEqual([""], [""]); +}; + +exports['test throw AssertionError'] = function () { + + //Testing the throwing + function thrower(errorConstructor){ + throw new errorConstructor('test'); + } + var aethrow = makeBlock(thrower, assert.AssertionError); + var aethrow = makeBlock(thrower, assert.AssertionError); + //the basic calls work + assert['throws'](makeBlock(thrower, assert.AssertionError), assert.AssertionError, 'message'); + assert['throws'](makeBlock(thrower, assert.AssertionError), assert.AssertionError); + assert['throws'](makeBlock(thrower, assert.AssertionError)); + //if not passing an error, catch all. + assert['throws'](makeBlock(thrower, TypeError)); + //when passing a type, only catch errors of the appropriate type + var threw = false; + try { + assert['throws'](makeBlock(thrower, TypeError), assert.AssertionError); + } catch (e) { + threw = true; + assert.ok(e instanceof TypeError, 'type'); + } + assert.ok(threw, 'assert.throws with an explicit error is eating extra errors', assert.AssertionError); + threw = false; + +}; + +if (module == require.main) + require("test").run(exports); + diff --git a/js/common/test-data/modules/node_modules/TestA/index.js b/js/common/test-data/modules/node_modules/TestA/index.js new file mode 100644 index 0000000000..19a088badc --- /dev/null +++ b/js/common/test-data/modules/node_modules/TestA/index.js @@ -0,0 +1,5 @@ +exports.version = "A 1.0.0"; +exports.x = require("./x"); +exports.B = require("TestB"); +exports.C = require("TestC"); +exports.D = require("TestD"); diff --git a/js/common/test-data/modules/node_modules/TestA/node_modules/TestB/index.js b/js/common/test-data/modules/node_modules/TestA/node_modules/TestB/index.js new file mode 100644 index 0000000000..7ec079f710 --- /dev/null +++ b/js/common/test-data/modules/node_modules/TestA/node_modules/TestB/index.js @@ -0,0 +1 @@ +exports.version = "B 2.0.0"; diff --git a/js/common/test-data/modules/node_modules/TestA/node_modules/TestB/package.json b/js/common/test-data/modules/node_modules/TestA/node_modules/TestB/package.json new file mode 100644 index 0000000000..447071a2a9 --- /dev/null +++ b/js/common/test-data/modules/node_modules/TestA/node_modules/TestB/package.json @@ -0,0 +1,6 @@ +{ + "name": "B", + "description": "B", + "main": "index", + "version": "2.0.0" +} diff --git a/js/common/test-data/modules/node_modules/TestA/node_modules/TestC/index.js b/js/common/test-data/modules/node_modules/TestA/node_modules/TestC/index.js new file mode 100644 index 0000000000..303ee38433 --- /dev/null +++ b/js/common/test-data/modules/node_modules/TestA/node_modules/TestC/index.js @@ -0,0 +1,2 @@ +exports.version = "C 1.0.0"; +exports.B = require("TestB"); diff --git a/js/common/test-data/modules/node_modules/TestA/node_modules/TestC/package.json b/js/common/test-data/modules/node_modules/TestA/node_modules/TestC/package.json new file mode 100644 index 0000000000..b03bb8c694 --- /dev/null +++ b/js/common/test-data/modules/node_modules/TestA/node_modules/TestC/package.json @@ -0,0 +1,6 @@ +{ + "name": "C", + "description": "C", + "main": "index", + "version": "1.0.0" +} diff --git a/js/common/test-data/modules/node_modules/TestA/package.json b/js/common/test-data/modules/node_modules/TestA/package.json new file mode 100644 index 0000000000..4d781bfde6 --- /dev/null +++ b/js/common/test-data/modules/node_modules/TestA/package.json @@ -0,0 +1,6 @@ +{ + "name": "A", + "description": "A", + "main": "index", + "version": "1.0.0" +} diff --git a/js/common/test-data/modules/node_modules/TestA/x.js b/js/common/test-data/modules/node_modules/TestA/x.js new file mode 100644 index 0000000000..6847468a84 --- /dev/null +++ b/js/common/test-data/modules/node_modules/TestA/x.js @@ -0,0 +1 @@ +exports.version = "x 1.0.0"; diff --git a/js/common/test-data/modules/node_modules/TestB/index.js b/js/common/test-data/modules/node_modules/TestB/index.js new file mode 100644 index 0000000000..613ef085a3 --- /dev/null +++ b/js/common/test-data/modules/node_modules/TestB/index.js @@ -0,0 +1 @@ +exports.version = "B 1.0.0"; diff --git a/js/common/test-data/modules/node_modules/TestB/package.json b/js/common/test-data/modules/node_modules/TestB/package.json new file mode 100644 index 0000000000..c71c4e3d7c --- /dev/null +++ b/js/common/test-data/modules/node_modules/TestB/package.json @@ -0,0 +1,6 @@ +{ + "name": "B", + "description": "B", + "main": "index", + "version": "1.0.0" +} diff --git a/js/common/test-data/modules/node_modules/TestD/index.js b/js/common/test-data/modules/node_modules/TestD/index.js new file mode 100644 index 0000000000..33b2d22cf4 --- /dev/null +++ b/js/common/test-data/modules/node_modules/TestD/index.js @@ -0,0 +1 @@ +exports.version = "D 1.0.0"; diff --git a/js/common/test-data/modules/node_modules/TestD/package.json b/js/common/test-data/modules/node_modules/TestD/package.json new file mode 100644 index 0000000000..5e1206560e --- /dev/null +++ b/js/common/test-data/modules/node_modules/TestD/package.json @@ -0,0 +1,6 @@ +{ + "name": "D", + "description": "D", + "main": "index", + "version": "1.0.0" +} diff --git a/js/common/tests/shell-database.js b/js/common/tests/shell-database.js old mode 100755 new mode 100644 diff --git a/js/common/tests/shell-require.js b/js/common/tests/shell-require.js new file mode 100644 index 0000000000..bbf503b200 --- /dev/null +++ b/js/common/tests/shell-require.js @@ -0,0 +1,151 @@ +/*jslint indent: 2, nomen: true, maxlen: 80 */ +/*global require, assertEqual, assertTrue */ + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test the module and package require +/// +/// @file +/// +/// DISCLAIMER +/// +/// Copyright 2010-2012 triagens GmbH, Cologne, Germany +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// +/// Copyright holder is triAGENS GmbH, Cologne, Germany +/// +/// @author Jan Steemann +/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany +//////////////////////////////////////////////////////////////////////////////// + +var jsunity = require("jsunity"); + +// ----------------------------------------------------------------------------- +// --SECTION-- require package suite +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test suite +//////////////////////////////////////////////////////////////////////////////// + +function RequirePackageSuite () { + + return { + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test package loading +//////////////////////////////////////////////////////////////////////////////// + + testPackage : function () { + var m = require("TestA"); + + assertEqual(m.version, "A 1.0.0"); + assertEqual(m.x.version, "x 1.0.0"); + assertEqual(m.B.version, "B 2.0.0"); + assertEqual(m.C.version, "C 1.0.0"); + assertEqual(m.C.B.version, "B 2.0.0"); + assertEqual(m.D.version, "D 1.0.0"); + + assertEqual(m.B, m.C.B); + + var n = require("TestB"); + + assertEqual(n.version, "B 1.0.0"); + assertNotEqual(n, m.B); + } + + }; +} + +// ----------------------------------------------------------------------------- +// --SECTION-- require module suite +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test suite +//////////////////////////////////////////////////////////////////////////////// + +function RequireModuleSuite () { + var internal = require("internal"); + var console = require("console"); + var modulePath = internal.MODULES_PATH; + var first = modulePath[0]; + + function appendModulePath (testPath) { + internal.MODULES_PATH = modulePath.concat([ first + "/../../common/test-data/modules/commonjs/tests/modules/1.0/" + testPath ]); + module.root.unloadAll(); + + var test = internal.GlobalPackage.defineSystemModule("/test"); + + test.exports.print = internal.print; + + test.exports.assert = function (guard, message) { + console.log("running test %s", message); + assertEqual(guard !== false, true); + }; + } + + return { + +//////////////////////////////////////////////////////////////////////////////// +/// @brief tear down +//////////////////////////////////////////////////////////////////////////////// + + tearDown : function () { + internal.MODULES_PATH = modulePath; + module.root.unloadAll(); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test module loading +//////////////////////////////////////////////////////////////////////////////// + + testRequireCommonJS : function () { + var i; + var tests = [ + "absolute", "cyclic", "determinism", "exactExports", "hasOwnProperty", + "method", "missing", "monkeys", "nested", "relative", "transitive" ]; + + for (i = 0; i < tests.length; i++) { + var name = tests[i]; + + console.log("running CommonJS test '%s'", name); + appendModulePath(name); + require("program"); + } + } + + }; +} + +// ----------------------------------------------------------------------------- +// --SECTION-- main +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @brief executes the test suite +//////////////////////////////////////////////////////////////////////////////// + +jsunity.run(RequirePackageSuite); +jsunity.run(RequireModuleSuite); + +return jsunity.done(); + +// ----------------------------------------------------------------------------- +// --SECTION-- END-OF-FILE +// ----------------------------------------------------------------------------- + +// Local Variables: +// mode: outline-minor +// outline-regexp: "/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}" +// End: diff --git a/lib/V8/v8-utils.cpp b/lib/V8/v8-utils.cpp index b89e9f9e69..11952d0bc8 100644 --- a/lib/V8/v8-utils.cpp +++ b/lib/V8/v8-utils.cpp @@ -199,6 +199,28 @@ static bool LoadJavaScriptDirectory (char const* path, return result; } +//////////////////////////////////////////////////////////////////////////////// +/// @brief creates the path list +//////////////////////////////////////////////////////////////////////////////// + +v8::Handle pathList (string const& modules) { + v8::HandleScope scope; + +#ifdef _WIN32 + vector paths = StringUtils::split(modules, ";",'\0'); +#else + vector paths = StringUtils::split(modules, ";:"); +#endif + + v8::Handle modulesPaths = v8::Array::New(); + + for (uint32_t i = 0; i < (uint32_t) paths.size(); ++i) { + modulesPaths->Set(i, v8::String::New(paths[i].c_str())); + } + + return scope.Close(modulesPaths); +} + //////////////////////////////////////////////////////////////////////////////// /// @} //////////////////////////////////////////////////////////////////////////////// @@ -1446,7 +1468,9 @@ v8::Handle TRI_CreateErrorObject (int errorNumber, string const& mes /// @brief stores the V8 utils functions inside the global variable //////////////////////////////////////////////////////////////////////////////// -void TRI_InitV8Utils (v8::Handle context, string const& path) { +void TRI_InitV8Utils (v8::Handle context, + string const& modules, + string const& nodes) { v8::HandleScope scope; v8::Handle ft; @@ -1494,25 +1518,14 @@ void TRI_InitV8Utils (v8::Handle context, string const& path) { // create the global variables // ............................................................................. - // ............................................................................. // The spilt has been modified -- only except semicolon, previously we excepted // a colon as well. So as not to break existing configurations, we only // make the modification for windows version -- since there isn't one yet! // ............................................................................. -#ifdef _WIN32 - vector paths = StringUtils::split(path, ";",'\0'); -#else - vector paths = StringUtils::split(path, ";:"); -#endif - v8::Handle modulesPaths = v8::Array::New(); - - for (uint32_t i = 0; i < (uint32_t) paths.size(); ++i) { - modulesPaths->Set(i, v8::String::New(paths[i].c_str())); - } - - context->Global()->Set(v8::String::New("MODULES_PATH"), modulesPaths); + context->Global()->Set(v8::String::New("MODULES_PATH"), pathList(modules)); + context->Global()->Set(v8::String::New("PACKAGE_PATH"), pathList(nodes)); } #ifdef TRI_HAVE_ICU diff --git a/lib/V8/v8-utils.h b/lib/V8/v8-utils.h index 64566df188..fa3abd5167 100644 --- a/lib/V8/v8-utils.h +++ b/lib/V8/v8-utils.h @@ -166,8 +166,9 @@ v8::Handle TRI_CreateErrorObject (int errorNumber, std::string const /// @brief stores the V8 utils function inside the global variable //////////////////////////////////////////////////////////////////////////////// -void TRI_InitV8Utils (v8::Handle, std::string const&); - +void TRI_InitV8Utils (v8::Handle, + std::string const& modules, + std::string const& nodes); //////////////////////////////////////////////////////////////////////////////// /// @brief Converts an object to a UTF-8-encoded and normalized character array.