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 459741e9a..d3abf8903 100644 --- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vHtml.spec.ts.snap +++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vHtml.spec.ts.snap @@ -1,5 +1,19 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html +exports[`v-html > should convert v-html to innerHTML 1`] = ` +"import { template as _template, children as _children, effect as _effect, setHtml as _setHtml } from 'vue/vapor'; + +export function render(_ctx) { + const t0 = _template("
") + const n0 = t0() + const { 0: [n1],} = _children(n0) + _effect(() => { + _setHtml(n1, undefined, _ctx.code) + }) + return n0 +}" +`; + exports[`v-html > should raise error and ignore children when v-html is present 1`] = ` "import { template as _template, children as _children, effect as _effect, setHtml as _setHtml } from 'vue/vapor'; @@ -25,17 +39,3 @@ export function render(_ctx) { return n0 }" `; - -exports[`v-html > simple expression 1`] = ` -"import { template as _template, children as _children, effect as _effect, setHtml as _setHtml } from 'vue/vapor'; - -export function render(_ctx) { - const t0 = _template("
") - const n0 = t0() - const { 0: [n1],} = _children(n0) - _effect(() => { - _setHtml(n1, undefined, _ctx.code) - }) - 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 f2b62b2ee..d18e398b1 100644 --- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vText.spec.ts.snap +++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vText.spec.ts.snap @@ -1,18 +1,6 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`v-text > no expression 1`] = ` -"import { template as _template, children as _children, setText as _setText } from 'vue/vapor'; - -export function render(_ctx) { - const t0 = _template("
") - const n0 = t0() - const { 0: [n1],} = _children(n0) - _setText(n1, undefined, "") - return n0 -}" -`; - -exports[`v-text > simple expression 1`] = ` +exports[`v-text > should convert v-text to textContent 1`] = ` "import { template as _template, children as _children, effect as _effect, setText as _setText } from 'vue/vapor'; export function render(_ctx) { @@ -25,3 +13,29 @@ export function render(_ctx) { return n0 }" `; + +exports[`v-text > should raise error and ignore children when v-text is present 1`] = ` +"import { template as _template, children as _children, effect as _effect, setText as _setText } from 'vue/vapor'; + +export function render(_ctx) { + const t0 = _template("
") + const n0 = t0() + const { 0: [n1],} = _children(n0) + _effect(() => { + _setText(n1, undefined, _ctx.test) + }) + return n0 +}" +`; + +exports[`v-text > should raise error if has no expression 1`] = ` +"import { template as _template, children as _children, setText as _setText } from 'vue/vapor'; + +export function render(_ctx) { + const t0 = _template("
") + const n0 = t0() + const { 0: [n1],} = _children(n0) + _setText(n1, undefined, "") + return n0 +}" +`; diff --git a/packages/compiler-vapor/__tests__/transforms/vHtml.spec.ts b/packages/compiler-vapor/__tests__/transforms/vHtml.spec.ts index 6d0492fa6..0e38f9e45 100644 --- a/packages/compiler-vapor/__tests__/transforms/vHtml.spec.ts +++ b/packages/compiler-vapor/__tests__/transforms/vHtml.spec.ts @@ -1,39 +1,119 @@ -import { type RootNode, BindingTypes, DOMErrorCodes } from '@vue/compiler-dom' -import { type CompilerOptions, compile as _compile } from '../../src' +import { + BindingTypes, + DOMErrorCodes, + NodeTypes, + parse, +} from '@vue/compiler-dom' +import { + type CompilerOptions, + compile as _compile, + RootIRNode, + transform, + generate, + IRNodeTypes, +} from '../../src' +import { getBaseTransformPreset } from '../../src/compile' -function compile(template: string | RootNode, options: CompilerOptions = {}) { - let { code } = _compile(template, { - ...options, - mode: 'module', +function compileWithVHtml( + template: string, + options: CompilerOptions = {}, +): { + ir: RootIRNode + code: string +} { + const ast = parse(template, { prefixIdentifiers: true, ...options }) + const [nodeTransforms, directiveTransforms] = getBaseTransformPreset(true) + const ir = transform(ast, { + nodeTransforms, + directiveTransforms, prefixIdentifiers: true, + ...options, }) - return code + const { code } = generate(ir, { prefixIdentifiers: true, ...options }) + return { ir, code } } describe('v-html', () => { - test('simple expression', () => { - const code = compile(`
`, { + test('should convert v-html to innerHTML', () => { + const { code, ir } = compileWithVHtml(`
`, { bindingMetadata: { code: BindingTypes.SETUP_REF, }, }) + + expect(ir.vaporHelpers).contains('setHtml') + expect(ir.helpers.size).toBe(0) + + expect(ir.operation).toEqual([]) + expect(ir.effect).toMatchObject([ + { + expressions: [ + { + type: NodeTypes.SIMPLE_EXPRESSION, + content: 'code', + isStatic: false, + }, + ], + operations: [ + { + type: IRNodeTypes.SET_HTML, + element: 1, + value: { + type: NodeTypes.SIMPLE_EXPRESSION, + content: 'code', + isStatic: false, + }, + }, + ], + }, + ]) + expect(code).matchSnapshot() }) test('should raise error and ignore children when v-html is present', () => { const onError = vi.fn() - const code = compile(`
hello
`, { + const { code, ir } = compileWithVHtml(`
hello
`, { onError, }) - expect(code).matchSnapshot() + + expect(ir.vaporHelpers).contains('setHtml') + expect(ir.helpers.size).toBe(0) + + expect(ir.operation).toEqual([]) + expect(ir.effect).toMatchObject([ + { + expressions: [ + { + type: NodeTypes.SIMPLE_EXPRESSION, + content: 'test', + isStatic: false, + }, + ], + operations: [ + { + type: IRNodeTypes.SET_HTML, + element: 1, + value: { + type: NodeTypes.SIMPLE_EXPRESSION, + content: 'test', + isStatic: false, + }, + }, + ], + }, + ]) + expect(onError.mock.calls).toMatchObject([ [{ code: DOMErrorCodes.X_V_HTML_WITH_CHILDREN }], ]) + + expect(code).matchSnapshot() }) test('should raise error if has no expression', () => { const onError = vi.fn() - const code = compile(`
`, { + const { code } = compileWithVHtml(`
`, { onError, }) expect(code).matchSnapshot() diff --git a/packages/compiler-vapor/__tests__/transforms/vText.spec.ts b/packages/compiler-vapor/__tests__/transforms/vText.spec.ts index 0989ef19f..bae5c9166 100644 --- a/packages/compiler-vapor/__tests__/transforms/vText.spec.ts +++ b/packages/compiler-vapor/__tests__/transforms/vText.spec.ts @@ -1,28 +1,120 @@ -import { type RootNode, BindingTypes, DOMErrorCodes } from '@vue/compiler-dom' -import { type CompilerOptions, compile as _compile } from '../../src' +import { + BindingTypes, + DOMErrorCodes, + NodeTypes, + parse, +} from '@vue/compiler-dom' +import { + type CompilerOptions, + compile as _compile, + RootIRNode, + transform, + generate, + IRNodeTypes, +} from '../../src' +import { getBaseTransformPreset } from '../../src/compile' -function compile(template: string | RootNode, options: CompilerOptions = {}) { - let { code } = _compile(template, { - ...options, - mode: 'module', +function compileWithVText( + template: string, + options: CompilerOptions = {}, +): { + ir: RootIRNode + code: string +} { + const ast = parse(template, { prefixIdentifiers: true, ...options }) + const [nodeTransforms, directiveTransforms] = getBaseTransformPreset(true) + const ir = transform(ast, { + nodeTransforms, + directiveTransforms, prefixIdentifiers: true, + ...options, }) - return code + const { code } = generate(ir, { prefixIdentifiers: true, ...options }) + return { ir, code } } describe('v-text', () => { - test('simple expression', () => { - const code = compile(`
`, { + test('should convert v-text to textContent', () => { + const { code, ir } = compileWithVText(`
`, { bindingMetadata: { str: BindingTypes.SETUP_REF, }, }) + + expect(ir.vaporHelpers).contains('setText') + expect(ir.helpers.size).toBe(0) + + expect(ir.operation).toEqual([]) + + expect(ir.effect).toMatchObject([ + { + expressions: [ + { + type: NodeTypes.SIMPLE_EXPRESSION, + content: 'str', + isStatic: false, + }, + ], + operations: [ + { + type: IRNodeTypes.SET_TEXT, + element: 1, + value: { + type: NodeTypes.SIMPLE_EXPRESSION, + content: 'str', + isStatic: false, + }, + }, + ], + }, + ]) + expect(code).matchSnapshot() }) - test('no expression', () => { + test('should raise error and ignore children when v-text is present', () => { const onError = vi.fn() - const code = compile(`
`, { onError }) + const { code, ir } = compileWithVText(`
hello
`, { + onError, + }) + expect(onError.mock.calls).toMatchObject([ + [{ code: DOMErrorCodes.X_V_TEXT_WITH_CHILDREN }], + ]) + + // children should have been removed + expect(ir.template).toMatchObject([{ template: '
' }]) + + expect(ir.effect).toMatchObject([ + { + expressions: [ + { + type: NodeTypes.SIMPLE_EXPRESSION, + content: 'test', + isStatic: false, + }, + ], + operations: [ + { + type: IRNodeTypes.SET_TEXT, + element: 1, + value: { + type: NodeTypes.SIMPLE_EXPRESSION, + content: 'test', + isStatic: false, + }, + }, + ], + }, + ]) + + expect(code).matchSnapshot() + // children should have been removed + expect(code).contains('template("
")') + }) + + test('should raise error if has no expression', () => { + const onError = vi.fn() + const { code } = compileWithVText(`
`, { onError }) expect(code).matchSnapshot() expect(onError.mock.calls).toMatchObject([ [{ code: DOMErrorCodes.X_V_TEXT_NO_EXPRESSION }], diff --git a/packages/compiler-vapor/src/transforms/vText.ts b/packages/compiler-vapor/src/transforms/vText.ts index 7a235a793..729c859aa 100644 --- a/packages/compiler-vapor/src/transforms/vText.ts +++ b/packages/compiler-vapor/src/transforms/vText.ts @@ -13,7 +13,7 @@ export const transformVText: DirectiveTransform = (dir, node, context) => { context.options.onError( createDOMCompilerError(DOMErrorCodes.X_V_TEXT_WITH_CHILDREN, loc), ) - node.children.length = 0 + context.childrenTemplate.length = 0 } context.registerEffect(