@glimmer/di
Version:
Dependency injection support for Glimmer applications.
297 lines (264 loc) • 10 kB
JavaScript
define('@glimmer/di', ['exports'], function (exports) { 'use strict';
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var Container = function () {
function Container(registry) {
var resolver = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
_classCallCheck(this, Container);
this._registry = registry;
this._resolver = resolver;
this._lookups = {};
this._factoryDefinitionLookups = {};
}
Container.prototype.factoryFor = function factoryFor(specifier) {
var factoryDefinition = this._factoryDefinitionLookups[specifier];
if (!factoryDefinition) {
if (this._resolver) {
factoryDefinition = this._resolver.retrieve(specifier);
}
if (!factoryDefinition) {
factoryDefinition = this._registry.registration(specifier);
}
if (factoryDefinition) {
this._factoryDefinitionLookups[specifier] = factoryDefinition;
}
}
if (!factoryDefinition) {
return;
}
return this.buildFactory(specifier, factoryDefinition);
};
Container.prototype.lookup = function lookup(specifier) {
var singleton = this._registry.registeredOption(specifier, 'singleton') !== false;
if (singleton) {
var lookup = this._lookups[specifier];
if (lookup) {
return lookup.instance;
}
}
var factory = this.factoryFor(specifier);
if (!factory) {
return;
}
if (this._registry.registeredOption(specifier, 'instantiate') === false) {
return factory.class;
}
var instance = factory.create();
if (singleton && instance) {
this._lookups[specifier] = { factory: factory, instance: instance };
}
return instance;
};
Container.prototype.defaultInjections = function defaultInjections(specifier) {
return {};
};
Container.prototype.teardown = function teardown() {
var specifiers = Object.keys(this._lookups);
for (var i = 0; i < specifiers.length; i++) {
var specifier = specifiers[i];
var _lookups$specifier = this._lookups[specifier],
factory = _lookups$specifier.factory,
instance = _lookups$specifier.instance;
factory.teardown(instance);
}
};
Container.prototype.defaultTeardown = function defaultTeardown(instance) {};
Container.prototype.buildInjections = function buildInjections(specifier) {
var hash = this.defaultInjections(specifier);
var injections = this._registry.registeredInjections(specifier);
var injection = void 0;
for (var i = 0; i < injections.length; i++) {
injection = injections[i];
hash[injection.property] = this.lookup(injection.source);
}
return hash;
};
Container.prototype.buildFactory = function buildFactory(specifier, factoryDefinition) {
var _this = this;
var injections = this.buildInjections(specifier);
return {
class: factoryDefinition,
teardown: function (instance) {
if (factoryDefinition.teardown) {
factoryDefinition.teardown(instance);
} else {
_this.defaultTeardown(instance);
}
},
create: function (options) {
var mergedOptions = Object.assign({}, injections, options);
return factoryDefinition.create(mergedOptions);
}
};
};
return Container;
}();
function _classCallCheck$1(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var Registry = function () {
function Registry(options) {
_classCallCheck$1(this, Registry);
this._registrations = {};
this._registeredOptions = {};
this._registeredInjections = {};
if (options && options.fallback) {
this._fallback = options.fallback;
}
}
Registry.prototype.register = function register(specifier, factoryDefinition, options) {
this._registrations[specifier] = factoryDefinition;
if (options) {
this._registeredOptions[specifier] = options;
}
};
Registry.prototype.registration = function registration(specifier) {
var registration = this._registrations[specifier];
if (registration === undefined && this._fallback) {
registration = this._fallback.registration(specifier);
}
return registration;
};
Registry.prototype.unregister = function unregister(specifier) {
delete this._registrations[specifier];
delete this._registeredOptions[specifier];
delete this._registeredInjections[specifier];
};
Registry.prototype.registerOption = function registerOption(specifier, option, value) {
var options = this._registeredOptions[specifier];
if (!options) {
options = {};
this._registeredOptions[specifier] = options;
}
options[option] = value;
};
Registry.prototype.registeredOption = function registeredOption(specifier, option) {
var result = void 0;
var options = this.registeredOptions(specifier);
if (options) {
result = options[option];
}
if (result === undefined && this._fallback !== undefined) {
result = this._fallback.registeredOption(specifier, option);
}
return result;
};
Registry.prototype.registeredOptions = function registeredOptions(specifier) {
var options = this._registeredOptions[specifier];
if (options === undefined) {
var type = specifier.split(':')[0];
options = this._registeredOptions[type];
}
return options;
};
Registry.prototype.unregisterOption = function unregisterOption(specifier, option) {
var options = this._registeredOptions[specifier];
if (options) {
delete options[option];
}
};
Registry.prototype.registerInjection = function registerInjection(specifier, property, source) {
var injections = this._registeredInjections[specifier];
if (injections === undefined) {
this._registeredInjections[specifier] = injections = [];
}
injections.push({
property: property,
source: source
});
};
Registry.prototype.registeredInjections = function registeredInjections(specifier) {
var type = specifier.split(':')[0];
var injections = this._fallback ? this._fallback.registeredInjections(specifier) : [];
Array.prototype.push.apply(injections, this._registeredInjections[type]);
Array.prototype.push.apply(injections, this._registeredInjections[specifier]);
return injections;
};
return Registry;
}();
// TODO - use symbol
var OWNER = '__owner__';
function getOwner(object) {
return object[OWNER];
}
function setOwner(object, owner) {
object[OWNER] = owner;
}
function isSpecifierStringAbsolute(specifier) {
var split = specifier.split(':');
var type = split[0];
var path = split[1];
return !!(type && path && path.indexOf('/') === 0 && path.split('/').length > 3);
}
function isSpecifierObjectAbsolute(specifier) {
return specifier.rootName !== undefined && specifier.collection !== undefined && specifier.name !== undefined && specifier.type !== undefined;
}
function serializeSpecifier(specifier) {
var type = specifier.type;
var path = serializeSpecifierPath(specifier);
if (path) {
return type + ':' + path;
} else {
return type;
}
}
function serializeSpecifierPath(specifier) {
var path = [];
if (specifier.rootName) {
path.push(specifier.rootName);
}
if (specifier.collection) {
path.push(specifier.collection);
}
if (specifier.namespace) {
path.push(specifier.namespace);
}
if (specifier.name) {
path.push(specifier.name);
}
if (path.length > 0) {
var fullPath = path.join('/');
if (isSpecifierObjectAbsolute(specifier)) {
fullPath = '/' + fullPath;
}
return fullPath;
}
}
function deserializeSpecifier(specifier) {
var obj = {};
if (specifier.indexOf(':') > -1) {
var split = specifier.split(':');
var type = split[0];
var path = split[1];
obj.type = type;
var pathSegments = void 0;
if (path.indexOf('/') === 0) {
pathSegments = path.substr(1).split('/');
if (path.substr(1).startsWith('@')) {
obj.rootName = pathSegments.shift() + '/' + pathSegments.shift();
} else {
obj.rootName = pathSegments.shift();
}
obj.collection = pathSegments.shift();
} else {
pathSegments = path.split('/');
}
if (pathSegments.length > 0) {
obj.name = pathSegments.pop();
if (pathSegments.length > 0) {
obj.namespace = pathSegments.join('/');
}
}
} else {
obj.type = specifier;
}
return obj;
}
exports.Container = Container;
exports.Registry = Registry;
exports.getOwner = getOwner;
exports.setOwner = setOwner;
exports.OWNER = OWNER;
exports.isSpecifierStringAbsolute = isSpecifierStringAbsolute;
exports.isSpecifierObjectAbsolute = isSpecifierObjectAbsolute;
exports.serializeSpecifier = serializeSpecifier;
exports.deserializeSpecifier = deserializeSpecifier;
Object.defineProperty(exports, '__esModule', { value: true });
});