Skip to content

Commit 6d96fbe

Browse files
committed
feat(effectScope): add lazy-initialized signal getter with automatic abort on stop
1 parent 5ce227b commit 6d96fbe

File tree

2 files changed

+30
-0
lines changed

2 files changed

+30
-0
lines changed

packages/reactivity/__tests__/effectScope.spec.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,23 @@ describe('reactivity/effect/scope', () => {
363363
expect(getEffectsCount(scope)).toBe(0)
364364
expect(scope.cleanupsLength).toBe(0)
365365
})
366+
367+
test('signal', () => {
368+
const scope = effectScope()
369+
// should not create an `AbortController` until `scope.signal` is accessed
370+
expect((scope as any)._controller).toBeUndefined()
371+
372+
const { signal } = scope
373+
expect((scope as any)._controller).toBeDefined()
374+
expect(signal).toBeDefined()
375+
376+
const spy = vi.fn()
377+
signal.addEventListener('abort', spy)
378+
379+
scope.stop()
380+
// should trigger `abort` on the `signal` when `scope.stop()` is called.
381+
expect(spy).toBeCalled()
382+
})
366383
})
367384

368385
function getEffectsCount(scope: EffectScope): number {

packages/reactivity/src/effectScope.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,16 @@ export class EffectScope implements ReactiveNode {
1919
* @internal
2020
*/
2121
cleanupsLength = 0
22+
/**
23+
* @internal
24+
*/
25+
private _controller: AbortController | undefined
26+
27+
get signal(): AbortSignal {
28+
if (!this._controller) this._controller = new AbortController()
29+
30+
return this._controller.signal
31+
}
2232

2333
constructor(detached = false) {
2434
if (!detached && activeEffectScope) {
@@ -72,6 +82,9 @@ export class EffectScope implements ReactiveNode {
7282
if (!this.active) {
7383
return
7484
}
85+
if (this._controller) {
86+
this._controller.abort()
87+
}
7588
this.flags = EffectFlags.STOP
7689
let dep = this.deps
7790
while (dep !== undefined) {

0 commit comments

Comments
 (0)