From 62d2fe02acff8003660639cec1cadd6b7b6fbf7e Mon Sep 17 00:00:00 2001 From: ygj6 Date: Fri, 9 Jul 2021 14:54:18 +0800 Subject: [PATCH 1/2] fix(customReactive): avoid circular reference. --- src/mixin.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/mixin.ts b/src/mixin.ts index 3adde308..a235648b 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 }) From 91d88975c78c5376972365ac586d37c5a8e750c1 Mon Sep 17 00:00:00 2001 From: ygj6 Date: Mon, 12 Jul 2021 14:53:57 +0800 Subject: [PATCH 2/2] test: add test case --- test/setupContext.spec.ts | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) 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() + }) })