From 410144149fbaaecad2b2d36a9cfe965ab7b2b6e6 Mon Sep 17 00:00:00 2001 From: Evan You Date: Tue, 10 May 2022 17:34:15 +0800 Subject: [PATCH] fix(compiler-sfc): defineProps return binding or rest binding should be considered reactive --- packages/compiler-core/src/options.ts | 4 ++++ .../compiler-core/src/transforms/transformElement.ts | 4 +++- .../src/transforms/transformExpression.ts | 6 +++++- packages/compiler-sfc/__tests__/compileScript.spec.ts | 2 +- .../__tests__/compileScriptPropsTransform.spec.ts | 2 +- packages/compiler-sfc/src/compileScript.ts | 11 ++++++++--- 6 files changed, 22 insertions(+), 7 deletions(-) diff --git a/packages/compiler-core/src/options.ts b/packages/compiler-core/src/options.ts index a0658b4d..1221772f 100644 --- a/packages/compiler-core/src/options.ts +++ b/packages/compiler-core/src/options.ts @@ -97,6 +97,10 @@ export const enum BindingTypes { * template expressions. */ SETUP_CONST = 'setup-const', + /** + * a const binding that does not need `unref()`, but may be mutated. + */ + SETUP_REACTIVE_CONST = 'setup-reactive-const', /** * a const binding that may be a ref. */ diff --git a/packages/compiler-core/src/transforms/transformElement.ts b/packages/compiler-core/src/transforms/transformElement.ts index 7143963d..3e2f74c0 100644 --- a/packages/compiler-core/src/transforms/transformElement.ts +++ b/packages/compiler-core/src/transforms/transformElement.ts @@ -352,7 +352,9 @@ function resolveSetupReference(name: string, context: TransformContext) { } } - const fromConst = checkType(BindingTypes.SETUP_CONST) + const fromConst = + checkType(BindingTypes.SETUP_CONST) || + checkType(BindingTypes.SETUP_REACTIVE_CONST) if (fromConst) { return context.inline ? // in inline mode, const setup bindings (e.g. imports) can be used as-is diff --git a/packages/compiler-core/src/transforms/transformExpression.ts b/packages/compiler-core/src/transforms/transformExpression.ts index 7a5e699e..a3a48be6 100644 --- a/packages/compiler-core/src/transforms/transformExpression.ts +++ b/packages/compiler-core/src/transforms/transformExpression.ts @@ -122,7 +122,11 @@ export function processExpression( const isDestructureAssignment = parent && isInDestructureAssignment(parent, parentStack) - if (type === BindingTypes.SETUP_CONST || localVars[raw]) { + if ( + type === BindingTypes.SETUP_CONST || + type === BindingTypes.SETUP_REACTIVE_CONST || + localVars[raw] + ) { return raw } else if (type === BindingTypes.SETUP_REF) { return `${raw}.value` diff --git a/packages/compiler-sfc/__tests__/compileScript.spec.ts b/packages/compiler-sfc/__tests__/compileScript.spec.ts index f87a326c..d7b10f5d 100644 --- a/packages/compiler-sfc/__tests__/compileScript.spec.ts +++ b/packages/compiler-sfc/__tests__/compileScript.spec.ts @@ -68,7 +68,7 @@ const bar = 1 expect(bindings).toStrictEqual({ foo: BindingTypes.PROPS, bar: BindingTypes.SETUP_CONST, - props: BindingTypes.SETUP_CONST + props: BindingTypes.SETUP_REACTIVE_CONST }) // should remove defineOptions import and call diff --git a/packages/compiler-sfc/__tests__/compileScriptPropsTransform.spec.ts b/packages/compiler-sfc/__tests__/compileScriptPropsTransform.spec.ts index e7fbb31c..0dafc020 100644 --- a/packages/compiler-sfc/__tests__/compileScriptPropsTransform.spec.ts +++ b/packages/compiler-sfc/__tests__/compileScriptPropsTransform.spec.ts @@ -141,7 +141,7 @@ describe('sfc props transform', () => { foo: BindingTypes.PROPS, bar: BindingTypes.PROPS, baz: BindingTypes.PROPS, - rest: BindingTypes.SETUP_CONST + rest: BindingTypes.SETUP_REACTIVE_CONST }) }) diff --git a/packages/compiler-sfc/src/compileScript.ts b/packages/compiler-sfc/src/compileScript.ts index 7c16bcc8..5ac05b31 100644 --- a/packages/compiler-sfc/src/compileScript.ts +++ b/packages/compiler-sfc/src/compileScript.ts @@ -1207,7 +1207,8 @@ export function compileScript( // props aliases if (propsDestructureDecl) { if (propsDestructureRestId) { - bindingMetadata[propsDestructureRestId] = BindingTypes.SETUP_CONST + bindingMetadata[propsDestructureRestId] = + BindingTypes.SETUP_REACTIVE_CONST } for (const key in propsDestructuredBindings) { const { local } = propsDestructuredBindings[key] @@ -1525,14 +1526,18 @@ function walkDeclaration( const userReactiveBinding = userImportAlias['reactive'] || 'reactive' if (isCallOf(init, userReactiveBinding)) { // treat reactive() calls as let since it's meant to be mutable - bindingType = BindingTypes.SETUP_LET + bindingType = isConst + ? BindingTypes.SETUP_REACTIVE_CONST + : BindingTypes.SETUP_LET } else if ( // if a declaration is a const literal, we can mark it so that // the generated render fn code doesn't need to unref() it isDefineCall || (isConst && canNeverBeRef(init!, userReactiveBinding)) ) { - bindingType = BindingTypes.SETUP_CONST + bindingType = isCallOf(init, DEFINE_PROPS) + ? BindingTypes.SETUP_REACTIVE_CONST + : BindingTypes.SETUP_CONST } else if (isConst) { if (isCallOf(init, userImportAlias['ref'] || 'ref')) { bindingType = BindingTypes.SETUP_REF