Comparing version 1.1.0 to 2.0.0
@@ -1,2 +0,2 @@ | ||
// Copyright (c) 2011 Daniel Ennis <aikar@aikar.co> | ||
// Copyright (c) 2013 Daniel Ennis <aikar@aikar.co> | ||
// | ||
@@ -20,164 +20,71 @@ // Permission is hereby granted, free of charge, to any person obtaining a copy | ||
// THE SOFTWARE. | ||
var | ||
fs = require("fs"), | ||
path = require("path"); | ||
var getters = {}; | ||
var gettersIndex = []; | ||
var nameIndex = {}; | ||
var fileIndex = {}; | ||
function getIndex(obj) { | ||
var idx = gettersIndex.indexOf(obj); | ||
if (idx == -1) { | ||
idx = gettersIndex.push(obj)-1; | ||
var path = require("path"); | ||
var dirMap = []; | ||
var indexMap = []; | ||
function registerAutoloader(filePath, obj) { | ||
obj = obj || global; | ||
var index = indexMap.indexOf(obj); | ||
if (index == -1) { | ||
index = indexMap.length; | ||
indexMap.push(obj); | ||
obj.__proto__ = forwarder(obj.__proto__, loadModule); | ||
dirMap[index] = []; | ||
} | ||
dirMap[index].push(filePath); | ||
if (!getters[idx]) { | ||
getters[idx] = {}; | ||
nameIndex[idx] = {}; | ||
fileIndex[idx] = {}; | ||
} | ||
return idx; | ||
} | ||
function defineGetter(obj, objpath, fn, fullPath) { | ||
obj = obj || global | ||
var idx = getIndex(obj); | ||
var getp1 = getters[idx]; | ||
var getp2 = getters[idx]; | ||
var tmpobj = obj; | ||
var curnamearray = []; | ||
objpath.forEach(function(val) { | ||
curnamearray.push(val) | ||
var curname = curnamearray.join('.'); | ||
if (typeof getp1[val] != 'object' || !getp1[val].children) { | ||
var self = getp1[val] = { | ||
parent: getp2, | ||
name: curname, | ||
children: {}, | ||
getter: function() { | ||
if (self.parent && self.parent.getter) { | ||
self.parent.getter(); | ||
return self.getter() | ||
} | ||
return undefined; | ||
}, | ||
create: function() { | ||
return {}; | ||
function loadModule(obj, key) { | ||
var file = key.replace(/_/,"/"); | ||
var dirs = dirMap[index]; | ||
for (var i = 0; i < dirs.length; i++) { | ||
var dir = dirs[i]; | ||
if (typeof dir == 'function') { | ||
var result = dir(key, obj); | ||
if (result !== undefined) { | ||
return result; | ||
} | ||
} | ||
nameIndex[idx][curname] = getp1[val]; | ||
} | ||
if (typeof tmpobj == 'object' && tmpobj && !tmpobj.__lookupGetter__(val)) { | ||
if (tmpobj[val] === undefined) { | ||
(function applyGetter(val, currentp, currentobj) { | ||
currentp.getter = function () { | ||
delete currentobj[val]; | ||
var ret = currentp.create(currentobj, val); | ||
//console.error("getter executed", val, Object.keys(ret)) | ||
// if the callback function set the var for us, don't overwrite it. | ||
if (currentobj[val] == undefined) { | ||
currentobj[val] = ret; | ||
} | ||
Object.keys(currentp.children).forEach(function(key) { | ||
applyGetter(key, currentp.children[key], currentobj[val]); | ||
}); | ||
currentp.getter = function() { | ||
return currentobj[val]; | ||
}; | ||
//console.error("returning", Object.keys(currentobj[val])); | ||
return currentobj[val]; | ||
}; | ||
currentobj.__defineGetter__(val, currentp.getter); | ||
})(val, getp1[val], tmpobj); | ||
tmpobj = null; | ||
} else { | ||
tmpobj = tmpobj[val] | ||
try { | ||
return require(path.join(dir, file)); | ||
} catch (ignored) { } | ||
} | ||
} else { | ||
tmpobj = null | ||
} | ||
getp2 = getp1[val]; | ||
getp1 = getp1[val].children; | ||
}); | ||
// tree built, set creation method... | ||
getp2.create = fn; | ||
fileIndex[idx][fullPath] = getp2; | ||
} | ||
} | ||
module.exports = registerAutoloader; | ||
function forwarder(target, cb){ | ||
var traps = { | ||
getOwnPropertyDescriptor: Object.getOwnPropertyDescriptor.bind(null, target), | ||
getOwnPropertyNames: Object.getOwnPropertyNames.bind(null, target), | ||
getPropertyNames: Object.getOwnPropertyNames.bind(null, target), | ||
keys: Object.keys.bind(null, target), | ||
defineProperty: Object.defineProperty.bind(null, target), | ||
get: function(r,k){ return target[k] }, | ||
set: function(r,k,v){ target[k] = v; return true }, | ||
has: function(k){ return k in target }, | ||
hasOwn: function(k){ return {}.hasOwnProperty.call(target, k) }, | ||
delete: function(k){ delete target[k]; return true }, | ||
enumerate: function(){ var i=0,k=[]; for (k[i++] in target); return k } | ||
}; | ||
function getobjbykey(obj, key) { | ||
key.forEach(function(val) { | ||
if (typeof obj[val] == "object") { | ||
obj = obj[val] | ||
} | ||
}); | ||
return obj | ||
} | ||
function registerAutoloader(filePath, cb, objpath, obj) { | ||
obj = obj || global; | ||
objpath = objpath && objpath.slice(0) || []; | ||
var files = fs.readdirSync(filePath); | ||
files.forEach(function(file) { | ||
var fullPath = filePath + '/' + file; | ||
var stat = fs.statSync(fullPath); | ||
if (stat.isDirectory()) { | ||
registerAutoloader(fullPath, cb, objpath.concat(file), obj); | ||
} else { | ||
var baseDirName = path.basename(filePath, '/'); | ||
if (baseDirName == path.basename(file,'.js')) { | ||
autoload(obj, objpath, fullPath, cb) | ||
} else if (file == 'index.js') { | ||
autoload(obj, objpath, fullPath, cb) | ||
} else { | ||
var extLoc = file.lastIndexOf('.'); | ||
if (extLoc != -1) { | ||
var ext = file.substr(extLoc); | ||
if (require.extensions[ext]) { | ||
autoload(obj, objpath.concat(path.basename(file,ext)), fullPath, cb) | ||
return Proxy.create(Proxy.create({ | ||
get: function(r, trap){ | ||
return function(a, b){ | ||
if (trap === 'get' && b != 'v8debug' && !target[b]) { | ||
var result = cb(a, b); | ||
if (typeof result == 'undefined') { | ||
throw new ReferenceError(b + ' is not defined'); | ||
} else { | ||
return result; | ||
} | ||
} | ||
if (trap in traps) { | ||
return traps[trap].apply(target, arguments); | ||
} | ||
} | ||
} | ||
}); | ||
return obj; | ||
}), Object.getPrototypeOf(target)); | ||
} | ||
function autoload(obj, objpath, fullPath, cb) { | ||
//console.log("AUTOLOAD", objpath, fullPath) | ||
var load = function(obj, key) { | ||
var module = null; | ||
if (typeof cb == 'function') { | ||
module = cb(fullPath, objpath.join('.'), obj, key); | ||
} | ||
if (!module) { | ||
module = require(fullPath); | ||
} | ||
return module; | ||
} | ||
defineGetter(obj, objpath, load, fullPath); | ||
} | ||
module.exports = { | ||
autoload: registerAutoloader, | ||
loadByName: function(name, obj) { | ||
obj = obj || global; | ||
var idx = getIndex(obj); | ||
var p = nameIndex[idx][name] | ||
if (p) { | ||
return p.getter(); | ||
} | ||
return null; | ||
}, | ||
loadByFile: function(file, obj) { | ||
obj = obj || global; | ||
var idx = getIndex(obj); | ||
var p = fileIndex[idx][file] | ||
if (p) { | ||
return p.getter(); | ||
} | ||
return null; | ||
} | ||
} |
{ | ||
"author": "Aikar <aikar@aikar.co> (http://aikar.co)", | ||
"name": "autoloader", | ||
"description": "Autoloads JS Files (designed for Joose)", | ||
"version": "1.1.0", | ||
"description": "Autoloads JS Files", | ||
"version": "2.0.0", | ||
"homepage": "http://aikar.co", | ||
"main": "autoloader.js", | ||
"engines": { | ||
"node": ">=0.4" | ||
"node": ">=0.10" | ||
}, | ||
"dependencies": {}, | ||
"scripts": { | ||
"start":"node autoloader.js" | ||
}, | ||
"devDependencies": {} | ||
} | ||
} |
@@ -11,2 +11,10 @@ ## About | ||
## 2.0 Requirements | ||
2.0 Drastically changes how this project works. It now requires --harmony under Node 0.10, and the usage | ||
scenarios have completely changed. It now will replace underscores as seperators such as Foo_Bar instead | ||
of Foo.Bar. | ||
It also does not have to do any directory scanning and setting up tons of getters, simple Proxy on global catches unreferenced variables! | ||
## Install | ||
@@ -18,2 +26,4 @@ | ||
Run node with --harmony | ||
Folder structure: | ||
@@ -23,4 +33,4 @@ | ||
Foo/ | ||
Foo.js | ||
Bar.js | ||
Foo.js | ||
test.js | ||
@@ -31,13 +41,13 @@ package.json (main: 'test.js') | ||
Foo.js: | ||
lib/Foo.js: | ||
module.export = function() { | ||
console.log("Foo") | ||
Foo.Bar(); | ||
Foo_Bar(); | ||
}; | ||
Bar.js: | ||
lib/Foo/Bar.js: | ||
module.export = function() { | ||
console.log("Foo.Bar") | ||
console.log("Foo_Bar") | ||
}; | ||
@@ -48,34 +58,24 @@ | ||
require('autoloader').autoload(__dirname + '/lib') | ||
require('autoloader')(__dirname + '/lib') | ||
Foo(); | ||
loading the module would print to screen: | ||
Loading the module would print to screen: | ||
Foo | ||
Foo.Bar | ||
ALL MODULES MUST RETURN AN OBJECT/FUNCTION. It can not return Scalar Values! | ||
Foo_Bar | ||
## Custom Loaders | ||
If you pass a function as the 2nd argument, autoloader will execute that before | ||
requiring the file with the following arguments: | ||
If you pass a function as the 1st argument, autoloader will execute that instead of | ||
loading by directory, allowing you to control what is returned. | ||
Callback signature | ||
function (fullPath, className, object, key) { } | ||
fullPath will be the full path to the module file to load, classname would | ||
be 'Foo.Bar.Baz' for example, object would be the object to add a new value | ||
to, and key is the key of object to assign the response. | ||
function (name, object) { } | ||
so if you load 'Foo', object is global, and key is Foo, likewise if you load | ||
Foo.Bar, object is Foo and key is 'Bar'. | ||
You can then do what ever magic it is you need to do, and optionally assign it yourself. | ||
You will need to assign the value yourself if you wish to not have your loader fire every access. | ||
If you don't assign it yourself, simply return the value and autoloader will | ||
assign it for you. | ||
## License | ||
The MIT License | ||
Copyright (c) 2011 Daniel Ennis <aikar@aikar.co> | ||
Copyright (c) 2013 Daniel Ennis <aikar@aikar.co> | ||
@@ -82,0 +82,0 @@ Permission is hereby granted, free of charge, to any person obtaining a copy |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
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
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Non-existent author
Supply chain riskThe package was published by an npm account that no longer exists.
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
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
7
0
2
7695
93
2