parent
ba62ccd55d
commit
488e2bcfef
@ -187,5 +187,32 @@ describe('reactivity/reactive', () => {
|
|||||||
props.n = reactive({ foo: 2 })
|
props.n = reactive({ foo: 2 })
|
||||||
expect(isReactive(props.n)).toBe(true)
|
expect(isReactive(props.n)).toBe(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('should not observe when iterating', () => {
|
||||||
|
const shallowSet = shallowReactive(new Set())
|
||||||
|
const a = {}
|
||||||
|
shallowSet.add(a)
|
||||||
|
|
||||||
|
const spreadA = [...shallowSet][0]
|
||||||
|
expect(isReactive(spreadA)).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should not get reactive entry', () => {
|
||||||
|
const shallowMap = shallowReactive(new Map())
|
||||||
|
const a = {}
|
||||||
|
const key = 'a'
|
||||||
|
|
||||||
|
shallowMap.set(key, a)
|
||||||
|
|
||||||
|
expect(isReactive(shallowMap.get(key))).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should not get reactive on foreach', () => {
|
||||||
|
const shallowSet = shallowReactive(new Set())
|
||||||
|
const a = {}
|
||||||
|
shallowSet.add(a)
|
||||||
|
|
||||||
|
shallowSet.forEach(x => expect(isReactive(x)).toBe(false))
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -22,13 +22,15 @@ const toReactive = <T extends unknown>(value: T): T =>
|
|||||||
const toReadonly = <T extends unknown>(value: T): T =>
|
const toReadonly = <T extends unknown>(value: T): T =>
|
||||||
isObject(value) ? readonly(value) : value
|
isObject(value) ? readonly(value) : value
|
||||||
|
|
||||||
|
const toShallow = <T extends unknown>(value: T): T => value
|
||||||
|
|
||||||
const getProto = <T extends CollectionTypes>(v: T): any =>
|
const getProto = <T extends CollectionTypes>(v: T): any =>
|
||||||
Reflect.getPrototypeOf(v)
|
Reflect.getPrototypeOf(v)
|
||||||
|
|
||||||
function get(
|
function get(
|
||||||
target: MapTypes,
|
target: MapTypes,
|
||||||
key: unknown,
|
key: unknown,
|
||||||
wrap: typeof toReactive | typeof toReadonly
|
wrap: typeof toReactive | typeof toReadonly | typeof toShallow
|
||||||
) {
|
) {
|
||||||
target = toRaw(target)
|
target = toRaw(target)
|
||||||
const rawKey = toRaw(key)
|
const rawKey = toRaw(key)
|
||||||
@ -132,7 +134,7 @@ function clear(this: IterableCollections) {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
function createForEach(isReadonly: boolean) {
|
function createForEach(isReadonly: boolean, shallow: boolean) {
|
||||||
return function forEach(
|
return function forEach(
|
||||||
this: IterableCollections,
|
this: IterableCollections,
|
||||||
callback: Function,
|
callback: Function,
|
||||||
@ -140,7 +142,7 @@ function createForEach(isReadonly: boolean) {
|
|||||||
) {
|
) {
|
||||||
const observed = this
|
const observed = this
|
||||||
const target = toRaw(observed)
|
const target = toRaw(observed)
|
||||||
const wrap = isReadonly ? toReadonly : toReactive
|
const wrap = isReadonly ? toReadonly : shallow ? toShallow : toReactive
|
||||||
!isReadonly && track(target, TrackOpTypes.ITERATE, ITERATE_KEY)
|
!isReadonly && track(target, TrackOpTypes.ITERATE, ITERATE_KEY)
|
||||||
// important: create sure the callback is
|
// important: create sure the callback is
|
||||||
// 1. invoked with the reactive map as `this` and 3rd arg
|
// 1. invoked with the reactive map as `this` and 3rd arg
|
||||||
@ -152,14 +154,18 @@ function createForEach(isReadonly: boolean) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function createIterableMethod(method: string | symbol, isReadonly: boolean) {
|
function createIterableMethod(
|
||||||
|
method: string | symbol,
|
||||||
|
isReadonly: boolean,
|
||||||
|
shallow: boolean
|
||||||
|
) {
|
||||||
return function(this: IterableCollections, ...args: unknown[]) {
|
return function(this: IterableCollections, ...args: unknown[]) {
|
||||||
const target = toRaw(this)
|
const target = toRaw(this)
|
||||||
const isMap = target instanceof Map
|
const isMap = target instanceof Map
|
||||||
const isPair = method === 'entries' || (method === Symbol.iterator && isMap)
|
const isPair = method === 'entries' || (method === Symbol.iterator && isMap)
|
||||||
const isKeyOnly = method === 'keys' && isMap
|
const isKeyOnly = method === 'keys' && isMap
|
||||||
const innerIterator = getProto(target)[method].apply(target, args)
|
const innerIterator = getProto(target)[method].apply(target, args)
|
||||||
const wrap = isReadonly ? toReadonly : toReactive
|
const wrap = isReadonly ? toReadonly : shallow ? toShallow : toReactive
|
||||||
!isReadonly &&
|
!isReadonly &&
|
||||||
track(
|
track(
|
||||||
target,
|
target,
|
||||||
@ -212,7 +218,22 @@ const mutableInstrumentations: Record<string, Function> = {
|
|||||||
set,
|
set,
|
||||||
delete: deleteEntry,
|
delete: deleteEntry,
|
||||||
clear,
|
clear,
|
||||||
forEach: createForEach(false)
|
forEach: createForEach(false, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
const shallowInstrumentations: Record<string, Function> = {
|
||||||
|
get(this: MapTypes, key: unknown) {
|
||||||
|
return get(this, key, toShallow)
|
||||||
|
},
|
||||||
|
get size() {
|
||||||
|
return size((this as unknown) as IterableCollections)
|
||||||
|
},
|
||||||
|
has,
|
||||||
|
add,
|
||||||
|
set,
|
||||||
|
delete: deleteEntry,
|
||||||
|
clear,
|
||||||
|
forEach: createForEach(false, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
const readonlyInstrumentations: Record<string, Function> = {
|
const readonlyInstrumentations: Record<string, Function> = {
|
||||||
@ -227,25 +248,34 @@ const readonlyInstrumentations: Record<string, Function> = {
|
|||||||
set: createReadonlyMethod(TriggerOpTypes.SET),
|
set: createReadonlyMethod(TriggerOpTypes.SET),
|
||||||
delete: createReadonlyMethod(TriggerOpTypes.DELETE),
|
delete: createReadonlyMethod(TriggerOpTypes.DELETE),
|
||||||
clear: createReadonlyMethod(TriggerOpTypes.CLEAR),
|
clear: createReadonlyMethod(TriggerOpTypes.CLEAR),
|
||||||
forEach: createForEach(true)
|
forEach: createForEach(true, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
const iteratorMethods = ['keys', 'values', 'entries', Symbol.iterator]
|
const iteratorMethods = ['keys', 'values', 'entries', Symbol.iterator]
|
||||||
iteratorMethods.forEach(method => {
|
iteratorMethods.forEach(method => {
|
||||||
mutableInstrumentations[method as string] = createIterableMethod(
|
mutableInstrumentations[method as string] = createIterableMethod(
|
||||||
method,
|
method,
|
||||||
|
false,
|
||||||
false
|
false
|
||||||
)
|
)
|
||||||
readonlyInstrumentations[method as string] = createIterableMethod(
|
readonlyInstrumentations[method as string] = createIterableMethod(
|
||||||
method,
|
method,
|
||||||
|
true,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
shallowInstrumentations[method as string] = createIterableMethod(
|
||||||
|
method,
|
||||||
|
true,
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
function createInstrumentationGetter(isReadonly: boolean) {
|
function createInstrumentationGetter(isReadonly: boolean, shallow: boolean) {
|
||||||
const instrumentations = isReadonly
|
const instrumentations = shallow
|
||||||
? readonlyInstrumentations
|
? shallowInstrumentations
|
||||||
: mutableInstrumentations
|
: isReadonly
|
||||||
|
? readonlyInstrumentations
|
||||||
|
: mutableInstrumentations
|
||||||
|
|
||||||
return (
|
return (
|
||||||
target: CollectionTypes,
|
target: CollectionTypes,
|
||||||
@ -271,11 +301,15 @@ function createInstrumentationGetter(isReadonly: boolean) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const mutableCollectionHandlers: ProxyHandler<CollectionTypes> = {
|
export const mutableCollectionHandlers: ProxyHandler<CollectionTypes> = {
|
||||||
get: createInstrumentationGetter(false)
|
get: createInstrumentationGetter(false, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const shallowCollectionHandlers: ProxyHandler<CollectionTypes> = {
|
||||||
|
get: createInstrumentationGetter(false, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const readonlyCollectionHandlers: ProxyHandler<CollectionTypes> = {
|
export const readonlyCollectionHandlers: ProxyHandler<CollectionTypes> = {
|
||||||
get: createInstrumentationGetter(true)
|
get: createInstrumentationGetter(true, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkIdentityKeys(
|
function checkIdentityKeys(
|
||||||
|
@ -7,7 +7,8 @@ import {
|
|||||||
} from './baseHandlers'
|
} from './baseHandlers'
|
||||||
import {
|
import {
|
||||||
mutableCollectionHandlers,
|
mutableCollectionHandlers,
|
||||||
readonlyCollectionHandlers
|
readonlyCollectionHandlers,
|
||||||
|
shallowCollectionHandlers
|
||||||
} from './collectionHandlers'
|
} from './collectionHandlers'
|
||||||
import { UnwrapRef, Ref } from './ref'
|
import { UnwrapRef, Ref } from './ref'
|
||||||
|
|
||||||
@ -67,7 +68,7 @@ export function shallowReactive<T extends object>(target: T): T {
|
|||||||
target,
|
target,
|
||||||
false,
|
false,
|
||||||
shallowReactiveHandlers,
|
shallowReactiveHandlers,
|
||||||
mutableCollectionHandlers
|
shallowCollectionHandlers
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user