Skip to content

Disposing container does not dispose singleton resolved from child container #237

@eduardvercaemer

Description

@eduardvercaemer

Describe the bug
Disposing container does not dispose singleton resolved from child container.

See reproduction for details:

To Reproduce

import "reflect-metadata";
import {
  container,
  Disposable,
  injectable,
  Lifecycle,
  scoped,
  singleton,
} from "tsyringe";

@singleton()
@injectable()
class Foo implements Disposable {
  constructor() {
    console.log("making foo!");
  }

  dispose(): void | Promise<void> {
    console.log("disposing foo!");
  }
}

@scoped(Lifecycle.ContainerScoped)
@injectable()
class Bar {
  constructor(private readonly foo: Foo) {
    console.log("making bar!");
  }
}

const childA = container.createChildContainer();
const childB = container.createChildContainer();

/**
 * making foo!
 * making bar!
 * making bar!
 */
childA.resolve(Bar);
childB.resolve(Bar);

/**
 * no output, container already has a Foo
 */
container.resolve(Foo);

/**
 * no output, is not disposing of Foo...
 */
await container.dispose();

/**
 * disposing foo!
 */
await childA.dispose();

Expected behavior
I expect singletons to always execute their dispose function even when calling dispose on a container which wasn't used when they where first resolved.

i.e. I expect the same behavior of first resolving the singleton from the root container and then resolving it from child containers:

import {
  container,
  Disposable,
  injectable,
  Lifecycle,
  scoped,
  singleton,
} from "tsyringe";

@singleton()
@injectable()
class Foo implements Disposable {
  constructor() {
    console.log("making foo!");
  }

  dispose(): void | Promise<void> {
    console.log("disposing foo!");
  }
}

@scoped(Lifecycle.ContainerScoped)
@injectable()
class Bar {
  constructor(private readonly foo: Foo) {
    console.log("making bar!");
  }
}

/**
 * making foo!
 */
container.resolve(Foo);

const childA = container.createChildContainer();
const childB = container.createChildContainer();

/**
 * making bar!
 * making bar!
 */
childA.resolve(Bar);
childB.resolve(Bar);

/**
 * disposing foo!
 */
await container.dispose();

Version: 4.8.0

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions