Skip to content

Commit c97d1ba

Browse files
authored
fix(reactivity): shallowReactive collection to not-readonly (#1212)
1 parent 3f80183 commit c97d1ba

File tree

3 files changed

+127
-48
lines changed

3 files changed

+127
-48
lines changed

packages/reactivity/__tests__/reactive.spec.ts

+1-47
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
11
import { ref, isRef } from '../src/ref'
2-
import {
3-
reactive,
4-
isReactive,
5-
toRaw,
6-
markRaw,
7-
shallowReactive
8-
} from '../src/reactive'
2+
import { reactive, isReactive, toRaw, markRaw } from '../src/reactive'
93
import { mockWarn } from '@vue/shared'
104
import { computed } from '../src/computed'
115

@@ -175,44 +169,4 @@ describe('reactivity/reactive', () => {
175169
})
176170
expect(isReactive(obj.foo)).toBe(false)
177171
})
178-
179-
describe('shallowReactive', () => {
180-
test('should not make non-reactive properties reactive', () => {
181-
const props = shallowReactive({ n: { foo: 1 } })
182-
expect(isReactive(props.n)).toBe(false)
183-
})
184-
185-
test('should keep reactive properties reactive', () => {
186-
const props: any = shallowReactive({ n: reactive({ foo: 1 }) })
187-
props.n = reactive({ foo: 2 })
188-
expect(isReactive(props.n)).toBe(true)
189-
})
190-
191-
test('should not observe when iterating', () => {
192-
const shallowSet = shallowReactive(new Set())
193-
const a = {}
194-
shallowSet.add(a)
195-
196-
const spreadA = [...shallowSet][0]
197-
expect(isReactive(spreadA)).toBe(false)
198-
})
199-
200-
test('should not get reactive entry', () => {
201-
const shallowMap = shallowReactive(new Map())
202-
const a = {}
203-
const key = 'a'
204-
205-
shallowMap.set(key, a)
206-
207-
expect(isReactive(shallowMap.get(key))).toBe(false)
208-
})
209-
210-
test('should not get reactive on foreach', () => {
211-
const shallowSet = shallowReactive(new Set())
212-
const a = {}
213-
shallowSet.add(a)
214-
215-
shallowSet.forEach(x => expect(isReactive(x)).toBe(false))
216-
})
217-
})
218172
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
import { shallowReactive, isReactive, reactive } from '../src/reactive'
2+
import { effect } from '../src/effect'
3+
4+
describe('shallowReactive', () => {
5+
test('should not make non-reactive properties reactive', () => {
6+
const props = shallowReactive({ n: { foo: 1 } })
7+
expect(isReactive(props.n)).toBe(false)
8+
})
9+
10+
test('should keep reactive properties reactive', () => {
11+
const props: any = shallowReactive({ n: reactive({ foo: 1 }) })
12+
props.n = reactive({ foo: 2 })
13+
expect(isReactive(props.n)).toBe(true)
14+
})
15+
16+
describe('collections', () => {
17+
test('should be reactive', () => {
18+
const shallowSet = shallowReactive(new Set())
19+
const a = {}
20+
let size
21+
22+
effect(() => {
23+
size = shallowSet.size
24+
})
25+
26+
expect(size).toBe(0)
27+
28+
shallowSet.add(a)
29+
expect(size).toBe(1)
30+
31+
shallowSet.delete(a)
32+
expect(size).toBe(0)
33+
})
34+
35+
test('should not observe when iterating', () => {
36+
const shallowSet = shallowReactive(new Set())
37+
const a = {}
38+
shallowSet.add(a)
39+
40+
const spreadA = [...shallowSet][0]
41+
expect(isReactive(spreadA)).toBe(false)
42+
})
43+
44+
test('should not get reactive entry', () => {
45+
const shallowMap = shallowReactive(new Map())
46+
const a = {}
47+
const key = 'a'
48+
49+
shallowMap.set(key, a)
50+
51+
expect(isReactive(shallowMap.get(key))).toBe(false)
52+
})
53+
54+
test('should not get reactive on foreach', () => {
55+
const shallowSet = shallowReactive(new Set())
56+
const a = {}
57+
shallowSet.add(a)
58+
59+
shallowSet.forEach(x => expect(isReactive(x)).toBe(false))
60+
})
61+
62+
// #1210
63+
test('onTrack on called on objectSpread', () => {
64+
const onTrackFn = jest.fn()
65+
const shallowSet = shallowReactive(new Set())
66+
let a
67+
effect(
68+
() => {
69+
a = Array.from(shallowSet)
70+
},
71+
{
72+
onTrack: onTrackFn
73+
}
74+
)
75+
76+
expect(a).toMatchObject([])
77+
expect(onTrackFn).toHaveBeenCalled()
78+
})
79+
})
80+
81+
describe('array', () => {
82+
test('should be reactive', () => {
83+
const shallowArray = shallowReactive<unknown[]>([])
84+
const a = {}
85+
let size
86+
87+
effect(() => {
88+
size = shallowArray.length
89+
})
90+
91+
expect(size).toBe(0)
92+
93+
shallowArray.push(a)
94+
expect(size).toBe(1)
95+
96+
shallowArray.pop()
97+
expect(size).toBe(0)
98+
})
99+
test('should not observe when iterating', () => {
100+
const shallowArray = shallowReactive<object[]>([])
101+
const a = {}
102+
shallowArray.push(a)
103+
104+
const spreadA = [...shallowArray][0]
105+
expect(isReactive(spreadA)).toBe(false)
106+
})
107+
108+
test('onTrack on called on objectSpread', () => {
109+
const onTrackFn = jest.fn()
110+
const shallowArray = shallowReactive([])
111+
let a
112+
effect(
113+
() => {
114+
a = Array.from(shallowArray)
115+
},
116+
{
117+
onTrack: onTrackFn
118+
}
119+
)
120+
121+
expect(a).toMatchObject([])
122+
expect(onTrackFn).toHaveBeenCalled()
123+
})
124+
})
125+
})

packages/reactivity/src/collectionHandlers.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ iteratorMethods.forEach(method => {
265265
)
266266
shallowInstrumentations[method as string] = createIterableMethod(
267267
method,
268-
true,
268+
false,
269269
true
270270
)
271271
})

0 commit comments

Comments
 (0)