diff --git a/packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap b/packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap
index f70e66d95..1e5e4cf4f 100644
--- a/packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap
+++ b/packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap
@@ -22,6 +22,27 @@ export function render(_ctx) {
}"
`;
+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';
+const t0 = _template("
")
+
+export function render(_ctx) {
+ const _component_Bar = _resolveComponent("Bar")
+ const _component_Comp = _resolveComponent("Comp")
+ const n0 = _createIf(() => (true), () => {
+ const n3 = t0()
+ const n2 = _createComponent(_component_Bar)
+ _withDirectives(n2, [[_resolveDirective("vHello"), void 0, void 0, { world: true }]])
+ _insert(n2, n3)
+ return n3
+ })
+ _insert(n0, n4)
+ const n4 = _createComponent(_component_Comp, null, true)
+ _withDirectives(n4, [[_resolveDirective("vTest")]])
+ return n4
+}"
+`;
+
exports[`compile > directives > custom directive > basic 1`] = `
"import { withDirectives as _withDirectives, template as _template } from 'vue/vapor';
const t0 = _template("")
diff --git a/packages/compiler-vapor/__tests__/compile.spec.ts b/packages/compiler-vapor/__tests__/compile.spec.ts
index b406d9e95..b0e31e7e7 100644
--- a/packages/compiler-vapor/__tests__/compile.spec.ts
+++ b/packages/compiler-vapor/__tests__/compile.spec.ts
@@ -201,5 +201,16 @@ describe('compile', () => {
const code = compile(``)
expect(code).matchSnapshot()
})
+
+ test('component', () => {
+ const code = compile(`
+
+
+
+
+
+ `)
+ expect(code).matchSnapshot()
+ })
})
})
diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vModel.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vModel.spec.ts.snap
index 7502b73bf..a8764d6e1 100644
--- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vModel.spec.ts.snap
+++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vModel.spec.ts.snap
@@ -177,10 +177,10 @@ const t0 = _template("")
export function render(_ctx) {
const n0 = t0()
- const n1 = t0()
- const n2 = t0()
_withDirectives(n0, [[_vModelText, () => _ctx.setupRef.child]])
+ const n1 = t0()
_withDirectives(n1, [[_vModelText, () => _ctx.setupLet.child]])
+ const n2 = t0()
_withDirectives(n2, [[_vModelText, () => _ctx.setupMaybeRef.child]])
_delegate(n0, "update:modelValue", () => $event => (_ctx.setupRef.child = $event))
_delegate(n1, "update:modelValue", () => $event => (_ctx.setupLet.child = $event))
@@ -192,10 +192,10 @@ export function render(_ctx) {
exports[`compiler: vModel transform > should support member expression w/ inline 1`] = `
"(() => {
const n0 = t0()
- const n1 = t0()
- const n2 = t0()
_withDirectives(n0, [[_vModelText, () => setupRef.value.child]])
+ const n1 = t0()
_withDirectives(n1, [[_vModelText, () => _unref(setupLet).child]])
+ const n2 = t0()
_withDirectives(n2, [[_vModelText, () => _unref(setupMaybeRef).child]])
_delegate(n0, "update:modelValue", () => $event => (setupRef.value.child = $event))
_delegate(n1, "update:modelValue", () => $event => (_unref(setupLet).child = $event))
diff --git a/packages/compiler-vapor/src/generate.ts b/packages/compiler-vapor/src/generate.ts
index bd36453d8..b7e55de60 100644
--- a/packages/compiler-vapor/src/generate.ts
+++ b/packages/compiler-vapor/src/generate.ts
@@ -3,7 +3,7 @@ import type {
BaseCodegenResult,
CodegenSourceMapGenerator,
} from '@vue/compiler-dom'
-import type { IREffect, RootIRNode, VaporHelper } from './ir'
+import type { BlockIRNode, IREffect, RootIRNode, VaporHelper } from './ir'
import { SourceMapGenerator } from 'source-map-js'
import { extend, remove } from '@vue/shared'
import { genBlockContent } from './generators/block'
@@ -43,11 +43,12 @@ export class CodegenContext {
identifiers: Record = Object.create(null)
+ block: BlockIRNode
genEffects: Array<
(effects: IREffect[], context: CodegenContext) => CodeFragment[]
> = []
- withId = (fn: () => T, map: Record): T => {
+ withId(fn: () => T, map: Record): T {
const { identifiers } = this
const ids = Object.keys(map)
@@ -62,6 +63,12 @@ export class CodegenContext {
return ret
}
+ enterBlock(block: BlockIRNode) {
+ const parent = this.block
+ this.block = block
+ return () => (this.block = parent)
+ }
+
constructor(
public ir: RootIRNode,
options: CodegenOptions,
@@ -84,6 +91,7 @@ export class CodegenContext {
expressionPlugins: [],
}
this.options = extend(defaultOptions, options)
+ this.block = ir.block
const [code, push] = buildCodeFragment()
this.code = code
diff --git a/packages/compiler-vapor/src/generators/block.ts b/packages/compiler-vapor/src/generators/block.ts
index 4ed4e00d4..8a5e43923 100644
--- a/packages/compiler-vapor/src/generators/block.ts
+++ b/packages/compiler-vapor/src/generators/block.ts
@@ -1,9 +1,4 @@
-import {
- type BlockIRNode,
- IRNodeTypes,
- type OperationNode,
- type WithDirectiveIRNode,
-} from '../ir'
+import type { BlockIRNode } from '../ir'
import {
type CodeFragment,
INDENT_END,
@@ -13,7 +8,6 @@ import {
genCall,
} from './utils'
import type { CodegenContext } from '../generate'
-import { genWithDirective } from './directive'
import { genEffects, genOperations } from './operation'
import { genChildren } from './template'
import { genMulti } from './utils'
@@ -38,12 +32,14 @@ export function genBlock(
}
export function genBlockContent(
- { dynamic, effect, operation, returns }: BlockIRNode,
+ block: BlockIRNode,
context: CodegenContext,
root?: boolean,
customReturns?: (returns: CodeFragment[]) => CodeFragment[],
): CodeFragment[] {
const [frag, push] = buildCodeFragment()
+ const { dynamic, effect, operation, returns } = block
+ const resetBlock = context.enterBlock(block)
if (root)
for (const name of context.ir.component) {
@@ -61,10 +57,6 @@ export function genBlockContent(
push(...genChildren(child, context, child.id!))
}
- for (const directives of groupDirective(operation)) {
- push(...genWithDirective(directives, context))
- }
-
push(...genOperations(operation, context))
push(
...(context.genEffects.length
@@ -80,19 +72,6 @@ export function genBlockContent(
: [`n${returns[0]}`]
push(...(customReturns ? customReturns(returnsCode) : returnsCode))
+ resetBlock()
return frag
}
-
-function groupDirective(operation: OperationNode[]): WithDirectiveIRNode[][] {
- const directiveOps = operation.filter(
- (oper): oper is WithDirectiveIRNode =>
- oper.type === IRNodeTypes.WITH_DIRECTIVE,
- )
-
- const directiveMap: Record = {}
- for (const oper of directiveOps) {
- if (!directiveMap[oper.element]) directiveMap[oper.element] = []
- directiveMap[oper.element].push(oper)
- }
- return Object.values(directiveMap)
-}
diff --git a/packages/compiler-vapor/src/generators/component.ts b/packages/compiler-vapor/src/generators/component.ts
index 34d349d41..8ab455a70 100644
--- a/packages/compiler-vapor/src/generators/component.ts
+++ b/packages/compiler-vapor/src/generators/component.ts
@@ -13,7 +13,7 @@ import { genExpression } from './expression'
import { genPropKey } from './prop'
import { createSimpleExpression } from '@vue/compiler-dom'
import { genEventHandler } from './event'
-import { genDirectiveModifiers } from './directive'
+import { genDirectiveModifiers, genDirectivesForElement } from './directive'
import { genModelHandler } from './modelValue'
// TODO: generate component slots
@@ -36,6 +36,7 @@ export function genCreateComponent(
rawProps || (isRoot ? 'null' : false),
isRoot && 'true',
),
+ ...genDirectivesForElement(oper.id, context),
]
function genTag() {
diff --git a/packages/compiler-vapor/src/generators/directive.ts b/packages/compiler-vapor/src/generators/directive.ts
index 452b79f9d..9c6468b76 100644
--- a/packages/compiler-vapor/src/generators/directive.ts
+++ b/packages/compiler-vapor/src/generators/directive.ts
@@ -3,7 +3,16 @@ import { camelize } from '@vue/shared'
import { genExpression } from './expression'
import type { CodegenContext } from '../generate'
import { type CodeFragment, NEWLINE, genCall, genMulti } from './utils'
-import type { WithDirectiveIRNode } from '../ir'
+import {
+ IRNodeTypes,
+ type OperationNode,
+ type WithDirectiveIRNode,
+} from '../ir'
+
+export function genDirectivesForElement(id: number, context: CodegenContext) {
+ const dirs = filterDirectives(id, context.block.operation)
+ return dirs.length ? genWithDirective(dirs, context) : []
+}
export function genWithDirective(
opers: WithDirectiveIRNode[],
@@ -72,3 +81,13 @@ export function genDirectiveModifiers(modifiers: string[]) {
)
.join(', ')
}
+
+function filterDirectives(
+ id: number,
+ operations: OperationNode[],
+): WithDirectiveIRNode[] {
+ return operations.filter(
+ (oper): oper is WithDirectiveIRNode =>
+ oper.type === IRNodeTypes.WITH_DIRECTIVE && oper.element === id,
+ )
+}
diff --git a/packages/compiler-vapor/src/generators/template.ts b/packages/compiler-vapor/src/generators/template.ts
index 4187e501f..0ece5bcc9 100644
--- a/packages/compiler-vapor/src/generators/template.ts
+++ b/packages/compiler-vapor/src/generators/template.ts
@@ -1,5 +1,6 @@
import type { CodegenContext } from '../generate'
import { DynamicFlag, type IRDynamicInfo } from '../ir'
+import { genDirectivesForElement } from './directive'
import { type CodeFragment, NEWLINE, buildCodeFragment, genCall } from './utils'
export function genTemplates(
@@ -27,6 +28,7 @@ export function genChildren(
if (id !== undefined && template !== undefined) {
push(NEWLINE, `const n${id} = t${template}()`)
+ push(...genDirectivesForElement(id, context))
}
let prev: [id: number, elementIndex: number] | undefined
@@ -71,6 +73,7 @@ export function genChildren(
)
}
}
+ push(...genDirectivesForElement(id, context))
prev = [id, elementIndex]
push(...genChildren(child, context, id, []))
}