/packages/jsio.js
JavaScript | 783 lines | 603 code | 70 blank | 110 comment | 81 complexity | f74994e9275f8f188bf154a8cbba42bf MD5 | raw file
- // Copyright (c) 2010
- // Michael Carter (cartermichael@gmail.com)
- // Martin Hunt (mghunt@gmail.com)
- //
- // 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.
- // Initialization of js.io occurs in a closure, preventing local variables
- // from entering the global scope. During execution, the method `jsio` is
- // added to the global scope.
- ;(function() {
- function init(cloneFrom) {
- // We expect this code to be minified before production use, so we may
- // write code slightly more verbosely than we otherwise would.
-
- // Should we parse syntax errors in the browser?
- var DEBUG = true;
-
- // Store a reference to the slice function for converting objects of
- // type arguments to type array.
- var SLICE = Array.prototype.slice;
-
- // js.io supports multiple JavaScript environments such as node.js and
- // most web browsers (IE, Firefox, WebKit). The ENV object wraps
- // any utility functions that contain environment-specific code (e.g.
- // reading a file using node's `fs` library or a browser's
- // `XMLHttpRequest`). Running js.io in other JavaScript environments
- // is as easy as implementing an environment object that conforms to
- // the abstract interface for an environment (provided below) and
- // calling `jsio.setEnv()`.
- var ENV;
-
- // Checks if the last character in a string is `/`.
- var rexpEndSlash = /\/$/;
-
- // Creates an object containing metadata about a module.
- function makeModuleDef(path, baseMod, basePath) {
- var def = util.splitPath(path + '.js');
- if (baseMod) {
- def.baseMod = baseMod;
- def.basePath = basePath;
- }
- return def;
- }
-
- // Utility functions
- var util = {
- // `util.bind` returns a function that, when called, will execute
- // the method passed in with the provided context and any additional
- // arguments passed to `util.bind`.
- // util.bind(obj, 'f', a) -> function() { return obj.f(a); }
- // util.bind(obj, g, a, b, c) -> function() { return g.call(g, a, b, c); }
- bind: function(context, method/*, args... */) {
- var args = SLICE.call(arguments, 2);
- return function() {
- method = (typeof method == 'string' ? context[method] : method);
- return method.apply(context, args.concat(SLICE.call(arguments, 0)));
- };
- },
-
- // `util.addEndSlash` accepts a string. That string is returned with a `/`
- // appended if the string did not already end in a `/`.
- addEndSlash: function(str) {
- return rexpEndSlash.test(str) ? str : str + '/';
- },
-
- // `util.removeEndSlash` accepts a string. It removes a trailing `/` if
- // one is found.
- removeEndSlash: function(str) {
- return str.replace(rexpEndSlash, '');
- },
-
- // `util.makeRelativePath` accepts two paths (strings) and returns the first path
- // made relative to the second. Note: this function needs some work. It currently
- // handles the most common use cases, but may fail in unexpected edge cases.
- //
- // - Simple case: if `path` starts with `relativeTo`, then we can strip `path`
- // off the `relativeTo` part and we're done.
- //
- // util.makeRelativePath('abc/def/', 'abc') -> 'def'
- //
- // - Harder case: `path` starts with some substring of `relativeTo`. We want to remove this substring and then add `../` for each remaining segment of `relativeTo`.
- //
- // util.makeRelativePath('abc/def/', 'abc/hij') -> '../def'
- //
- makeRelativePath: function(path, relativeTo) {
- var len = relativeTo.length;
- if (path.substring(0, len) == relativeTo) {
- /* Note: we're casting a boolean to an int by adding len to it */
- return path.slice((path.charAt(len) == '/') + len);
- }
-
- var sA = util.removeEndSlash(path).split('/'),
- sB = util.removeEndSlash(relativeTo).split('/'),
- i = 0;
-
- /* Count how many segments match. */
- while(sA[i] == sB[i]) { ++i; }
-
- if (i) {
- /* If at least some segments matched, remove them. The result is our new path. */
- path = sA.slice(i).join('/');
-
- /* Prepend `../` for each segment remaining in `relativeTo`. */
- for (var j = sB.length - i; j > 0; --j) { path = '../' + path; }
- }
-
- return path;
- },
-
- // `buildPath` accepts an arbitrary number of string arguments to concatenate into a path.
- // util.buildPath('a', 'b', 'c/', 'd/') -> 'a/b/c/d/'
- buildPath: function() {
- return util.resolveRelativePath(Array.prototype.join.call(arguments, '/'));
- },
-
- // `resolveRelativePath` removes relative path indicators. For example:
- // util.resolveRelativePath('a/../b') -> b
- resolveRelativePath: function(path) {
- /* If the path starts with a protocol, store it and remove it (add it
- back later) so we don't accidently modify it. */
- var protocol = path.match(/^(\w+:\/\/)(.*)$/);
- if (protocol) { path = protocol[2]; }
-
- /* Remove multiple slashes and trivial dots (`/./ -> /`). */
- path = path.replace(/\/+/g, '/').replace(/\/\.\//g, '/');
-
- /* Loop to collapse instances of `../` in the path by matching a previous
- path segment. Essentially, we find substrings of the form `/abc/../`
- where abc is not `.` or `..` and replace the substrings with `/`.
- We loop until the string no longer changes since after collapsing all
- possible instances once, we may have created more instances that can
- be collapsed.
- */
- var o;
- while((o = path) != (path = path.replace(/(^|\/)(?!\.?\.\/)([^\/]+)\/\.\.\//g, '$1'))) {}
- /* Don't forget to prepend any protocol we might have removed earlier. */
- return protocol ? protocol[1] + path : path;
- },
-
- resolveRelativeModule: function(modulePath, directory) {
- var result = [],
- parts = modulePath.split('.'),
- len = parts.length,
- relative = (len > 1 && !parts[0]),
- i = relative ? 0 : -1;
-
- while(++i < len) { result.push(parts[i] ? parts[i] : '..'); }
- return util.buildPath(relative ? directory : '', result.join('/'));
- },
- resolveModulePath: function(modulePath, directory) {
- // resolve relative paths
- if(modulePath.charAt(0) == '.') {
- return [makeModuleDef(util.resolveRelativeModule(modulePath, directory))];
- }
-
- // resolve absolute paths with respect to jsio packages/
- var pathSegments = modulePath.split('.'),
- baseMod = pathSegments[0],
- pathString = pathSegments.join('/');
-
- if (jsio.path.cache.hasOwnProperty(baseMod)) {
- return [makeModuleDef(util.buildPath(jsio.path.cache[baseMod], pathString))];
- }
-
- var out = [],
- paths = jsio.path.get(),
- len = paths.length;
- for (var i = 0; i < len; ++i) {
- out.push(makeModuleDef(util.buildPath(paths[i], pathString), baseMod, paths[i]));
- }
- return out;
- },
- splitPath: function(path) {
- var i = path.lastIndexOf('/') + 1;
- return {
- path: path,
- directory: path.substring(0, i),
- filename: path.substring(i)
- };
- }
- };
-
- var jsio = util.bind(this, importer, null, null, null);
- jsio.__util = util;
- jsio.__init__ = init;
-
- // explicitly use jsio.__srcCache to avoid obfuscation with closure compiler
- var sourceCache = jsio.__srcCache = {};
- if (cloneFrom && cloneFrom.__srcCache) { sourceCache = jsio.__srcCache = cloneFrom.__srcCache; }
- (function() {
- this.__filename = 'jsio.js';
- this.__preprocessors = {};
- this.__cmds = [];
- this.__jsio = this;
- this.__importer = importer;
- this.__modules = {preprocessors:{}};
-
- this.path = {
- set: function(path) { this.value = (typeof path == 'string' ? [path] : path); },
- get: function() { return this.value.slice(0); },
- add: function(path) {
- var v = this.value, len = v.length;
- for (var i = 0; i < len; ++i) {
- if (v[i] == path) { return; }
- }
- v.push(path);
- },
- remove: function(path) {
- var v = this.value, len = v.length;
- for (var i = 0; i < len; ++i) {
- if (v[i] == path) {
- v.splice(i, 1);
- }
- }
- },
- value: [],
- cache: {}
- };
-
- this.addPath = util.bind(this.path, 'add');
-
- this.setCachedSrc = function(path, src) { sourceCache[path] = { path: path, src: src }; }
- this.getCachedSrc = function(path) { return sourceCache[path]; }
-
- this.addPreprocessor = function(name, preprocessor) { this.__preprocessors[name] = preprocessor; }
- this.addCmd = function(processor) { this.__cmds.push(processor); }
-
- this.setEnv = function(envCtor) {
- if (!envCtor && cloneFrom) {
- ENV = cloneFrom.__env;
- } else if (typeof envCtor == 'string') {
- switch(envCtor) {
- case 'node':
- ENV = new ENV_node(util);
- break;
- case 'browser':
- default:
- ENV = new ENV_browser(util);
- break;
- }
- } else {
- ENV = new envCtor(util);
- }
-
- this.__env = ENV;
- this.__dir = ENV.getCwd();
- this.path.set(ENV.getPath());
- }
- }).call(jsio);
-
- if (cloneFrom) {
- jsio.setEnv();
- } else if (typeof process !== 'undefined' && process.version) {
- jsio.setEnv('node');
- } else if (typeof XMLHttpRequest != 'undefined' || typeof ActiveXObject != 'undefined') {
- jsio.setEnv('browser');
- }
- /*
- function ENV_abstract() {
- this.global = null;
- this.getCwd = function() {};
- this.getPath = function() {};
- this.eval = function(code, path) {};
- this.fetch = function(path) { return contentsOfPath; };
- this.log = function(args...) {};
- }
- */
-
- function ENV_node() {
- var fs = require('fs'),
- sys = require('sys');
-
- this.name = 'node';
- this.global = GLOBAL;
- this.getCwd = process.cwd;
- this.log = function() {
- var msg;
- try {
- sys.error(msg = Array.prototype.map.call(arguments, function(a) {
- if ((a instanceof Error) && a.message) {
- return 'Error:' + a.message + '\nStack:' + a.stack + '\nArguments:' + a.arguments;
- }
- return typeof a == 'string' ? a : JSON.stringify(a);
- }).join(' '));
- } catch(e) {
- sys.error(msg = Array.prototype.join.call(arguments, ' ') + '\n');
- }
- return msg;
- }
-
- this.getPath = function() {
- var segments = __filename.split('/');
- segments.pop();
- return util.makeRelativePath(segments.join('/') || '.', this.getCwd());
- }
- this.eval = process.compile;
-
- this.fetch = function(path) {
- try { return fs.readFileSync(path, 'utf8'); } catch(e) {}
- return false;
- }
-
- this.require = require;
- }
-
- function ENV_browser() {
- var XHR = window.XMLHttpRequest || function() { return new ActiveXObject("Msxml2.XMLHTTP"); },
- cwd = null,
- path = null;
-
- this.name = 'browser';
- this.global = window;
- this.global.jsio = jsio;
-
- this.log = function() {
- var args = SLICE.call(arguments, 0);
- if (typeof console != 'undefined' && console.log) {
- //for iOS mobile safari w/ debugger console enabled,
- //uncomment the following two lines for more useful
- //messages
- //console.log(args.join(' '));
- //return;
-
- if (console.log.apply) {
- console.log.apply(console, arguments);
- } else { // IE doesn't support log.apply, and the argument cannot be arguments - it must be an array
- console.log(args);
- }
- }
- return args.join(' ');
- }
-
- this.getCwd = function() {
- if(!cwd) {
- var loc = window.location, path = loc.pathname;
- cwd = loc.protocol + '//' + loc.host + path.substring(0, path.lastIndexOf('/') + 1);
- }
- return cwd;
- }
-
- this.getPath = function() {
- if(!path) {
- try {
- var filename = new RegExp('(.*?)' + jsio.__filename + '(\\?.*)?$'),
- scripts = document.getElementsByTagName('script');
-
- for (var i = 0, script; script = scripts[i]; ++i) {
- var result = script.src.match(filename);
- if (result) {
- path = result[1];
- if (/^[A-Za-z]*:\/\//.test(path)) { path = util.makeRelativePath(path, this.getCwd()); }
- break;
- }
- }
- } catch(e) {}
-
- if(!path) { path = '.'; }
- }
- return path;
- }
-
- this.debugPath = function(path) { return path; }
- // IE6 won't return an anonymous function from eval, so use the function constructor instead
- var rawEval = typeof eval('(function(){})') == 'undefined'
- ? function(src, path) { return (new Function('return ' + src))(); }
- : function(src, path) { var src = src + '\n//@ sourceURL=' + path; return window.eval(src); };
- // provide an eval with reasonable debugging
- this.eval = function(code, path, origCode) {
- try {
- return rawEval(code, this.debugPath(path));
- } catch(e) {
- if(e instanceof SyntaxError) {
- ENV.log("a syntax error is preventing execution of " + path);
- if (DEBUG && this.checkSyntax) {
- this.checkSyntax(origCode, path);
- }
- }
- throw e;
- }
- }
-
- this.checkSyntax = function(code, path) {
- try {
- var syntax = jsio('import util.syntax', {suppressErrors: true, dontExport: true}),
- result = syntax(code);
- syntax.display(result, path);
- } catch(e) {}
- }
-
- this.fetch = function(path) {
- var xhr = new XHR();
- try {
- xhr.open('GET', path, false);
- xhr.send(null);
- } catch(e) {
- ENV.log('e:', e);
- return false; // firefox file://
- }
-
- if (xhr.status == 404 || // all browsers, http://
- xhr.status == -1100 || // safari file://
- // XXX: We have no way to tell in opera if a file exists and is empty, or is 404
- // XXX: Use flash?
- //(!failed && xhr.status == 0 && !xhr.responseText && EXISTS)) // opera
- false)
- {
- return false;
- }
-
- return xhr.responseText;
- }
- };
-
- var preprocessorCheck = /^"use (.*?)"\s*;\s*\n/,
- preprocessorFunc = /^(.+)\(.+\)$/,
- failedFetch = {};
-
- function findModule(possibilities, opts) {
- var src;
- for (var i = 0, possible; possible = possibilities[i]; ++i) {
- var path = possible.path,
- cachedVersion = sourceCache[path];
-
- if (cachedVersion) {
- possible.src = cachedVersion.src;
- return possible;
- }
-
- /*if (/^\.\//.test(path)) {
- // remove one path segment for each dot from the cwd
- path = addEndSlash(ENV.getCwd()) + path;
- }*/
-
- src = ENV.fetch(path);
-
- if (src !== false) {
- possible.src = src;
- return possible;
- } else {
- failedFetch[path] = true;
- }
- }
-
- return false;
- }
-
- // load a module from a file
- function loadModule(fromDir, fromFile, modulePath, opts) {
- var possibilities = util.resolveModulePath(modulePath, fromDir);
- for (var i = 0, p; p = possibilities[i]; ++i) {
- var path = possibilities[i].path;
- if (!opts.reload && (path in jsio.__modules)) {
- return possibilities[i];
- }
- if (path in failedFetch) { possibilities.splice(i--, 1); }
- }
-
- if (!possibilities.length) {
- if (opts.suppressErrors) { return false; }
- var e = new Error('Module failed to load (again)');
- e.jsioLogged = true;
- throw e;
- }
-
- var moduleDef = findModule(possibilities, opts),
- match;
-
- if (!moduleDef) {
- if (opts.suppressErrors) { return false; }
- var paths = [];
- for (var i = 0, p; p = possibilities[i]; ++i) { paths.push(p.path); }
- throw new Error(fromDir + fromFile + ": \n\tcurrent directory: " + ENV.getCwd() + "\n\tlooked in:\n\t\t" + paths.join('\n\t\t') + '\n\tImport Stack:\n\t\t' + importStack.join('\n\t\t') + "\n\tError: requested import (" + modulePath + ") not found.");
- }
-
- moduleDef.friendlyPath = modulePath;
-
- if (moduleDef.baseMod && !(moduleDef.baseMod in jsio.path.cache)) {
- jsio.path.cache[moduleDef.baseMod] = moduleDef.basePath;
- }
-
- // the order here is somewhat arbitrary and might be overly restrictive (... or overly powerful)
- while (moduleDef.src.charAt(0) == '"' && (match = moduleDef.src.match(preprocessorCheck))) {
- moduleDef.src = moduleDef.src.substring(match[0].length - 1);
- applyPreprocessors(fromDir, moduleDef, match[1].split(','), opts);
- }
-
- if (opts.preprocessors) {
- applyPreprocessors(fromDir, moduleDef, opts.preprocessors, opts);
- }
-
- return moduleDef;
- }
-
- function applyPreprocessors(path, moduleDef, names, opts) {
- for (var i = 0, len = names.length; i < len; ++i) {
- p = getPreprocessor(names[i]);
- if (p) {
- p(path, moduleDef, opts);
- }
- }
- }
-
- function getPreprocessor(name) {
- return typeof name == 'function'
- ? name
- : (jsio.__modules['preprocessors.' + name]
- || jsio('import preprocessors.' + name, {dontExport: true}));
- }
-
- function execModuleDef(context, moduleDef) {
- var code = "(function(_){with(_){delete _;return function $$" + moduleDef.friendlyPath.replace(/[\/.]/g, '_') + "(){" + moduleDef.src + "\n}}})";
- var fn = ENV.eval(code, moduleDef.path, moduleDef.src);
- fn = fn(context);
- fn.call(context.exports);
- };
-
- function resolveImportRequest(context, request, opts) {
- var cmds = jsio.__cmds,
- imports = [],
- result = false;
-
- for (var i = 0, imp; imp = cmds[i]; ++i) {
- if ((result = imp(context, request, opts, imports))) { break; }
- }
-
- if (result !== true) {
- throw new (typeof SyntaxError != 'undefined' ? SyntaxError : Error)(String(result || 'invalid jsio command: jsio(\'' + request + '\')'));
- }
-
- return imports;
- };
-
- function makeContext(ctx, modulePath, moduleDef, dontAddBase) {
- if (!ctx) { ctx = {}; }
- if (!ctx.exports) { ctx.exports = {}; }
- ctx.jsio = util.bind(this, importer, ctx, moduleDef.directory, moduleDef.filename);
- ctx.require = function(request, opts) {
- if (!opts) { opts = {}; }
- opts.dontExport = true;
- opts.suppressErrors = true;
-
- try {
- var ret = ctx.jsio(request, opts);
- if (ret === false) {
- // need this to trigger require attempt due to suppresserrors = true
- throw "module failed to load";
- } else {
- return ret;
- }
- } catch(e) {
- try {
- return require(request);
- } catch(e2) {
- ENV.log('Error loading request ' + request + ':');
- ENV.log(e);
- ENV.log('Also could not load using standard CommonJS');
- ENV.log(e2);
- throw e;
- }
- }
- };
-
- ctx.module = {id: modulePath, exports: ctx.exports};
- if (!dontAddBase && modulePath != 'base') {
- ctx.jsio('from base import *');
- ctx.logging.__create(modulePath, ctx);
- }
-
- // TODO: FIX for "trailing ." case
- ctx.jsio.__jsio = jsio;
- ctx.jsio.__env = jsio.__env;
- ctx.jsio.__dir = moduleDef.directory;
- ctx.jsio.__filename = moduleDef.filename;
- ctx.jsio.__path = modulePath;
- ctx.jsio.path = jsio.path;
- return ctx;
- };
-
- var importStack = [];
- function importer(boundContext, fromDir, fromFile, request, opts) {
- opts = opts || {};
- fromDir = fromDir || './';
- fromFile = fromFile || '<initial file>';
-
- // importer is bound to a module's (or global) context -- we can override this
- // by using opts.exportInto
- var exportInto = opts.exportInto || boundContext || ENV.global;
-
- // parse the import request(s)
- var imports = resolveImportRequest(exportInto, request, opts),
- numImports = imports.length,
- retVal = numImports > 1 ? {} : null;
-
- // import each requested item
- for(var i = 0; i < numImports; ++i) {
- var item = imports[i],
- modulePath = item.from,
- modules = jsio.__modules;
-
- try {
- var moduleDef = loadModule(fromDir, fromFile, modulePath, opts);
- if (moduleDef === false) { return false; }
- } catch(e) {
- if (!e.jsioLogged) {
- ENV.log('\nError loading module:\n\trequested:', modulePath, '\n\tfrom:', fromDir + fromFile, '\n\tfull request:', request, '\n');
- e.jsioLogged = true;
- }
- throw e;
- }
-
- importStack.push(importStack.length + ' : ' + moduleDef.friendlyPath + ' (' + moduleDef.path + ')');
-
- // eval any packages that we don't know about already
- var path = moduleDef.path;
- if(!(path in modules)) {
- var newContext = makeContext(opts.context, modulePath, moduleDef, item.dontAddBase);
- modules[path] = newContext.exports;
- if(item.dontUseExports) {
- var src = [';(function(){'], k = 1;
- for (var j in item['import']) {
- newContext.exports[j] = undefined;
- src[k++] = 'if(typeof '+j+'!="undefined"&&exports.'+j+'==undefined)exports.'+j+'='+j+';';
- }
- src[k] = '})();';
- moduleDef.src += src.join('');
- }
- execModuleDef(newContext, moduleDef);
- modules[path] = newContext.exports;
- }
-
- importStack.pop();
-
- var module = modules[path];
-
- // return the module if we're only importing one module
- if (numImports == 1) { retVal = module; }
-
- if (!opts.dontExport) {
- // add the module to the current context
- if (item.as) {
- // remove trailing/leading dots
- var as = item.as.match(/^\.*(.*?)\.*$/)[1],
- segments = as.split('.'),
- kMax = segments.length - 1,
- c = exportInto;
-
- // build the object in the context
- for(var k = 0; k < kMax; ++k) {
- var segment = segments[k];
- if (!segment) continue;
- if (!c[segment]) { c[segment] = {}; }
- c = c[segment];
- }
-
- c[segments[kMax]] = module;
-
- // there can be multiple module imports with this syntax (import foo, bar)
- if (numImports > 1) {
- retVal[as] = module;
- }
- } else if(item['import']) {
- // there can only be one module import with this syntax
- // (from foo import bar), so retVal will already be set here
- if(item['import']['*']) {
- for(var k in modules[path]) { exportInto[k] = module[k]; }
- } else {
- try {
- for(var k in item['import']) { exportInto[item['import'][k]] = module[k]; }
- } catch(e) {
- ENV.log('module: ', modules);
- throw e;
- }
- }
- }
- }
- }
-
- return retVal;
- }
-
- // DEFINE SYNTAX FOR JSIO('cmd')
-
- // from myPackage import myFunc
- // external myPackage import myFunc
- jsio.addCmd(function(context, request, opts, imports) {
- var match = request.match(/^\s*(from|external)\s+([\w.$]+)\s+(import|grab)\s+(.*)$/);
- if(match) {
- imports.push({
- from: match[2],
- dontAddBase: match[1] == 'external',
- dontUseExports: match[3] == 'grab' || match[1] == 'external',
- 'import': {}
- });
-
- match[4].replace(/\s*([\w.$*]+)(?:\s+as\s+([\w.$]+))?/g, function(_, item, as) {
- imports[0]['import'][item] = as || item;
- });
- return true;
- }
- });
- // import myPackage
- jsio.addCmd(function(context, request, opts, imports) {
- var match = request.match(/^\s*import\s+(.*)$/);
- if (match) {
- match[1].replace(/\s*([\w.$]+)(?:\s+as\s+([\w.$]+))?,?/g, function(_, fullPath, as) {
- imports.push(
- as ? {
- from: fullPath,
- as: as
- } : {
- from: fullPath,
- as: fullPath
- });
- });
- return true;
- }
- });
- // CommonJS syntax
- jsio.addCmd(function(context, request, opts, imports) {
-
- // ./../b -> ..b
- // ../../b -> ...b
- // ../b -> ..b
- // ./b -> .b
-
- var match = request.match(/^\s*[\w.0-9$\/]+\s*$/);
- if (match) {
-
- var req = util.resolveRelativePath(match[0]),
- isRelative = req.charAt(0) == '.';
-
- req = req
- // .replace(/^\//, '') // remove any leading slash
- .replace(/\.\.\//g, '.') // replace relative path indicators with dots
- .replace(/\.\//g, '')
- .replace(/\//g, '.'); // any remaining slashes are path separators
- imports[0] = { from: (isRelative ? '.' : '') + req };
- return true;
- }
- });
-
- jsio.install = function(){
- jsio('from base import *');
- GLOBAL['logger'] = logging.get('jsiocore');
- };
-
- jsio.clone = function() {
- var copy = jsio.__init__(jsio);
- if (ENV.name == 'browser') { window.jsio = jsio; }
- return copy;
- }
- return jsio;
- }
- jsio = init();
- })();