Skip to content

Commit 33622d6

Browse files
committed
perf(reactivity): only trigger all effects on Array length mutation if new length is shorter than old length
1 parent 9882788 commit 33622d6

File tree

3 files changed

+34
-55
lines changed

3 files changed

+34
-55
lines changed

packages/reactivity/src/baseHandlers.ts

+5-20
Original file line numberDiff line numberDiff line change
@@ -91,20 +91,10 @@ function createSetter(isReadonly = false, shallow = false) {
9191
const result = Reflect.set(target, key, value, receiver)
9292
// don't trigger if target is something up in the prototype chain of original
9393
if (target === toRaw(receiver)) {
94-
/* istanbul ignore else */
95-
if (__DEV__) {
96-
const extraInfo = { oldValue, newValue: value }
97-
if (!hadKey) {
98-
trigger(target, TriggerOpTypes.ADD, key, extraInfo)
99-
} else if (hasChanged(value, oldValue)) {
100-
trigger(target, TriggerOpTypes.SET, key, extraInfo)
101-
}
102-
} else {
103-
if (!hadKey) {
104-
trigger(target, TriggerOpTypes.ADD, key)
105-
} else if (hasChanged(value, oldValue)) {
106-
trigger(target, TriggerOpTypes.SET, key)
107-
}
94+
if (!hadKey) {
95+
trigger(target, TriggerOpTypes.ADD, key, value)
96+
} else if (hasChanged(value, oldValue)) {
97+
trigger(target, TriggerOpTypes.SET, key, value, oldValue)
10898
}
10999
}
110100
return result
@@ -116,12 +106,7 @@ function deleteProperty(target: object, key: string | symbol): boolean {
116106
const oldValue = (target as any)[key]
117107
const result = Reflect.deleteProperty(target, key)
118108
if (result && hadKey) {
119-
/* istanbul ignore else */
120-
if (__DEV__) {
121-
trigger(target, TriggerOpTypes.DELETE, key, { oldValue })
122-
} else {
123-
trigger(target, TriggerOpTypes.DELETE, key)
124-
}
109+
trigger(target, TriggerOpTypes.DELETE, key, undefined, oldValue)
125110
}
126111
return result
127112
}

packages/reactivity/src/collectionHandlers.ts

+7-32
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,7 @@ function add(this: SetTypes, value: unknown) {
5151
const hadKey = proto.has.call(target, value)
5252
const result = proto.add.call(target, value)
5353
if (!hadKey) {
54-
/* istanbul ignore else */
55-
if (__DEV__) {
56-
trigger(target, TriggerOpTypes.ADD, value, { newValue: value })
57-
} else {
58-
trigger(target, TriggerOpTypes.ADD, value)
59-
}
54+
trigger(target, TriggerOpTypes.ADD, value, value)
6055
}
6156
return result
6257
}
@@ -69,20 +64,10 @@ function set(this: MapTypes, key: unknown, value: unknown) {
6964
const hadKey = proto.has.call(target, key)
7065
const oldValue = proto.get.call(target, key)
7166
const result = proto.set.call(target, key, value)
72-
/* istanbul ignore else */
73-
if (__DEV__) {
74-
const extraInfo = { oldValue, newValue: value }
75-
if (!hadKey) {
76-
trigger(target, TriggerOpTypes.ADD, key, extraInfo)
77-
} else if (hasChanged(value, oldValue)) {
78-
trigger(target, TriggerOpTypes.SET, key, extraInfo)
79-
}
80-
} else {
81-
if (!hadKey) {
82-
trigger(target, TriggerOpTypes.ADD, key)
83-
} else if (hasChanged(value, oldValue)) {
84-
trigger(target, TriggerOpTypes.SET, key)
85-
}
67+
if (!hadKey) {
68+
trigger(target, TriggerOpTypes.ADD, key, value)
69+
} else if (hasChanged(value, oldValue)) {
70+
trigger(target, TriggerOpTypes.SET, key, value, oldValue)
8671
}
8772
return result
8873
}
@@ -96,12 +81,7 @@ function deleteEntry(this: CollectionTypes, key: unknown) {
9681
// forward the operation before queueing reactions
9782
const result = proto.delete.call(target, key)
9883
if (hadKey) {
99-
/* istanbul ignore else */
100-
if (__DEV__) {
101-
trigger(target, TriggerOpTypes.DELETE, key, { oldValue })
102-
} else {
103-
trigger(target, TriggerOpTypes.DELETE, key)
104-
}
84+
trigger(target, TriggerOpTypes.DELETE, key, undefined, oldValue)
10585
}
10686
return result
10787
}
@@ -117,12 +97,7 @@ function clear(this: IterableCollections) {
11797
// forward the operation before queueing reactions
11898
const result = getProto(target).clear.call(target)
11999
if (hadItems) {
120-
/* istanbul ignore else */
121-
if (__DEV__) {
122-
trigger(target, TriggerOpTypes.CLEAR, void 0, { oldTarget })
123-
} else {
124-
trigger(target, TriggerOpTypes.CLEAR)
125-
}
100+
trigger(target, TriggerOpTypes.CLEAR, undefined, undefined, oldTarget)
126101
}
127102
return result
128103
}

packages/reactivity/src/effect.ts

+22-3
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,9 @@ export function trigger(
165165
target: object,
166166
type: TriggerOpTypes,
167167
key?: unknown,
168-
extraInfo?: DebuggerEventExtraInfo
168+
newValue?: unknown,
169+
oldValue?: unknown,
170+
oldTarget?: Map<unknown, unknown> | Set<unknown>
169171
) {
170172
const depsMap = targetMap.get(target)
171173
if (depsMap === void 0) {
@@ -174,7 +176,12 @@ export function trigger(
174176
}
175177
const effects = new Set<ReactiveEffect>()
176178
const computedRunners = new Set<ReactiveEffect>()
177-
if (type === TriggerOpTypes.CLEAR || (key === 'length' && isArray(target))) {
179+
if (
180+
type === TriggerOpTypes.CLEAR ||
181+
(key === 'length' &&
182+
isArray(target) &&
183+
(newValue as number) < (oldValue as number))
184+
) {
178185
// collection being cleared or Array length mutation
179186
// trigger all effects for target
180187
depsMap.forEach(dep => {
@@ -196,7 +203,19 @@ export function trigger(
196203
}
197204
}
198205
const run = (effect: ReactiveEffect) => {
199-
scheduleRun(effect, target, type, key, extraInfo)
206+
scheduleRun(
207+
effect,
208+
target,
209+
type,
210+
key,
211+
__DEV__
212+
? {
213+
newValue,
214+
oldValue,
215+
oldTarget
216+
}
217+
: undefined
218+
)
200219
}
201220
// Important: computed effects must be run first so that computed getters
202221
// can be invalidated before any normal effects that depend on them are run.

0 commit comments

Comments
 (0)