diff --git a/packages/compiler-core/src/transforms/transformElement.ts b/packages/compiler-core/src/transforms/transformElement.ts index f2f1459e0..c9d1a3ee4 100644 --- a/packages/compiler-core/src/transforms/transformElement.ts +++ b/packages/compiler-core/src/transforms/transformElement.ts @@ -29,8 +29,7 @@ import { isObject, isReservedProp, capitalize, - camelize, - EMPTY_OBJ + camelize } from '@vue/shared' import { createCompilerError, ErrorCodes } from '../errors' import { @@ -255,34 +254,16 @@ export function resolveComponentType( } // 3. user component (from setup bindings) - const bindings = context.bindingMetadata - if (bindings !== EMPTY_OBJ) { - const checkType = (type: BindingTypes) => { - let resolvedTag = tag - if ( - bindings[resolvedTag] === type || - bindings[(resolvedTag = camelize(tag))] === type || - bindings[(resolvedTag = capitalize(camelize(tag)))] === type - ) { - return resolvedTag - } - } - const tagFromConst = checkType(BindingTypes.SETUP_CONST) - if (tagFromConst) { - return context.inline - ? // in inline mode, const setup bindings (e.g. imports) can be used as-is - tagFromConst - : `$setup[${JSON.stringify(tagFromConst)}]` - } - const tagFromSetup = - checkType(BindingTypes.SETUP_LET) || - checkType(BindingTypes.SETUP_REF) || - checkType(BindingTypes.SETUP_MAYBE_REF) - if (tagFromSetup) { - return context.inline - ? // setup scope bindings that may be refs need to be unrefed - `${context.helperString(UNREF)}(${tagFromSetup})` - : `$setup[${JSON.stringify(tagFromSetup)}]` + // this is skipped in browser build since browser builds do not perform + // binding analysis. + if (!__BROWSER__) { + const fromSetup = resolveSetupReference( + tag, + capitalize(camelize(tag)), + context + ) + if (fromSetup) { + return fromSetup } } @@ -292,6 +273,45 @@ export function resolveComponentType( return toValidAssetId(tag, `component`) } +function resolveSetupReference( + name: string, + interopName: string, + context: TransformContext +) { + const bindings = context.bindingMetadata + if (!bindings) { + return + } + + const checkType = (type: BindingTypes) => { + if (bindings[name] === type) { + return name + } + if (bindings[interopName] === type) { + return interopName + } + } + + const fromConst = checkType(BindingTypes.SETUP_CONST) + if (fromConst) { + return context.inline + ? // in inline mode, const setup bindings (e.g. imports) can be used as-is + fromConst + : `$setup[${JSON.stringify(fromConst)}]` + } + + const fromMaybeRef = + checkType(BindingTypes.SETUP_LET) || + checkType(BindingTypes.SETUP_REF) || + checkType(BindingTypes.SETUP_MAYBE_REF) + if (fromMaybeRef) { + return context.inline + ? // setup scope bindings that may be refs need to be unrefed + `${context.helperString(UNREF)}(${fromMaybeRef})` + : `$setup[${JSON.stringify(fromMaybeRef)}]` + } +} + export type PropsExpression = ObjectExpression | CallExpression | ExpressionNode export function buildProps( @@ -590,12 +610,28 @@ function buildDirectiveArgs( const dirArgs: ArrayExpression['elements'] = [] const runtime = directiveImportMap.get(dir) if (runtime) { + // built-in directive with runtime dirArgs.push(context.helperString(runtime)) } else { - // inject statement for resolving directive - context.helper(RESOLVE_DIRECTIVE) - context.directives.add(dir.name) - dirArgs.push(toValidAssetId(dir.name, `directive`)) + // user directive. + // see if we have directives exposed via + + `, + { inlineTemplate: true } + ) + expect(content).toMatch('[_unref(vMyDir)]') + expect(content).toMatch('_createVNode(ChildComp)') + // kebab-case component support + expect(content).toMatch('_createVNode(SomeOtherComp)') + assertCode(content) + }) + test('avoid unref() when necessary', () => { // function, const, component import const { content } = compile( diff --git a/packages/template-explorer/src/options.ts b/packages/template-explorer/src/options.ts index cdf00ec87..dab7f8adf 100644 --- a/packages/template-explorer/src/options.ts +++ b/packages/template-explorer/src/options.ts @@ -19,7 +19,8 @@ export const compilerOptions: CompilerOptions = reactive({ setupConst: BindingTypes.SETUP_CONST, setupLet: BindingTypes.SETUP_LET, setupMaybeRef: BindingTypes.SETUP_MAYBE_REF, - setupProp: BindingTypes.PROPS + setupProp: BindingTypes.PROPS, + vMySetupDir: BindingTypes.SETUP_CONST } })