You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
152 lines
7.0 KiB
152 lines
7.0 KiB
4 weeks ago
|
import { BindingCount } from "../bindings/binding_count";
|
||
|
import * as ERROR_MSGS from "../constants/error_msgs";
|
||
|
import { BindingTypeEnum, TargetTypeEnum } from "../constants/literal_types";
|
||
|
import * as METADATA_KEY from "../constants/metadata_keys";
|
||
|
import { isStackOverflowExeption } from "../utils/exceptions";
|
||
|
import { circularDependencyToException, getServiceIdentifierAsString, listMetadataForTarget, listRegisteredBindingsForServiceIdentifier } from "../utils/serialization";
|
||
|
import { Context } from "./context";
|
||
|
import { Metadata } from "./metadata";
|
||
|
import { Plan } from "./plan";
|
||
|
import { getBaseClassDependencyCount, getDependencies, getFunctionName } from "./reflection_utils";
|
||
|
import { Request } from "./request";
|
||
|
import { Target } from "./target";
|
||
|
function getBindingDictionary(cntnr) {
|
||
|
return cntnr._bindingDictionary;
|
||
|
}
|
||
|
function _createTarget(isMultiInject, targetType, serviceIdentifier, name, key, value) {
|
||
|
var metadataKey = isMultiInject ? METADATA_KEY.MULTI_INJECT_TAG : METADATA_KEY.INJECT_TAG;
|
||
|
var injectMetadata = new Metadata(metadataKey, serviceIdentifier);
|
||
|
var target = new Target(targetType, name, serviceIdentifier, injectMetadata);
|
||
|
if (key !== undefined) {
|
||
|
var tagMetadata = new Metadata(key, value);
|
||
|
target.metadata.push(tagMetadata);
|
||
|
}
|
||
|
return target;
|
||
|
}
|
||
|
function _getActiveBindings(metadataReader, avoidConstraints, context, parentRequest, target) {
|
||
|
var bindings = getBindings(context.container, target.serviceIdentifier);
|
||
|
var activeBindings = [];
|
||
|
if (bindings.length === BindingCount.NoBindingsAvailable &&
|
||
|
context.container.options.autoBindInjectable &&
|
||
|
typeof target.serviceIdentifier === "function" &&
|
||
|
metadataReader.getConstructorMetadata(target.serviceIdentifier).compilerGeneratedMetadata) {
|
||
|
context.container.bind(target.serviceIdentifier).toSelf();
|
||
|
bindings = getBindings(context.container, target.serviceIdentifier);
|
||
|
}
|
||
|
if (!avoidConstraints) {
|
||
|
activeBindings = bindings.filter(function (binding) {
|
||
|
var request = new Request(binding.serviceIdentifier, context, parentRequest, binding, target);
|
||
|
return binding.constraint(request);
|
||
|
});
|
||
|
}
|
||
|
else {
|
||
|
activeBindings = bindings;
|
||
|
}
|
||
|
_validateActiveBindingCount(target.serviceIdentifier, activeBindings, target, context.container);
|
||
|
return activeBindings;
|
||
|
}
|
||
|
function _validateActiveBindingCount(serviceIdentifier, bindings, target, container) {
|
||
|
switch (bindings.length) {
|
||
|
case BindingCount.NoBindingsAvailable:
|
||
|
if (target.isOptional()) {
|
||
|
return bindings;
|
||
|
}
|
||
|
else {
|
||
|
var serviceIdentifierString = getServiceIdentifierAsString(serviceIdentifier);
|
||
|
var msg = ERROR_MSGS.NOT_REGISTERED;
|
||
|
msg += listMetadataForTarget(serviceIdentifierString, target);
|
||
|
msg += listRegisteredBindingsForServiceIdentifier(container, serviceIdentifierString, getBindings);
|
||
|
throw new Error(msg);
|
||
|
}
|
||
|
case BindingCount.OnlyOneBindingAvailable:
|
||
|
if (!target.isArray()) {
|
||
|
return bindings;
|
||
|
}
|
||
|
case BindingCount.MultipleBindingsAvailable:
|
||
|
default:
|
||
|
if (!target.isArray()) {
|
||
|
var serviceIdentifierString = getServiceIdentifierAsString(serviceIdentifier);
|
||
|
var msg = ERROR_MSGS.AMBIGUOUS_MATCH + " " + serviceIdentifierString;
|
||
|
msg += listRegisteredBindingsForServiceIdentifier(container, serviceIdentifierString, getBindings);
|
||
|
throw new Error(msg);
|
||
|
}
|
||
|
else {
|
||
|
return bindings;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
function _createSubRequests(metadataReader, avoidConstraints, serviceIdentifier, context, parentRequest, target) {
|
||
|
var activeBindings;
|
||
|
var childRequest;
|
||
|
if (parentRequest === null) {
|
||
|
activeBindings = _getActiveBindings(metadataReader, avoidConstraints, context, null, target);
|
||
|
childRequest = new Request(serviceIdentifier, context, null, activeBindings, target);
|
||
|
var thePlan = new Plan(context, childRequest);
|
||
|
context.addPlan(thePlan);
|
||
|
}
|
||
|
else {
|
||
|
activeBindings = _getActiveBindings(metadataReader, avoidConstraints, context, parentRequest, target);
|
||
|
childRequest = parentRequest.addChildRequest(target.serviceIdentifier, activeBindings, target);
|
||
|
}
|
||
|
activeBindings.forEach(function (binding) {
|
||
|
var subChildRequest = null;
|
||
|
if (target.isArray()) {
|
||
|
subChildRequest = childRequest.addChildRequest(binding.serviceIdentifier, binding, target);
|
||
|
}
|
||
|
else {
|
||
|
if (binding.cache) {
|
||
|
return;
|
||
|
}
|
||
|
subChildRequest = childRequest;
|
||
|
}
|
||
|
if (binding.type === BindingTypeEnum.Instance && binding.implementationType !== null) {
|
||
|
var dependencies = getDependencies(metadataReader, binding.implementationType);
|
||
|
if (!context.container.options.skipBaseClassChecks) {
|
||
|
var baseClassDependencyCount = getBaseClassDependencyCount(metadataReader, binding.implementationType);
|
||
|
if (dependencies.length < baseClassDependencyCount) {
|
||
|
var error = ERROR_MSGS.ARGUMENTS_LENGTH_MISMATCH(getFunctionName(binding.implementationType));
|
||
|
throw new Error(error);
|
||
|
}
|
||
|
}
|
||
|
dependencies.forEach(function (dependency) {
|
||
|
_createSubRequests(metadataReader, false, dependency.serviceIdentifier, context, subChildRequest, dependency);
|
||
|
});
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
function getBindings(container, serviceIdentifier) {
|
||
|
var bindings = [];
|
||
|
var bindingDictionary = getBindingDictionary(container);
|
||
|
if (bindingDictionary.hasKey(serviceIdentifier)) {
|
||
|
bindings = bindingDictionary.get(serviceIdentifier);
|
||
|
}
|
||
|
else if (container.parent !== null) {
|
||
|
bindings = getBindings(container.parent, serviceIdentifier);
|
||
|
}
|
||
|
return bindings;
|
||
|
}
|
||
|
function plan(metadataReader, container, isMultiInject, targetType, serviceIdentifier, key, value, avoidConstraints) {
|
||
|
if (avoidConstraints === void 0) { avoidConstraints = false; }
|
||
|
var context = new Context(container);
|
||
|
var target = _createTarget(isMultiInject, targetType, serviceIdentifier, "", key, value);
|
||
|
try {
|
||
|
_createSubRequests(metadataReader, avoidConstraints, serviceIdentifier, context, null, target);
|
||
|
return context;
|
||
|
}
|
||
|
catch (error) {
|
||
|
if (isStackOverflowExeption(error)) {
|
||
|
if (context.plan) {
|
||
|
circularDependencyToException(context.plan.rootRequest);
|
||
|
}
|
||
|
}
|
||
|
throw error;
|
||
|
}
|
||
|
}
|
||
|
function createMockRequest(container, serviceIdentifier, key, value) {
|
||
|
var target = new Target(TargetTypeEnum.Variable, "", serviceIdentifier, new Metadata(key, value));
|
||
|
var context = new Context(container);
|
||
|
var request = new Request(serviceIdentifier, context, null, [], target);
|
||
|
return request;
|
||
|
}
|
||
|
export { plan, createMockRequest, getBindingDictionary };
|