fix(compiler-sfc): defineProps return binding or rest binding should be considered reactive

This commit is contained in:
Evan You 2022-05-10 17:34:15 +08:00
parent 03b03eee44
commit 410144149f
6 changed files with 22 additions and 7 deletions

View File

@ -97,6 +97,10 @@ export const enum BindingTypes {
* template expressions. * template expressions.
*/ */
SETUP_CONST = 'setup-const', 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. * a const binding that may be a ref.
*/ */

View File

@ -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) { if (fromConst) {
return context.inline return context.inline
? // in inline mode, const setup bindings (e.g. imports) can be used as-is ? // in inline mode, const setup bindings (e.g. imports) can be used as-is

View File

@ -122,7 +122,11 @@ export function processExpression(
const isDestructureAssignment = const isDestructureAssignment =
parent && isInDestructureAssignment(parent, parentStack) 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 return raw
} else if (type === BindingTypes.SETUP_REF) { } else if (type === BindingTypes.SETUP_REF) {
return `${raw}.value` return `${raw}.value`

View File

@ -68,7 +68,7 @@ const bar = 1
expect(bindings).toStrictEqual({ expect(bindings).toStrictEqual({
foo: BindingTypes.PROPS, foo: BindingTypes.PROPS,
bar: BindingTypes.SETUP_CONST, bar: BindingTypes.SETUP_CONST,
props: BindingTypes.SETUP_CONST props: BindingTypes.SETUP_REACTIVE_CONST
}) })
// should remove defineOptions import and call // should remove defineOptions import and call

View File

@ -141,7 +141,7 @@ describe('sfc props transform', () => {
foo: BindingTypes.PROPS, foo: BindingTypes.PROPS,
bar: BindingTypes.PROPS, bar: BindingTypes.PROPS,
baz: BindingTypes.PROPS, baz: BindingTypes.PROPS,
rest: BindingTypes.SETUP_CONST rest: BindingTypes.SETUP_REACTIVE_CONST
}) })
}) })

View File

@ -1207,7 +1207,8 @@ export function compileScript(
// props aliases // props aliases
if (propsDestructureDecl) { if (propsDestructureDecl) {
if (propsDestructureRestId) { if (propsDestructureRestId) {
bindingMetadata[propsDestructureRestId] = BindingTypes.SETUP_CONST bindingMetadata[propsDestructureRestId] =
BindingTypes.SETUP_REACTIVE_CONST
} }
for (const key in propsDestructuredBindings) { for (const key in propsDestructuredBindings) {
const { local } = propsDestructuredBindings[key] const { local } = propsDestructuredBindings[key]
@ -1525,14 +1526,18 @@ function walkDeclaration(
const userReactiveBinding = userImportAlias['reactive'] || 'reactive' const userReactiveBinding = userImportAlias['reactive'] || 'reactive'
if (isCallOf(init, userReactiveBinding)) { if (isCallOf(init, userReactiveBinding)) {
// treat reactive() calls as let since it's meant to be mutable // 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 ( } else if (
// if a declaration is a const literal, we can mark it so that // if a declaration is a const literal, we can mark it so that
// the generated render fn code doesn't need to unref() it // the generated render fn code doesn't need to unref() it
isDefineCall || isDefineCall ||
(isConst && canNeverBeRef(init!, userReactiveBinding)) (isConst && canNeverBeRef(init!, userReactiveBinding))
) { ) {
bindingType = BindingTypes.SETUP_CONST bindingType = isCallOf(init, DEFINE_PROPS)
? BindingTypes.SETUP_REACTIVE_CONST
: BindingTypes.SETUP_CONST
} else if (isConst) { } else if (isConst) {
if (isCallOf(init, userImportAlias['ref'] || 'ref')) { if (isCallOf(init, userImportAlias['ref'] || 'ref')) {
bindingType = BindingTypes.SETUP_REF bindingType = BindingTypes.SETUP_REF