Skip to content

Commit fc76e81

Browse files
committed
refactor: move code to reactiveEffect.ts
1 parent 93b5beb commit fc76e81

File tree

7 files changed

+160
-152
lines changed

7 files changed

+160
-152
lines changed

packages/reactivity/__tests__/effect.spec.ts

+2-6
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,8 @@ import {
1111
readonly,
1212
ReactiveEffectRunner
1313
} from '../src/index'
14-
import {
15-
ITERATE_KEY,
16-
getDepFromReactive,
17-
pauseScheduling,
18-
resetScheduling
19-
} from '../src/effect'
14+
import { pauseScheduling, resetScheduling } from '../src/effect'
15+
import { ITERATE_KEY, getDepFromReactive } from '../src/reactiveEffect'
2016

2117
describe('reactivity/effect', () => {
2218
it('should run the passed function once (wrapped by a effect)', () => {

packages/reactivity/src/baseHandlers.ts

+1-3
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,12 @@ import {
1212
} from './reactive'
1313
import { ReactiveFlags, TrackOpTypes, TriggerOpTypes } from './constants'
1414
import {
15-
track,
16-
trigger,
17-
ITERATE_KEY,
1815
pauseTracking,
1916
resetTracking,
2017
pauseScheduling,
2118
resetScheduling
2219
} from './effect'
20+
import { track, trigger, ITERATE_KEY } from './reactiveEffect'
2321
import {
2422
isObject,
2523
hasOwn,

packages/reactivity/src/collectionHandlers.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
import { toRaw, toReactive, toReadonly } from './reactive'
2-
import { track, trigger, ITERATE_KEY, MAP_KEY_ITERATE_KEY } from './effect'
2+
import {
3+
track,
4+
trigger,
5+
ITERATE_KEY,
6+
MAP_KEY_ITERATE_KEY
7+
} from './reactiveEffect'
38
import { ReactiveFlags, TrackOpTypes, TriggerOpTypes } from './constants'
49
import { capitalize, hasOwn, hasChanged, toRawType, isMap } from '@vue/shared'
510

packages/reactivity/src/effect.ts

+3-138
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,8 @@
1+
import { extend } from '@vue/shared'
2+
import type { ComputedRefImpl } from './computed'
13
import { DirtyLevels, TrackOpTypes, TriggerOpTypes } from './constants'
2-
import { extend, isArray, isIntegerKey, isMap } from '@vue/shared'
4+
import type { Dep } from './dep'
35
import { EffectScope, recordEffectScope } from './effectScope'
4-
import { createDep, Dep } from './dep'
5-
import type { ComputedRefImpl } from './computed'
6-
7-
// The main WeakMap that stores {target -> key -> dep} connections.
8-
// Conceptually, it's easier to think of a dependency as a Dep class
9-
// which maintains a Set of subscribers, but we simply store them as
10-
// raw Sets to reduce memory overhead.
11-
type KeyToDepMap = Map<any, Dep>
12-
const targetMap = new WeakMap<object, KeyToDepMap>()
136

147
export type EffectScheduler = (
158
onScheduled: (cb: () => void) => void,
@@ -31,9 +24,6 @@ export type DebuggerEventExtraInfo = {
3124

3225
export let activeEffect: ReactiveEffect | undefined
3326

34-
export const ITERATE_KEY = Symbol(__DEV__ ? 'iterate' : '')
35-
export const MAP_KEY_ITERATE_KEY = Symbol(__DEV__ ? 'Map key iterate' : '')
36-
3727
export class ReactiveEffect<T = any> {
3828
active = true
3929
deps: Dep[] = []
@@ -260,38 +250,6 @@ export function resetScheduling() {
260250
}
261251
}
262252

263-
/**
264-
* Tracks access to a reactive property.
265-
*
266-
* This will check which effect is running at the moment and record it as dep
267-
* which records all effects that depend on the reactive property.
268-
*
269-
* @param target - Object holding the reactive property.
270-
* @param type - Defines the type of access to the reactive property.
271-
* @param key - Identifier of the reactive property to track.
272-
*/
273-
export function track(target: object, type: TrackOpTypes, key: unknown) {
274-
if (shouldTrack && activeEffect) {
275-
let depsMap = targetMap.get(target)
276-
if (!depsMap) {
277-
targetMap.set(target, (depsMap = new Map()))
278-
}
279-
let dep = depsMap.get(key)
280-
if (!dep) {
281-
depsMap.set(key, (dep = createDep(() => depsMap!.delete(key))))
282-
}
283-
if (__DEV__) {
284-
trackEffect(activeEffect, dep, {
285-
target,
286-
type,
287-
key
288-
})
289-
} else {
290-
trackEffect(activeEffect, dep)
291-
}
292-
}
293-
}
294-
295253
export function trackEffect(
296254
effect: ReactiveEffect,
297255
dep: Dep,
@@ -314,95 +272,6 @@ export function trackEffect(
314272
}
315273
}
316274

317-
/**
318-
* Finds all deps associated with the target (or a specific property) and
319-
* triggers the effects stored within.
320-
*
321-
* @param target - The reactive object.
322-
* @param type - Defines the type of the operation that needs to trigger effects.
323-
* @param key - Can be used to target a specific reactive property in the target object.
324-
*/
325-
export function trigger(
326-
target: object,
327-
type: TriggerOpTypes,
328-
key?: unknown,
329-
newValue?: unknown,
330-
oldValue?: unknown,
331-
oldTarget?: Map<unknown, unknown> | Set<unknown>
332-
) {
333-
const depsMap = targetMap.get(target)
334-
if (!depsMap) {
335-
// never been tracked
336-
return
337-
}
338-
339-
let deps: (Dep | undefined)[] = []
340-
if (type === TriggerOpTypes.CLEAR) {
341-
// collection being cleared
342-
// trigger all effects for target
343-
deps = [...depsMap.values()]
344-
} else if (key === 'length' && isArray(target)) {
345-
const newLength = Number(newValue)
346-
depsMap.forEach((dep, key) => {
347-
if (key === 'length' || key >= newLength) {
348-
deps.push(dep)
349-
}
350-
})
351-
} else {
352-
// schedule runs for SET | ADD | DELETE
353-
if (key !== void 0) {
354-
deps.push(depsMap.get(key))
355-
}
356-
357-
// also run for iteration key on ADD | DELETE | Map.SET
358-
switch (type) {
359-
case TriggerOpTypes.ADD:
360-
if (!isArray(target)) {
361-
deps.push(depsMap.get(ITERATE_KEY))
362-
if (isMap(target)) {
363-
deps.push(depsMap.get(MAP_KEY_ITERATE_KEY))
364-
}
365-
} else if (isIntegerKey(key)) {
366-
// new index added to array -> length changes
367-
deps.push(depsMap.get('length'))
368-
}
369-
break
370-
case TriggerOpTypes.DELETE:
371-
if (!isArray(target)) {
372-
deps.push(depsMap.get(ITERATE_KEY))
373-
if (isMap(target)) {
374-
deps.push(depsMap.get(MAP_KEY_ITERATE_KEY))
375-
}
376-
}
377-
break
378-
case TriggerOpTypes.SET:
379-
if (isMap(target)) {
380-
deps.push(depsMap.get(ITERATE_KEY))
381-
}
382-
break
383-
}
384-
}
385-
386-
pauseScheduling()
387-
for (const dep of deps) {
388-
if (dep) {
389-
if (__DEV__) {
390-
triggerEffects(dep, DirtyLevels.Dirty, {
391-
target,
392-
type,
393-
key,
394-
newValue,
395-
oldValue,
396-
oldTarget
397-
})
398-
} else {
399-
triggerEffects(dep, DirtyLevels.Dirty)
400-
}
401-
}
402-
}
403-
resetScheduling()
404-
}
405-
406275
const queueEffectCbs: (() => void)[] = []
407276
const pushEffectCb = queueEffectCbs.push.bind(queueEffectCbs)
408277

@@ -436,7 +305,3 @@ export function triggerEffects(
436305
}
437306
resetScheduling()
438307
}
439-
440-
export function getDepFromReactive(object: any, key: string | number | symbol) {
441-
return targetMap.get(object)?.get(key)
442-
}

packages/reactivity/src/index.ts

+1-3
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,11 @@ export { deferredComputed } from './deferredComputed'
4848
export {
4949
effect,
5050
stop,
51-
trigger,
52-
track,
5351
enableTracking,
5452
pauseTracking,
5553
resetTracking,
5654
pauseScheduling,
5755
resetScheduling,
58-
ITERATE_KEY,
5956
ReactiveEffect,
6057
type ReactiveEffectRunner,
6158
type ReactiveEffectOptions,
@@ -64,6 +61,7 @@ export {
6461
type DebuggerEvent,
6562
type DebuggerEventExtraInfo
6663
} from './effect'
64+
export { trigger, track, ITERATE_KEY } from './reactiveEffect'
6765
export {
6866
effectScope,
6967
EffectScope,
+146
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
import { isArray, isIntegerKey, isMap } from '@vue/shared'
2+
import { DirtyLevels, TrackOpTypes, TriggerOpTypes } from './constants'
3+
import { createDep, Dep } from './dep'
4+
import {
5+
activeEffect,
6+
pauseScheduling,
7+
resetScheduling,
8+
shouldTrack,
9+
trackEffect,
10+
triggerEffects
11+
} from './effect'
12+
13+
// The main WeakMap that stores {target -> key -> dep} connections.
14+
// Conceptually, it's easier to think of a dependency as a Dep class
15+
// which maintains a Set of subscribers, but we simply store them as
16+
// raw Sets to reduce memory overhead.
17+
type KeyToDepMap = Map<any, Dep>
18+
const targetMap = new WeakMap<object, KeyToDepMap>()
19+
20+
export const ITERATE_KEY = Symbol(__DEV__ ? 'iterate' : '')
21+
export const MAP_KEY_ITERATE_KEY = Symbol(__DEV__ ? 'Map key iterate' : '')
22+
23+
/**
24+
* Tracks access to a reactive property.
25+
*
26+
* This will check which effect is running at the moment and record it as dep
27+
* which records all effects that depend on the reactive property.
28+
*
29+
* @param target - Object holding the reactive property.
30+
* @param type - Defines the type of access to the reactive property.
31+
* @param key - Identifier of the reactive property to track.
32+
*/
33+
export function track(target: object, type: TrackOpTypes, key: unknown) {
34+
if (shouldTrack && activeEffect) {
35+
let depsMap = targetMap.get(target)
36+
if (!depsMap) {
37+
targetMap.set(target, (depsMap = new Map()))
38+
}
39+
let dep = depsMap.get(key)
40+
if (!dep) {
41+
depsMap.set(key, (dep = createDep(() => depsMap!.delete(key))))
42+
}
43+
if (__DEV__) {
44+
trackEffect(activeEffect, dep, {
45+
target,
46+
type,
47+
key
48+
})
49+
} else {
50+
trackEffect(activeEffect, dep)
51+
}
52+
}
53+
}
54+
55+
/**
56+
* Finds all deps associated with the target (or a specific property) and
57+
* triggers the effects stored within.
58+
*
59+
* @param target - The reactive object.
60+
* @param type - Defines the type of the operation that needs to trigger effects.
61+
* @param key - Can be used to target a specific reactive property in the target object.
62+
*/
63+
export function trigger(
64+
target: object,
65+
type: TriggerOpTypes,
66+
key?: unknown,
67+
newValue?: unknown,
68+
oldValue?: unknown,
69+
oldTarget?: Map<unknown, unknown> | Set<unknown>
70+
) {
71+
const depsMap = targetMap.get(target)
72+
if (!depsMap) {
73+
// never been tracked
74+
return
75+
}
76+
77+
let deps: (Dep | undefined)[] = []
78+
if (type === TriggerOpTypes.CLEAR) {
79+
// collection being cleared
80+
// trigger all effects for target
81+
deps = [...depsMap.values()]
82+
} else if (key === 'length' && isArray(target)) {
83+
const newLength = Number(newValue)
84+
depsMap.forEach((dep, key) => {
85+
if (key === 'length' || key >= newLength) {
86+
deps.push(dep)
87+
}
88+
})
89+
} else {
90+
// schedule runs for SET | ADD | DELETE
91+
if (key !== void 0) {
92+
deps.push(depsMap.get(key))
93+
}
94+
95+
// also run for iteration key on ADD | DELETE | Map.SET
96+
switch (type) {
97+
case TriggerOpTypes.ADD:
98+
if (!isArray(target)) {
99+
deps.push(depsMap.get(ITERATE_KEY))
100+
if (isMap(target)) {
101+
deps.push(depsMap.get(MAP_KEY_ITERATE_KEY))
102+
}
103+
} else if (isIntegerKey(key)) {
104+
// new index added to array -> length changes
105+
deps.push(depsMap.get('length'))
106+
}
107+
break
108+
case TriggerOpTypes.DELETE:
109+
if (!isArray(target)) {
110+
deps.push(depsMap.get(ITERATE_KEY))
111+
if (isMap(target)) {
112+
deps.push(depsMap.get(MAP_KEY_ITERATE_KEY))
113+
}
114+
}
115+
break
116+
case TriggerOpTypes.SET:
117+
if (isMap(target)) {
118+
deps.push(depsMap.get(ITERATE_KEY))
119+
}
120+
break
121+
}
122+
}
123+
124+
pauseScheduling()
125+
for (const dep of deps) {
126+
if (dep) {
127+
if (__DEV__) {
128+
triggerEffects(dep, DirtyLevels.Dirty, {
129+
target,
130+
type,
131+
key,
132+
newValue,
133+
oldValue,
134+
oldTarget
135+
})
136+
} else {
137+
triggerEffects(dep, DirtyLevels.Dirty)
138+
}
139+
}
140+
}
141+
resetScheduling()
142+
}
143+
144+
export function getDepFromReactive(object: any, key: string | number | symbol) {
145+
return targetMap.get(object)?.get(key)
146+
}

packages/reactivity/src/ref.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import {
22
activeEffect,
3-
getDepFromReactive,
43
shouldTrack,
54
trackEffect,
65
triggerEffects
@@ -19,6 +18,7 @@ import type { ShallowReactiveMarker } from './reactive'
1918
import { CollectionTypes } from './collectionHandlers'
2019
import { createDep, Dep } from './dep'
2120
import { ComputedRefImpl } from './computed'
21+
import { getDepFromReactive } from './reactiveEffect'
2222

2323
declare const RefSymbol: unique symbol
2424
export declare const RawSymbol: unique symbol

0 commit comments

Comments
 (0)