From a307696ea76d558a6a77381b5729aed554a75606 Mon Sep 17 00:00:00 2001 From: HcySunYang Date: Thu, 21 Jan 2021 11:08:55 +0800 Subject: [PATCH 1/3] fix(runtime-core): component methods should override global properties in DEV --- packages/runtime-core/src/componentOptions.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/runtime-core/src/componentOptions.ts b/packages/runtime-core/src/componentOptions.ts index 2017b98f6af..eaa247de97b 100644 --- a/packages/runtime-core/src/componentOptions.ts +++ b/packages/runtime-core/src/componentOptions.ts @@ -604,7 +604,15 @@ export function applyOptions( for (const key in methods) { const methodHandler = (methods as MethodOptions)[key] if (isFunction(methodHandler)) { - ctx[key] = methodHandler.bind(publicThis) + if (__DEV__) { + Object.defineProperty(ctx, key, { + value: methodHandler.bind(publicThis), + configurable: true, + enumerable: false + }) + } else { + ctx[key] = methodHandler.bind(publicThis) + } if (__DEV__) { checkDuplicateProperties!(OptionTypes.METHODS, key) } From 5cf347995f86f556fa5ef04d95fb53cd22d1f31f Mon Sep 17 00:00:00 2001 From: HcySunYang Date: Thu, 21 Jan 2021 11:17:32 +0800 Subject: [PATCH 2/3] test: add test case --- .../runtime-core/__tests__/apiOptions.spec.ts | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/packages/runtime-core/__tests__/apiOptions.spec.ts b/packages/runtime-core/__tests__/apiOptions.spec.ts index d60842db450..31300410272 100644 --- a/packages/runtime-core/__tests__/apiOptions.spec.ts +++ b/packages/runtime-core/__tests__/apiOptions.spec.ts @@ -8,7 +8,8 @@ import { nextTick, renderToString, ref, - defineComponent + defineComponent, + createApp } from '@vue/runtime-test' describe('api: options', () => { @@ -105,6 +106,24 @@ describe('api: options', () => { expect(serializeInner(root)).toBe(`
2
`) }) + test('component’s own methods have higher priority than global properties', async () => { + const app = createApp({ + methods: { + foo() { + return 'foo' + } + }, + render() { + return this.foo() + } + }) + app.config.globalProperties.foo = () => 'bar' + + const root = nodeOps.createElement('div') + app.mount(root) + expect(serializeInner(root)).toBe(`foo`) + }) + test('watch', async () => { function returnThis(this: any) { return this From e514300549aa7c70c4ff00929daa337995e0f981 Mon Sep 17 00:00:00 2001 From: HcySunYang Date: Thu, 21 Jan 2021 20:43:50 +0800 Subject: [PATCH 3/3] chore: annotation --- packages/runtime-core/src/componentOptions.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/runtime-core/src/componentOptions.ts b/packages/runtime-core/src/componentOptions.ts index eaa247de97b..c836f125493 100644 --- a/packages/runtime-core/src/componentOptions.ts +++ b/packages/runtime-core/src/componentOptions.ts @@ -604,6 +604,8 @@ export function applyOptions( for (const key in methods) { const methodHandler = (methods as MethodOptions)[key] if (isFunction(methodHandler)) { + // In dev mode, we use the `createRenderContext` function to define methods to the proxy target, + // and those are read-only but reconfigurable, so it needs to be redefined here if (__DEV__) { Object.defineProperty(ctx, key, { value: methodHandler.bind(publicThis),