From dfb34fd514b513b39cf2583b118674b73b9c4ac2 Mon Sep 17 00:00:00 2001 From: liuseen-l <773890440@qq.com> Date: Mon, 5 Jun 2023 19:27:12 +0800 Subject: [PATCH 1/3] fix(reactivity): shallowReactive map "unwraps" the nested refs --- .../reactivity/__tests__/shallowReactive.spec.ts | 10 ++++++++++ packages/reactivity/src/collectionHandlers.ts | 16 ++++++++++------ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/packages/reactivity/__tests__/shallowReactive.spec.ts b/packages/reactivity/__tests__/shallowReactive.spec.ts index bc49078029a..f1b1c1a8701 100644 --- a/packages/reactivity/__tests__/shallowReactive.spec.ts +++ b/packages/reactivity/__tests__/shallowReactive.spec.ts @@ -123,6 +123,16 @@ describe('shallowReactive', () => { shallowSet.forEach(x => expect(isReactive(x)).toBe(false)) }) + test('Setting a reactive object on a shallowReactive map', () => { + const msg = ref('ads') + const bar = reactive({ msg }) + const foo = shallowReactive(new Map([['foo1', bar]])) + foo.set('foo2', bar) + + expect(isReactive(foo.get('foo2'))).toBe(true) + expect(isReactive(foo.get('foo1'))).toBe(true) + }) + // #1210 test('onTrack on called on objectSpread', () => { const onTrackFn = vi.fn() diff --git a/packages/reactivity/src/collectionHandlers.ts b/packages/reactivity/src/collectionHandlers.ts index 1d07af3be8c..fa80b494293 100644 --- a/packages/reactivity/src/collectionHandlers.ts +++ b/packages/reactivity/src/collectionHandlers.ts @@ -66,8 +66,8 @@ function size(target: IterableCollections, isReadonly = false) { return Reflect.get(target, 'size', target) } -function add(this: SetTypes, value: unknown) { - value = toRaw(value) +function add(this: SetTypes, value: unknown, isShallow = false) { + value = isShallow ? value : toRaw(value) const target = toRaw(this) const proto = getProto(target) const hadKey = proto.has.call(target, value) @@ -78,8 +78,8 @@ function add(this: SetTypes, value: unknown) { return this } -function set(this: MapTypes, key: unknown, value: unknown) { - value = toRaw(value) +function set(this: MapTypes, key: unknown, value: unknown, isShallow = false) { + value = isShallow ? value : toRaw(value) const target = toRaw(this) const { has, get } = getProto(target) @@ -251,8 +251,12 @@ function createInstrumentations() { return size(this as unknown as IterableCollections) }, has, - add, - set, + add(this: SetTypes, value: unknown) { + return add.call(this, value, true) + }, + set(this: MapTypes, key: unknown, value: unknown) { + return set.call(this, key, value, true) + }, delete: deleteEntry, clear, forEach: createForEach(false, true) From 2fd7acb120f621af1d7643da455ea14f733e52fe Mon Sep 17 00:00:00 2001 From: liuseen-l <773890440@qq.com> Date: Tue, 25 Jun 2024 18:46:56 +0800 Subject: [PATCH 2/3] feat(test): add test case for set --- .../reactivity/__tests__/shallowReactive.spec.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/packages/reactivity/__tests__/shallowReactive.spec.ts b/packages/reactivity/__tests__/shallowReactive.spec.ts index 050b68a589b..cb5ef8e6d97 100644 --- a/packages/reactivity/__tests__/shallowReactive.spec.ts +++ b/packages/reactivity/__tests__/shallowReactive.spec.ts @@ -133,6 +133,19 @@ describe('shallowReactive', () => { expect(isReactive(foo.get('foo1'))).toBe(true) }) + test('Setting a reactive object on a shallowReactive set', () => { + const msg = ref(1) + const bar = reactive({ msg }) + const foo = reactive({ msg }) + + const deps = shallowReactive(new Set([bar])) + deps.add(foo) + + deps.forEach(dep => { + expect(isReactive(dep)).toBe(true) + }) + }) + // #1210 test('onTrack on called on objectSpread', () => { const onTrackFn = vi.fn() From a289e54c742cc0b432795e3cd95d6c9f948d7705 Mon Sep 17 00:00:00 2001 From: liuseen-l <773890440@qq.com> Date: Fri, 28 Jun 2024 22:33:22 +0800 Subject: [PATCH 3/3] fix(reactive): The result of assignment and value fetching is inconsistent --- .../reactivity/__tests__/reactive.spec.ts | 23 +++++++++++++++++++ packages/reactivity/src/collectionHandlers.ts | 20 ++++++++++++---- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/packages/reactivity/__tests__/reactive.spec.ts b/packages/reactivity/__tests__/reactive.spec.ts index bd4ec402bb2..1c25c49121b 100644 --- a/packages/reactivity/__tests__/reactive.spec.ts +++ b/packages/reactivity/__tests__/reactive.spec.ts @@ -2,6 +2,8 @@ import { isRef, ref } from '../src/ref' import { isProxy, isReactive, + isReadonly, + isShallow, markRaw, reactive, readonly, @@ -359,4 +361,25 @@ describe('reactivity/reactive', () => { const c = computed(() => {}) expect(isProxy(c)).toBe(false) }) + + test('The results of the shallow and readonly assignments are the same (Map)', () => { + const map = reactive(new Map()) + map.set('foo', shallowReactive({ a: 2 })) + expect(isShallow(map.get('foo'))).toBe(true) + + map.set('bar', readonly({ b: 2 })) + expect(isReadonly(map.get('bar'))).toBe(true) + }) + + test('The results of the shallow and readonly assignments are the same (Set)', () => { + const set = reactive(new Set()) + set.add(shallowReactive({ a: 2 })) + set.add(readonly({ b: 2 })) + let count = 0 + for (const i of set) { + if (count === 0) expect(isShallow(i)).toBe(true) + else expect(isReadonly(i)).toBe(true) + count++ + } + }) }) diff --git a/packages/reactivity/src/collectionHandlers.ts b/packages/reactivity/src/collectionHandlers.ts index 3dc93027c68..c39e3ed48cd 100644 --- a/packages/reactivity/src/collectionHandlers.ts +++ b/packages/reactivity/src/collectionHandlers.ts @@ -1,4 +1,10 @@ -import { toRaw, toReactive, toReadonly } from './reactive' +import { + isReadonly, + isShallow, + toRaw, + toReactive, + toReadonly, +} from './reactive' import { ITERATE_KEY, MAP_KEY_ITERATE_KEY, @@ -72,8 +78,10 @@ function size(target: IterableCollections, isReadonly = false) { return Reflect.get(target, 'size', target) } -function add(this: SetTypes, value: unknown, isShallow = false) { - value = isShallow ? value : toRaw(value) +function add(this: SetTypes, value: unknown, _isShallow = false) { + if (!_isShallow && !isShallow(value) && !isReadonly(value)) { + value = toRaw(value) + } const target = toRaw(this) const proto = getProto(target) const hadKey = proto.has.call(target, value) @@ -84,8 +92,10 @@ function add(this: SetTypes, value: unknown, isShallow = false) { return this } -function set(this: MapTypes, key: unknown, value: unknown, isShallow = false) { - value = isShallow ? value : toRaw(value) +function set(this: MapTypes, key: unknown, value: unknown, _isShallow = false) { + if (!_isShallow && !isShallow(value) && !isReadonly(value)) { + value = toRaw(value) + } const target = toRaw(this) const { has, get } = getProto(target)