@inversifyjs/core
Version:
InversifyJs core package
96 lines • 5.71 kB
JavaScript
import { BindingConstraintsImplementation, } from '../../binding/models/BindingConstraintsImplementation.js';
import { isStackOverflowError } from '../../error/calculations/isStackOverflowError.js';
import { InversifyCoreError } from '../../error/models/InversifyCoreError.js';
import { InversifyCoreErrorKind } from '../../error/models/InversifyCoreErrorKind.js';
import { LazyPlanServiceNode } from '../models/LazyPlanServiceNode.js';
import { curryBuildServiceNodeBindings } from './curryBuildServiceNodeBindings.js';
import { curryLazyBuildPlanServiceNodeFromClassElementMetadata } from './curryLazyBuildPlanServiceNodeFromClassElementMetadata.js';
import { curryLazyBuildPlanServiceNodeFromResolvedValueElementMetadata } from './curryLazyBuildPlanServiceNodeFromResolvedValueElementMetadata.js';
import { currySubplan } from './currySubplan.js';
import { buildPlanServiceNodeFromClassElementMetadata, buildPlanServiceNodeFromResolvedValueElementMetadata, } from './plan.js';
const subplan = currySubplan(buildPlanServiceNodeFromClassElementMetadata, buildPlanServiceNodeFromResolvedValueElementMetadata, circularLazyBuildPlanServiceNodeFromClassElementMetadata, circularLazyBuildPlanServiceNodeFromResolvedValueElementMetadata);
const buildServiceNodeBindings = curryBuildServiceNodeBindings(subplan);
const lazyBuildPlanServiceNodeFromClassElementMetadata = curryLazyBuildPlanServiceNodeFromClassElementMetadata(buildServiceNodeBindings);
const lazyBuildPlanServiceNodeFromResolvedValueElementMetadata = curryLazyBuildPlanServiceNodeFromResolvedValueElementMetadata(buildServiceNodeBindings);
function circularLazyBuildPlanServiceNodeFromClassElementMetadata(params, bindingConstraintsList, elementMetadata) {
return lazyBuildPlanServiceNodeFromClassElementMetadata(params, bindingConstraintsList, elementMetadata);
}
function circularLazyBuildPlanServiceNodeFromResolvedValueElementMetadata(params, bindingConstraintsList, elementMetadata) {
return lazyBuildPlanServiceNodeFromResolvedValueElementMetadata(params, bindingConstraintsList, elementMetadata);
}
/**
* Attach a binding to a service node if the binding is context-free.
* @param params The plan parameters.
* @param serviceNode The service node to attach the binding to.
* @param binding The binding to attach.
* @param bindingConstraintsList The list of binding constraints.
* @param chainedBindings Whether the bindings are chained.
* @returns True if the binding requires ancestor metadata, false otherwise.
*/
export function addServiceNodeBindingIfContextFree(params, serviceNode, binding, bindingConstraintsList, chainedBindings) {
if (LazyPlanServiceNode.is(serviceNode) && !serviceNode.isExpanded()) {
return {
isContextFreeBinding: true,
shouldInvalidateServiceNode: false,
};
}
const bindingConstraints = new BindingConstraintsImplementation(bindingConstraintsList.last);
if (!binding.isSatisfiedBy(bindingConstraints) ||
bindingConstraintsList.last.elem.getAncestorsCalled) {
return {
isContextFreeBinding: !bindingConstraintsList.last.elem.getAncestorsCalled,
shouldInvalidateServiceNode: false,
};
}
return addServiceNodeSatisfiedBindingIfContextFree(params, serviceNode, binding, bindingConstraintsList, chainedBindings);
}
function addServiceNodeSatisfiedBindingIfContextFree(params, serviceNode, binding, bindingConstraintsList, chainedBindings) {
let serviceNodeBinding;
try {
[serviceNodeBinding] = buildServiceNodeBindings(params, bindingConstraintsList, [binding], serviceNode, chainedBindings);
}
catch (error) {
if (isStackOverflowError(error) ||
InversifyCoreError.isErrorOfKind(error, InversifyCoreErrorKind.planningMaxDepthExceeded)) {
/**
* We could potentially detect if we managed to traverse at least one iteration of the circular dependency loop.
* If so, the binding is context free if and only if bindingConstraintsList.last.elem.getAncestorsCalled is false.
*
* Having said that, computing this does not solve an underlying issue with circular dependencies: further cache
* refreshes are likely to encounter the same issue again and again. Recovering from stack overflow errors constantly
* is not feasible, so we prefer to declare the binding as non context free, asking for a more aggressive cache
* invalidation strategy, which is likely to be a cache clear.
*/
return {
isContextFreeBinding: false,
shouldInvalidateServiceNode: true,
};
}
throw error;
}
return addServiceNodeBindingNodeIfContextFree(serviceNode, serviceNodeBinding);
}
function addServiceNodeBindingNodeIfContextFree(serviceNode, serviceNodeBinding) {
if (Array.isArray(serviceNode.bindings)) {
serviceNode.bindings.push(serviceNodeBinding);
}
else {
if (serviceNode.bindings === undefined) {
serviceNode.bindings = serviceNodeBinding;
}
else {
if (!LazyPlanServiceNode.is(serviceNode)) {
throw new InversifyCoreError(InversifyCoreErrorKind.planning, 'Unexpected non-lazy plan service node. This is likely a bug in the planning logic. Please, report this issue');
}
return {
isContextFreeBinding: true,
shouldInvalidateServiceNode: true,
};
}
}
return {
isContextFreeBinding: true,
shouldInvalidateServiceNode: false,
};
}
//# sourceMappingURL=addServiceNodeBindingIfContextFree.js.map