Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(reactivity): more efficient reactivity system #5912

Merged
merged 225 commits into from
Oct 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
225 commits
Select commit Hold shift + click to select a range
f485ea0
perf: calculate embedded `computed()` on-demand
johnsoncodehk May 13, 2022
208e59c
fix: computed effect dons't transfer
johnsoncodehk May 13, 2022
4a3e554
fix: revert effects trigger order
johnsoncodehk May 13, 2022
ed871c2
refactor: remove `computedToAskDirty` arg from `trigger()`
johnsoncodehk May 13, 2022
fbf214a
chore: use `hasChanged()` instead of `!==`
johnsoncodehk May 13, 2022
399f155
perf: reduce `triggerRefValue()` triggered
johnsoncodehk May 14, 2022
0e0c44e
perf: avoid duplicate trigger effect to deps
johnsoncodehk Jan 11, 2023
7768d43
fix: avoid track unrelated effects
johnsoncodehk Feb 2, 2023
a353eac
chore: make `_computedsToAskDirty` private
johnsoncodehk Feb 2, 2023
014dcd5
fix: jest -> vitest
johnsoncodehk Feb 2, 2023
eb0f8fa
fix: urgent assessment edge case
johnsoncodehk Apr 5, 2023
f3a0071
feat: more purposeful test
johnsoncodehk Apr 5, 2023
998c400
chore: add test for effect() on-demand trigger
johnsoncodehk Apr 6, 2023
b5527a1
Revert "chore: add test for effect() on-demand trigger"
johnsoncodehk Apr 6, 2023
3e0c2af
wip: on-demand effect()
johnsoncodehk Apr 6, 2023
62dc5ee
fix: ref newVal arg incorrect
johnsoncodehk Apr 7, 2023
e34619f
Merge branch 'computed-ondemand' into effect-ondemand
johnsoncodehk Apr 7, 2023
8895117
release: v3.3.0-alpha.9
haoqunjiang Apr 7, 2023
909afcc
fix: fixed effect for tests
johnsoncodehk Apr 7, 2023
da6263c
refactor: implement simplify
johnsoncodehk Apr 7, 2023
d2fd264
Revert "release: v3.3.0-alpha.9"
haoqunjiang Apr 7, 2023
f4d345d
Merge remote-tracking branch 'upstream/main' into computed-ondemand
johnsoncodehk Apr 8, 2023
866a3ee
Merge branch 'computed-ondemand' into effect-ondemand
johnsoncodehk Apr 8, 2023
0a16e82
Merge branch 'main' into pr/5912
johnsoncodehk Jul 31, 2023
6c9f058
chore: naming
johnsoncodehk Jul 31, 2023
66bcc3e
chore: with "s"
johnsoncodehk Jul 31, 2023
06f813e
Merge branch 'pr/5912' into pr/8043
johnsoncodehk Jul 31, 2023
debddde
chore: naming
johnsoncodehk Jul 31, 2023
ba66880
chore: undo format
johnsoncodehk Jul 31, 2023
cb081f6
chore: `_c` -> `deferredComputed`
johnsoncodehk Jul 31, 2023
7d21edf
Merge branch 'pr/5912' into pr/8043
johnsoncodehk Jul 31, 2023
76e2e6e
chore: `_c` -> `deferredComputed`
johnsoncodehk Jul 31, 2023
de4e436
chore: expressiveness
johnsoncodehk Jul 31, 2023
6c13a30
refactor: reuse `effectTrackDepth`
johnsoncodehk Jul 31, 2023
ef2a6e3
refactor: remove unneeded `pauseTracking()`, `resetTracking()`
johnsoncodehk Jul 31, 2023
7bc1069
chore: sort in one line
johnsoncodehk Jul 31, 2023
d77f842
Merge branch 'pr/5912' into pr/8043
johnsoncodehk Jul 31, 2023
f0512d6
chore: sort in one line
johnsoncodehk Jul 31, 2023
7e2ac74
chore: naming
johnsoncodehk Jul 31, 2023
e98d329
chore: import type
johnsoncodehk Jul 31, 2023
02805c5
Merge branch 'pr/5912' into pr/8043
johnsoncodehk Jul 31, 2023
d5595cb
chore: narrow `pauseTracking()`
johnsoncodehk Aug 1, 2023
01c7b80
Merge branch 'pr/5912' into pr/8043
johnsoncodehk Aug 1, 2023
44cbb5e
perf: cache dep indexes
johnsoncodehk Aug 14, 2023
8a3c786
perf: redo `length >= 2`
johnsoncodehk Aug 14, 2023
76da327
chore: hoist `triggerRefValue` for readability
johnsoncodehk Aug 14, 2023
9002b93
chore: always clear dep indexes cache to avoid memory leak
johnsoncodehk Aug 14, 2023
0f2c388
chore: less type hack
johnsoncodehk Aug 14, 2023
3b912e8
Merge branch 'main' into pr/5912
johnsoncodehk Aug 26, 2023
f8ff93a
chore: format
johnsoncodehk Aug 26, 2023
17342d5
refactor: abstract deferred computeds into ReactiveEffect
johnsoncodehk Aug 26, 2023
0194f02
fix: fixes _dirty updating for deferredComputed
johnsoncodehk Aug 26, 2023
16dc2b8
chore: revert deferredComputed
johnsoncodehk Aug 26, 2023
1b666b9
chore: format
johnsoncodehk Aug 26, 2023
bf89e57
perf: more efficient `watch()`
johnsoncodehk Aug 26, 2023
09e3512
chore(effect): use allow function
johnsoncodehk Aug 26, 2023
25578fd
chore(effect): release _deferredComputeds earlier
johnsoncodehk Aug 26, 2023
4b72c94
refactor(effect): make `scheduler` required
johnsoncodehk Aug 26, 2023
0257e69
refactor(effect): dirty -> applyDirty()
johnsoncodehk Aug 27, 2023
37d5c03
chore(effect): applyDirty() -> dirty, _dirty
johnsoncodehk Aug 27, 2023
1269644
chore(effect): add triggerEffectCallbacks()
johnsoncodehk Aug 27, 2023
07da2dd
chore(effect): triggerEffectCallbacks -> scheduleEffectCallbacks
johnsoncodehk Aug 27, 2023
891d937
chore(effect): fix syntax
johnsoncodehk Aug 27, 2023
3350c24
perf(reactivity): Array `shift()` should only trigger effect once
johnsoncodehk Aug 27, 2023
c187177
refactor(effect): de-abstract `scheduled`
johnsoncodehk Aug 28, 2023
d3517e0
Merge branch 'computed-ondemand' into array-effect
johnsoncodehk Aug 28, 2023
8f58ea3
chore(effect): mark dirty by default
johnsoncodehk Aug 28, 2023
770b2de
refactor(effect): abstract `dirty` setter
johnsoncodehk Aug 28, 2023
e0ef714
Merge branch 'computed-ondemand' into array-effect
johnsoncodehk Aug 28, 2023
e5e895d
fix(effect): revert updates for watch apis
johnsoncodehk Aug 28, 2023
3a89f4d
Merge branch 'computed-ondemand' into array-effect
johnsoncodehk Aug 28, 2023
3fc6349
chore: remove unneeded change
johnsoncodehk Aug 28, 2023
3821687
fix(computed): polyfill `_dirty`
johnsoncodehk Aug 28, 2023
a4b8bd2
Merge branch 'computed-ondemand' into array-effect
johnsoncodehk Aug 28, 2023
eb360e6
perf(runtime-core): re-render on deps changed
johnsoncodehk Aug 28, 2023
128b1eb
chore: format
johnsoncodehk Aug 28, 2023
a8f2bba
fix: computed causes render twice at the beginning
johnsoncodehk Aug 28, 2023
3aaa3af
chore: format
johnsoncodehk Aug 28, 2023
72c3312
Merge branch 'computed-ondemand' into renderer-ondemand
johnsoncodehk Aug 28, 2023
c7567d0
Merge branch 'computed-ondemand' into array-effect
johnsoncodehk Aug 28, 2023
1be6c50
fix: multiple computed triggers render multiple times
johnsoncodehk Aug 29, 2023
d2a5706
fix: computed getter trigger effect repeatedly
johnsoncodehk Aug 29, 2023
13c9a2c
fix: avoid computed side effects causing re-rendering
johnsoncodehk Aug 29, 2023
53db76c
chore: _mode -> _
johnsoncodehk Aug 29, 2023
e76b42c
chore: format
johnsoncodehk Aug 29, 2023
35f0ddd
chore: remove computed.init
johnsoncodehk Aug 29, 2023
914f62d
Merge branch 'computed-ondemand' into renderer-ondemand
johnsoncodehk Aug 29, 2023
e83221a
Merge branch 'computed-ondemand' into array-effect
johnsoncodehk Aug 29, 2023
e605560
refactor: TriggerReason -> TriggerType
johnsoncodehk Aug 29, 2023
fe8d996
chore: use resetDirty
johnsoncodehk Aug 29, 2023
9ab4eb1
chore: format
johnsoncodehk Aug 29, 2023
942be5d
chore: format
johnsoncodehk Aug 29, 2023
b1bd1de
fix: don't reset hard reset dirty for computed
johnsoncodehk Aug 29, 2023
ee05427
fix: computed deps update should re-trigger effects
johnsoncodehk Aug 29, 2023
99af87b
refactor(effect): add dirty setter
johnsoncodehk Aug 29, 2023
a181339
fix: computed should allow recursion dirty trigger
johnsoncodehk Aug 29, 2023
8084d74
fix: avoid tree shaking `deferredComputed.value`
johnsoncodehk Aug 30, 2023
194f8a8
perf: reuse `_depIndexes`
johnsoncodehk Aug 30, 2023
d4bf9ad
Merge branch 'computed-ondemand' into array-effect
johnsoncodehk Aug 30, 2023
85a7f22
Merge branch 'computed-ondemand' into renderer-ondemand
johnsoncodehk Aug 30, 2023
f620aa9
chore: fix tests
johnsoncodehk Aug 30, 2023
254d923
Merge branch 'computed-ondemand' into array-effect
johnsoncodehk Aug 30, 2023
8f8f384
Squashed commit of the following:
johnsoncodehk Aug 30, 2023
c02f650
perf: faster computed effect spread
johnsoncodehk Sep 1, 2023
8094661
Merge branch 'computed-ondemand' into array-effect
johnsoncodehk Sep 1, 2023
e74cd43
chore: format
johnsoncodehk Sep 1, 2023
fd1c9be
Merge branch 'computed-ondemand' into array-effect
johnsoncodehk Sep 1, 2023
9214ff4
Merge branch 'computed-ondemand' into renderer-ondemand
johnsoncodehk Sep 1, 2023
f5b0331
refactor: remove deferredComputed arg
johnsoncodehk Sep 1, 2023
9e64219
fix: fix vant test
johnsoncodehk Sep 1, 2023
b43c494
chore: fix triggerRefValue newValue for dev
johnsoncodehk Sep 1, 2023
c522871
chore: remove _alwaysAcceptComputedValueUpdated
johnsoncodehk Sep 1, 2023
5bd18ef
chore: less changes
johnsoncodehk Sep 1, 2023
b8c0a72
chore: less changes
johnsoncodehk Sep 1, 2023
e41763c
Merge branch 'computed-ondemand' into array-effect
johnsoncodehk Sep 1, 2023
857f60e
chore: remove unneeded `deps.includes`
johnsoncodehk Sep 1, 2023
174626c
refactor: reduce `dep` arg for triggerEffect()
johnsoncodehk Sep 1, 2023
d73ba7a
chore: move `_valueMaybeDirty = false`
johnsoncodehk Sep 1, 2023
80ea250
fix: remove `_valueMaybeDirty` for fix vuetify test
johnsoncodehk Sep 1, 2023
bc85a96
Merge branch 'computed-ondemand' into array-effect
johnsoncodehk Sep 1, 2023
e339def
refactor: abstract triggerType
johnsoncodehk Sep 1, 2023
f3625b0
chore: fix deferredComputed
johnsoncodehk Sep 1, 2023
f41bc9b
feat: redo apiWatch
johnsoncodehk Sep 1, 2023
09d6f05
fix: continuous effects cause computed dirty race condition
johnsoncodehk Sep 2, 2023
576be5f
fix: render triggers twice
johnsoncodehk Sep 2, 2023
7058975
refactor: remove queueEffectCbs
johnsoncodehk Sep 2, 2023
b3f502e
chore: DepsMaybeDirty -> ComputedValueMaybeDirty
johnsoncodehk Sep 3, 2023
a1cb22a
fix: computed scheduler should always trigger
johnsoncodehk Sep 3, 2023
bf85f9a
refactor: remove computed hack
johnsoncodehk Sep 3, 2023
710c7c5
feat(runtime-core): add `once` option to watch (#9034)
Alfred-Skyblue Aug 30, 2023
f5088d2
feat(compiler-sfc): expose resolve type-based props and emits (#8874)
sxzz Sep 4, 2023
ef8070c
feat(compiler-core): export error message (#8729)
shengxinjing Sep 5, 2023
f9bf306
Merge branch 'computed-ondemand' into array-effect
johnsoncodehk Sep 7, 2023
ab25229
Update deferredComputed.ts
johnsoncodehk Sep 7, 2023
3f5c373
make new logic working for `watch()`
johnsoncodehk Sep 7, 2023
1591ce1
update test result
johnsoncodehk Sep 7, 2023
eec0a78
sync #9056
johnsoncodehk Sep 7, 2023
b5eba14
Merge branch 'computed-ondemand' into array-effect
johnsoncodehk Sep 7, 2023
01e21d2
update test comment
johnsoncodehk Sep 7, 2023
0bdacad
chore: remove scheduleEffectCallbacks
johnsoncodehk Sep 7, 2023
3b0c4a7
combine if & while
johnsoncodehk Sep 8, 2023
f1eb3b6
deprecated deferredComputed
johnsoncodehk Sep 9, 2023
9f6d9b6
[autofix.ci] apply automated fixes
autofix-ci[bot] Sep 9, 2023
27a0b40
simplify triggerEffects
johnsoncodehk Sep 9, 2023
0147f1d
`dep.computed` -> `dep.triggerDirty()`
johnsoncodehk Sep 9, 2023
f4b13db
Update dep.ts
johnsoncodehk Sep 9, 2023
ee6fcca
update test title
johnsoncodehk Sep 9, 2023
7c59d8e
remove async
johnsoncodehk Sep 9, 2023
fc326b2
perf: check _scheduled
johnsoncodehk Sep 9, 2023
e26976f
refactor: operations.ts -> constants.ts
johnsoncodehk Sep 9, 2023
6af9492
Merge remote-tracking branch 'upstream/3.4' into computed-ondemand
johnsoncodehk Sep 9, 2023
a0b4fcb
add test for pauseScheduling
johnsoncodehk Sep 19, 2023
5978311
expose pauseScheduling, resetScheduling
johnsoncodehk Sep 19, 2023
52ac1ab
chore: fix test message
johnsoncodehk Sep 19, 2023
c44cb56
feat(runtime-core): add `once` option to watch (#9034)
Alfred-Skyblue Aug 30, 2023
7bc3ab1
feat(compiler-sfc): expose resolve type-based props and emits (#8874)
sxzz Sep 4, 2023
dc30885
feat(compiler-core): export error message (#8729)
shengxinjing Sep 5, 2023
f2bb0ea
chore: mark `@internal` for pauseScheduling, resetScheduling
johnsoncodehk Sep 22, 2023
f59957d
Merge branch 'minor' into computed-ondemand
johnsoncodehk Sep 22, 2023
196cdd3
Update packages/reactivity/src/computed.ts
johnsoncodehk Sep 22, 2023
e6ee9f3
fixs https://github.com/vuejs/core/pull/5912/commits/196cdd3eb8fa1b5e…
johnsoncodehk Sep 22, 2023
f5e93b7
Update computed.ts
johnsoncodehk Sep 22, 2023
d573e50
feat(runtime-core): add `once` option to watch (#9034)
Alfred-Skyblue Aug 30, 2023
d52617f
feat(compiler-sfc): expose resolve type-based props and emits (#8874)
sxzz Sep 4, 2023
be91d43
feat(compiler-core): export error message (#8729)
shengxinjing Sep 5, 2023
81cba7c
Merge branch 'minor' into computed-ondemand
johnsoncodehk Sep 22, 2023
3a3b46d
chore: less diff
johnsoncodehk Sep 22, 2023
3170eff
test: add test for #6018
johnsoncodehk Sep 27, 2023
afd7c54
fix: chained computed dirty reallocation after querying dirty
johnsoncodehk Sep 28, 2023
0f99a01
fix: always cleanup effect
johnsoncodehk Sep 29, 2023
34f0d26
refactor: alternative for `wasTracked`, `newTracked` markers
johnsoncodehk Sep 30, 2023
de25d13
perf: don't set deps length to 0 if no change
johnsoncodehk Sep 30, 2023
a9f0c02
chore: cleanup invalid deps for `trigger()`
johnsoncodehk Sep 30, 2023
6cd8340
chore: remove unneeded code
johnsoncodehk Sep 30, 2023
6e8700e
refactor: simplify `trigger()`
johnsoncodehk Oct 2, 2023
c75c3b3
chore: inline debug info
johnsoncodehk Oct 2, 2023
191e00b
chore: redo `cleanupEffect()`
johnsoncodehk Oct 2, 2023
951073b
perf: only schedule when dirty level change
johnsoncodehk Oct 2, 2023
2cf67b1
perf: use number for `pauseScheduling()`
johnsoncodehk Oct 2, 2023
ca1e1f1
chore: less condition
johnsoncodehk Oct 2, 2023
16127eb
chore: cleanup invalid effects before trigger callbacks
johnsoncodehk Oct 3, 2023
e0b1b88
refactor: only trigger with dirty level 0
johnsoncodehk Oct 3, 2023
586aa70
perf: defer reset `_scheduled`
johnsoncodehk Oct 3, 2023
2785f88
fix(computed): dirty not schedule edge case
johnsoncodehk Oct 4, 2023
33aab34
chore(computed): only reset _scheduled when value change
johnsoncodehk Oct 4, 2023
0636bac
test(computed): add a failed edge case
johnsoncodehk Oct 4, 2023
e13a421
fix(computed): remove unneeded `_scheduled` and fixes failed test
johnsoncodehk Oct 4, 2023
9d31bc9
refactor: cleanup deps just in time and avoid memory leak
johnsoncodehk Oct 5, 2023
fa80d44
chore: remove queryDirty
johnsoncodehk Oct 5, 2023
adc3ad7
chore: trigger side effects after scheduled for watch() and render()
johnsoncodehk Oct 10, 2023
dc54c59
Revert "feat(compiler-core): export error message (#8729)"
johnsoncodehk Oct 14, 2023
59a8c26
Revert "feat(compiler-sfc): expose resolve type-based props and emits…
johnsoncodehk Oct 14, 2023
34a0de4
remove a test
johnsoncodehk Oct 14, 2023
50418be
Revert "feat(runtime-core): add `once` option to watch (#9034)"
johnsoncodehk Oct 14, 2023
93b5beb
fix(reactivity): fix dep memory leak
johnsoncodehk Oct 18, 2023
fc76e81
refactor: move code to reactiveEffect.ts
johnsoncodehk Oct 18, 2023
66da31a
fix: use `WeakRef` for dep to avoid `ReactiveEffect` memory leak (#9233)
johnsoncodehk Oct 20, 2023
9f8f02e
perf: deferred create track token
johnsoncodehk Oct 20, 2023
e67116c
chore: _queryingDirty -> _queryings
johnsoncodehk Oct 20, 2023
3364351
chore: add missing dep cleanup
johnsoncodehk Oct 20, 2023
d3ff222
fix: only auto gc computed
johnsoncodehk Oct 20, 2023
8ff2a89
chore: stubbed WeakRef
johnsoncodehk Oct 20, 2023
9cd9335
chore: remove schedulerJob variable
johnsoncodehk Oct 20, 2023
888d934
Merge remote-tracking branch 'upstream/main' into computed-ondemand
johnsoncodehk Oct 21, 2023
c4829f3
Update reactiveEffect.ts
johnsoncodehk Oct 21, 2023
526faea
Update apiWatch.ts
johnsoncodehk Oct 21, 2023
081ccd4
fix: use FinalizationRegistry to cleanup unused computed
johnsoncodehk Oct 21, 2023
c388d13
Update effect.ts [skip ci]
johnsoncodehk Oct 21, 2023
c6b9bd2
test: disable threads for `FinalizationRegistry.register`
johnsoncodehk Oct 21, 2023
78c50e3
chore: remove `@internal` for fix dts build
johnsoncodehk Oct 21, 2023
3353fb4
chore: remove FakeFinalizationRegistry
johnsoncodehk Oct 21, 2023
c53bd48
chore: use const
johnsoncodehk Oct 21, 2023
ee17f37
fix: create trackToken when actually track [skip ci]
johnsoncodehk Oct 21, 2023
2bbb451
chore: remove StrongRef
johnsoncodehk Oct 21, 2023
3540dd1
chore: add TrackToken type [skip ci]
johnsoncodehk Oct 21, 2023
6799da0
chore: move TrackToken type [skip ci]
johnsoncodehk Oct 21, 2023
7023234
Merge remote-tracking branch 'upstream/main' into computed-ondemand
johnsoncodehk Oct 22, 2023
1e2db5b
chore: sort code
johnsoncodehk Oct 22, 2023
e888f58
asdf
johnsoncodehk Oct 25, 2023
1ce784b
qwer
johnsoncodehk Oct 25, 2023
b98b6b8
chore: avoid exposing internal properties on ReactiveEffect
yyx990803 Oct 26, 2023
600966b
refactor: use NOOP for empty triggers
yyx990803 Oct 26, 2023
265c22f
refactor: unuse `FinalizationRegistry`, `WeakRef`
johnsoncodehk Oct 26, 2023
b93299c
chore: remove `TrackToken` type
johnsoncodehk Oct 26, 2023
0555892
chore: revert `threads` option
johnsoncodehk Oct 26, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
165 changes: 164 additions & 1 deletion packages/reactivity/__tests__/computed.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ describe('reactivity/computed', () => {
// mutate n
n.value++
// on the 2nd run, plusOne.value should have already updated.
expect(plusOneValues).toMatchObject([1, 2, 2])
expect(plusOneValues).toMatchObject([1, 2])
})

it('should warn if trying to set a readonly computed', () => {
Expand Down Expand Up @@ -288,4 +288,167 @@ describe('reactivity/computed', () => {
oldValue: 2
})
})

// https://github.com/vuejs/core/pull/5912#issuecomment-1497596875
it('should query deps dirty sequentially', () => {
const cSpy = vi.fn()

const a = ref<null | { v: number }>({
v: 1
})
const b = computed(() => {
return a.value
})
const c = computed(() => {
cSpy()
return b.value?.v
})
const d = computed(() => {
if (b.value) {
return c.value
}
return 0
})

d.value
a.value!.v = 2
a.value = null
d.value
expect(cSpy).toHaveBeenCalledTimes(1)
})

// https://github.com/vuejs/core/pull/5912#issuecomment-1738257692
it('chained computed dirty reallocation after querying dirty', () => {
let _msg: string | undefined

const items = ref<number[]>()
const isLoaded = computed(() => {
return !!items.value
})
const msg = computed(() => {
if (isLoaded.value) {
return 'The items are loaded'
} else {
return 'The items are not loaded'
}
})

effect(() => {
_msg = msg.value
})

items.value = [1, 2, 3]
items.value = [1, 2, 3]
items.value = undefined

expect(_msg).toBe('The items are not loaded')
})

it('chained computed dirty reallocation after trigger computed getter', () => {
let _msg: string | undefined

const items = ref<number[]>()
const isLoaded = computed(() => {
return !!items.value
})
const msg = computed(() => {
if (isLoaded.value) {
return 'The items are loaded'
} else {
return 'The items are not loaded'
}
})

_msg = msg.value
items.value = [1, 2, 3]
isLoaded.value // <- trigger computed getter
_msg = msg.value
items.value = undefined
_msg = msg.value

expect(_msg).toBe('The items are not loaded')
})

// https://github.com/vuejs/core/pull/5912#issuecomment-1739159832
it('deps order should be consistent with the last time get value', () => {
const cSpy = vi.fn()

const a = ref(0)
const b = computed(() => {
return a.value % 3 !== 0
})
const c = computed(() => {
cSpy()
if (a.value % 3 === 2) {
return 'expensive'
}
return 'cheap'
})
const d = computed(() => {
return a.value % 3 === 2
})
const e = computed(() => {
if (b.value) {
if (d.value) {
return 'Avoiding expensive calculation'
}
}
return c.value
})

e.value
a.value++
e.value

expect(e.effect.deps.length).toBe(3)
expect(e.effect.deps.indexOf((b as any).dep)).toBe(0)
expect(e.effect.deps.indexOf((d as any).dep)).toBe(1)
expect(e.effect.deps.indexOf((c as any).dep)).toBe(2)
expect(cSpy).toHaveBeenCalledTimes(2)

a.value++
e.value

expect(cSpy).toHaveBeenCalledTimes(2)
})

it('should trigger by the second computed that maybe dirty', () => {
const cSpy = vi.fn()

const src1 = ref(0)
const src2 = ref(0)
const c1 = computed(() => src1.value)
const c2 = computed(() => (src1.value % 2) + src2.value)
const c3 = computed(() => {
cSpy()
c1.value
c2.value
})

c3.value
src1.value = 2
c3.value
expect(cSpy).toHaveBeenCalledTimes(2)
src2.value = 1
c3.value
expect(cSpy).toHaveBeenCalledTimes(3)
})

it('should trigger the second effect', () => {
const fnSpy = vi.fn()
const v = ref(1)
const c = computed(() => v.value)

effect(() => {
c.value
})
effect(() => {
c.value
fnSpy()
})

expect(fnSpy).toBeCalledTimes(1)
v.value = 2
expect(fnSpy).toBeCalledTimes(2)
})
})
62 changes: 16 additions & 46 deletions packages/reactivity/__tests__/deferredComputed.spec.ts
Original file line number Diff line number Diff line change
@@ -1,57 +1,32 @@
import { computed, deferredComputed, effect, ref } from '../src'
import { computed, effect, ref } from '../src'

describe('deferred computed', () => {
const tick = Promise.resolve()

test('should only trigger once on multiple mutations', async () => {
test('should not trigger if value did not change', () => {
const src = ref(0)
const c = deferredComputed(() => src.value)
const c = computed(() => src.value % 2)
const spy = vi.fn()
effect(() => {
spy(c.value)
})
expect(spy).toHaveBeenCalledTimes(1)
src.value = 1
src.value = 2
src.value = 3
// not called yet
expect(spy).toHaveBeenCalledTimes(1)
await tick
// should only trigger once
expect(spy).toHaveBeenCalledTimes(2)
expect(spy).toHaveBeenCalledWith(c.value)
})

test('should not trigger if value did not change', async () => {
const src = ref(0)
const c = deferredComputed(() => src.value % 2)
const spy = vi.fn()
effect(() => {
spy(c.value)
})
expect(spy).toHaveBeenCalledTimes(1)
src.value = 1
src.value = 2

await tick
// should not trigger
expect(spy).toHaveBeenCalledTimes(1)

src.value = 3
src.value = 4
src.value = 5
await tick
// should trigger because latest value changes
expect(spy).toHaveBeenCalledTimes(2)
})

test('chained computed trigger', async () => {
test('chained computed trigger', () => {
const effectSpy = vi.fn()
const c1Spy = vi.fn()
const c2Spy = vi.fn()

const src = ref(0)
const c1 = deferredComputed(() => {
const c1 = computed(() => {
c1Spy()
return src.value % 2
})
Expand All @@ -69,19 +44,18 @@ describe('deferred computed', () => {
expect(effectSpy).toHaveBeenCalledTimes(1)

src.value = 1
await tick
expect(c1Spy).toHaveBeenCalledTimes(2)
expect(c2Spy).toHaveBeenCalledTimes(2)
expect(effectSpy).toHaveBeenCalledTimes(2)
})

test('chained computed avoid re-compute', async () => {
test('chained computed avoid re-compute', () => {
const effectSpy = vi.fn()
const c1Spy = vi.fn()
const c2Spy = vi.fn()

const src = ref(0)
const c1 = deferredComputed(() => {
const c1 = computed(() => {
c1Spy()
return src.value % 2
})
Expand All @@ -98,26 +72,24 @@ describe('deferred computed', () => {
src.value = 2
src.value = 4
src.value = 6
await tick
// c1 should re-compute once.
expect(c1Spy).toHaveBeenCalledTimes(2)
expect(c1Spy).toHaveBeenCalledTimes(4)
// c2 should not have to re-compute because c1 did not change.
expect(c2Spy).toHaveBeenCalledTimes(1)
// effect should not trigger because c2 did not change.
expect(effectSpy).toHaveBeenCalledTimes(1)
})

test('chained computed value invalidation', async () => {
test('chained computed value invalidation', () => {
const effectSpy = vi.fn()
const c1Spy = vi.fn()
const c2Spy = vi.fn()

const src = ref(0)
const c1 = deferredComputed(() => {
const c1 = computed(() => {
c1Spy()
return src.value % 2
})
const c2 = deferredComputed(() => {
const c2 = computed(() => {
c2Spy()
return c1.value + 1
})
Expand All @@ -139,17 +111,17 @@ describe('deferred computed', () => {
expect(c2Spy).toHaveBeenCalledTimes(2)
})

test('sync access of invalidated chained computed should not prevent final effect from running', async () => {
test('sync access of invalidated chained computed should not prevent final effect from running', () => {
const effectSpy = vi.fn()
const c1Spy = vi.fn()
const c2Spy = vi.fn()

const src = ref(0)
const c1 = deferredComputed(() => {
const c1 = computed(() => {
c1Spy()
return src.value % 2
})
const c2 = deferredComputed(() => {
const c2 = computed(() => {
c2Spy()
return c1.value + 1
})
Expand All @@ -162,14 +134,13 @@ describe('deferred computed', () => {
src.value = 1
// sync access c2
c2.value
await tick
expect(effectSpy).toHaveBeenCalledTimes(2)
})

test('should not compute if deactivated before scheduler is called', async () => {
test('should not compute if deactivated before scheduler is called', () => {
const c1Spy = vi.fn()
const src = ref(0)
const c1 = deferredComputed(() => {
const c1 = computed(() => {
c1Spy()
return src.value % 2
})
Expand All @@ -179,7 +150,6 @@ describe('deferred computed', () => {
c1.effect.stop()
// trigger
src.value++
await tick
expect(c1Spy).toHaveBeenCalledTimes(1)
})
})
Loading