diff --git a/packages/compiler-core/src/options.ts b/packages/compiler-core/src/options.ts index b0af0cef..5f0f06db 100644 --- a/packages/compiler-core/src/options.ts +++ b/packages/compiler-core/src/options.ts @@ -62,7 +62,7 @@ export type HoistTransform = ( ) => void export interface BindingMetadata { - [key: string]: 'data' | 'props' | 'setup' | 'options' + [key: string]: 'data' | 'props' | 'setup' | 'options' | 'component-import' } interface SharedTransformCodegenOptions { diff --git a/packages/compiler-core/src/transforms/transformElement.ts b/packages/compiler-core/src/transforms/transformElement.ts index f0e8d7cb..1025e602 100644 --- a/packages/compiler-core/src/transforms/transformElement.ts +++ b/packages/compiler-core/src/transforms/transformElement.ts @@ -40,7 +40,8 @@ import { TO_HANDLERS, TELEPORT, KEEP_ALIVE, - SUSPENSE + SUSPENSE, + UNREF } from '../runtimeHelpers' import { getInnerRange, @@ -53,6 +54,7 @@ import { } from '../utils' import { buildSlots } from './vSlot' import { getStaticType } from './hoistStatic' +import { BindingMetadata } from '../options' // some directive transforms (e.g. v-model) may return a symbol for runtime // import, which should be used instead of a resolveDirective call. @@ -249,20 +251,33 @@ export function resolveComponentType( } // 3. user component (from setup bindings) - let tagFromSetup = tag const bindings = context.bindingMetadata - if ( - bindings !== EMPTY_OBJ && - (bindings[tagFromSetup] === 'setup' || - bindings[(tagFromSetup = camelize(tag))] === 'setup' || - bindings[(tagFromSetup = capitalize(camelize(tag)))] === 'setup') - ) { - return context.inline - ? tagFromSetup - : `$setup[${JSON.stringify(tagFromSetup)}]` + if (bindings !== EMPTY_OBJ) { + const checkType = (type: BindingMetadata[string]) => { + let resolvedTag = tag + if ( + bindings[resolvedTag] === type || + bindings[(resolvedTag = camelize(tag))] === type || + bindings[(resolvedTag = capitalize(camelize(tag)))] === type + ) { + return resolvedTag + } + } + const tagFromSetup = checkType('setup') + if (tagFromSetup) { + return context.inline + ? // setup scope bindings may be refs so they need to be unrefed + `${context.helperString(UNREF)}(${tagFromSetup})` + : `$setup[${JSON.stringify(tagFromSetup)}]` + } + const tagFromImport = checkType('component-import') + if (tagFromImport) { + // imports can be used as-is + return tagFromImport + } } - // 5. user component (resolve) + // 4. user component (resolve) context.helper(RESOLVE_COMPONENT) context.components.add(tag) return toValidAssetId(tag, `component`) diff --git a/packages/compiler-core/src/transforms/transformExpression.ts b/packages/compiler-core/src/transforms/transformExpression.ts index 7552177c..52a35538 100644 --- a/packages/compiler-core/src/transforms/transformExpression.ts +++ b/packages/compiler-core/src/transforms/transformExpression.ts @@ -107,6 +107,8 @@ export function processExpression( return `${inlinePropsIdentifier}.${raw}` } else if (type === 'setup') { return `${context.helperString(UNREF)}(${raw})` + } else if (type === 'component-import') { + return raw } } // fallback to normal diff --git a/packages/compiler-sfc/src/compileScript.ts b/packages/compiler-sfc/src/compileScript.ts index ab5aa43a..08583941 100644 --- a/packages/compiler-sfc/src/compileScript.ts +++ b/packages/compiler-sfc/src/compileScript.ts @@ -736,7 +736,7 @@ export function compileScript( `\nexport ${hasAwait ? `async ` : ``}function setup(${args}) {\n` ) - const exposedBindings = { ...userImports, ...setupBindings } + const allBindings = { ...userImports, ...setupBindings } // 9. inject `useCssVars` calls if (hasCssVars) { @@ -746,7 +746,7 @@ export function compileScript( if (typeof vars === 'string') { s.prependRight( endOffset, - `\n${genCssVarsCode(vars, !!style.scoped, exposedBindings)}` + `\n${genCssVarsCode(vars, !!style.scoped, allBindings)}` ) } } @@ -756,12 +756,23 @@ export function compileScript( if (scriptAst) { Object.assign(bindingMetadata, analyzeScriptBindings(scriptAst)) } - Object.keys(exposedBindings).forEach(key => { - bindingMetadata[key] = 'setup' - }) - Object.keys(typeDeclaredProps).forEach(key => { + if (options.inlineTemplate) { + for (const [key, value] of Object.entries(userImports)) { + bindingMetadata[key] = value.endsWith('.vue') + ? 'component-import' + : 'setup' + } + for (const key in setupBindings) { + bindingMetadata[key] = 'setup' + } + } else { + for (const key in allBindings) { + bindingMetadata[key] = 'setup' + } + } + for (const key in typeDeclaredProps) { bindingMetadata[key] = 'props' - }) + } Object.assign(bindingMetadata, analyzeScriptBindings(scriptSetupAst)) // 11. generate return statement @@ -799,7 +810,7 @@ export function compileScript( } } else { // return bindings from setup - returned = `{ ${Object.keys(exposedBindings).join(', ')} }` + returned = `{ ${Object.keys(allBindings).join(', ')} }` } s.appendRight(endOffset, `\nreturn ${returned}\n}\n\n`)