Skip to content

Commit 160412b

Browse files
committed
refactor: more refinement
1 parent 70adc07 commit 160412b

File tree

10 files changed

+72
-101
lines changed

10 files changed

+72
-101
lines changed

packages/reactivity/__tests__/effectScope.spec.ts

Lines changed: 35 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,16 @@ import {
33
reactive,
44
effect,
55
EffectScope,
6-
onDispose,
6+
onScopeDispose,
77
computed,
88
ref,
99
ComputedRef
1010
} from '../src'
1111

1212
describe('reactivity/effect/scope', () => {
13-
it('should run the passed function once (wrapped by a effect)', () => {
13+
it('should run', () => {
1414
const fnSpy = jest.fn(() => {})
15-
new EffectScope(fnSpy)
15+
new EffectScope().run(fnSpy)
1616
expect(fnSpy).toHaveBeenCalledTimes(1)
1717
})
1818

@@ -21,8 +21,13 @@ describe('reactivity/effect/scope', () => {
2121
expect(scope.effects.length).toBe(0)
2222
})
2323

24+
it('should return run value', () => {
25+
expect(new EffectScope().run(() => 1)).toBe(1)
26+
})
27+
2428
it('should collect the effects', () => {
25-
const scope = new EffectScope(() => {
29+
const scope = new EffectScope()
30+
scope.run(() => {
2631
let dummy
2732
const counter = reactive({ num: 0 })
2833
effect(() => (dummy = counter.num))
@@ -39,7 +44,8 @@ describe('reactivity/effect/scope', () => {
3944
let dummy, doubled
4045
const counter = reactive({ num: 0 })
4146

42-
const scope = new EffectScope(() => {
47+
const scope = new EffectScope()
48+
scope.run(() => {
4349
effect(() => (dummy = counter.num))
4450
effect(() => (doubled = counter.num * 2))
4551
})
@@ -62,10 +68,11 @@ describe('reactivity/effect/scope', () => {
6268
let dummy, doubled
6369
const counter = reactive({ num: 0 })
6470

65-
const scope = new EffectScope(() => {
71+
const scope = new EffectScope()
72+
scope.run(() => {
6673
effect(() => (dummy = counter.num))
6774
// nested scope
68-
new EffectScope(() => {
75+
new EffectScope().run(() => {
6976
effect(() => (doubled = counter.num * 2))
7077
})
7178
})
@@ -90,12 +97,13 @@ describe('reactivity/effect/scope', () => {
9097
let dummy, doubled
9198
const counter = reactive({ num: 0 })
9299

93-
const scope = new EffectScope(() => {
100+
const scope = new EffectScope()
101+
scope.run(() => {
94102
effect(() => (dummy = counter.num))
95103
// nested scope
96-
new EffectScope(() => {
104+
new EffectScope(true).run(() => {
97105
effect(() => (doubled = counter.num * 2))
98-
}, true)
106+
})
99107
})
100108

101109
expect(scope.effects.length).toBe(1)
@@ -114,17 +122,18 @@ describe('reactivity/effect/scope', () => {
114122
expect(doubled).toBe(12)
115123
})
116124

117-
it('able to extend the scope', () => {
125+
it('able to run the scope', () => {
118126
let dummy, doubled
119127
const counter = reactive({ num: 0 })
120128

121-
const scope = new EffectScope(() => {
129+
const scope = new EffectScope()
130+
scope.run(() => {
122131
effect(() => (dummy = counter.num))
123132
})
124133

125134
expect(scope.effects.length).toBe(1)
126135

127-
scope.extend(() => {
136+
scope.run(() => {
128137
effect(() => (doubled = counter.num * 2))
129138
})
130139

@@ -137,25 +146,24 @@ describe('reactivity/effect/scope', () => {
137146
scope.stop()
138147
})
139148

140-
it('can not extend an inactive scope', () => {
149+
it('can not run an inactive scope', () => {
141150
let dummy, doubled
142151
const counter = reactive({ num: 0 })
143152

144-
const scope = new EffectScope(() => {
153+
const scope = new EffectScope()
154+
scope.run(() => {
145155
effect(() => (dummy = counter.num))
146156
})
147157

148158
expect(scope.effects.length).toBe(1)
149159

150160
scope.stop()
151161

152-
scope.extend(() => {
162+
scope.run(() => {
153163
effect(() => (doubled = counter.num * 2))
154164
})
155165

156-
expect(
157-
'[Vue warn] cannot extend an inactive effect scope.'
158-
).toHaveBeenWarned()
166+
expect('[Vue warn] cannot run an inactive effect scope.').toHaveBeenWarned()
159167

160168
expect(scope.effects.length).toBe(1)
161169

@@ -164,34 +172,17 @@ describe('reactivity/effect/scope', () => {
164172
expect(doubled).toBe(undefined)
165173
})
166174

167-
it('should fire onStop hook', () => {
168-
let dummy = 0
169-
170-
const scope = new EffectScope(onStop => {
171-
onStop(() => (dummy += 1))
172-
onStop(() => (dummy += 2))
173-
})
174-
175-
scope.extend(onStop => {
176-
onStop(() => (dummy += 4))
177-
})
178-
179-
expect(dummy).toBe(0)
180-
181-
scope.stop()
182-
expect(dummy).toBe(7)
183-
})
184-
185175
it('should fire onDispose hook', () => {
186176
let dummy = 0
187177

188-
const scope = new EffectScope(() => {
189-
onDispose(() => (dummy += 1))
190-
onDispose(() => (dummy += 2))
178+
const scope = new EffectScope()
179+
scope.run(() => {
180+
onScopeDispose(() => (dummy += 1))
181+
onScopeDispose(() => (dummy += 2))
191182
})
192183

193-
scope.extend(() => {
194-
onDispose(() => (dummy += 4))
184+
scope.run(() => {
185+
onScopeDispose(() => (dummy += 4))
195186
})
196187

197188
expect(dummy).toBe(0)
@@ -208,7 +199,8 @@ describe('reactivity/effect/scope', () => {
208199
const watchEffectSpy = jest.fn()
209200

210201
let c: ComputedRef
211-
const scope = new EffectScope(() => {
202+
const scope = new EffectScope()
203+
scope.run(() => {
212204
c = computed(() => {
213205
computedSpy()
214206
return r.value + 1

packages/reactivity/src/effectScope.ts

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import { ReactiveEffect } from './effect'
22
import { warn } from './warning'
33

4-
export type EffectScopeOnStopHook = (fn: (() => void)) => void
5-
64
let activeEffectScope: EffectScope | undefined
75
const effectScopeStack: EffectScope[] = []
86

@@ -11,27 +9,24 @@ export class EffectScope {
119
effects: (ReactiveEffect | EffectScope)[] = []
1210
cleanups: (() => void)[] = []
1311

14-
constructor(fn?: (onStop: EffectScopeOnStopHook) => any, detached?: boolean) {
12+
constructor(detached?: boolean) {
1513
if (!detached) {
1614
recordEffectScope(this)
1715
}
18-
if (fn) {
19-
this.extend(fn)
20-
}
2116
}
2217

23-
extend(fn: (onStop: EffectScopeOnStopHook) => any) {
18+
run(fn: () => any) {
2419
if (this.active) {
2520
try {
2621
effectScopeStack.push(this)
2722
activeEffectScope = this
28-
fn(cleanup => this.cleanups.push(cleanup))
23+
return fn()
2924
} finally {
3025
effectScopeStack.pop()
3126
activeEffectScope = effectScopeStack[effectScopeStack.length - 1]
3227
}
3328
} else if (__DEV__) {
34-
warn(`cannot extend an inactive effect scope.`)
29+
warn(`cannot run an inactive effect scope.`)
3530
}
3631
}
3732

@@ -58,7 +53,7 @@ export function getCurrentScope() {
5853
return activeEffectScope
5954
}
6055

61-
export function onDispose(fn: () => void) {
56+
export function onScopeDispose(fn: () => void) {
6257
if (activeEffectScope) {
6358
activeEffectScope.cleanups.push(fn)
6459
} else if (__DEV__) {

packages/reactivity/src/index.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,5 @@ export {
5151
EffectScheduler,
5252
DebuggerEvent
5353
} from './effect'
54-
export {
55-
EffectScope,
56-
getCurrentScope,
57-
onDispose,
58-
EffectScopeOnStopHook
59-
} from './effectScope'
54+
export { EffectScope, getCurrentScope, onScopeDispose } from './effectScope'
6055
export { TrackOpTypes, TriggerOpTypes } from './operations'

packages/runtime-core/__tests__/apiWatch.spec.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -848,16 +848,16 @@ describe('api: watch', () => {
848848
render(h(Comp), nodeOps.createElement('div'))
849849

850850
expect(instance!).toBeDefined()
851-
expect(instance!.effectScope.effects).toBeInstanceOf(Array)
851+
expect(instance!.scope.effects).toBeInstanceOf(Array)
852852
// includes the component's own render effect AND the watcher effect
853-
expect(instance!.effectScope.effects!.length).toBe(2)
853+
expect(instance!.scope.effects!.length).toBe(2)
854854

855855
_show!.value = false
856856

857857
await nextTick()
858858
await nextTick()
859859

860-
expect(instance!.effectScope.effects![0].active).toBe(false)
860+
expect(instance!.scope.effects![0].active).toBe(false)
861861
})
862862

863863
test('this.$watch should pass `this.proxy` to watch source as the first argument ', () => {

packages/runtime-core/src/apiLifecycle.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,11 @@ export function injectHook(
3737
// This assumes the hook does not synchronously trigger other hooks, which
3838
// can only be false when the user does something really funky.
3939
setCurrentInstance(target)
40-
const res = callWithAsyncErrorHandling(hook, target, type, args)
40+
const res = target.scope.active
41+
? target.scope.run(() =>
42+
callWithAsyncErrorHandling(hook, target, type, args)
43+
)
44+
: callWithAsyncErrorHandling(hook, target, type, args)
4145
setCurrentInstance(null)
4246
resetTracking()
4347
return res

packages/runtime-core/src/apiWatch.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ function doWatch(
325325
}
326326
}
327327

328-
const scope = instance && instance.effectScope
328+
const scope = instance && instance.scope
329329
const effect = new ReactiveEffect(getter, scheduler, scope)
330330

331331
if (__DEV__) {

packages/runtime-core/src/compat/global.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import {
2-
stop,
32
isReactive,
43
reactive,
54
track,
@@ -564,7 +563,7 @@ function installCompatMount(
564563
}
565564
delete app._container.__vue_app__
566565
} else {
567-
const { bum, effectScope, um } = instance
566+
const { bum, scope, um } = instance
568567
// beforeDestroy hooks
569568
if (bum) {
570569
invokeArrayFns(bum)
@@ -573,8 +572,8 @@ function installCompatMount(
573572
instance.emit('hook:beforeDestroy')
574573
}
575574
// stop effects
576-
if (effectScope) {
577-
stop(effectScope)
575+
if (scope) {
576+
scope.stop()
578577
}
579578
// unmounted hook
580579
if (um) {

packages/runtime-core/src/component.ts

Lines changed: 9 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { VNode, VNodeChild, isVNode } from './vnode'
22
import {
3-
ReactiveEffect,
43
pauseTracking,
54
resetTracking,
65
shallowReadonly,
@@ -218,11 +217,6 @@ export interface ComponentInternalInstance {
218217
* Root vnode of this component's own vdom tree
219218
*/
220219
subTree: VNode
221-
/**
222-
* Main update effect
223-
* @internal
224-
*/
225-
effect: ReactiveEffect
226220
/**
227221
* Bound effect runner to be passed to schedulers
228222
*/
@@ -247,7 +241,7 @@ export interface ComponentInternalInstance {
247241
* so that they can be automatically stopped on component unmount
248242
* @internal
249243
*/
250-
effectScope: EffectScope
244+
scope: EffectScope
251245
/**
252246
* cache for proxy access type to avoid hasOwnProperty calls
253247
* @internal
@@ -452,14 +446,13 @@ export function createComponentInstance(
452446
root: null!, // to be immediately set
453447
next: null,
454448
subTree: null!, // will be set synchronously right after creation
455-
effect: null!, // will be set synchronously right after creation
456449
update: null!, // will be set synchronously right after creation
450+
scope: new EffectScope(),
457451
render: null,
458452
proxy: null,
459453
exposed: null,
460454
exposeProxy: null,
461455
withProxy: null,
462-
effectScope: new EffectScope(),
463456
provides: parent ? parent.provides : Object.create(appContext.provides),
464457
accessCache: null!,
465458
renderCache: [],
@@ -616,23 +609,17 @@ function setupStatefulComponent(
616609
// 2. call setup()
617610
const { setup } = Component
618611
if (setup) {
619-
let setupResult: any
620612
const setupContext = (instance.setupContext =
621613
setup.length > 1 ? createSetupContext(instance) : null)
622614

623615
currentInstance = instance
624616
pauseTracking()
625-
instance.effectScope.extend(() => {
626-
setupResult = callWithErrorHandling(
627-
setup,
628-
instance,
629-
ErrorCodes.SETUP_FUNCTION,
630-
[
631-
__DEV__ ? shallowReadonly(instance.props) : instance.props,
632-
setupContext
633-
]
634-
)
635-
})
617+
const setupResult = instance.scope.run(() =>
618+
callWithErrorHandling(setup, instance, ErrorCodes.SETUP_FUNCTION, [
619+
__DEV__ ? shallowReadonly(instance.props) : instance.props,
620+
setupContext
621+
])
622+
)
636623
resetTracking()
637624
currentInstance = null
638625

@@ -810,9 +797,7 @@ export function finishComponentSetup(
810797
if (__FEATURE_OPTIONS_API__ && !(__COMPAT__ && skipOptions)) {
811798
currentInstance = instance
812799
pauseTracking()
813-
instance.effectScope.extend(() => {
814-
applyOptions(instance)
815-
})
800+
instance.scope.run(() => applyOptions(instance))
816801
resetTracking()
817802
currentInstance = null
818803
}

0 commit comments

Comments
 (0)