Skip to content

Commit 075f215

Browse files
committed
wip: onTrack/onTrigger debugger options
1 parent 15c5c43 commit 075f215

File tree

9 files changed

+174
-90
lines changed

9 files changed

+174
-90
lines changed

src/core/observer/array.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* dynamically accessing methods on Array prototype
44
*/
55

6+
import { TriggerOpTypes } from '../../v3'
67
import { def } from '../util/index'
78

89
const arrayProto = Array.prototype
@@ -39,7 +40,15 @@ methodsToPatch.forEach(function (method) {
3940
}
4041
if (inserted) ob.observeArray(inserted)
4142
// notify change
42-
ob.dep.notify()
43+
if (__DEV__) {
44+
ob.dep.notify({
45+
type: TriggerOpTypes.ARRAY_MUTATION,
46+
target: this,
47+
key: method
48+
})
49+
} else {
50+
ob.dep.notify()
51+
}
4352
return result
4453
})
4554
})

src/core/observer/index.ts

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {
1515
isServerRendering,
1616
hasChanged
1717
} from '../util/index'
18-
import { isReadonly, isRef, TrackOpTypes } from '../../v3'
18+
import { isReadonly, isRef, TrackOpTypes, TriggerOpTypes } from '../../v3'
1919

2020
const arrayKeys = Object.getOwnPropertyNames(arrayMethods)
2121

@@ -198,11 +198,22 @@ export function defineReactive(
198198
return
199199
} else if (isRef(value) && !isRef(newVal)) {
200200
value.value = newVal
201+
return
201202
} else {
202203
val = newVal
203204
}
204205
childOb = !shallow && observe(newVal)
205-
dep.notify()
206+
if (__DEV__) {
207+
dep.notify({
208+
type: TriggerOpTypes.SET,
209+
target: obj,
210+
key,
211+
newValue: newVal,
212+
oldValue: value
213+
})
214+
} else {
215+
dep.notify()
216+
}
206217
}
207218
})
208219

@@ -251,7 +262,17 @@ export function set(
251262
return val
252263
}
253264
defineReactive(ob.value, key, val)
254-
ob.dep.notify()
265+
if (__DEV__) {
266+
ob.dep.notify({
267+
type: TriggerOpTypes.ADD,
268+
target: target,
269+
key,
270+
newValue: val,
271+
oldValue: undefined
272+
})
273+
} else {
274+
ob.dep.notify()
275+
}
255276
return val
256277
}
257278

@@ -289,7 +310,15 @@ export function del(target: Array<any> | Object, key: any) {
289310
if (!ob) {
290311
return
291312
}
292-
ob.dep.notify()
313+
if (__DEV__) {
314+
ob.dep.notify({
315+
type: TriggerOpTypes.DELETE,
316+
target: target,
317+
key
318+
})
319+
} else {
320+
ob.dep.notify()
321+
}
293322
}
294323

