Просмотр исходного кода

fix(reactivity): handle `Set` with initial reactive values edge case (#12393)

fix #8647
hudson 1 месяц назад
Родитель
Сommit
5dc27ca68f

+ 13 - 0
packages/reactivity/__tests__/reactive.spec.ts

@@ -112,6 +112,19 @@ describe('reactivity/reactive', () => {
     expect(dummy).toBe(false)
   })
 
+  // #8647
+  test('observing Set with reactive initial value', () => {
+    const observed = reactive({})
+    const observedSet = reactive(new Set([observed]))
+
+    expect(observedSet.has(observed)).toBe(true)
+    expect(observedSet.size).toBe(1)
+
+    // expect nothing happens
+    observedSet.add(observed)
+    expect(observedSet.size).toBe(1)
+  })
+
   test('observed value should proxy mutations to original (Object)', () => {
     const original: any = { foo: 1 }
     const observed = reactive(original)

+ 9 - 6
packages/reactivity/src/collectionHandlers.ts

@@ -167,15 +167,18 @@ function createInstrumentations(
         }
       : {
           add(this: SetTypes, value: unknown) {
-            if (!shallow && !isShallow(value) && !isReadonly(value)) {
-              value = toRaw(value)
-            }
             const target = toRaw(this)
             const proto = getProto(target)
-            const hadKey = proto.has.call(target, value)
+            const valueToAdd =
+              !shallow && !isShallow(value) && !isReadonly(value)
+                ? toRaw(value)
+                : value
+            const hadKey =
+              proto.has.call(target, valueToAdd) ||
+              (value !== valueToAdd && proto.has.call(target, value))
             if (!hadKey) {
-              target.add(value)
-              trigger(target, TriggerOpTypes.ADD, value, value)
+              target.add(valueToAdd)
+              trigger(target, TriggerOpTypes.ADD, valueToAdd, valueToAdd)
             }
             return this
           },