Skip to content

Commit

Permalink
feat(minor): support WeakRef targets in DisposeAggregator and `As…
Browse files Browse the repository at this point in the history
…yncDisposeAggregator`
  • Loading branch information
giladgd committed Nov 25, 2023
1 parent 0ab3474 commit 60360d6
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 7 deletions.
12 changes: 11 additions & 1 deletion src/AsyncDisposeAggregator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export class AsyncDisposeAggregator {

/**
* Disposes all the targets that have been added and clears the list of targets.
* You can wrap the target with a `WeakRef` to prevent this class from holding a strong reference to the target.
* @returns {Promise<void>}
*/
public async dispose(): Promise<void> {
Expand All @@ -75,6 +76,9 @@ export class AsyncDisposeAggregator {
} /* c8 ignore stop */
}

if (typeof WeakRef !== "undefined" && disposeTarget instanceof WeakRef)
disposeTarget = disposeTarget.deref();

if (disposeTarget == null)
continue;
else if (
Expand Down Expand Up @@ -117,4 +121,10 @@ type DisposeTarget = (() => void | Promise<void>) | {
[Symbol.dispose](): void
} | {
dispose(): void | Promise<void>
};
} | WeakRef<{
[Symbol.asyncDispose](): void | Promise<void>
} | {
[Symbol.dispose](): void
} | {
dispose(): void | Promise<void>
}>;
12 changes: 10 additions & 2 deletions src/DisposeAggregator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,16 @@ export class DisposeAggregator {

/**
* Disposes all the targets that have been added and clears the list of targets.
* You can wrap the target with a `WeakRef` to prevent this class from holding a strong reference to the target.
*/
public dispose(): void {
this._ensureNotDisposed();

while (this._targets.length > 0) {
const disposeTarget = this._targets.shift();
let disposeTarget = this._targets.shift();

if (typeof WeakRef !== "undefined" && disposeTarget instanceof WeakRef)
disposeTarget = disposeTarget.deref();

if (disposeTarget == null)
continue;
Expand Down Expand Up @@ -84,4 +88,8 @@ type DisposeAggregatorTarget = (() => void) | {
[Symbol.dispose](): void
} | {
dispose(): void
};
} | WeakRef<{
[Symbol.dispose](): void
} | {
dispose(): void
}>;
4 changes: 2 additions & 2 deletions test/AsyncDisposeAggregator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,13 @@ describe("AsyncDisposeAggregator", () => {
expect(stub3.disposed).toBe(false);
});

test("Symbol.asyncDispose", async () => {
test("WeakRef, Symbol.asyncDispose", async () => {
const disposeAggregator = new AsyncDisposeAggregator();

const stub = new DisposeStub();
expect(stub.disposed).toBe(false);

disposeAggregator.add(stub);
disposeAggregator.add(new WeakRef(stub));
expect(disposeAggregator.targetCount).toBe(1);

await disposeAggregator[Symbol.asyncDispose]();
Expand Down
4 changes: 2 additions & 2 deletions test/DisposeAggregator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ describe("DisposeAggregator", () => {
expect(stub2.disposed).toBe(false);
});

test("Symbol.asyncDispose", () => {
test("WeakRef, Symbol.dispose", () => {
const disposeAggregator = new DisposeAggregator();

const stub = new DisposeStub();
expect(stub.disposed).toBe(false);

disposeAggregator.add(stub);
disposeAggregator.add(new WeakRef(stub));
expect(disposeAggregator.targetCount).toBe(1);

disposeAggregator[Symbol.dispose]();
Expand Down
35 changes: 35 additions & 0 deletions test/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"compilerOptions": {
"lib": ["es2022"],
"module": "es2022",
"target": "es2022",
"esModuleInterop": true,
"noImplicitAny": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noImplicitOverride": true,
"removeComments": false,
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"skipLibCheck": true,
"moduleResolution": "node",
"resolveJsonModule": false,
"strictNullChecks": true,
"isolatedModules": true,
"noEmit": false,
"outDir": "./dist",
"strict": true,
"sourceMap": true,
"composite": false,
"declaration": true,
"stripInternal": true
},
"files": [],
"include": [
"."
],
"ts-node": {
"esm": true
}
}

0 comments on commit 60360d6

Please sign in to comment.