Skip to content

Commit 93f54ed

Browse files
fix(core): attach root inquirer for nested transient providers
1 parent 732fd3b commit 93f54ed

File tree

2 files changed

+25
-5
lines changed

2 files changed

+25
-5
lines changed

packages/core/injector/injector.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import { CircularDependencyException } from '../errors/exceptions';
3232
import { RuntimeException } from '../errors/exceptions/runtime.exception';
3333
import { UndefinedDependencyException } from '../errors/exceptions/undefined-dependency.exception';
3434
import { UnknownDependenciesException } from '../errors/exceptions/unknown-dependencies.exception';
35+
import { Barrier } from '../helpers/barrier';
3536
import { STATIC_CONTEXT } from './constants';
3637
import { INQUIRER } from './inquirer';
3738
import {
@@ -42,7 +43,6 @@ import {
4243
} from './instance-wrapper';
4344
import { Module } from './module';
4445
import { SettlementSignal } from './settlement-signal';
45-
import { Barrier } from '../helpers/barrier';
4646

4747
/**
4848
* The type of an injectable dependency
@@ -327,8 +327,10 @@ export class Injector {
327327
return parentInquirer && parentInquirer.instance;
328328
}
329329
if (inquirer?.isTransient && parentInquirer) {
330-
inquirer = parentInquirer;
331-
inquirerId = this.getInquirerId(parentInquirer);
330+
// When `inquirer` is transient too, inherit the parent inquirer
331+
// This is required to ensure that transient providers are only resolved
332+
// when requested
333+
inquirer.attachRootInquirer(parentInquirer);
332334
}
333335
const paramWrapper = await this.resolveSingleParam<T>(
334336
wrapper,

packages/core/injector/instance-wrapper.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,11 @@ export class InstanceWrapper<T = any> {
8282
| undefined;
8383
private isTreeStatic: boolean | undefined;
8484
private isTreeDurable: boolean | undefined;
85+
/**
86+
* The root inquirer reference. Present only if child instance wrapper
87+
* is transient and has a parent inquirer.
88+
*/
89+
private rootInquirer: InstanceWrapper | undefined;
8590

8691
constructor(
8792
metadata: Partial<InstanceWrapper<T>> & Partial<InstancePerContext<T>> = {},
@@ -405,15 +410,28 @@ export class InstanceWrapper<T = any> {
405410
const isInquirerRequestScoped =
406411
inquirer && !inquirer.isDependencyTreeStatic();
407412
const isStaticTransient = this.isTransient && !isInquirerRequestScoped;
408-
413+
const rootInquirer = inquirer?.getRootInquirer();
409414
return (
410415
this.isDependencyTreeStatic() &&
411416
contextId === STATIC_CONTEXT &&
412417
(!this.isTransient ||
413-
(isStaticTransient && !!inquirer && !inquirer.isTransient))
418+
(isStaticTransient && !!inquirer && !inquirer.isTransient) ||
419+
(isStaticTransient && !!rootInquirer && !rootInquirer.isTransient))
414420
);
415421
}
416422

423+
public attachRootInquirer(inquirer: InstanceWrapper) {
424+
if (!this.isTransient) {
425+
// Only attach root inquirer if the instance wrapper is transient
426+
return;
427+
}
428+
this.rootInquirer = inquirer.getRootInquirer() ?? inquirer;
429+
}
430+
431+
getRootInquirer(): InstanceWrapper | undefined {
432+
return this.rootInquirer;
433+
}
434+
417435
public getStaticTransientInstances() {
418436
if (!this.transientMap) {
419437
return [];

0 commit comments

Comments
 (0)