mirror of https://github.com/vuejs/core.git
Merge 853e9332e6
into 56be3dd4db
This commit is contained in:
commit
8c7dcea619
|
@ -112,6 +112,80 @@ describe('reactivity/reactive', () => {
|
|||
expect(dummy).toBe(false)
|
||||
})
|
||||
|
||||
test('reactive object with custom Symbol.toStringTag triggers reactivity', () => {
|
||||
const original = { [Symbol.toStringTag]: 'Goat', foo: 1 }
|
||||
const observed = reactive(original)
|
||||
|
||||
expect(isReactive(observed)).toBe(true)
|
||||
expect(isProxy(observed)).toBe(true)
|
||||
|
||||
let dummy: number | undefined
|
||||
effect(() => {
|
||||
dummy = observed.foo
|
||||
})
|
||||
|
||||
expect(dummy).toBe(1)
|
||||
|
||||
observed.foo = 2
|
||||
expect(dummy).toBe(2)
|
||||
})
|
||||
|
||||
test('custom collection type with custom Symbol.toStringTag is handled as a collection', () => {
|
||||
class MyCustomMap extends Map {
|
||||
get [Symbol.toStringTag]() {
|
||||
return 'MyCustomMap'
|
||||
}
|
||||
}
|
||||
|
||||
const myCustomMap = new MyCustomMap()
|
||||
|
||||
expect(Object.prototype.toString.call(myCustomMap)).toBe(
|
||||
'[object MyCustomMap]',
|
||||
)
|
||||
|
||||
const observed = reactive(myCustomMap)
|
||||
|
||||
expect(isReactive(observed)).toBe(true)
|
||||
expect(isProxy(observed)).toBe(true)
|
||||
|
||||
let dummy: boolean = false
|
||||
effect(() => {
|
||||
dummy = observed.has('foo')
|
||||
})
|
||||
|
||||
expect(dummy).toBe(false)
|
||||
|
||||
observed.set('foo', 'bar')
|
||||
expect(dummy).toBe(true)
|
||||
})
|
||||
|
||||
test('custom array type with custom Symbol.toStringTag is handled as a common object', () => {
|
||||
class MyArray extends Array {
|
||||
get [Symbol.toStringTag]() {
|
||||
return 'MyArray'
|
||||
}
|
||||
}
|
||||
|
||||
const myArr = new MyArray()
|
||||
|
||||
expect(Object.prototype.toString.call(myArr)).toBe('[object MyArray]')
|
||||
|
||||
const observed = reactive(myArr)
|
||||
|
||||
expect(isReactive(observed)).toBe(true)
|
||||
expect(isProxy(observed)).toBe(true)
|
||||
|
||||
let dummy: number = 0
|
||||
effect(() => {
|
||||
dummy = observed.length
|
||||
})
|
||||
|
||||
expect(dummy).toBe(0)
|
||||
|
||||
observed.push(42)
|
||||
expect(dummy).toBe(1)
|
||||
})
|
||||
|
||||
test('observed value should proxy mutations to original (Object)', () => {
|
||||
const original: any = { foo: 1 }
|
||||
const observed = reactive(original)
|
||||
|
|
|
@ -40,7 +40,8 @@ enum TargetType {
|
|||
COLLECTION = 2,
|
||||
}
|
||||
|
||||
function targetTypeMap(rawType: string) {
|
||||
function targetTypeMap(value: Target): TargetType {
|
||||
const rawType = toRawType(value)
|
||||
switch (rawType) {
|
||||
case 'Object':
|
||||
case 'Array':
|
||||
|
@ -51,14 +52,34 @@ function targetTypeMap(rawType: string) {
|
|||
case 'WeakSet':
|
||||
return TargetType.COLLECTION
|
||||
default:
|
||||
if (
|
||||
value instanceof Map ||
|
||||
value instanceof Set ||
|
||||
value instanceof WeakMap ||
|
||||
value instanceof WeakSet
|
||||
) {
|
||||
return TargetType.COLLECTION
|
||||
}
|
||||
if (value instanceof Array || isPlainObject(value)) {
|
||||
return TargetType.COMMON
|
||||
}
|
||||
return TargetType.INVALID
|
||||
}
|
||||
}
|
||||
|
||||
function isPlainObject(value: unknown): value is object {
|
||||
return (
|
||||
typeof value === 'object' &&
|
||||
value !== null &&
|
||||
(Object.getPrototypeOf(value) === Object.prototype ||
|
||||
Object.getPrototypeOf(value) === null)
|
||||
)
|
||||
}
|
||||
|
||||
function getTargetType(value: Target) {
|
||||
return value[ReactiveFlags.SKIP] || !Object.isExtensible(value)
|
||||
? TargetType.INVALID
|
||||
: targetTypeMap(toRawType(value))
|
||||
: targetTypeMap(value)
|
||||
}
|
||||
|
||||
// only unwrap nested ref
|
||||
|
|
Loading…
Reference in New Issue