Comparing version 2.0.0-pre-7 to 2.0.0-pre-8
@@ -11,3 +11,3 @@ define(['./util'], function($__0) { | ||
($traceurRuntime.createClass)(TransientScope, {}, {}); | ||
var InjectAnnotation = function InjectAnnotation() { | ||
var Inject = function Inject() { | ||
for (var tokens = [], | ||
@@ -18,5 +18,6 @@ $__6 = 0; $__6 < arguments.length; $__6++) | ||
this.isPromise = false; | ||
this.isLazy = false; | ||
}; | ||
($traceurRuntime.createClass)(InjectAnnotation, {}, {}); | ||
var InjectPromiseAnnotation = function InjectPromiseAnnotation() { | ||
($traceurRuntime.createClass)(Inject, {}, {}); | ||
var InjectPromise = function InjectPromise() { | ||
for (var tokens = [], | ||
@@ -27,15 +28,6 @@ $__7 = 0; $__7 < arguments.length; $__7++) | ||
this.isPromise = true; | ||
this.isLazy = false; | ||
}; | ||
($traceurRuntime.createClass)(InjectPromiseAnnotation, {}, {}, InjectAnnotation); | ||
var ProvideAnnotation = function ProvideAnnotation(token) { | ||
this.token = token; | ||
this.isPromise = false; | ||
}; | ||
($traceurRuntime.createClass)(ProvideAnnotation, {}, {}); | ||
var ProvidePromiseAnnotation = function ProvidePromiseAnnotation(token) { | ||
this.token = token; | ||
this.isPromise = true; | ||
}; | ||
($traceurRuntime.createClass)(ProvidePromiseAnnotation, {}, {}, ProvideAnnotation); | ||
var InjectLazyAnnotation = function InjectLazyAnnotation() { | ||
($traceurRuntime.createClass)(InjectPromise, {}, {}, Inject); | ||
var InjectLazy = function InjectLazy() { | ||
for (var tokens = [], | ||
@@ -48,8 +40,13 @@ $__8 = 0; $__8 < arguments.length; $__8++) | ||
}; | ||
($traceurRuntime.createClass)(InjectLazyAnnotation, {}, {}, InjectAnnotation); | ||
var Inject = InjectAnnotation; | ||
var InjectPromise = InjectPromiseAnnotation; | ||
var Provide = ProvideAnnotation; | ||
var ProvidePromise = ProvidePromiseAnnotation; | ||
var InjectLazy = InjectLazyAnnotation; | ||
($traceurRuntime.createClass)(InjectLazy, {}, {}, Inject); | ||
var Provide = function Provide(token) { | ||
this.token = token; | ||
this.isPromise = false; | ||
}; | ||
($traceurRuntime.createClass)(Provide, {}, {}); | ||
var ProvidePromise = function ProvidePromise(token) { | ||
this.token = token; | ||
this.isPromise = true; | ||
}; | ||
($traceurRuntime.createClass)(ProvidePromise, {}, {}, Provide); | ||
function annotate(fn, annotation) { | ||
@@ -76,7 +73,7 @@ fn.annotations = fn.annotations || []; | ||
var collectedAnnotations = { | ||
provideToken: null, | ||
isPromise: false, | ||
injectTokens: [], | ||
injectPromises: [], | ||
injectLazily: [] | ||
provide: { | ||
token: null, | ||
isPromise: false | ||
}, | ||
params: [] | ||
}; | ||
@@ -88,8 +85,14 @@ if (fn.annotations && fn.annotations.length) { | ||
{ | ||
if (annotation instanceof InjectAnnotation) { | ||
collectedAnnotations.injectTokens = annotation.tokens; | ||
if (annotation instanceof Inject) { | ||
collectedAnnotations.params = annotation.tokens.map((function(token) { | ||
return { | ||
token: token, | ||
isPromise: annotation.isPromise, | ||
isLazy: annotation.isLazy | ||
}; | ||
})); | ||
} | ||
if (annotation instanceof ProvideAnnotation) { | ||
collectedAnnotations.provideToken = annotation.token; | ||
collectedAnnotations.isPromise = annotation.isPromise; | ||
if (annotation instanceof Provide) { | ||
collectedAnnotations.provide.token = annotation.token; | ||
collectedAnnotations.provide.isPromise = annotation.isPromise; | ||
} | ||
@@ -105,10 +108,14 @@ } | ||
{ | ||
if (isFunction(paramAnnotation) && !collectedAnnotations.injectTokens[idx]) { | ||
collectedAnnotations.injectTokens[idx] = paramAnnotation; | ||
collectedAnnotations.injectPromises[idx] = false; | ||
collectedAnnotations.injectLazily[idx] = false; | ||
} else if (paramAnnotation instanceof InjectAnnotation) { | ||
collectedAnnotations.injectTokens[idx] = paramAnnotation.tokens[0]; | ||
collectedAnnotations.injectPromises[idx] = paramAnnotation.isPromise; | ||
collectedAnnotations.injectLazily[idx] = paramAnnotation.isLazy; | ||
if (isFunction(paramAnnotation) && !collectedAnnotations.params[idx]) { | ||
collectedAnnotations.params[idx] = { | ||
token: paramAnnotation, | ||
isPromise: false, | ||
isLazy: false | ||
}; | ||
} else if (paramAnnotation instanceof Inject) { | ||
collectedAnnotations.params[idx] = { | ||
token: paramAnnotation.tokens[0], | ||
isPromise: paramAnnotation.isPromise, | ||
isLazy: paramAnnotation.isLazy | ||
}; | ||
} | ||
@@ -126,2 +133,8 @@ } | ||
}, | ||
get hasAnnotation() { | ||
return hasAnnotation; | ||
}, | ||
get readAnnotations() { | ||
return readAnnotations; | ||
}, | ||
get SuperConstructor() { | ||
@@ -136,37 +149,16 @@ return SuperConstructor; | ||
}, | ||
get InjectAnnotation() { | ||
return InjectAnnotation; | ||
}, | ||
get InjectPromise() { | ||
return InjectPromise; | ||
}, | ||
get InjectPromiseAnnotation() { | ||
return InjectPromiseAnnotation; | ||
}, | ||
get InjectLazy() { | ||
return InjectLazy; | ||
}, | ||
get InjectLazyAnnotation() { | ||
return InjectLazyAnnotation; | ||
}, | ||
get Provide() { | ||
return Provide; | ||
}, | ||
get ProvideAnnotation() { | ||
return ProvideAnnotation; | ||
}, | ||
get ProvidePromise() { | ||
return ProvidePromise; | ||
}, | ||
get ProvidePromiseAnnotation() { | ||
return ProvidePromiseAnnotation; | ||
}, | ||
get hasAnnotation() { | ||
return hasAnnotation; | ||
}, | ||
get readAnnotations() { | ||
return readAnnotations; | ||
}, | ||
__esModule: true | ||
}; | ||
}); |
@@ -23,23 +23,11 @@ define(['./injector', './annotations'], function($__0,$__1) { | ||
}, | ||
get InjectAnnotation() { | ||
return $__annotations__.InjectAnnotation; | ||
}, | ||
get InjectPromise() { | ||
return $__annotations__.InjectPromise; | ||
}, | ||
get InjectPromiseAnnotation() { | ||
return $__annotations__.InjectPromiseAnnotation; | ||
}, | ||
get Provide() { | ||
return $__annotations__.Provide; | ||
}, | ||
get ProvideAnnotation() { | ||
return $__annotations__.ProvideAnnotation; | ||
}, | ||
get ProvidePromise() { | ||
return $__annotations__.ProvidePromise; | ||
}, | ||
get ProvidePromiseAnnotation() { | ||
return $__annotations__.ProvidePromiseAnnotation; | ||
}, | ||
get hasAnnotation() { | ||
@@ -46,0 +34,0 @@ return $__annotations__.hasAnnotation; |
@@ -1,2 +0,2 @@ | ||
define(['./annotations', './util', './profiler'], function($__0,$__1,$__2) { | ||
define(['./annotations', './util', './profiler', './providers'], function($__0,$__1,$__2,$__3) { | ||
"use strict"; | ||
@@ -10,16 +10,15 @@ var __moduleName = "injector"; | ||
$__2 = {'default': $__2}; | ||
var $__7 = $traceurRuntime.assertObject($__0), | ||
SuperConstructor = $__7.SuperConstructor, | ||
readAnnotations = $__7.readAnnotations, | ||
hasAnnotation = $__7.hasAnnotation, | ||
ProvideAnnotation = $__7.ProvideAnnotation, | ||
TransientScope = $__7.TransientScope; | ||
var $__7 = $traceurRuntime.assertObject($__1), | ||
isUpperCase = $__7.isUpperCase, | ||
isClass = $__7.isClass, | ||
isFunction = $__7.isFunction, | ||
isObject = $__7.isObject, | ||
toString = $__7.toString; | ||
if (!$__3 || !$__3.__esModule) | ||
$__3 = {'default': $__3}; | ||
var $__8 = $traceurRuntime.assertObject($__0), | ||
annotate = $__8.annotate, | ||
readAnnotations = $__8.readAnnotations, | ||
hasAnnotation = $__8.hasAnnotation, | ||
ProvideAnnotation = $__8.Provide, | ||
TransientScopeAnnotation = $__8.TransientScope; | ||
var $__8 = $traceurRuntime.assertObject($__1), | ||
isFunction = $__8.isFunction, | ||
toString = $__8.toString; | ||
var getUniqueId = $traceurRuntime.assertObject($__2).getUniqueId; | ||
var EmptyFunction = Object.getPrototypeOf(Function); | ||
var createProviderFromFnOrClass = $traceurRuntime.assertObject($__3).createProviderFromFnOrClass; | ||
function constructResolvingMessage(resolving) { | ||
@@ -35,11 +34,2 @@ var token = arguments[1] !== (void 0) ? arguments[1] : null; | ||
} | ||
var Provider = function Provider(provider, annotations) { | ||
this.provider = provider; | ||
this.isClass = isClass(provider); | ||
this.isPromise = annotations.isPromise; | ||
this.params = annotations.injectTokens; | ||
this.paramsPromises = annotations.injectPromises; | ||
this.paramsLazily = annotations.injectLazily; | ||
}; | ||
($traceurRuntime.createClass)(Provider, {}, {}); | ||
var Injector = function Injector() { | ||
@@ -68,13 +58,15 @@ var modules = arguments[0] !== (void 0) ? arguments[0] : []; | ||
_loadModules: function(modules) { | ||
var $__3 = this; | ||
for (var $__5 = modules[Symbol.iterator](), | ||
$__6; !($__6 = $__5.next()).done; ) { | ||
var module = $__6.value; | ||
var $__4 = this; | ||
for (var $__6 = modules[Symbol.iterator](), | ||
$__7; !($__7 = $__6.next()).done; ) { | ||
var module = $__7.value; | ||
{ | ||
if (isFunction(module)) { | ||
this._loadProvider(module); | ||
this._loadFnOrClass(module); | ||
continue; | ||
} | ||
Object.keys(module).forEach((function(key) { | ||
$__3._loadProvider(module[key], key); | ||
if (isFunction(module[key])) { | ||
$__4._loadFnOrClass(module[key], key); | ||
} | ||
})); | ||
@@ -84,9 +76,7 @@ } | ||
}, | ||
_loadProvider: function(provider, key) { | ||
if (!isFunction(provider)) { | ||
return; | ||
} | ||
var annotations = readAnnotations(provider); | ||
var token = annotations.provideToken || key || provider; | ||
this.providers.set(token, new Provider(provider, annotations)); | ||
_loadFnOrClass: function(fnOrClass, key) { | ||
var annotations = readAnnotations(fnOrClass); | ||
var token = annotations.provide.token || key || fnOrClass; | ||
var provider = createProviderFromFnOrClass(fnOrClass, annotations); | ||
this.providers.set(token, provider); | ||
}, | ||
@@ -106,25 +96,6 @@ _hasProviderFor: function(token) { | ||
var wantLazy = arguments[3] !== (void 0) ? arguments[3] : false; | ||
var $__3 = this; | ||
var defaultProvider; | ||
var $__4 = this; | ||
var resolvingMsg = ''; | ||
var instance; | ||
var injector = this; | ||
function instantiate(args, context, provider, resolving, token) { | ||
var returnedValue; | ||
try { | ||
returnedValue = provider.provider.apply(context, args); | ||
} catch (e) { | ||
resolvingMsg = constructResolvingMessage(resolving); | ||
var originalMsg = 'ORIGINAL ERROR: ' + e.message; | ||
e.message = ("Error during instantiation of " + toString(token) + "!" + resolvingMsg + "\n" + originalMsg); | ||
throw e; | ||
} | ||
if (provider.isClass && !isFunction(returnedValue) && !isObject(returnedValue)) { | ||
return context; | ||
} | ||
return returnedValue; | ||
} | ||
if (isFunction(token)) { | ||
defaultProvider = token; | ||
} | ||
if (token === $Injector) { | ||
@@ -137,3 +108,3 @@ if (wantPromise) { | ||
if (wantLazy) { | ||
return function() { | ||
return function createLazyInstance() { | ||
var lazyInjector = injector; | ||
@@ -145,6 +116,6 @@ if (arguments.length) { | ||
locals.push((function(ii) { | ||
var fn = function() { | ||
var fn = function createLocalInstance() { | ||
return args[ii + 1]; | ||
}; | ||
fn.annotations = [new ProvideAnnotation(args[ii])]; | ||
annotate(fn, new ProvideAnnotation(args[ii])); | ||
return fn; | ||
@@ -173,4 +144,4 @@ })(i)); | ||
var provider = this.providers.get(token); | ||
if (!provider && defaultProvider && !this._hasProviderFor(token)) { | ||
provider = new Provider(defaultProvider, readAnnotations(defaultProvider)); | ||
if (!provider && isFunction(token) && !this._hasProviderFor(token)) { | ||
provider = createProviderFromFnOrClass(token, readAnnotations(token)); | ||
this.providers.set(token, provider); | ||
@@ -183,3 +154,3 @@ } | ||
} | ||
return this.parent.get(token, resolving); | ||
return this.parent.get(token, resolving, wantPromise, wantLazy); | ||
} | ||
@@ -191,31 +162,10 @@ if (resolving.indexOf(token) !== -1) { | ||
resolving.push(token); | ||
var context; | ||
if (provider.isClass) { | ||
context = Object.create(provider.provider.prototype); | ||
} | ||
var delayingInstantiation = wantPromise && provider.params.some((function(token, i) { | ||
return !provider.paramsPromises[i]; | ||
var delayingInstantiation = wantPromise && provider.params.some((function(param) { | ||
return !param.isPromise; | ||
})); | ||
var args = provider.params.map((function(token, idx) { | ||
if (token === SuperConstructor) { | ||
var superConstructor = Object.getPrototypeOf(provider.provider); | ||
if (superConstructor === EmptyFunction) { | ||
resolvingMsg = constructResolvingMessage(resolving); | ||
throw new Error(("Only classes with a parent can ask for SuperConstructor!" + resolvingMsg)); | ||
} | ||
return function() { | ||
if (arguments.length > 0) { | ||
resolvingMsg = constructResolvingMessage(resolving); | ||
throw new Error(("SuperConstructor does not accept any arguments!" + resolvingMsg)); | ||
} | ||
var superArgs = readAnnotations(superConstructor).injectTokens.map((function(token) { | ||
return injector.get(token, resolving, false); | ||
})); | ||
superConstructor.apply(context, superArgs); | ||
}; | ||
} | ||
var args = provider.params.map((function(param) { | ||
if (delayingInstantiation) { | ||
return $__3.get(token, resolving, true, provider.paramsLazily[idx]); | ||
return $__4.get(param.token, resolving, true, param.isLazy); | ||
} | ||
return $__3.get(token, resolving, provider.paramsPromises[idx], provider.paramsLazily[idx]); | ||
return $__4.get(param.token, resolving, param.isPromise, param.isLazy); | ||
})); | ||
@@ -226,9 +176,11 @@ if (delayingInstantiation) { | ||
return Promise.all(args).then(function(args) { | ||
var instance = instantiate(args, context, provider, resolving, token); | ||
injector.cache.set(token, instance); | ||
var instance = provider.create(args, resolving, token); | ||
if (!hasAnnotation(provider.provider, TransientScopeAnnotation)) { | ||
injector.cache.set(token, instance); | ||
} | ||
return instance; | ||
}); | ||
} | ||
instance = instantiate(args, context, provider, resolving, token); | ||
if (!hasAnnotation(provider.provider, TransientScope)) { | ||
instance = provider.create(args, resolving, token); | ||
if (!hasAnnotation(provider.provider, TransientScopeAnnotation)) { | ||
this.cache.set(token, instance); | ||
@@ -249,3 +201,2 @@ } | ||
}, | ||
invoke: function(fn, context) {}, | ||
createChild: function() { | ||
@@ -255,5 +206,5 @@ var modules = arguments[0] !== (void 0) ? arguments[0] : []; | ||
var forcedProviders = new Map(); | ||
for (var $__5 = forceNewInstancesOf[Symbol.iterator](), | ||
$__6; !($__6 = $__5.next()).done; ) { | ||
var annotation = $__6.value; | ||
for (var $__6 = forceNewInstancesOf[Symbol.iterator](), | ||
$__7; !($__7 = $__6.next()).done; ) { | ||
var annotation = $__7.value; | ||
{ | ||
@@ -266,3 +217,3 @@ this._collectProvidersWithAnnotation(annotation, forcedProviders); | ||
dump: function() { | ||
var $__3 = this; | ||
var $__4 = this; | ||
var serialized = { | ||
@@ -276,3 +227,3 @@ id: this.id, | ||
name: token, | ||
dependencies: $__3.providers[token].params | ||
dependencies: $__4.providers[token].params | ||
}; | ||
@@ -279,0 +230,0 @@ })); |
@@ -1,2 +0,2 @@ | ||
define(['./injector', './annotations', './util'], function($__0,$__1,$__2) { | ||
define(['./injector', './annotations', './util', './providers'], function($__0,$__1,$__2,$__3) { | ||
"use strict"; | ||
@@ -10,10 +10,11 @@ var __moduleName = "testing"; | ||
$__2 = {'default': $__2}; | ||
if (!$__3 || !$__3.__esModule) | ||
$__3 = {'default': $__3}; | ||
var Injector = $traceurRuntime.assertObject($__0).Injector; | ||
var $__6 = $traceurRuntime.assertObject($__1), | ||
Inject = $__6.Inject, | ||
annotate = $__6.annotate, | ||
readAnnotations = $__6.readAnnotations; | ||
var $__6 = $traceurRuntime.assertObject($__2), | ||
isUpperCase = $__6.isUpperCase, | ||
isClass = $__6.isClass; | ||
var $__5 = $traceurRuntime.assertObject($__1), | ||
Inject = $__5.Inject, | ||
annotate = $__5.annotate, | ||
readAnnotations = $__5.readAnnotations; | ||
var isFunction = $traceurRuntime.assertObject($__2).isFunction; | ||
var createProviderFromFnOrClass = $traceurRuntime.assertObject($__3).createProviderFromFnOrClass; | ||
var currentSpec = null; | ||
@@ -57,4 +58,4 @@ beforeEach(function() { | ||
for (var params = [], | ||
$__5 = 0; $__5 < arguments.length; $__5++) | ||
params[$__5] = arguments[$__5]; | ||
$__4 = 0; $__4 < arguments.length; $__4++) | ||
params[$__4] = arguments[$__4]; | ||
var behavior = params.pop(); | ||
@@ -67,32 +68,22 @@ annotate(behavior, new (Function.prototype.bind.apply(Inject, $traceurRuntime.spread([null], params)))()); | ||
var annotations; | ||
for (var $__3 = currentSpec.$$providers[Symbol.iterator](), | ||
$__4; !($__4 = $__3.next()).done; ) { | ||
var providerWrapper = $__4.value; | ||
{ | ||
if (!providerWrapper.as) { | ||
modules.push(providerWrapper.provider); | ||
currentSpec.$$providers.forEach(function(providerWrapper) { | ||
if (!providerWrapper.as) { | ||
modules.push(providerWrapper.provider); | ||
} else { | ||
if (!isFunction(providerWrapper.provider)) { | ||
providers.set(providerWrapper.as, createProviderFromFnOrClass(function() { | ||
return providerWrapper.provider; | ||
}, { | ||
provide: { | ||
token: null, | ||
isPromise: false | ||
}, | ||
params: [] | ||
})); | ||
} else { | ||
if (typeof providerWrapper.provider !== 'function') { | ||
providers.set(providerWrapper.as, { | ||
provider: function() { | ||
return providerWrapper.provider; | ||
}, | ||
isPromise: false, | ||
params: [], | ||
paramsPromises: [], | ||
isClass: false | ||
}); | ||
} else { | ||
annotations = readAnnotations(providerWrapper.provider); | ||
providers.set(providerWrapper.as, { | ||
provider: providerWrapper.provider, | ||
isPromise: annotations.isPromise, | ||
params: annotations.injectTokens, | ||
paramsPromises: annotations.injectPromises, | ||
isClass: isClass(providerWrapper.provider) | ||
}); | ||
} | ||
annotations = readAnnotations(providerWrapper.provider); | ||
providers.set(providerWrapper.as, createProviderFromFnOrClass(providerWrapper.provider, annotations)); | ||
} | ||
} | ||
} | ||
}); | ||
currentSpec.$$injector = new Injector(modules, null, providers); | ||
@@ -99,0 +90,0 @@ } |
@@ -8,3 +8,3 @@ "use strict"; | ||
($traceurRuntime.createClass)(TransientScope, {}, {}); | ||
var InjectAnnotation = function InjectAnnotation() { | ||
var Inject = function Inject() { | ||
for (var tokens = [], | ||
@@ -15,5 +15,6 @@ $__5 = 0; $__5 < arguments.length; $__5++) | ||
this.isPromise = false; | ||
this.isLazy = false; | ||
}; | ||
($traceurRuntime.createClass)(InjectAnnotation, {}, {}); | ||
var InjectPromiseAnnotation = function InjectPromiseAnnotation() { | ||
($traceurRuntime.createClass)(Inject, {}, {}); | ||
var InjectPromise = function InjectPromise() { | ||
for (var tokens = [], | ||
@@ -24,15 +25,6 @@ $__6 = 0; $__6 < arguments.length; $__6++) | ||
this.isPromise = true; | ||
this.isLazy = false; | ||
}; | ||
($traceurRuntime.createClass)(InjectPromiseAnnotation, {}, {}, InjectAnnotation); | ||
var ProvideAnnotation = function ProvideAnnotation(token) { | ||
this.token = token; | ||
this.isPromise = false; | ||
}; | ||
($traceurRuntime.createClass)(ProvideAnnotation, {}, {}); | ||
var ProvidePromiseAnnotation = function ProvidePromiseAnnotation(token) { | ||
this.token = token; | ||
this.isPromise = true; | ||
}; | ||
($traceurRuntime.createClass)(ProvidePromiseAnnotation, {}, {}, ProvideAnnotation); | ||
var InjectLazyAnnotation = function InjectLazyAnnotation() { | ||
($traceurRuntime.createClass)(InjectPromise, {}, {}, Inject); | ||
var InjectLazy = function InjectLazy() { | ||
for (var tokens = [], | ||
@@ -45,8 +37,13 @@ $__7 = 0; $__7 < arguments.length; $__7++) | ||
}; | ||
($traceurRuntime.createClass)(InjectLazyAnnotation, {}, {}, InjectAnnotation); | ||
var Inject = InjectAnnotation; | ||
var InjectPromise = InjectPromiseAnnotation; | ||
var Provide = ProvideAnnotation; | ||
var ProvidePromise = ProvidePromiseAnnotation; | ||
var InjectLazy = InjectLazyAnnotation; | ||
($traceurRuntime.createClass)(InjectLazy, {}, {}, Inject); | ||
var Provide = function Provide(token) { | ||
this.token = token; | ||
this.isPromise = false; | ||
}; | ||
($traceurRuntime.createClass)(Provide, {}, {}); | ||
var ProvidePromise = function ProvidePromise(token) { | ||
this.token = token; | ||
this.isPromise = true; | ||
}; | ||
($traceurRuntime.createClass)(ProvidePromise, {}, {}, Provide); | ||
function annotate(fn, annotation) { | ||
@@ -73,7 +70,7 @@ fn.annotations = fn.annotations || []; | ||
var collectedAnnotations = { | ||
provideToken: null, | ||
isPromise: false, | ||
injectTokens: [], | ||
injectPromises: [], | ||
injectLazily: [] | ||
provide: { | ||
token: null, | ||
isPromise: false | ||
}, | ||
params: [] | ||
}; | ||
@@ -85,8 +82,14 @@ if (fn.annotations && fn.annotations.length) { | ||
{ | ||
if (annotation instanceof InjectAnnotation) { | ||
collectedAnnotations.injectTokens = annotation.tokens; | ||
if (annotation instanceof Inject) { | ||
collectedAnnotations.params = annotation.tokens.map((function(token) { | ||
return { | ||
token: token, | ||
isPromise: annotation.isPromise, | ||
isLazy: annotation.isLazy | ||
}; | ||
})); | ||
} | ||
if (annotation instanceof ProvideAnnotation) { | ||
collectedAnnotations.provideToken = annotation.token; | ||
collectedAnnotations.isPromise = annotation.isPromise; | ||
if (annotation instanceof Provide) { | ||
collectedAnnotations.provide.token = annotation.token; | ||
collectedAnnotations.provide.isPromise = annotation.isPromise; | ||
} | ||
@@ -102,10 +105,14 @@ } | ||
{ | ||
if (isFunction(paramAnnotation) && !collectedAnnotations.injectTokens[idx]) { | ||
collectedAnnotations.injectTokens[idx] = paramAnnotation; | ||
collectedAnnotations.injectPromises[idx] = false; | ||
collectedAnnotations.injectLazily[idx] = false; | ||
} else if (paramAnnotation instanceof InjectAnnotation) { | ||
collectedAnnotations.injectTokens[idx] = paramAnnotation.tokens[0]; | ||
collectedAnnotations.injectPromises[idx] = paramAnnotation.isPromise; | ||
collectedAnnotations.injectLazily[idx] = paramAnnotation.isLazy; | ||
if (isFunction(paramAnnotation) && !collectedAnnotations.params[idx]) { | ||
collectedAnnotations.params[idx] = { | ||
token: paramAnnotation, | ||
isPromise: false, | ||
isLazy: false | ||
}; | ||
} else if (paramAnnotation instanceof Inject) { | ||
collectedAnnotations.params[idx] = { | ||
token: paramAnnotation.tokens[0], | ||
isPromise: paramAnnotation.isPromise, | ||
isLazy: paramAnnotation.isLazy | ||
}; | ||
} | ||
@@ -123,2 +130,8 @@ } | ||
}, | ||
get hasAnnotation() { | ||
return hasAnnotation; | ||
}, | ||
get readAnnotations() { | ||
return readAnnotations; | ||
}, | ||
get SuperConstructor() { | ||
@@ -133,36 +146,15 @@ return SuperConstructor; | ||
}, | ||
get InjectAnnotation() { | ||
return InjectAnnotation; | ||
}, | ||
get InjectPromise() { | ||
return InjectPromise; | ||
}, | ||
get InjectPromiseAnnotation() { | ||
return InjectPromiseAnnotation; | ||
}, | ||
get InjectLazy() { | ||
return InjectLazy; | ||
}, | ||
get InjectLazyAnnotation() { | ||
return InjectLazyAnnotation; | ||
}, | ||
get Provide() { | ||
return Provide; | ||
}, | ||
get ProvideAnnotation() { | ||
return ProvideAnnotation; | ||
}, | ||
get ProvidePromise() { | ||
return ProvidePromise; | ||
}, | ||
get ProvidePromiseAnnotation() { | ||
return ProvidePromiseAnnotation; | ||
}, | ||
get hasAnnotation() { | ||
return hasAnnotation; | ||
}, | ||
get readAnnotations() { | ||
return readAnnotations; | ||
}, | ||
__esModule: true | ||
}; |
@@ -18,23 +18,11 @@ "use strict"; | ||
}, | ||
get InjectAnnotation() { | ||
return $__annotations__.InjectAnnotation; | ||
}, | ||
get InjectPromise() { | ||
return $__annotations__.InjectPromise; | ||
}, | ||
get InjectPromiseAnnotation() { | ||
return $__annotations__.InjectPromiseAnnotation; | ||
}, | ||
get Provide() { | ||
return $__annotations__.Provide; | ||
}, | ||
get ProvideAnnotation() { | ||
return $__annotations__.ProvideAnnotation; | ||
}, | ||
get ProvidePromise() { | ||
return $__annotations__.ProvidePromise; | ||
}, | ||
get ProvidePromiseAnnotation() { | ||
return $__annotations__.ProvidePromiseAnnotation; | ||
}, | ||
get hasAnnotation() { | ||
@@ -41,0 +29,0 @@ return $__annotations__.hasAnnotation; |
"use strict"; | ||
var __moduleName = "injector"; | ||
var $__4 = $traceurRuntime.assertObject(require('./annotations')), | ||
SuperConstructor = $__4.SuperConstructor, | ||
annotate = $__4.annotate, | ||
readAnnotations = $__4.readAnnotations, | ||
hasAnnotation = $__4.hasAnnotation, | ||
ProvideAnnotation = $__4.ProvideAnnotation, | ||
TransientScope = $__4.TransientScope; | ||
ProvideAnnotation = $__4.Provide, | ||
TransientScopeAnnotation = $__4.TransientScope; | ||
var $__4 = $traceurRuntime.assertObject(require('./util')), | ||
isUpperCase = $__4.isUpperCase, | ||
isClass = $__4.isClass, | ||
isFunction = $__4.isFunction, | ||
isObject = $__4.isObject, | ||
toString = $__4.toString; | ||
var getUniqueId = $traceurRuntime.assertObject(require('./profiler')).getUniqueId; | ||
var EmptyFunction = Object.getPrototypeOf(Function); | ||
var createProviderFromFnOrClass = $traceurRuntime.assertObject(require('./providers')).createProviderFromFnOrClass; | ||
function constructResolvingMessage(resolving) { | ||
@@ -27,11 +24,2 @@ var token = arguments[1] !== (void 0) ? arguments[1] : null; | ||
} | ||
var Provider = function Provider(provider, annotations) { | ||
this.provider = provider; | ||
this.isClass = isClass(provider); | ||
this.isPromise = annotations.isPromise; | ||
this.params = annotations.injectTokens; | ||
this.paramsPromises = annotations.injectPromises; | ||
this.paramsLazily = annotations.injectLazily; | ||
}; | ||
($traceurRuntime.createClass)(Provider, {}, {}); | ||
var Injector = function Injector() { | ||
@@ -66,7 +54,9 @@ var modules = arguments[0] !== (void 0) ? arguments[0] : []; | ||
if (isFunction(module)) { | ||
this._loadProvider(module); | ||
this._loadFnOrClass(module); | ||
continue; | ||
} | ||
Object.keys(module).forEach((function(key) { | ||
$__0._loadProvider(module[key], key); | ||
if (isFunction(module[key])) { | ||
$__0._loadFnOrClass(module[key], key); | ||
} | ||
})); | ||
@@ -76,9 +66,7 @@ } | ||
}, | ||
_loadProvider: function(provider, key) { | ||
if (!isFunction(provider)) { | ||
return; | ||
} | ||
var annotations = readAnnotations(provider); | ||
var token = annotations.provideToken || key || provider; | ||
this.providers.set(token, new Provider(provider, annotations)); | ||
_loadFnOrClass: function(fnOrClass, key) { | ||
var annotations = readAnnotations(fnOrClass); | ||
var token = annotations.provide.token || key || fnOrClass; | ||
var provider = createProviderFromFnOrClass(fnOrClass, annotations); | ||
this.providers.set(token, provider); | ||
}, | ||
@@ -99,24 +87,5 @@ _hasProviderFor: function(token) { | ||
var $__0 = this; | ||
var defaultProvider; | ||
var resolvingMsg = ''; | ||
var instance; | ||
var injector = this; | ||
function instantiate(args, context, provider, resolving, token) { | ||
var returnedValue; | ||
try { | ||
returnedValue = provider.provider.apply(context, args); | ||
} catch (e) { | ||
resolvingMsg = constructResolvingMessage(resolving); | ||
var originalMsg = 'ORIGINAL ERROR: ' + e.message; | ||
e.message = ("Error during instantiation of " + toString(token) + "!" + resolvingMsg + "\n" + originalMsg); | ||
throw e; | ||
} | ||
if (provider.isClass && !isFunction(returnedValue) && !isObject(returnedValue)) { | ||
return context; | ||
} | ||
return returnedValue; | ||
} | ||
if (isFunction(token)) { | ||
defaultProvider = token; | ||
} | ||
if (token === $Injector) { | ||
@@ -129,3 +98,3 @@ if (wantPromise) { | ||
if (wantLazy) { | ||
return function() { | ||
return function createLazyInstance() { | ||
var lazyInjector = injector; | ||
@@ -137,6 +106,6 @@ if (arguments.length) { | ||
locals.push((function(ii) { | ||
var fn = function() { | ||
var fn = function createLocalInstance() { | ||
return args[ii + 1]; | ||
}; | ||
fn.annotations = [new ProvideAnnotation(args[ii])]; | ||
annotate(fn, new ProvideAnnotation(args[ii])); | ||
return fn; | ||
@@ -165,4 +134,4 @@ })(i)); | ||
var provider = this.providers.get(token); | ||
if (!provider && defaultProvider && !this._hasProviderFor(token)) { | ||
provider = new Provider(defaultProvider, readAnnotations(defaultProvider)); | ||
if (!provider && isFunction(token) && !this._hasProviderFor(token)) { | ||
provider = createProviderFromFnOrClass(token, readAnnotations(token)); | ||
this.providers.set(token, provider); | ||
@@ -175,3 +144,3 @@ } | ||
} | ||
return this.parent.get(token, resolving); | ||
return this.parent.get(token, resolving, wantPromise, wantLazy); | ||
} | ||
@@ -183,31 +152,10 @@ if (resolving.indexOf(token) !== -1) { | ||
resolving.push(token); | ||
var context; | ||
if (provider.isClass) { | ||
context = Object.create(provider.provider.prototype); | ||
} | ||
var delayingInstantiation = wantPromise && provider.params.some((function(token, i) { | ||
return !provider.paramsPromises[i]; | ||
var delayingInstantiation = wantPromise && provider.params.some((function(param) { | ||
return !param.isPromise; | ||
})); | ||
var args = provider.params.map((function(token, idx) { | ||
if (token === SuperConstructor) { | ||
var superConstructor = Object.getPrototypeOf(provider.provider); | ||
if (superConstructor === EmptyFunction) { | ||
resolvingMsg = constructResolvingMessage(resolving); | ||
throw new Error(("Only classes with a parent can ask for SuperConstructor!" + resolvingMsg)); | ||
} | ||
return function() { | ||
if (arguments.length > 0) { | ||
resolvingMsg = constructResolvingMessage(resolving); | ||
throw new Error(("SuperConstructor does not accept any arguments!" + resolvingMsg)); | ||
} | ||
var superArgs = readAnnotations(superConstructor).injectTokens.map((function(token) { | ||
return injector.get(token, resolving, false); | ||
})); | ||
superConstructor.apply(context, superArgs); | ||
}; | ||
} | ||
var args = provider.params.map((function(param) { | ||
if (delayingInstantiation) { | ||
return $__0.get(token, resolving, true, provider.paramsLazily[idx]); | ||
return $__0.get(param.token, resolving, true, param.isLazy); | ||
} | ||
return $__0.get(token, resolving, provider.paramsPromises[idx], provider.paramsLazily[idx]); | ||
return $__0.get(param.token, resolving, param.isPromise, param.isLazy); | ||
})); | ||
@@ -218,9 +166,11 @@ if (delayingInstantiation) { | ||
return Promise.all(args).then(function(args) { | ||
var instance = instantiate(args, context, provider, resolving, token); | ||
injector.cache.set(token, instance); | ||
var instance = provider.create(args, resolving, token); | ||
if (!hasAnnotation(provider.provider, TransientScopeAnnotation)) { | ||
injector.cache.set(token, instance); | ||
} | ||
return instance; | ||
}); | ||
} | ||
instance = instantiate(args, context, provider, resolving, token); | ||
if (!hasAnnotation(provider.provider, TransientScope)) { | ||
instance = provider.create(args, resolving, token); | ||
if (!hasAnnotation(provider.provider, TransientScopeAnnotation)) { | ||
this.cache.set(token, instance); | ||
@@ -241,3 +191,2 @@ } | ||
}, | ||
invoke: function(fn, context) {}, | ||
createChild: function() { | ||
@@ -244,0 +193,0 @@ var modules = arguments[0] !== (void 0) ? arguments[0] : []; |
"use strict"; | ||
var __moduleName = "testing"; | ||
var Injector = $traceurRuntime.assertObject(require('./injector')).Injector; | ||
var $__3 = $traceurRuntime.assertObject(require('./annotations')), | ||
Inject = $__3.Inject, | ||
annotate = $__3.annotate, | ||
readAnnotations = $__3.readAnnotations; | ||
var $__3 = $traceurRuntime.assertObject(require('./util')), | ||
isUpperCase = $__3.isUpperCase, | ||
isClass = $__3.isClass; | ||
var $__1 = $traceurRuntime.assertObject(require('./annotations')), | ||
Inject = $__1.Inject, | ||
annotate = $__1.annotate, | ||
readAnnotations = $__1.readAnnotations; | ||
var isFunction = $traceurRuntime.assertObject(require('./util')).isFunction; | ||
var createProviderFromFnOrClass = $traceurRuntime.assertObject(require('./providers')).createProviderFromFnOrClass; | ||
var currentSpec = null; | ||
@@ -49,4 +48,4 @@ beforeEach(function() { | ||
for (var params = [], | ||
$__2 = 0; $__2 < arguments.length; $__2++) | ||
params[$__2] = arguments[$__2]; | ||
$__0 = 0; $__0 < arguments.length; $__0++) | ||
params[$__0] = arguments[$__0]; | ||
var behavior = params.pop(); | ||
@@ -59,32 +58,22 @@ annotate(behavior, new (Function.prototype.bind.apply(Inject, $traceurRuntime.spread([null], params)))()); | ||
var annotations; | ||
for (var $__0 = currentSpec.$$providers[Symbol.iterator](), | ||
$__1; !($__1 = $__0.next()).done; ) { | ||
var providerWrapper = $__1.value; | ||
{ | ||
if (!providerWrapper.as) { | ||
modules.push(providerWrapper.provider); | ||
currentSpec.$$providers.forEach(function(providerWrapper) { | ||
if (!providerWrapper.as) { | ||
modules.push(providerWrapper.provider); | ||
} else { | ||
if (!isFunction(providerWrapper.provider)) { | ||
providers.set(providerWrapper.as, createProviderFromFnOrClass(function() { | ||
return providerWrapper.provider; | ||
}, { | ||
provide: { | ||
token: null, | ||
isPromise: false | ||
}, | ||
params: [] | ||
})); | ||
} else { | ||
if (typeof providerWrapper.provider !== 'function') { | ||
providers.set(providerWrapper.as, { | ||
provider: function() { | ||
return providerWrapper.provider; | ||
}, | ||
isPromise: false, | ||
params: [], | ||
paramsPromises: [], | ||
isClass: false | ||
}); | ||
} else { | ||
annotations = readAnnotations(providerWrapper.provider); | ||
providers.set(providerWrapper.as, { | ||
provider: providerWrapper.provider, | ||
isPromise: annotations.isPromise, | ||
params: annotations.injectTokens, | ||
paramsPromises: annotations.injectPromises, | ||
isClass: isClass(providerWrapper.provider) | ||
}); | ||
} | ||
annotations = readAnnotations(providerWrapper.provider); | ||
providers.set(providerWrapper.as, createProviderFromFnOrClass(providerWrapper.provider, annotations)); | ||
} | ||
} | ||
} | ||
}); | ||
currentSpec.$$injector = new Injector(modules, null, providers); | ||
@@ -91,0 +80,0 @@ } |
{ | ||
"name": "di", | ||
"version": "2.0.0-pre-7", | ||
"version": "2.0.0-pre-8", | ||
"description": "A DI framework.", | ||
@@ -5,0 +5,0 @@ "main": "node/index.js", |
import {isFunction} from './util'; | ||
// This module contains: | ||
// - built-in annotation classes | ||
// - helpers to read/write annotations | ||
// ANNOTATIONS | ||
// A built-in token. | ||
// Used to ask for pre-injected parent constructor. | ||
// A class constructor can ask for this. | ||
class SuperConstructor {} | ||
// A built-in scope. | ||
// Never cache. | ||
class TransientScope {} | ||
class InjectAnnotation { | ||
class Inject { | ||
constructor(...tokens) { | ||
this.tokens = tokens; | ||
this.isPromise = false; | ||
this.isLazy = false; | ||
} | ||
} | ||
class InjectPromiseAnnotation extends InjectAnnotation { | ||
class InjectPromise extends Inject { | ||
constructor(...tokens) { | ||
this.tokens = tokens; | ||
this.isPromise = true; | ||
this.isLazy = false; | ||
} | ||
} | ||
class ProvideAnnotation { | ||
class InjectLazy extends Inject { | ||
constructor(...tokens) { | ||
this.tokens = tokens; | ||
this.isPromise = false; | ||
this.isLazy = true; | ||
} | ||
} | ||
class Provide { | ||
constructor(token) { | ||
@@ -28,3 +51,3 @@ this.token = token; | ||
class ProvidePromiseAnnotation extends ProvideAnnotation { | ||
class ProvidePromise extends Provide { | ||
constructor(token) { | ||
@@ -36,18 +59,7 @@ this.token = token; | ||
class InjectLazyAnnotation extends InjectAnnotation { | ||
constructor(...tokens) { | ||
this.tokens = tokens; | ||
this.isPromise = false; | ||
this.isLazy = true; | ||
} | ||
} | ||
// aliases | ||
var Inject = InjectAnnotation; | ||
var InjectPromise = InjectPromiseAnnotation; | ||
var Provide = ProvideAnnotation; | ||
var ProvidePromise = ProvidePromiseAnnotation; | ||
var InjectLazy = InjectLazyAnnotation; | ||
// HELPERS | ||
// Helpers for when annotations are not enabled in Traceur. | ||
// Append annotation on a function or class. | ||
// This can be helpful when not using ES6+. | ||
function annotate(fn, annotation) { | ||
@@ -59,2 +71,3 @@ fn.annotations = fn.annotations || []; | ||
// Read annotations on a function or class and return whether given annotation is present. | ||
function hasAnnotation(fn, annotationClass) { | ||
@@ -75,19 +88,17 @@ if (!fn.annotations || fn.annotations.length === 0) { | ||
// Read annotations on a function or class and collect "interesting" metadata: | ||
function readAnnotations(fn) { | ||
var collectedAnnotations = { | ||
// A token, what is provided by given function. | ||
// Parsed from @Provide or @ProvidePromise | ||
provideToken: null, | ||
// Boolean. | ||
// Does the provider provide the value as a promise? | ||
isPromise: false, | ||
// List of tokens. | ||
// What dependencies does this provide require? | ||
injectTokens: [], | ||
// List of booleans. | ||
// Is given dependency required as a promise? | ||
injectPromises: [], | ||
// List of booleans. | ||
// Is given dependency required lazily? | ||
injectLazily: [] | ||
// Description of the provided value. | ||
provide: { | ||
token: null, | ||
isPromise: false | ||
}, | ||
// List of parameter descriptions. | ||
// A parameter description is an object with properties: | ||
// - token (anything) | ||
// - isPromise (boolean) | ||
// - isLazy (boolean) | ||
params: [] | ||
}; | ||
@@ -97,11 +108,11 @@ | ||
for (var annotation of fn.annotations) { | ||
if (annotation instanceof InjectAnnotation) { | ||
collectedAnnotations.injectTokens = annotation.tokens; | ||
// TODO(vojta): set injectPromises | ||
// TODO(vojta): set injectLazily | ||
if (annotation instanceof Inject) { | ||
collectedAnnotations.params = annotation.tokens.map((token) => { | ||
return {token: token, isPromise: annotation.isPromise, isLazy: annotation.isLazy}; | ||
}); | ||
} | ||
if (annotation instanceof ProvideAnnotation) { | ||
collectedAnnotations.provideToken = annotation.token; | ||
collectedAnnotations.isPromise = annotation.isPromise; | ||
if (annotation instanceof Provide) { | ||
collectedAnnotations.provide.token = annotation.token; | ||
collectedAnnotations.provide.isPromise = annotation.isPromise; | ||
} | ||
@@ -116,10 +127,14 @@ } | ||
// Type annotation. | ||
if (isFunction(paramAnnotation) && !collectedAnnotations.injectTokens[idx]) { | ||
collectedAnnotations.injectTokens[idx] = paramAnnotation; | ||
collectedAnnotations.injectPromises[idx] = false; | ||
collectedAnnotations.injectLazily[idx] = false; | ||
} else if (paramAnnotation instanceof InjectAnnotation) { | ||
collectedAnnotations.injectTokens[idx] = paramAnnotation.tokens[0]; | ||
collectedAnnotations.injectPromises[idx] = paramAnnotation.isPromise; | ||
collectedAnnotations.injectLazily[idx] = paramAnnotation.isLazy; | ||
if (isFunction(paramAnnotation) && !collectedAnnotations.params[idx]) { | ||
collectedAnnotations.params[idx] = { | ||
token: paramAnnotation, | ||
isPromise: false, | ||
isLazy: false | ||
}; | ||
} else if (paramAnnotation instanceof Inject) { | ||
collectedAnnotations.params[idx] = { | ||
token: paramAnnotation.tokens[0], | ||
isPromise: paramAnnotation.isPromise, | ||
isLazy: paramAnnotation.isLazy | ||
}; | ||
} | ||
@@ -136,16 +151,12 @@ } | ||
annotate, | ||
hasAnnotation, | ||
readAnnotations, | ||
SuperConstructor, | ||
TransientScope, | ||
Inject, | ||
InjectAnnotation, | ||
InjectPromise, | ||
InjectPromiseAnnotation, | ||
InjectLazy, | ||
InjectLazyAnnotation, | ||
Provide, | ||
ProvideAnnotation, | ||
ProvidePromise, | ||
ProvidePromiseAnnotation, | ||
hasAnnotation, | ||
readAnnotations | ||
ProvidePromise | ||
}; |
@@ -6,11 +6,7 @@ export {Injector} from './injector'; | ||
Inject, | ||
InjectAnnotation, | ||
InjectPromise, | ||
InjectPromiseAnnotation, | ||
Provide, | ||
ProvideAnnotation, | ||
ProvidePromise, | ||
ProvidePromiseAnnotation, | ||
hasAnnotation, | ||
readAnnotations | ||
} from './annotations'; |
@@ -1,8 +0,13 @@ | ||
import {SuperConstructor, readAnnotations, hasAnnotation, ProvideAnnotation, TransientScope} from './annotations'; | ||
import {isUpperCase, isClass, isFunction, isObject, toString} from './util'; | ||
import { | ||
annotate, | ||
readAnnotations, | ||
hasAnnotation, | ||
Provide as ProvideAnnotation, | ||
TransientScope as TransientScopeAnnotation | ||
} from './annotations'; | ||
import {isFunction, toString} from './util'; | ||
import {getUniqueId} from './profiler'; | ||
import {createProviderFromFnOrClass} from './providers'; | ||
var EmptyFunction = Object.getPrototypeOf(Function); | ||
function constructResolvingMessage(resolving, token = null) { | ||
@@ -21,19 +26,14 @@ if (token) { | ||
// TODO(vojta): extract all the super constructor logic into a class provider | ||
// - add instantiate() method (value only returns, factory invokes, class apply on context) | ||
// - class provider will flatten all the deps (from parent constructors) first | ||
// - injector does not care about the concept of super constructor | ||
// - all deps (including all parent constructor's) are resolved before instantiate() | ||
class Provider { | ||
constructor(provider, annotations) { | ||
this.provider = provider; | ||
this.isClass = isClass(provider); | ||
this.isPromise = annotations.isPromise; | ||
this.params = annotations.injectTokens; | ||
this.paramsPromises = annotations.injectPromises; | ||
this.paramsLazily = annotations.injectLazily; | ||
} | ||
} | ||
// Injector encapsulate a life scope. | ||
// There is exactly one instance for given token in given injector. | ||
// | ||
// All the state is immutable, the only state changes is the cache. There is however no way to produce different instance under given token. In that sense it is immutable. | ||
// | ||
// Injector is responsible for: | ||
// - resolving tokens into | ||
// - provider | ||
// - value (cache/calling provider) | ||
// - dealing with isPromise | ||
// - dealing with isLazy | ||
// - loading different "providers" and modules | ||
class Injector { | ||
@@ -51,2 +51,4 @@ | ||
// Collect all registered providers that has given annotation. | ||
// Inclugind providers defined in parent injectors. | ||
_collectProvidersWithAnnotation(annotationClass, collectedProviders) { | ||
@@ -65,2 +67,4 @@ this.providers.forEach((provider, token) => { | ||
// Load modules/function/classes. | ||
// This mutates `this.providers`, but it is only called during the constructor. | ||
_loadModules(modules) { | ||
@@ -70,3 +74,3 @@ for (var module of modules) { | ||
if (isFunction(module)) { | ||
this._loadProvider(module); | ||
this._loadFnOrClass(module); | ||
continue; | ||
@@ -77,3 +81,5 @@ } | ||
Object.keys(module).forEach((key) => { | ||
this._loadProvider(module[key], key); | ||
if (isFunction(module[key])) { | ||
this._loadFnOrClass(module[key], key); | ||
} | ||
}); | ||
@@ -84,14 +90,16 @@ } | ||
_loadProvider(provider, key) { | ||
if (!isFunction(provider)) { | ||
return; | ||
} | ||
// Load a function or class. | ||
// This mutates `this.providers`, but it is only called during the constructor. | ||
_loadFnOrClass(fnOrClass, key) { | ||
// TODO(vojta): should we expose provider.token? | ||
var annotations = readAnnotations(fnOrClass); | ||
var token = annotations.provide.token || key || fnOrClass; | ||
var provider = createProviderFromFnOrClass(fnOrClass, annotations); | ||
var annotations = readAnnotations(provider); | ||
var token = annotations.provideToken || key || provider; | ||
this.providers.set(token, new Provider(provider, annotations)); | ||
this.providers.set(token, provider); | ||
} | ||
// Returns true if there is any provider registered for given token. | ||
// Inclugind parent injectors. | ||
_hasProviderFor(token) { | ||
@@ -110,4 +118,4 @@ if (this.providers.has(token)) { | ||
// Return an instance for given token. | ||
get(token, resolving = [], wantPromise = false, wantLazy = false) { | ||
var defaultProvider; | ||
var resolvingMsg = ''; | ||
@@ -117,26 +125,3 @@ var instance; | ||
function instantiate(args, context, provider, resolving, token) { | ||
var returnedValue; | ||
try { | ||
returnedValue = provider.provider.apply(context, args); | ||
} catch (e) { | ||
resolvingMsg = constructResolvingMessage(resolving); | ||
var originalMsg = 'ORIGINAL ERROR: ' + e.message; | ||
e.message = `Error during instantiation of ${toString(token)}!${resolvingMsg}\n${originalMsg}`; | ||
throw e; | ||
} | ||
if (provider.isClass && !isFunction(returnedValue) && !isObject(returnedValue)) { | ||
return context; | ||
} | ||
return returnedValue; | ||
} | ||
if (isFunction(token)) { | ||
defaultProvider = token; | ||
} | ||
// Special case, return Injector. | ||
// Special case, return itself. | ||
if (token === Injector) { | ||
@@ -152,3 +137,3 @@ if (wantPromise) { | ||
if (wantLazy) { | ||
return function() { | ||
return function createLazyInstance() { | ||
var lazyInjector = injector; | ||
@@ -162,6 +147,8 @@ | ||
locals.push((function(ii) { | ||
var fn = function() { | ||
var fn = function createLocalInstance() { | ||
return args[ii + 1]; | ||
}; | ||
fn.annotations = [new ProvideAnnotation(args[ii])] | ||
annotate(fn, new ProvideAnnotation(args[ii])); | ||
return fn; | ||
@@ -198,5 +185,5 @@ })(i)); | ||
// No provider defined (overriden), use the default provider. | ||
if (!provider && defaultProvider && !this._hasProviderFor(token)) { | ||
provider = new Provider(defaultProvider, readAnnotations(defaultProvider)); | ||
// No provider defined (overriden), use the default provider (token). | ||
if (!provider && isFunction(token) && !this._hasProviderFor(token)) { | ||
provider = createProviderFromFnOrClass(token, readAnnotations(token)); | ||
this.providers.set(token, provider); | ||
@@ -211,3 +198,3 @@ } | ||
return this.parent.get(token, resolving); | ||
return this.parent.get(token, resolving, wantPromise, wantLazy); | ||
} | ||
@@ -222,8 +209,2 @@ | ||
var context; | ||
if (provider.isClass) { | ||
context = Object.create(provider.provider.prototype); | ||
} | ||
// TODO(vojta): handle these cases: | ||
@@ -237,35 +218,10 @@ // 1/ | ||
// -> error, but let it go inside to throw where exactly is the async provider | ||
var delayingInstantiation = wantPromise && provider.params.some((token, i) => !provider.paramsPromises[i]); | ||
var delayingInstantiation = wantPromise && provider.params.some((param) => !param.isPromise); | ||
var args = provider.params.map((param) => { | ||
var args = provider.params.map((token, idx) => { | ||
// TODO(vojta): should be only allowed during the constructor? | ||
// TODO(vojta): support async arguments for super constructor? | ||
if (token === SuperConstructor) { | ||
var superConstructor = Object.getPrototypeOf(provider.provider); | ||
if (superConstructor === EmptyFunction) { | ||
resolvingMsg = constructResolvingMessage(resolving); | ||
throw new Error(`Only classes with a parent can ask for SuperConstructor!${resolvingMsg}`); | ||
} | ||
return function() { | ||
if (arguments.length > 0) { | ||
resolvingMsg = constructResolvingMessage(resolving); | ||
throw new Error(`SuperConstructor does not accept any arguments!${resolvingMsg}`); | ||
} | ||
var superArgs = readAnnotations(superConstructor).injectTokens.map((token) => { | ||
return injector.get(token, resolving, false); | ||
}); | ||
superConstructor.apply(context, superArgs); | ||
}; | ||
} | ||
if (delayingInstantiation) { | ||
return this.get(token, resolving, true, provider.paramsLazily[idx]); | ||
return this.get(param.token, resolving, true, param.isLazy); | ||
} | ||
return this.get(token, resolving, provider.paramsPromises[idx], provider.paramsLazily[idx]); | ||
return this.get(param.token, resolving, param.isPromise, param.isLazy); | ||
}); | ||
@@ -275,3 +231,3 @@ | ||
if (delayingInstantiation) { | ||
var delayedResolving = resolving.slice(); | ||
var delayedResolving = resolving.slice(); // clone | ||
@@ -282,5 +238,7 @@ resolving.pop(); | ||
return Promise.all(args).then(function(args) { | ||
var instance = instantiate(args, context, provider, resolving, token); | ||
var instance = provider.create(args, resolving, token); | ||
injector.cache.set(token, instance); | ||
if (!hasAnnotation(provider.provider, TransientScopeAnnotation)) { | ||
injector.cache.set(token, instance); | ||
} | ||
@@ -297,5 +255,5 @@ // TODO(vojta): if a provider returns a promise (but is not declared as @ProvidePromise), | ||
instance = instantiate(args, context, provider, resolving, token); | ||
instance = provider.create(args, resolving, token); | ||
if (!hasAnnotation(provider.provider, TransientScope)) { | ||
if (!hasAnnotation(provider.provider, TransientScopeAnnotation)) { | ||
this.cache.set(token, instance); | ||
@@ -325,7 +283,4 @@ } | ||
invoke(fn, context) { | ||
} | ||
// Create a child injector, which encapsulate shorter life scope. | ||
// It is possible to add additional providers and also force new instances of existing providers. | ||
createChild(modules = [], forceNewInstancesOf = []) { | ||
@@ -332,0 +287,0 @@ var forcedProviders = new Map(); |
import {Injector} from './injector'; | ||
import {Inject, annotate, readAnnotations} from './annotations'; | ||
import {isUpperCase, isClass} from './util'; | ||
import {isFunction} from './util'; | ||
import {createProviderFromFnOrClass} from './providers'; | ||
var currentSpec = null; | ||
@@ -65,3 +67,3 @@ beforeEach(function() { | ||
for (var providerWrapper of currentSpec.$$providers) { | ||
currentSpec.$$providers.forEach(function(providerWrapper) { | ||
if (!providerWrapper.as) { | ||
@@ -71,26 +73,14 @@ // load as a regular module | ||
} else { | ||
if (typeof providerWrapper.provider !== 'function') { | ||
if (!isFunction(providerWrapper.provider)) { | ||
// inlined mock | ||
providers.set(providerWrapper.as, { | ||
/*jshint loopfunc:true */ | ||
provider: function() {return providerWrapper.provider;}, | ||
/*jshint loopfunc:false */ | ||
isPromise: false, | ||
params: [], | ||
paramsPromises: [], | ||
isClass: false | ||
}); | ||
providers.set(providerWrapper.as, createProviderFromFnOrClass(function() { | ||
return providerWrapper.provider; | ||
}, {provide: {token: null, isPromise: false}, params: []})); | ||
} else { | ||
// a fn/class provider with overriden token | ||
annotations = readAnnotations(providerWrapper.provider); | ||
providers.set(providerWrapper.as, { | ||
provider: providerWrapper.provider, | ||
isPromise: annotations.isPromise, | ||
params: annotations.injectTokens, | ||
paramsPromises: annotations.injectPromises, | ||
isClass: isClass(providerWrapper.provider) | ||
}); | ||
providers.set(providerWrapper.as, createProviderFromFnOrClass(providerWrapper.provider, annotations)); | ||
} | ||
} | ||
} | ||
}); | ||
@@ -97,0 +87,0 @@ currentSpec.$$injector = new Injector(modules, null, providers); |
@@ -0,1 +1,4 @@ | ||
// A bunch of helper functions. | ||
function isUpperCase(char) { | ||
@@ -5,2 +8,3 @@ return char.toUpperCase() === char; | ||
function isClass(clsOrFunction) { | ||
@@ -14,2 +18,3 @@ if (clsOrFunction.name) { | ||
function isFunction(value) { | ||
@@ -19,2 +24,3 @@ return typeof value === 'function'; | ||
function isObject(value) { | ||
@@ -24,2 +30,3 @@ return typeof value === 'object'; | ||
function toString(token) { | ||
@@ -37,2 +44,3 @@ if (typeof token === 'string') { | ||
export { | ||
@@ -39,0 +47,0 @@ isUpperCase, |
872669
74
21847