diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vHtml.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vHtml.spec.ts.snap
index ecf886d7c..f78e395a7 100644
--- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vHtml.spec.ts.snap
+++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vHtml.spec.ts.snap
@@ -32,3 +32,13 @@ export function render(_ctx) {
return n0
}"
`;
+
+exports[`v-html > work with dynamic component 1`] = `
+"import { createDynamicComponent as _createDynamicComponent, setHtml as _setHtml, renderEffect as _renderEffect } from 'vue';
+
+export function render(_ctx) {
+ const n0 = _createDynamicComponent(() => ('button'), null, null, true)
+ _renderEffect(() => _setHtml(n0.nodes, _ctx.foo))
+ return n0
+}"
+`;
diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vText.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vText.spec.ts.snap
index 9a3b88acb..b17692a98 100644
--- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vText.spec.ts.snap
+++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vText.spec.ts.snap
@@ -33,3 +33,13 @@ export function render(_ctx) {
return n0
}"
`;
+
+exports[`v-text > work with dynamic component 1`] = `
+"import { createDynamicComponent as _createDynamicComponent, toDisplayString as _toDisplayString, setElementText as _setElementText, renderEffect as _renderEffect } from 'vue';
+
+export function render(_ctx) {
+ const n0 = _createDynamicComponent(() => ('button'), null, null, true)
+ _renderEffect(() => _setElementText(n0.nodes, _toDisplayString(_ctx.foo), true))
+ return n0
+}"
+`;
diff --git a/packages/compiler-vapor/__tests__/transforms/vHtml.spec.ts b/packages/compiler-vapor/__tests__/transforms/vHtml.spec.ts
index 0de0b6abc..0fcff932c 100644
--- a/packages/compiler-vapor/__tests__/transforms/vHtml.spec.ts
+++ b/packages/compiler-vapor/__tests__/transforms/vHtml.spec.ts
@@ -54,6 +54,14 @@ describe('v-html', () => {
expect(code).matchSnapshot()
})
+ test('work with dynamic component', () => {
+ const { code } = compileWithVHtml(
+ ``,
+ )
+ expect(code).matchSnapshot()
+ expect(code).contains('setHtml(n0.nodes, _ctx.foo))')
+ })
+
test('should raise error and ignore children when v-html is present', () => {
const onError = vi.fn()
const { code, ir, helpers } = compileWithVHtml(
diff --git a/packages/compiler-vapor/__tests__/transforms/vText.spec.ts b/packages/compiler-vapor/__tests__/transforms/vText.spec.ts
index 4f074fee8..e596062a7 100644
--- a/packages/compiler-vapor/__tests__/transforms/vText.spec.ts
+++ b/packages/compiler-vapor/__tests__/transforms/vText.spec.ts
@@ -58,6 +58,16 @@ describe('v-text', () => {
expect(code).matchSnapshot()
})
+ test('work with dynamic component', () => {
+ const { code } = compileWithVText(
+ ``,
+ )
+ expect(code).matchSnapshot()
+ expect(code).contains(
+ 'setElementText(n0.nodes, _toDisplayString(_ctx.foo), true)',
+ )
+ })
+
test('should raise error and ignore children when v-text is present', () => {
const onError = vi.fn()
const { code, ir } = compileWithVText(`
hello
`, {
diff --git a/packages/compiler-vapor/src/generators/component.ts b/packages/compiler-vapor/src/generators/component.ts
index 7c232db75..fdbc3415f 100644
--- a/packages/compiler-vapor/src/generators/component.ts
+++ b/packages/compiler-vapor/src/generators/component.ts
@@ -60,12 +60,15 @@ export function genCreateComponent(
[],
)
+ const isDynamicComponent = operation.dynamic && !operation.dynamic.isStatic
+ if (isDynamicComponent) context.block.dynamicComponents.push(operation.id)
+
return [
NEWLINE,
...inlineHandlers,
`const n${operation.id} = `,
...genCall(
- operation.dynamic && !operation.dynamic.isStatic
+ isDynamicComponent
? helper('createDynamicComponent')
: operation.asset
? helper('createComponentWithFallback')
diff --git a/packages/compiler-vapor/src/generators/html.ts b/packages/compiler-vapor/src/generators/html.ts
index 72af699dd..8fc6d07a4 100644
--- a/packages/compiler-vapor/src/generators/html.ts
+++ b/packages/compiler-vapor/src/generators/html.ts
@@ -7,10 +7,21 @@ export function genSetHtml(
oper: SetHtmlIRNode,
context: CodegenContext,
): CodeFragment[] {
- const { helper } = context
+ const {
+ helper,
+ block: { dynamicComponents },
+ } = context
+
+ const isDynamicComponent = dynamicComponents.includes(oper.element)
const { value, element } = oper
return [
NEWLINE,
- ...genCall(helper('setHtml'), `n${element}`, genExpression(value, context)),
+ ...genCall(
+ helper('setHtml'),
+ // if the element is a dynamic component (VaporFragment)
+ // it should set html to the VaporFragment's nodes
+ `n${element}${isDynamicComponent ? '.nodes' : ''}`,
+ genExpression(value, context),
+ ),
]
}
diff --git a/packages/compiler-vapor/src/generators/text.ts b/packages/compiler-vapor/src/generators/text.ts
index 89e3167c6..1f706ebd1 100644
--- a/packages/compiler-vapor/src/generators/text.ts
+++ b/packages/compiler-vapor/src/generators/text.ts
@@ -9,13 +9,33 @@ export function genSetText(
oper: SetTextIRNode,
context: CodegenContext,
): CodeFragment[] {
- const { helper } = context
+ const {
+ helper,
+ block: { dynamicComponents },
+ } = context
const { element, values, generated, jsx } = oper
const texts = combineValues(values, context, jsx)
- return [
- NEWLINE,
- ...genCall(helper('setText'), `${generated ? 'x' : 'n'}${element}`, texts),
- ]
+
+ // if the element is a dynamic component, we need to use `setElementText`
+ // to set the textContent of the VaporFragment's nodes.
+ return dynamicComponents.includes(oper.element)
+ ? [
+ NEWLINE,
+ ...genCall(
+ helper('setElementText'),
+ `n${element}.nodes`,
+ texts,
+ 'true', // isConverted
+ ),
+ ]
+ : [
+ NEWLINE,
+ ...genCall(
+ helper('setText'),
+ `${generated ? 'x' : 'n'}${element}`,
+ texts,
+ ),
+ ]
}
function combineValues(
@@ -40,6 +60,14 @@ export function genGetTextChild(
oper: GetTextChildIRNode,
context: CodegenContext,
): CodeFragment[] {
+ const {
+ block: { dynamicComponents },
+ } = context
+
+ // if the parent is a dynamic component, don't need to generate a child
+ // because it will use the `setElementText` helper directly.
+ if (dynamicComponents.includes(oper.parent)) return []
+
return [
NEWLINE,
`const x${oper.parent} = ${context.helper('child')}(n${oper.parent})`,
diff --git a/packages/compiler-vapor/src/ir/index.ts b/packages/compiler-vapor/src/ir/index.ts
index da6361132..dd105b08d 100644
--- a/packages/compiler-vapor/src/ir/index.ts
+++ b/packages/compiler-vapor/src/ir/index.ts
@@ -49,6 +49,7 @@ export interface BlockIRNode extends BaseIRNode {
type: IRNodeTypes.BLOCK
node: RootNode | TemplateChildNode
dynamic: IRDynamicInfo
+ dynamicComponents: number[]
tempId: number
effect: IREffect[]
operation: OperationNode[]
diff --git a/packages/compiler-vapor/src/transforms/utils.ts b/packages/compiler-vapor/src/transforms/utils.ts
index b8e7adc60..222449fe4 100644
--- a/packages/compiler-vapor/src/transforms/utils.ts
+++ b/packages/compiler-vapor/src/transforms/utils.ts
@@ -26,6 +26,7 @@ export const newBlock = (node: BlockIRNode['node']): BlockIRNode => ({
type: IRNodeTypes.BLOCK,
node,
dynamic: newDynamic(),
+ dynamicComponents: [],
effect: [],
operation: [],
returns: [],
diff --git a/packages/runtime-vapor/src/dom/prop.ts b/packages/runtime-vapor/src/dom/prop.ts
index 8c42ad766..04e576761 100644
--- a/packages/runtime-vapor/src/dom/prop.ts
+++ b/packages/runtime-vapor/src/dom/prop.ts
@@ -185,13 +185,16 @@ export function setText(el: Text & { $txt?: string }, value: string): void {
}
/**
- * Used by setDynamicProps only, so need to guard with `toDisplayString`
+ * Used by
+ * - setDynamicProps, need to guard with `toDisplayString`
+ * - v-text on dynamic component, value passed here is already converted
*/
export function setElementText(
el: Node & { $txt?: string },
value: unknown,
+ isConverted: boolean = false,
): void {
- if (el.$txt !== (value = toDisplayString(value))) {
+ if (el.$txt !== (value = isConverted ? value : toDisplayString(value))) {
el.textContent = el.$txt = value as string
}
}
diff --git a/packages/runtime-vapor/src/index.ts b/packages/runtime-vapor/src/index.ts
index 682532fa4..da060e7eb 100644
--- a/packages/runtime-vapor/src/index.ts
+++ b/packages/runtime-vapor/src/index.ts
@@ -22,6 +22,7 @@ export {
setProp,
setDOMProp,
setDynamicProps,
+ setElementText,
} from './dom/prop'
export { on, delegate, delegateEvents, setDynamicEvents } from './dom/event'
export { createIf } from './apiCreateIf'