Comparing version 0.3.0 to 0.4.0
237
install.js
@@ -1,38 +0,57 @@ | ||
(function (global, undefined) { | ||
if (global.makeInstaller) { | ||
return; | ||
} | ||
makeInstaller = function (options) { | ||
options = options || {}; | ||
function makeInstaller(options) { | ||
var root = new File({}); | ||
// These file extensions will be appended to required module identifiers | ||
// if they do not exactly match an installed module. | ||
var extensions = options.extensions || [".js", ".json"]; | ||
// Set up a simple queue for tracking required modules with unmet | ||
// dependencies. See also `queueAppend` and `queueFlush`. | ||
var q = root.q = {}; | ||
q.h = q.t = {}; // Queue head, queue tail. | ||
// Configurable function for deferring queue flushes. | ||
q.d = options && options.defer || function (fn) { | ||
setTimeout(fn, 0); | ||
}; | ||
// This constructor will be used to instantiate the module objects | ||
// passed to module factory functions (i.e. the third argument after | ||
// require and exports). | ||
var Module = options.Module || function Module(id, parent) { | ||
this.id = id; | ||
this.parent = parent; | ||
}; | ||
return function install(tree) { | ||
if (isObject(tree)) { | ||
fileMergeContents(root, tree); | ||
queueFlush(root.q); | ||
} | ||
return root.r; | ||
}; | ||
} | ||
// If defined, the options.onInstall function will be called any time | ||
// new modules are installed. | ||
var onInstall = options.onInstall; | ||
global.makeInstaller = makeInstaller; | ||
// If defined, the options.fallback function will be called when no | ||
// installed module is found for a required module identifier. Often | ||
// options.fallback will be implemented in terms of the native Node | ||
// require function, which has the ability to load binary modules. | ||
var fallback = options.fallback; | ||
if (typeof exports === "object") { | ||
exports.makeInstaller = makeInstaller; | ||
} | ||
// Whenever a new require function is created in the makeRequire | ||
// function below, any methods contained by options.requireMethods will | ||
// be bound and attached as methods to that function object. This option | ||
// is intended to support user-defined require.* extensions like | ||
// require.ensure and require.promise. | ||
var requireMethods = options.requireMethods; | ||
var extensions = [".js", ".json"]; | ||
// Sentinel returned by fileEvaluate when module resolution fails. | ||
var MISSING = {}; | ||
// Nothing special about MISSING.hasOwnProperty, except that it's fewer | ||
// characters than Object.prototype.hasOwnProperty after minification. | ||
var hasOwn = MISSING.hasOwnProperty; | ||
var Ap = Array.prototype; | ||
// The file object representing the root directory of the installed | ||
// module tree. | ||
var root = new File({}); | ||
// Merges the given tree of directories and module factory functions | ||
// into the tree of installed modules and returns a require function | ||
// that behaves as if called from a module in the root directory. | ||
function install(tree) { | ||
if (isObject(tree)) { | ||
fileMergeContents(root, tree); | ||
if (isFunction(onInstall)) { | ||
onInstall(root.r); | ||
} | ||
} | ||
return root.r; | ||
} | ||
function getOwn(obj, key) { | ||
@@ -54,53 +73,34 @@ return hasOwn.call(obj, key) && obj[key]; | ||
function queueAppend(q, file) { | ||
// Property names shortened to shave bytes: `.t` means `.tail`, `.h` | ||
// means `.head`, `.n` means `.next`, and `.f` means `.file`. | ||
q.t = q.t.n = { f: file }; | ||
if (q.h.n === q.t) { | ||
// If the queue contains only one File (the one we just added), go | ||
// ahead and schedule a flush. | ||
queueFlush(q); | ||
function makeRequire(file) { | ||
function require(id) { | ||
var result = fileEvaluate(fileResolve(file, id)); | ||
if (result === MISSING) { | ||
var error = new Error("Cannot find module '" + id + "'"); | ||
if (isFunction(fallback)) { | ||
result = fallback( | ||
id, // The missing module identifier. | ||
file.m.id, // The path of the enclosing directory. | ||
error // The error we would have thrown. | ||
); | ||
} else throw error; | ||
} | ||
return result; | ||
} | ||
} | ||
function queueFlush(q) { | ||
// The `q.p` property is set to indicate a flush is pending. | ||
q.p || (q.p = true, q.d(function () { | ||
q.p = undefined; | ||
var next = q.h.n; | ||
if (next && fileReady(next.f)) { | ||
queueFlush(q); // Schedule the next flush. | ||
q.h = next; | ||
fileEvaluate(next.f); | ||
} | ||
})); | ||
} | ||
// A function that immediately returns true iff all the transitive | ||
// dependencies of the module identified by id have been installed. | ||
// This function can be used with options.onInstall to implement | ||
// asynchronous module loading APIs like require.ensure. | ||
require.ready = function (id) { | ||
return fileReady(fileResolve(file, id)); | ||
}; | ||
// These `unbound{Require,Ensure}` functions need to be bound to File | ||
// objects before they can be used. See `makeRequire`. | ||
function unboundRequire(id) { | ||
var result = fileEvaluate(fileResolve(this, id)); | ||
if (result === MISSING) { | ||
throw new Error("Cannot find module '" + id + "'"); | ||
if (requireMethods) { | ||
Object.keys(requireMethods).forEach(function (name) { | ||
if (isFunction(requireMethods[name])) { | ||
require[name] = requireMethods[name].bind(require); | ||
} | ||
}); | ||
} | ||
return result; | ||
} | ||
function unboundEnsure() { | ||
// Flatten arguments into an array containing relative module | ||
// identifier strings and an optional callback function, then coerce | ||
// that array into a callback function with a `.d` property. | ||
var flatArgs = Ap.concat.apply(Ap, arguments); | ||
var callback = ensureObjectOrFunction(flatArgs); | ||
// Note that `queueAppend` schedules a flush if there are no other | ||
// callbacks waiting in the queue. | ||
queueAppend(this.q, new File(callback, this)); | ||
} | ||
function makeRequire(file) { | ||
var require = unboundRequire.bind(file); | ||
require.ensure = unboundEnsure.bind(file); | ||
// TODO Consider adding `require.promise`. | ||
return require; | ||
@@ -129,7 +129,8 @@ } | ||
// .exports property when/if the file is evaluated. | ||
file.m = { | ||
file.m = new Module( | ||
// If this file was created with `name`, join it with `parent.m.id` | ||
// to generate a module identifier. | ||
id: name ? (parent && parent.m.id || "") + "/" + name : null | ||
}; | ||
name ? (parent && parent.m.id || "") + "/" + name : null, | ||
parent && parent.m | ||
); | ||
@@ -174,3 +175,3 @@ // Queue for tracking required modules with unmet dependencies, | ||
}); | ||
factory.seen = undefined; | ||
factory.seen = false; | ||
} | ||
@@ -185,3 +186,3 @@ return result; | ||
if (! hasOwn.call(module, "exports")) { | ||
factory.call(global, file.r, module.exports = {}, module); | ||
factory(file.r, module.exports = {}, module); | ||
} | ||
@@ -198,21 +199,2 @@ return module.exports; | ||
function fileMergeContents(file, contents) { | ||
if ((contents = ensureObjectOrFunction(contents))) { | ||
var fileContents = file.c = file.c || ( | ||
isFunction(contents) ? contents : {} | ||
); | ||
if (isObject(contents) && fileIsDirectory(file)) { | ||
Object.keys(contents).forEach(function (key) { | ||
var child = getOwn(fileContents, key); | ||
if (child) { | ||
fileMergeContents(child, contents[key]); | ||
} else { | ||
fileContents[key] = new File(contents[key], file, key); | ||
} | ||
}); | ||
} | ||
} | ||
}; | ||
function ensureObjectOrFunction(contents) { | ||
// If contents is an array of strings and functions, return the last | ||
@@ -222,3 +204,2 @@ // function with a `.d` property containing all the strings. | ||
var deps = []; | ||
var func; | ||
@@ -229,20 +210,15 @@ contents.forEach(function (item) { | ||
} else if (isFunction(item)) { | ||
func = item; | ||
contents = item; | ||
} | ||
}); | ||
// If no function was found in the array, provide a default function | ||
// that simply requires each dependency (really common case). | ||
contents = func || function (require) { | ||
deps.forEach(function (key) { | ||
require.ensure(function () { | ||
require(key); | ||
}); | ||
}); | ||
}; | ||
if (isFunction(contents)) { | ||
contents.d = deps; | ||
} else { | ||
// If the array did not contain a function, merge nothing. | ||
contents = null; | ||
} | ||
contents.d = deps; | ||
} else if (isFunction(contents)) { | ||
// If contents is already a function, make sure it has deps. | ||
// If contents is already a function, make sure it has `.d`. | ||
contents.d = contents.d || []; | ||
@@ -252,7 +228,22 @@ | ||
// If contents is neither an array nor a function nor an object, | ||
// just give up and return null. | ||
// just give up and merge nothing. | ||
contents = null; | ||
} | ||
return contents; | ||
if (contents) { | ||
var fileContents = file.c = file.c || ( | ||
isFunction(contents) ? contents : {} | ||
); | ||
if (isObject(contents) && fileIsDirectory(file)) { | ||
Object.keys(contents).forEach(function (key) { | ||
var child = getOwn(fileContents, key); | ||
if (child) { | ||
fileMergeContents(child, contents[key]); | ||
} else { | ||
fileContents[key] = new File(contents[key], file, key); | ||
} | ||
}); | ||
} | ||
} | ||
} | ||
@@ -289,3 +280,3 @@ | ||
return exactChild; | ||
}; | ||
} | ||
@@ -300,6 +291,2 @@ function fileAppendId(file, id) { | ||
return file; | ||
}; | ||
function fileGetRoot(file) { | ||
return file && fileGetRoot(file.p) || file; | ||
} | ||
@@ -313,3 +300,3 @@ | ||
// file system. | ||
id.charAt(0) === "/" ? fileAppendId(fileGetRoot(file), id) : | ||
id.charAt(0) === "/" ? fileAppendId(root, id) : | ||
// Relative module identifiers are interpreted relative to the | ||
@@ -341,4 +328,8 @@ // current file, naturally. | ||
} | ||
})("object" === typeof global ? global : | ||
"object" === typeof window ? window : | ||
"object" === typeof self ? self : this); | ||
return install; | ||
}; | ||
if (typeof exports === "object") { | ||
exports.makeInstaller = makeInstaller; | ||
} |
@@ -1,1 +0,1 @@ | ||
!function(n,r){function t(n){var r=new p({}),t=r.q={};return t.h=t.t={},t.d=n&&n.defer||function(n){setTimeout(n,0)},function(n){return o(n)&&(y(r,n),c(r.q)),r.r}}function e(n,r){return A.call(n,r)&&n[r]}function o(n){return n&&"object"==typeof n}function u(n){return"function"==typeof n}function f(n){return"string"==typeof n}function i(n,r){n.t=n.t.n={f:r},n.h.n===n.t&&c(n)}function c(n){n.p||(n.p=!0,n.d(function(){n.p=r;var t=n.h.n;t&&v(t.f)&&(c(n),n.h=t,d(t.f))}))}function a(n){var r=d(g(this,n));if(r===q)throw new Error("Cannot find module '"+n+"'");return r}function s(){var n=E.concat.apply(E,arguments),r=m(n);i(this.q,new p(r,this))}function l(n){var r=a.bind(n);return r.ensure=s.bind(n),r}function p(n,r,t){var e=this;e.p=r=r||null,e.m={id:t?(r&&r.m.id||"")+"/"+t:null},e.q=r&&r.q,e.r=o(n)?l(e):r&&r.r,y(e,n),e.ready=h(e)&&{}}function v(n){var t=!!n,o=n&&n.c,f=u(o)&&o.d;if(f&&!e(o,"seen")){o.seen=!0;var i=n.p.ready;t=f.every(function(r){return i[r]=i[r]||v(g(n.p,r))}),o.seen=r}return t}function d(r){var t=r&&r.c;if(u(t)){var e=r.m;return A.call(e,"exports")||t.call(n,r.r,e.exports={},e),e.exports}return q}function h(n){return o(n.c)}function y(n,r){if(r=m(r)){var t=n.c=n.c||(u(r)?r:{});o(r)&&h(n)&&Object.keys(r).forEach(function(o){var u=e(t,o);u?y(u,r[o]):t[o]=new p(r[o],n,o)})}}function m(n){if(Array.isArray(n)){var r,t=[];n.forEach(function(n){f(n)?t.push(n):u(n)&&(r=n)}),n=r||function(n){t.forEach(function(r){n.ensure(function(){n(r)})})},n.d=t}else u(n)?n.d=n.d||[]:o(n)||(n=null);return n}function b(n,r,t){for(;n&&!h(n);)n=n.p;if(!n||!r||"."===r)return n;if(".."===r)return n.p;var o=e(n.c,r);if(t&&(!o||h(o)))for(var u=0;u<k.length;++u){var f=e(n.c,r+k[u]);if(f)return f}return o}function j(n,r){var t=r.split("/");return t.every(function(r,e){return n=b(n,r,e===t.length-1)}),n}function w(n){return n&&w(n.p)||n}function g(n,r){for(n="/"===r.charAt(0)?j(w(n),r):"."===r.charAt(0)?j(n,r):x(n,r);n&&h(n);){var t=d(b(n,"package.json"));n=t&&f(t.main)&&j(n,t.main)||b(n,"index.js")}return n}function x(n,r){return h(n)&&j(n,"node_modules/"+r)||n.p&&x(n.p,r)}if(!n.makeInstaller){n.makeInstaller=t,"object"==typeof exports&&(exports.makeInstaller=t);var k=[".js",".json"],q={},A=q.hasOwnProperty,E=Array.prototype}}("object"==typeof global?global:"object"==typeof window?window:"object"==typeof self?self:this); | ||
makeInstaller=function(n){function r(n){return e(n)&&(l(g,n),u(j)&&j(g.r)),g.r}function t(n,r){return w.call(n,r)&&n[r]}function e(n){return n&&"object"==typeof n}function u(n){return"function"==typeof n}function o(n){return"string"==typeof n}function i(n){function r(r){var t=a(v(n,r));if(t===b){var e=new Error("Cannot find module '"+r+"'");if(!u(k))throw e;t=k(r,n.m.id,e)}return t}return r.ready=function(r){return c(v(n,r))},x&&Object.keys(x).forEach(function(n){u(x[n])&&(r[n]=x[n].bind(r))}),r}function f(n,r,t){var u=this;u.p=r=r||null,u.m=new m(t?(r&&r.m.id||"")+"/"+t:null,r&&r.m),u.q=r&&r.q,u.r=e(n)?i(u):r&&r.r,l(u,n),u.ready=s(u)&&{}}function c(n){var r=!!n,e=n&&n.c,o=u(e)&&e.d;if(o&&!t(e,"seen")){e.seen=!0;var i=n.p.ready;r=o.every(function(r){return i[r]=i[r]||c(v(n.p,r))}),e.seen=!1}return r}function a(n){var r=n&&n.c;if(u(r)){var t=n.m;return w.call(t,"exports")||r(n.r,t.exports={},t),t.exports}return b}function s(n){return e(n.c)}function l(n,r){if(Array.isArray(r)){var i=[];r.forEach(function(n){o(n)?i.push(n):u(n)&&(r=n)}),u(r)?r.d=i:r=null}else u(r)?r.d=r.d||[]:e(r)||(r=null);if(r){var c=n.c=n.c||(u(r)?r:{});e(r)&&s(n)&&Object.keys(r).forEach(function(e){var u=t(c,e);u?l(u,r[e]):c[e]=new f(r[e],n,e)})}}function p(n,r,e){for(;n&&!s(n);)n=n.p;if(!n||!r||"."===r)return n;if(".."===r)return n.p;var u=t(n.c,r);if(e&&(!u||s(u)))for(var o=0;o<y.length;++o){var i=t(n.c,r+y[o]);if(i)return i}return u}function d(n,r){var t=r.split("/");return t.every(function(r,e){return n=p(n,r,e===t.length-1)}),n}function v(n,r){for(n="/"===r.charAt(0)?d(g,r):"."===r.charAt(0)?d(n,r):h(n,r);n&&s(n);){var t=a(p(n,"package.json"));n=t&&o(t.main)&&d(n,t.main)||p(n,"index.js")}return n}function h(n,r){return s(n)&&d(n,"node_modules/"+r)||n.p&&h(n.p,r)}n=n||{};var y=n.extensions||[".js",".json"],m=n.Module||function(n,r){this.id=n,this.parent=r},j=n.onInstall,k=n.fallback,x=n.requireMethods,b={},w=b.hasOwnProperty,g=new f({});return r},"object"==typeof exports&&(exports.makeInstaller=makeInstaller); |
@@ -18,3 +18,3 @@ { | ||
], | ||
"version": "0.3.0", | ||
"version": "0.4.0", | ||
"license": "MIT", | ||
@@ -21,0 +21,0 @@ "homepage": "http://github.com/benjamn/install", |
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
421970
22
1104
4