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)
|
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)', () => {
|
test('observed value should proxy mutations to original (Object)', () => {
|
||||||
const original: any = { foo: 1 }
|
const original: any = { foo: 1 }
|
||||||
const observed = reactive(original)
|
const observed = reactive(original)
|
||||||
|
|
|
@ -40,7 +40,8 @@ enum TargetType {
|
||||||
COLLECTION = 2,
|
COLLECTION = 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
function targetTypeMap(rawType: string) {
|
function targetTypeMap(value: Target): TargetType {
|
||||||
|
const rawType = toRawType(value)
|
||||||
switch (rawType) {
|
switch (rawType) {
|
||||||
case 'Object':
|
case 'Object':
|
||||||
case 'Array':
|
case 'Array':
|
||||||
|
@ -51,14 +52,34 @@ function targetTypeMap(rawType: string) {
|
||||||
case 'WeakSet':
|
case 'WeakSet':
|
||||||
return TargetType.COLLECTION
|
return TargetType.COLLECTION
|
||||||
default:
|
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
|
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) {
|
function getTargetType(value: Target) {
|
||||||
return value[ReactiveFlags.SKIP] || !Object.isExtensible(value)
|
return value[ReactiveFlags.SKIP] || !Object.isExtensible(value)
|
||||||
? TargetType.INVALID
|
? TargetType.INVALID
|
||||||
: targetTypeMap(toRawType(value))
|
: targetTypeMap(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// only unwrap nested ref
|
// only unwrap nested ref
|
||||||
|
|
Loading…
Reference in New Issue