This commit is contained in:
Kim 2025-05-05 20:41:45 +00:00 committed by GitHub
commit ea15c02e08
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 34 additions and 19 deletions

View File

@ -207,6 +207,13 @@ describe('reactivity/reactive', () => {
expect(raw).toBe(original) expect(raw).toBe(original)
}) })
test('toRaw on collection types using reactive as prototype', () => {
const originalCollection = reactive(new Map())
const collection = Object.create(originalCollection)
const rawCollection = toRaw(collection)
expect(rawCollection).toBe(collection)
})
test('should not unwrap Ref<T>', () => { test('should not unwrap Ref<T>', () => {
const observedNumberRef = reactive(ref(1)) const observedNumberRef = reactive(ref(1))
const observedObjectRef = reactive(ref({ foo: 1 })) const observedObjectRef = reactive(ref({ foo: 1 }))

View File

@ -46,6 +46,30 @@ function hasOwnProperty(this: object, key: unknown) {
return obj.hasOwnProperty(key as string) return obj.hasOwnProperty(key as string)
} }
export function getRawValue(
receiver: object,
isReadonly: boolean,
isShallow: boolean,
target: Target,
): Target | undefined {
if (
receiver ===
(isReadonly
? isShallow
? shallowReadonlyMap
: readonlyMap
: isShallow
? shallowReactiveMap
: reactiveMap
).get(target) ||
// receiver is not the reactive proxy, but has the same prototype
// this means the receiver is a user proxy of the reactive proxy
Object.getPrototypeOf(target) === Object.getPrototypeOf(receiver)
) {
return target
}
}
class BaseReactiveHandler implements ProxyHandler<Target> { class BaseReactiveHandler implements ProxyHandler<Target> {
constructor( constructor(
protected readonly _isReadonly = false, protected readonly _isReadonly = false,
@ -64,24 +88,7 @@ class BaseReactiveHandler implements ProxyHandler<Target> {
} else if (key === ReactiveFlags.IS_SHALLOW) { } else if (key === ReactiveFlags.IS_SHALLOW) {
return isShallow return isShallow
} else if (key === ReactiveFlags.RAW) { } else if (key === ReactiveFlags.RAW) {
if ( return getRawValue(receiver, isReadonly, isShallow, target)
receiver ===
(isReadonly
? isShallow
? shallowReadonlyMap
: readonlyMap
: isShallow
? shallowReactiveMap
: reactiveMap
).get(target) ||
// receiver is not the reactive proxy, but has the same prototype
// this means the receiver is a user proxy of the reactive proxy
Object.getPrototypeOf(target) === Object.getPrototypeOf(receiver)
) {
return target
}
// early return undefined
return
} }
const targetIsArray = isArray(target) const targetIsArray = isArray(target)

View File

@ -17,6 +17,7 @@ import {
toRawType, toRawType,
} from '@vue/shared' } from '@vue/shared'
import { warn } from './warning' import { warn } from './warning'
import { getRawValue } from './baseHandlers'
type CollectionTypes = IterableCollections | WeakCollections type CollectionTypes = IterableCollections | WeakCollections
@ -273,7 +274,7 @@ function createInstrumentationGetter(isReadonly: boolean, shallow: boolean) {
} else if (key === ReactiveFlags.IS_READONLY) { } else if (key === ReactiveFlags.IS_READONLY) {
return isReadonly return isReadonly
} else if (key === ReactiveFlags.RAW) { } else if (key === ReactiveFlags.RAW) {
return target return getRawValue(receiver, isReadonly, shallow, target)
} }
return Reflect.get( return Reflect.get(