Closed remojansen closed 6 years ago
This seems to be flaky on earlier versions of Node (at least 9.1.0) as well.
Is there any chance you could provide a minimal reproduction using non-transpiled code?
I will try but I'ven unable to reproduce it using minimal code so far.
Hi @addaleax I added many more versions of node to my CI build I I've seen some versions with inconsistent failures but one thing that seems to be consistent is that the first issue takes place in 8.3.0 I checked the change log and I have seem that 8.3.0 introduced a change that is directly related with this:
[357873ddb0] - (SEMVER-MINOR) v8: fix stack overflow in recursive method (Ben Noordhuis) #14004
My guess is that somethign wen't wrong with that change but I know nothing about V8 and C++ so I can't help here :(
Maybe @bnoordhuis can help here?
I have tried to change my implementation.
I was using the following:
function factoryWrapper<T extends Function>(
factoryType: FactoryType,
serviceIdentifier: interfaces.ServiceIdentifier<any>,
factory: T
) {
return (...args: any[]) => {
try {
return factory(...args);
} catch (error) {
if (isStackOverflowExeption(error)) {
throw new Error(
ERROR_MSGS.CIRCULAR_DEPENDENCY_IN_FACTORY(factoryType, serviceIdentifier)
);
} else {
throw error;
}
}
};
}
To wrap some factories:
public toAutoFactory<T2>(serviceIdentifier: interfaces.ServiceIdentifier<T2>): interfaces.BindingWhenOnSyntax<T> {
this._binding.type = BindingTypeEnum.Factory;
this._binding.factory = (context) => {
const autofactory = () => context.container.get<T2>(serviceIdentifier);
return factoryWrapper(
"toAutoFactory",
this._binding.serviceIdentifier.toString(),
autofactory
);
};
return new BindingWhenOnSyntax<T>(this._binding);
}
public toProvider<T2>(provider: interfaces.ProviderCreator<T2>): interfaces.BindingWhenOnSyntax<T> {
this._binding.type = BindingTypeEnum.Provider;
this._binding.provider = factoryWrapper(
"toProvider",
this._binding.serviceIdentifier.toString(),
provider
);
return new BindingWhenOnSyntax<T>(this._binding);
}
Now I'm wrapping them in a different way:
const invokeFactory = (
factoryType: FactoryType,
serviceIdentifier: interfaces.ServiceIdentifier<any>,
fn: () => any
) => {
try {
return fn();
} catch (error) {
if (isStackOverflowExeption(error)) {
throw new Error(
ERROR_MSGS.CIRCULAR_DEPENDENCY_IN_FACTORY(factoryType, serviceIdentifier.toString())
);
} else {
throw error;
}
}
};
} else if (binding.type === BindingTypeEnum.Provider && binding.provider !== null) {
result = invokeFactory(
"toProvider",
binding.serviceIdentifier,
() => binding.provider ? binding.provider(request.parentContext) : undefined
);
} else if (binding.type === BindingTypeEnum.Instance && binding.implementationType !== null) {
result = resolveInstance(
binding.implementationType,
childRequests,
_resolveRequest(requestScope)
);
}
The only difference between the previous and the new implementations is that in the previous (the failing one) there is an extra closure return (...args: any[]) => {
however the CI results are very different: https://travis-ci.org/inversify/InversifyJS/builds/316903
@bnoordhuis It happens in 8.0.0 so please forget about the 8.3.0 commit
Thanks for your time and sorry but now I think it was a case of https://github.com/nodejs/node/issues/14311 the only thing I can suggest since this is a known limitation is maybe try to come up with a way to warn the developers about this but I understand that it is not an easy one.
I'm the author of InversifyJS. InversifyJS is an IoC container and it is designed to throw an exception if it finds a circular dependency.
The
willThrow
function should catch an Error of typeMaximum call stack size exceeded
and throw a custom error this is the case in versions 7.10.1, 8.8.1 but not the case in 9.2.0 or 9.3.0.It is quite crazy because it is resolving an object that cannot be resolved (a circular object).
I have tried 9.3.0 in a few machines:
The only machines with the expected behavior (an exception is thrown) are the Macbook Pro and the WIndows machine.
I have a build that reproduces the issue https://travis-ci.org/inversify/InversifyJS/builds/316498439 and a PR https://github.com/inversify/InversifyJS/pull/716.
Thanks