295324
/**

src/v3/reactivity/operations.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ export const enum TrackOpTypes {
99
export const enum TriggerOpTypes {
1010
SET = 'set',
1111
ADD = 'add',
12-
DELETE = 'delete'
12+
DELETE = 'delete',
13+
ARRAY_MUTATION = 'array mutation'
1314
}

src/v3/reactivity/ref.ts

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
import type { IfAny } from 'typescript/utils'
88
import Dep from 'core/observer/dep'
99
import { warn, isArray, def } from 'core/util'
10-
import { TrackOpTypes } from './operations'
10+
import { TrackOpTypes, TriggerOpTypes } from './operations'
1111

1212
declare const RefSymbol: unique symbol
1313
export declare const RawSymbol: unique symbol
@@ -74,7 +74,16 @@ export function triggerRef(ref: Ref) {
7474
if (__DEV__ && !ref.dep) {
7575
warn(`received object is not a triggerable ref.`)
7676
}
77-
ref.dep && ref.dep.notify()
77+
if (__DEV__) {
78+
ref.dep &&
79+
ref.dep.notify({
80+
type: TriggerOpTypes.SET,
81+
target: ref,
82+
key: 'value'
83+
})
84+
} else {
85+
ref.dep && ref.dep.notify()
86+
}
7887
}
7988

8089
export function unref<T>(ref: T | Ref<T>): T {
@@ -104,7 +113,15 @@ export function customRef<T>(factory: CustomRefFactory<T>): Ref<T> {
104113
}
105114
},
106115
() => {
107-
dep.notify()
116+
if (__DEV__) {
117+
dep.notify({
118+
target: ref,
119+
type: TriggerOpTypes.SET,
120+
key: 'value'
121+
})
122+
} else {
123+
dep.notify()
124+
}
108125
}
109126
)
110127
const ref = {

test/unit/features/v3/apiWatch.spec.ts

Lines changed: 53 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -789,7 +789,6 @@ describe('api: watch', () => {
789789
const obj = reactive({ foo: 1 })
790790
const r = ref(2)
791791
const c = computed(() => r.value + 1)
792-
// TODO computed & ref
793792
watchEffect(
794793
() => {
795794
dummy = obj.foo + r.value + c.value
@@ -818,43 +817,59 @@ describe('api: watch', () => {
818817
])
819818
})
820819

821-
// it('onTrigger', async () => {
822-
// const events: DebuggerEvent[] = []
823-
// let dummy
824-
// const onTrigger = vi.fn((e: DebuggerEvent) => {
825-
// events.push(e)
826-
// })
827-
// const obj = reactive<{ foo?: number }>({ foo: 1 })
828-
// watchEffect(
829-
// () => {
830-
// dummy = obj.foo
831-
// },
832-
// { onTrigger }
833-
// )
834-
// await nextTick()
835-
// expect(dummy).toBe(1)
836-
837-
// obj.foo!++
838-
// await nextTick()
839-
// expect(dummy).toBe(2)
840-
// expect(onTrigger).toHaveBeenCalledTimes(1)
841-
// expect(events[0]).toMatchObject({
842-
// type: TriggerOpTypes.SET,
843-
// key: 'foo',
844-
// oldValue: 1,
845-
// newValue: 2
846-
// })
847-
848-
// delete obj.foo
849-
// await nextTick()
850-
// expect(dummy).toBeUndefined()
851-
// expect(onTrigger).toHaveBeenCalledTimes(2)
852-
// expect(events[1]).toMatchObject({
853-
// type: TriggerOpTypes.DELETE,
854-
// key: 'foo',
855-
// oldValue: 2
856-
// })
857-
// })
820+
it('onTrigger', async () => {
821+
const events: DebuggerEvent[] = []
822+
let dummy
823+
const onTrigger = vi.fn((e: DebuggerEvent) => {
824+
events.push(e)
825+
})
826+
const obj = reactive<{
827+
foo: number
828+
bar: any[]
829+
baz: { qux?: number }
830+
}>({ foo: 1, bar: [], baz: {} })
831+
832+
watchEffect(
833+
() => {
834+
dummy = obj.foo + (obj.bar[0] || 0) + (obj.baz.qux || 0)
835+
},
836+
{ onTrigger }
837+
)
838+
await nextTick()
839+
expect(dummy).toBe(1)
840+
841+
obj.foo++
842+
await nextTick()
843+
expect(dummy).toBe(2)
844+
expect(onTrigger).toHaveBeenCalledTimes(1)
845+
expect(events[0]).toMatchObject({
846+
type: TriggerOpTypes.SET,
847+
key: 'foo',
848+
target: obj,
849+
oldValue: 1,
850+
newValue: 2
851+
})
852+
853+
obj.bar.push(1)
854+
await nextTick()
855+
expect(dummy).toBe(3)
856+
expect(onTrigger).toHaveBeenCalledTimes(2)
857+
expect(events[1]).toMatchObject({
858+
type: TriggerOpTypes.ARRAY_MUTATION,
859+
target: obj.bar,
860+
key: 'push'
861+
})
862+
863+
set(obj.baz, 'qux', 1)
864+
await nextTick()
865+
expect(dummy).toBe(4)
866+
expect(onTrigger).toHaveBeenCalledTimes(3)
867+
expect(events[2]).toMatchObject({
868+
type: TriggerOpTypes.ADD,
869+
target: obj.baz,
870+
key: 'qux'
871+
})
872+
})
858873

859874
it('should work sync', () => {
860875
const v = ref(1)

test/unit/features/v3/reactivity/computed.spec.ts

Lines changed: 48 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@ import {
55
isReadonly,
66
WritableComputedRef,
77
DebuggerEvent,
8-
TrackOpTypes
8+
TrackOpTypes,
9+
TriggerOpTypes
910
} from 'v3'
1011
import { effect } from 'v3/reactivity/effect'
1112
import { nextTick } from 'core/util'
12-
// import { TrackOpTypes, TriggerOpTypes } from 'v3/reactivity/operations'
13+
import { set, del } from 'core/observer/index'
1314

1415
describe('reactivity/computed', () => {
1516
it('should return updated value', () => {
@@ -252,40 +253,49 @@ describe('reactivity/computed', () => {
252253
])
253254
})
254255

255-
// TODO
256-
// it('debug: onTrigger', () => {
257-
// let events: DebuggerEvent[] = []
258-
// const onTrigger = vi.fn((e: DebuggerEvent) => {
259-
// events.push(e)
260-
// })
261-
// const obj = reactive({ foo: 1 })
262-
// const c = computed(() => obj.foo, { onTrigger })
263-
264-
// // computed won't trigger compute until accessed
265-
// c.value
266-
267-
// obj.foo++
268-
// expect(c.value).toBe(2)
269-
// expect(onTrigger).toHaveBeenCalledTimes(1)
270-
// expect(events[0]).toEqual({
271-
// effect: c.effect,
272-
// target: toRaw(obj),
273-
// type: TriggerOpTypes.SET,
274-
// key: 'foo',
275-
// oldValue: 1,
276-
// newValue: 2
277-
// })
278-
279-
// // @ts-ignore
280-
// delete obj.foo
281-
// expect(c.value).toBeUndefined()
282-
// expect(onTrigger).toHaveBeenCalledTimes(2)
283-
// expect(events[1]).toEqual({
284-
// effect: c.effect,
285-
// target: toRaw(obj),
286-
// type: TriggerOpTypes.DELETE,
287-
// key: 'foo',
288-
// oldValue: 2
289-
// })
290-
// })
256+
it('debug: onTrigger', () => {
257+
let events: DebuggerEvent[] = []
258+
const onTrigger = vi.fn((e: DebuggerEvent) => {
259+
events.push(e)
260+
})
261+
const obj = reactive({ foo: 1, bar: { baz: 2 } })
262+
const c = computed(() => obj.foo + (obj.bar.baz || 0), { onTrigger })
263+
264+
// computed won't trigger compute until accessed
265+
c.value
266+
267+
obj.foo++
268+
expect(c.value).toBe(4)
269+
expect(onTrigger).toHaveBeenCalledTimes(1)
270+
expect(events[0]).toEqual({
271+
effect: c.effect,
272+
target: obj,
273+
type: TriggerOpTypes.SET,
274+
key: 'foo',
275+
oldValue: 1,
276+
newValue: 2
277+
})
278+
279+
del(obj.bar, 'baz')
280+
expect(c.value).toBe(2)
281+
expect(onTrigger).toHaveBeenCalledTimes(2)
282+
expect(events[1]).toEqual({
283+
effect: c.effect,
284+
target: obj.bar,
285+
type: TriggerOpTypes.DELETE,
286+
key: 'baz'
287+
})
288+
289+
set(obj.bar, 'baz', 1)
290+
expect(c.value).toBe(3)
291+
expect(onTrigger).toHaveBeenCalledTimes(3)
292+
expect(events[2]).toEqual({
293+
effect: c.effect,
294+
target: obj.bar,
295+
type: TriggerOpTypes.ADD,
296+
key: 'baz',
297+
oldValue: undefined,
298+
newValue: 1
299+
})
300+
})
291301
})

test/unit/features/v3/reactivity/ref.spec.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ import {
1010
Ref,
1111
isReactive,
1212
isShallow,
13-
reactive
13+
reactive,
14+
computed
1415
} from 'v3'
1516
import { effect } from 'v3/reactivity/effect'
1617

@@ -237,7 +238,7 @@ describe('reactivity/ref', () => {
237238

238239
test('isRef', () => {
239240
expect(isRef(ref(1))).toBe(true)
240-
// TODO expect(isRef(computed(() => 1))).toBe(true)
241+
expect(isRef(computed(() => 1))).toBe(true)
241242

242243
expect(isRef(0)).toBe(false)
243244
expect(isRef(1)).toBe(false)

typescript/component.d.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,10 @@ export declare class Component {
4646
$isServer: boolean
4747

4848
// public methods
49-
$mount: (el?: Element | string, hydrating?: boolean) => Component
49+
$mount: (
50+
el?: Element | string,
51+
hydrating?: boolean
52+
) => Component & { [key: string]: any }
5053
$forceUpdate: () => void
5154
$destroy: () => void
5255
$set: <T>(

typescript/global-api.d.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { Config } from '../src/core/config'
22
import { Component } from './component'
3-
import { ComponentOptions } from './options'
43

54
declare interface GlobalAPI {
65
// new(options?: any): Component
@@ -10,7 +9,7 @@ declare interface GlobalAPI {
109
config: Config
1110
util: Object
1211

13-
extend: (options: typeof Component | ComponentOptions) => typeof Component
12+
extend: (options: typeof Component | object) => typeof Component
1413
set: <T>(target: Object | Array<T>, key: string | number, value: T) => T
1514
delete: <T>(target: Object | Array<T>, key: string | number) => void
1615
nextTick: (fn: Function, context?: Object) => void | Promise<any>

0 commit comments

Comments
 (0)