diff --git a/packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap b/packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap
index 9e401d0ba..4acc91a94 100644
--- a/packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap
+++ b/packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap
@@ -16,30 +16,34 @@ exports[`compile > custom directive > basic 1`] = `
const t0 = _template("
")
export function render(_ctx) {
+ const _directive_test = _resolveDirective("test")
+ const _directive_hello = _resolveDirective("hello")
const n0 = t0()
- _withDirectives(n0, [[_resolveDirective("vTest")], [_resolveDirective("vHello"), void 0, void 0, { world: true }]])
+ _withDirectives(n0, [[_directive_test], [_directive_hello, void 0, void 0, { world: true }]])
return n0
}"
`;
exports[`compile > custom directive > component 1`] = `
-"import { resolveComponent as _resolveComponent, createComponent as _createComponent, resolveDirective as _resolveDirective, withDirectives as _withDirectives, insert as _insert, createIf as _createIf, template as _template } from 'vue/vapor';
+"import { resolveComponent as _resolveComponent, resolveDirective as _resolveDirective, createComponent as _createComponent, withDirectives as _withDirectives, insert as _insert, createIf as _createIf, template as _template } from 'vue/vapor';
const t0 = _template("")
export function render(_ctx) {
const _component_Bar = _resolveComponent("Bar")
const _component_Comp = _resolveComponent("Comp")
+ const _directive_hello = _resolveDirective("hello")
+ const _directive_test = _resolveDirective("test")
const n4 = _createComponent(_component_Comp, null, { default: () => {
const n0 = _createIf(() => (true), () => {
const n3 = t0()
const n2 = _createComponent(_component_Bar)
- _withDirectives(n2, [[_resolveDirective("vHello"), void 0, void 0, { world: true }]])
+ _withDirectives(n2, [[_directive_hello, void 0, void 0, { world: true }]])
_insert(n2, n3)
return n3
})
return n0
} }, null, true)
- _withDirectives(n4, [[_resolveDirective("vTest")]])
+ _withDirectives(n4, [[_directive_test]])
return n4
}"
`;
diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformSlotOutlet.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformSlotOutlet.spec.ts.snap
index 8d0b2ade5..eab69c82b 100644
--- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformSlotOutlet.spec.ts.snap
+++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformSlotOutlet.spec.ts.snap
@@ -71,9 +71,10 @@ export function render(_ctx) {
`;
exports[`compiler: transform outlets > error on unexpected custom directive on 1`] = `
-"import { createSlot as _createSlot } from 'vue/vapor';
+"import { resolveDirective as _resolveDirective, createSlot as _createSlot } from 'vue/vapor';
export function render(_ctx) {
+ const _directive_foo = _resolveDirective("foo")
const n0 = _createSlot("default", null)
return n0
}"
diff --git a/packages/compiler-vapor/__tests__/transforms/transformElement.spec.ts b/packages/compiler-vapor/__tests__/transforms/transformElement.spec.ts
index 248241246..bb5b8970f 100644
--- a/packages/compiler-vapor/__tests__/transforms/transformElement.spec.ts
+++ b/packages/compiler-vapor/__tests__/transforms/transformElement.spec.ts
@@ -36,7 +36,7 @@ describe('compiler: element transform', () => {
type: IRNodeTypes.CREATE_COMPONENT_NODE,
id: 0,
tag: 'Foo',
- resolve: true,
+ asset: true,
root: true,
props: [[]],
},
@@ -66,7 +66,7 @@ describe('compiler: element transform', () => {
{
type: IRNodeTypes.CREATE_COMPONENT_NODE,
tag: 'Example',
- resolve: false,
+ asset: false,
},
])
})
@@ -172,7 +172,7 @@ describe('compiler: element transform', () => {
type: IRNodeTypes.CREATE_COMPONENT_NODE,
id: 0,
tag: 'Example',
- resolve: true,
+ asset: true,
},
])
})
@@ -212,7 +212,7 @@ describe('compiler: element transform', () => {
{
type: IRNodeTypes.CREATE_COMPONENT_NODE,
tag: 'Foo',
- resolve: true,
+ asset: true,
root: true,
props: [
[
diff --git a/packages/compiler-vapor/src/generators/block.ts b/packages/compiler-vapor/src/generators/block.ts
index 41b2b0bda..3ce28cc1d 100644
--- a/packages/compiler-vapor/src/generators/block.ts
+++ b/packages/compiler-vapor/src/generators/block.ts
@@ -1,4 +1,4 @@
-import type { BlockIRNode } from '../ir'
+import type { BlockIRNode, VaporHelper } from '../ir'
import {
type CodeFragment,
DELIMITERS_ARRAY,
@@ -12,6 +12,7 @@ import {
import type { CodegenContext } from '../generate'
import { genEffects, genOperations } from './operation'
import { genChildren } from './template'
+import { toValidAssetId } from '@vue/compiler-dom'
export function genBlock(
oper: BlockIRNode,
@@ -43,16 +44,8 @@ export function genBlockContent(
const resetBlock = context.enterBlock(block)
if (root) {
- for (const name of context.ir.component) {
- push(
- NEWLINE,
- `const _component_${name} = `,
- ...genCall(
- context.vaporHelper('resolveComponent'),
- JSON.stringify(name),
- ),
- )
- }
+ genResolveAssets('component', 'resolveComponent')
+ genResolveAssets('directive', 'resolveDirective')
}
for (const child of dynamic.children) {
@@ -77,4 +70,17 @@ export function genBlockContent(
resetBlock()
return frag
+
+ function genResolveAssets(
+ kind: 'component' | 'directive',
+ helper: VaporHelper,
+ ) {
+ for (const name of context.ir[kind]) {
+ push(
+ NEWLINE,
+ `const ${toValidAssetId(name, kind)} = `,
+ ...genCall(context.vaporHelper(helper), JSON.stringify(name)),
+ )
+ }
+ }
}
diff --git a/packages/compiler-vapor/src/generators/component.ts b/packages/compiler-vapor/src/generators/component.ts
index b48763266..ea626505c 100644
--- a/packages/compiler-vapor/src/generators/component.ts
+++ b/packages/compiler-vapor/src/generators/component.ts
@@ -21,7 +21,7 @@ import {
} from './utils'
import { genExpression } from './expression'
import { genPropKey } from './prop'
-import { createSimpleExpression } from '@vue/compiler-dom'
+import { createSimpleExpression, toValidAssetId } from '@vue/compiler-dom'
import { genEventHandler } from './event'
import { genDirectiveModifiers, genDirectivesForElement } from './directive'
import { genModelHandler } from './modelValue'
@@ -52,8 +52,8 @@ export function genCreateComponent(
]
function genTag() {
- if (oper.resolve) {
- return [`_component_${oper.tag}`]
+ if (oper.asset) {
+ return toValidAssetId(oper.tag, 'component')
} else {
return genExpression(
extend(createSimpleExpression(oper.tag, false), { ast: null }),
diff --git a/packages/compiler-vapor/src/generators/directive.ts b/packages/compiler-vapor/src/generators/directive.ts
index 7fdcb7bbf..fddfc8e32 100644
--- a/packages/compiler-vapor/src/generators/directive.ts
+++ b/packages/compiler-vapor/src/generators/directive.ts
@@ -1,5 +1,9 @@
-import { createSimpleExpression, isSimpleIdentifier } from '@vue/compiler-dom'
-import { camelize } from '@vue/shared'
+import {
+ createSimpleExpression,
+ isSimpleIdentifier,
+ toValidAssetId,
+} from '@vue/compiler-dom'
+import { extend } from '@vue/shared'
import { genExpression } from './expression'
import type { CodegenContext } from '../generate'
import {
@@ -36,7 +40,12 @@ export function genWithDirective(
...genCall(vaporHelper('withDirectives'), element, directives),
]
- function genDirective({ dir, builtin }: WithDirectiveIRNode): CodeFragment[] {
+ function genDirective({
+ dir,
+ name,
+ builtin,
+ asset,
+ }: WithDirectiveIRNode): CodeFragment[] {
const directive = genDirective()
const value = dir.exp && ['() => ', ...genExpression(dir.exp, context)]
const argument = dir.arg && genExpression(dir.arg, context)
@@ -55,24 +64,15 @@ export function genWithDirective(
)
function genDirective() {
- const {
- vaporHelper,
- options: { bindingMetadata },
- } = context
- if (dir.name === 'show') {
- return [vaporHelper('vShow')]
- } else if (builtin) {
- return [vaporHelper(builtin)]
+ if (builtin) {
+ return vaporHelper(name as any)
+ } else if (asset) {
+ return toValidAssetId(name, 'directive')
} else {
- const directiveReference = camelize(`v-${dir.name}`)
- // TODO resolve directive
- if (bindingMetadata[directiveReference]) {
- const directiveExpression = createSimpleExpression(directiveReference)
- directiveExpression.ast = null
- return genExpression(directiveExpression, context)
- } else {
- return `${vaporHelper('resolveDirective')}("${directiveReference}")`
- }
+ return genExpression(
+ extend(createSimpleExpression(name, false), { ast: null }),
+ context,
+ )
}
}
}
diff --git a/packages/compiler-vapor/src/ir.ts b/packages/compiler-vapor/src/ir.ts
index 01ea36d0c..27420d7f6 100644
--- a/packages/compiler-vapor/src/ir.ts
+++ b/packages/compiler-vapor/src/ir.ts
@@ -60,6 +60,7 @@ export interface RootIRNode {
source: string
template: string[]
component: Set
+ directive: Set
block: BlockIRNode
}
@@ -197,7 +198,9 @@ export interface WithDirectiveIRNode extends BaseIRNode {
type: IRNodeTypes.WITH_DIRECTIVE
element: number
dir: VaporDirectiveNode
- builtin?: VaporHelper
+ name: string
+ builtin?: boolean
+ asset?: boolean
}
export interface ComponentSlotBlockIRNode extends BlockIRNode {
@@ -219,7 +222,7 @@ export interface CreateComponentIRNode extends BaseIRNode {
slots?: ComponentSlots
dynamicSlots?: ComponentDynamicSlot[]
- resolve: boolean
+ asset: boolean
root: boolean
}
diff --git a/packages/compiler-vapor/src/transform.ts b/packages/compiler-vapor/src/transform.ts
index 893efce1f..48b00ffb7 100644
--- a/packages/compiler-vapor/src/transform.ts
+++ b/packages/compiler-vapor/src/transform.ts
@@ -79,6 +79,8 @@ export class TransformContext {
comment: CommentNode[] = []
component: Set = this.ir.component
+ directive: Set = this.ir.directive
+
slots?: ComponentSlots
dynamicSlots?: ComponentDynamicSlot[]
@@ -220,6 +222,7 @@ export function transform(
source: node.source,
template: [],
component: new Set(),
+ directive: new Set(),
block: newBlock(node),
}
diff --git a/packages/compiler-vapor/src/transforms/transformElement.ts b/packages/compiler-vapor/src/transforms/transformElement.ts
index c16ddd2e7..f79102405 100644
--- a/packages/compiler-vapor/src/transforms/transformElement.ts
+++ b/packages/compiler-vapor/src/transforms/transformElement.ts
@@ -72,24 +72,24 @@ function transformComponentElement(
propsResult: PropsResult,
context: TransformContext,
) {
- let resolve = true
+ let asset = true
if (!__BROWSER__) {
const fromSetup = resolveSetupReference(tag, context)
if (fromSetup) {
tag = fromSetup
- resolve = false
+ asset = false
}
const dotIndex = tag.indexOf('.')
if (dotIndex > 0) {
const ns = resolveSetupReference(tag.slice(0, dotIndex), context)
if (ns) {
tag = ns + tag.slice(dotIndex)
- resolve = false
+ asset = false
}
}
}
- if (resolve) {
+ if (asset) {
context.component.add(tag)
}
@@ -102,7 +102,7 @@ function transformComponentElement(
id: context.reference(),
tag,
props: propsResult[0] ? propsResult[1] : [propsResult[1]],
- resolve,
+ asset,
root,
slots: context.slots,
dynamicSlots: context.dynamicSlots,
@@ -287,7 +287,7 @@ function transformProp(
node: ElementNode,
context: TransformContext,
): DirectiveTransformResult | void {
- const { name } = prop
+ let { name } = prop
if (prop.type === NodeTypes.ATTRIBUTE) {
if (isReservedProp(name)) return
@@ -305,10 +305,20 @@ function transformProp(
}
if (!isBuiltInDirective(name)) {
+ const fromSetup =
+ !__BROWSER__ && resolveSetupReference(`v-${name}`, context)
+ if (fromSetup) {
+ name = fromSetup
+ } else {
+ context.directive.add(name)
+ }
+
context.registerOperation({
type: IRNodeTypes.WITH_DIRECTIVE,
element: context.reference(),
dir: prop,
+ name,
+ asset: !fromSetup,
})
}
}
diff --git a/packages/compiler-vapor/src/transforms/vModel.ts b/packages/compiler-vapor/src/transforms/vModel.ts
index 72382ffb4..5f46aa786 100644
--- a/packages/compiler-vapor/src/transforms/vModel.ts
+++ b/packages/compiler-vapor/src/transforms/vModel.ts
@@ -62,8 +62,6 @@ export const transformVModel: DirectiveTransform = (dir, node, context) => {
}
const isComponent = node.tagType === ElementTypes.COMPONENT
- let runtimeDirective: VaporHelper | undefined
-
if (isComponent) {
return {
key: arg ? arg : createSimpleExpression('modelValue', true),
@@ -71,74 +69,74 @@ export const transformVModel: DirectiveTransform = (dir, node, context) => {
model: true,
modelModifiers: dir.modifiers,
}
- } else {
- if (dir.arg)
- context.options.onError(
- createDOMCompilerError(
- DOMErrorCodes.X_V_MODEL_ARG_ON_ELEMENT,
- dir.arg.loc,
- ),
- )
- const { tag } = node
- const isCustomElement = context.options.isCustomElement(tag)
- runtimeDirective = 'vModelText'
- if (
- tag === 'input' ||
- tag === 'textarea' ||
- tag === 'select' ||
- isCustomElement
- ) {
- if (tag === 'input' || isCustomElement) {
- const type = findProp(node, 'type')
- if (type) {
- if (type.type === NodeTypes.DIRECTIVE) {
- // :type="foo"
- runtimeDirective = 'vModelDynamic'
- } else if (type.value) {
- switch (type.value.content) {
- case 'radio':
- runtimeDirective = 'vModelRadio'
- break
- case 'checkbox':
- runtimeDirective = 'vModelCheckbox'
- break
- case 'file':
- runtimeDirective = undefined
- context.options.onError(
- createDOMCompilerError(
- DOMErrorCodes.X_V_MODEL_ON_FILE_INPUT_ELEMENT,
- dir.loc,
- ),
- )
- break
- default:
- // text type
- __DEV__ && checkDuplicatedValue()
- break
- }
- }
- } else if (hasDynamicKeyVBind(node)) {
- // element has bindings with dynamic keys, which can possibly contain
- // "type".
+ }
+
+ if (dir.arg)
+ context.options.onError(
+ createDOMCompilerError(
+ DOMErrorCodes.X_V_MODEL_ARG_ON_ELEMENT,
+ dir.arg.loc,
+ ),
+ )
+ const { tag } = node
+ const isCustomElement = context.options.isCustomElement(tag)
+ let runtimeDirective: VaporHelper | undefined = 'vModelText'
+ if (
+ tag === 'input' ||
+ tag === 'textarea' ||
+ tag === 'select' ||
+ isCustomElement
+ ) {
+ if (tag === 'input' || isCustomElement) {
+ const type = findProp(node, 'type')
+ if (type) {
+ if (type.type === NodeTypes.DIRECTIVE) {
+ // :type="foo"
runtimeDirective = 'vModelDynamic'
- } else {
- // text type
- __DEV__ && checkDuplicatedValue()
+ } else if (type.value) {
+ switch (type.value.content) {
+ case 'radio':
+ runtimeDirective = 'vModelRadio'
+ break
+ case 'checkbox':
+ runtimeDirective = 'vModelCheckbox'
+ break
+ case 'file':
+ runtimeDirective = undefined
+ context.options.onError(
+ createDOMCompilerError(
+ DOMErrorCodes.X_V_MODEL_ON_FILE_INPUT_ELEMENT,
+ dir.loc,
+ ),
+ )
+ break
+ default:
+ // text type
+ __DEV__ && checkDuplicatedValue()
+ break
+ }
}
- } else if (tag === 'select') {
- runtimeDirective = 'vModelSelect'
+ } else if (hasDynamicKeyVBind(node)) {
+ // element has bindings with dynamic keys, which can possibly contain
+ // "type".
+ runtimeDirective = 'vModelDynamic'
} else {
- // textarea
+ // text type
__DEV__ && checkDuplicatedValue()
}
+ } else if (tag === 'select') {
+ runtimeDirective = 'vModelSelect'
} else {
- context.options.onError(
- createDOMCompilerError(
- DOMErrorCodes.X_V_MODEL_ON_INVALID_ELEMENT,
- dir.loc,
- ),
- )
+ // textarea
+ __DEV__ && checkDuplicatedValue()
}
+ } else {
+ context.options.onError(
+ createDOMCompilerError(
+ DOMErrorCodes.X_V_MODEL_ON_INVALID_ELEMENT,
+ dir.loc,
+ ),
+ )
}
context.registerOperation({
@@ -154,7 +152,8 @@ export const transformVModel: DirectiveTransform = (dir, node, context) => {
type: IRNodeTypes.WITH_DIRECTIVE,
element: context.reference(),
dir,
- builtin: runtimeDirective,
+ name: runtimeDirective,
+ builtin: true,
})
function checkDuplicatedValue() {
diff --git a/packages/compiler-vapor/src/transforms/vShow.ts b/packages/compiler-vapor/src/transforms/vShow.ts
index 7be355396..0553a3de7 100644
--- a/packages/compiler-vapor/src/transforms/vShow.ts
+++ b/packages/compiler-vapor/src/transforms/vShow.ts
@@ -14,5 +14,7 @@ export const transformVShow: DirectiveTransform = (dir, node, context) => {
type: IRNodeTypes.WITH_DIRECTIVE,
element: context.reference(),
dir,
+ name: 'vShow',
+ builtin: true,
})
}