From 2bd6ea5c08f04e67c4dca057461283757bfd3586 Mon Sep 17 00:00:00 2001 From: ygj6 Date: Mon, 12 Jul 2021 18:01:39 +0800 Subject: [PATCH] fix(customReactive): avoid circular reference. (#758) --- src/mixin.ts | 6 ++++-- test/setupContext.spec.ts | 30 ++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/mixin.ts b/src/mixin.ts index 078c846c..3dc3b191 100644 --- a/src/mixin.ts +++ b/src/mixin.ts @@ -149,7 +149,8 @@ export function mixin(Vue: VueConstructor) { } } - function customReactive(target: object) { + function customReactive(target: object, visited = new Set()) { + if (visited.has(target)) return if ( !isPlainObject(target) || isRef(target) || @@ -165,7 +166,8 @@ export function mixin(Vue: VueConstructor) { const val = target[k] defineReactive(target, k, val) if (val) { - customReactive(val) + visited.add(val) + customReactive(val, visited) } return }) diff --git a/test/setupContext.spec.ts b/test/setupContext.spec.ts index cb602031..6ec978f7 100644 --- a/test/setupContext.spec.ts +++ b/test/setupContext.spec.ts @@ -5,9 +5,12 @@ import { ref, nextTick, SetupContext, + getCurrentInstance, } from '../src' +import { mockWarn } from './helpers' describe('setupContext', () => { + mockWarn(true) it('should have proper properties', () => { let context: SetupContext = undefined! @@ -195,4 +198,31 @@ describe('setupContext', () => { expect(_attrs.foo).toBe('bar2') }) + + // #563 + it('should not RangeError: Maximum call stack size exceeded', async () => { + createApp( + defineComponent({ + template: `
`, + setup() { + // @ts-expect-error + const app = getCurrentInstance().proxy + let mockNT: any = [] + mockNT.__ob__ = {} + const test = { + app, + mockNT, + } + return { + test, + } + }, + }) + ).mount() + + await nextTick() + expect( + `"RangeError: Maximum call stack size exceeded"` + ).not.toHaveBeenWarned() + }) })