fix(reactivity): fix iOS 12 JSON.stringify error on reactive objects

- Use WeakMap for raw -> reactive/readonly storage. This is slightly
  more expensive than using a field on the taget object but avoids
  polluting the original.

- also fix Collection.forEach callback value

fix #1916
This commit is contained in:
Evan You
2020-08-24 15:26:53 -04:00
parent 410e7abbbb
commit 016ba116a8
4 changed files with 33 additions and 30 deletions

View File

@@ -145,17 +145,17 @@ function createForEach(isReadonly: boolean, isShallow: boolean) {
callback: Function,
thisArg?: unknown
) {
const observed = this
const target = toRaw(observed)
const observed = this as any
const target = observed[ReactiveFlags.RAW]
const rawTarget = toRaw(target)
const wrap = isReadonly ? toReadonly : isShallow ? toShallow : toReactive
!isReadonly && track(target, TrackOpTypes.ITERATE, ITERATE_KEY)
// important: create sure the callback is
// 1. invoked with the reactive map as `this` and 3rd arg
// 2. the value received should be a corresponding reactive/readonly.
function wrappedCallback(value: unknown, key: unknown) {
!isReadonly && track(rawTarget, TrackOpTypes.ITERATE, ITERATE_KEY)
return target.forEach((value: unknown, key: unknown) => {
// important: make sure the callback is
// 1. invoked with the reactive map as `this` and 3rd arg
// 2. the value received should be a corresponding reactive/readonly.
return callback.call(thisArg, wrap(value), wrap(key), observed)
}
return getProto(target).forEach.call(target, wrappedCallback)
})
}
}