new(injector): new injector v2.0

- not connected to keep the CL small
This commit is contained in:
Misko Hevery
2011-10-31 15:33:52 -07:00
parent 4c10d33eb4
commit c925f8a657
6 changed files with 412 additions and 16 deletions

View File

@@ -948,7 +948,7 @@ function angularInit(config, document){
if (autobind) {
var element = isString(autobind) ? document.getElementById(autobind) : document,
injector = createInjector(),
injector = createInjector(angularService),
scope = injector('$rootScope');
injector('$compile')(element)(scope);

View File

@@ -154,3 +154,142 @@ function inferInjectionArgs(fn) {
}
return fn.$inject;
}
///////////////////////////////////////
function createInjector2(modulesToLoad, moduleRegistry) {
var cache = {},
$injector = internalInjector(cache),
providerSuffix = 'Provider',
providerSuffixLength = providerSuffix.length;
function $provide(name) {
var provider = cache['#' + name + providerSuffix];
if (provider) {
return provider;
} else {
throw Error("No provider for: " + name);
}
}
$provide.service = function(name, provider) {
if (isFunction(provider)){
provider = $injector.instantiate(provider);
}
if (!provider.$get) {
throw Error('Providers must define $get factory method.');
}
cache['#' + name + providerSuffix] = provider;
};
$provide.factory = function(name, factoryFn) { $provide.service(name, { $get:factoryFn }); };
$provide.value = function(name, value) { $provide.factory(name, valueFn(value)); };
$provide.value('$injector', $injector);
$provide.value('$provide', $provide);
function internalInjector(cache) {
var path = [];
function injector(value) {
switch(typeof value) {
case 'function':
return invoke(null, value);
case 'string':
var instanceKey = '#' + value;
if (cache[instanceKey]) {
return cache[instanceKey];
}
try {
path.unshift(value);
var providerKey = instanceKey + providerSuffix,
provider = cache[providerKey];
if (provider) {
return cache[instanceKey] = invoke(provider, provider.$get);
} else {
throw Error("Unknown provider for '" + path.join("' <- '") + "'.");
}
} finally {
path.shift();
}
case 'object':
if (value instanceof Array) {
return invoke(null, value);
}
default:
throw Error('Injector expects name or function.');
}
}
function invoke(self, fn){
var args = [],
$inject,
length;
switch(typeof fn){
case 'function':
$inject = inferInjectionArgs(fn);
length = $inject.length;
break;
case 'object':
if (typeof fn.length == 'number') {
$inject = fn;
length = $inject.length;
fn = $inject[--length];
}
default:
assertArgFn(fn, 'fn');
};
while(length--) {
args.unshift(injector($inject[length], path));
}
switch (self ? -1 : args.length) {
case 0: return fn();
case 1: return fn(args[0]);
case 2: return fn(args[0], args[1]);
case 3: return fn(args[0], args[1], args[2]);
case 4: return fn(args[0], args[1], args[2], args[3]);
case 5: return fn(args[0], args[1], args[2], args[3], args[4]);
case 6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);
case 7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
case 8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
case 9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);
case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);
default: return fn.apply(self, args);
}
};
injector.invoke = invoke;
injector.instantiate = function(Type, locals){
var Constructor = function(){},
instance;
Constructor.prototype = Type.prototype;
instance = new Constructor();
return invoke(instance, Type, locals) || instance;
};
return injector;
}
forEach(modulesToLoad, function(module){
if (isString(module)) {
module = moduleRegistry[module];
}
if (isFunction(module) || isArray(module)) {
$injector(module);
} else {
assertArgFn(module, 'module');
}
});
// instantiate $eager providers
// for perf we can't do forEach
for(var name in cache) {
var index = name.indexOf(providerSuffix);
if (index == name.length - providerSuffixLength && cache[name].$eager) {
$injector(name.substring(1, index));
}
}
return $injector;
}