diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOnce.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOnce.spec.ts.snap index b255f5d0b..4b8e89d6d 100644 --- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOnce.spec.ts.snap +++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vOnce.spec.ts.snap @@ -1,6 +1,6 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`v-once > as root node 1`] = ` +exports[`compiler: v-once > as root node 1`] = ` "import { template as _template, children as _children, setAttr as _setAttr } from 'vue/vapor'; export function render(_ctx) { @@ -12,7 +12,7 @@ export function render(_ctx) { }" `; -exports[`v-once > basic 1`] = ` +exports[`compiler: v-once > basic 1`] = ` "import { template as _template, children as _children, createTextNode as _createTextNode, setText as _setText, setAttr as _setAttr, prepend as _prepend } from 'vue/vapor'; export function render(_ctx) { @@ -26,3 +26,25 @@ export function render(_ctx) { return n0 }" `; + +exports[`compiler: v-once > inside v-once 1`] = ` +"import { template as _template } from 'vue/vapor'; + +export function render(_ctx) { + const t0 = _template("
") + const n0 = t0() + return n0 +}" +`; + +exports[`compiler: v-once > on nested plain element 1`] = ` +"import { template as _template, children as _children, setAttr as _setAttr } from 'vue/vapor'; + +export function render(_ctx) { + const t0 = _template("
") + const n0 = t0() + const { 0: [, { 0: [n1],}],} = _children(n0) + _setAttr(n1, "id", undefined, _ctx.foo) + return n0 +}" +`; diff --git a/packages/compiler-vapor/__tests__/transforms/vOnce.spec.ts b/packages/compiler-vapor/__tests__/transforms/vOnce.spec.ts index 8c87f3b2a..bdf493c0d 100644 --- a/packages/compiler-vapor/__tests__/transforms/vOnce.spec.ts +++ b/packages/compiler-vapor/__tests__/transforms/vOnce.spec.ts @@ -1,18 +1,36 @@ -import { type RootNode, BindingTypes } from '@vue/compiler-dom' -import { type CompilerOptions, compile as _compile } from '../../src' +import { BindingTypes, NodeTypes, parse } from '@vue/compiler-dom' +import { + type CompilerOptions, + compile as _compile, + transform, + generate as generate, + IRNodeTypes, + RootIRNode, +} from '../../src' +import { getBaseTransformPreset } from '../../src/compile' -function compile(template: string | RootNode, options: CompilerOptions = {}) { - let { code } = _compile(template, { - ...options, - mode: 'module', +function compileWithOnce( + 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-once', () => { +describe('compiler: v-once', () => { test('basic', () => { - const code = compile( + const { ir, code } = compileWithOnce( `
{{ msg }} @@ -24,12 +42,118 @@ describe('v-once', () => { }, }, ) - expect(code).matchSnapshot() + expect(ir.helpers.size).toBe(0) + expect(ir.effect).toEqual([]) + + expect(ir.operation).toMatchObject([ + { + id: 1, + type: IRNodeTypes.CREATE_TEXT_NODE, + value: { + type: NodeTypes.SIMPLE_EXPRESSION, + content: 'msg', + isStatic: false, + }, + }, + { + element: 1, + type: IRNodeTypes.SET_TEXT, + value: { + type: NodeTypes.SIMPLE_EXPRESSION, + content: 'msg', + isStatic: false, + }, + }, + { + element: 2, + key: { + type: NodeTypes.SIMPLE_EXPRESSION, + content: 'class', + isStatic: true, + }, + type: IRNodeTypes.SET_PROP, + value: { + type: NodeTypes.SIMPLE_EXPRESSION, + content: 'clz', + isStatic: false, + }, + }, + { + type: IRNodeTypes.PREPEND_NODE, + elements: [1], + parent: 3, + }, + ]) + + expect(code).toMatchSnapshot() }) test('as root node', () => { - const code = compile(`
`) + const { ir, code } = compileWithOnce(`
`) + + expect(ir.helpers.size).toBe(0) + expect(ir.effect).toEqual([]) + + expect(ir.operation).toMatchObject([ + { + type: IRNodeTypes.SET_PROP, + element: 1, + key: { + type: NodeTypes.SIMPLE_EXPRESSION, + content: 'id', + isStatic: true, + }, + value: { + type: NodeTypes.SIMPLE_EXPRESSION, + content: 'foo', + isStatic: false, + }, + }, + ]) + expect(code).toMatchSnapshot() expect(code).not.contains('effect') }) + + test('on nested plain element', () => { + const { ir, code } = compileWithOnce(`
`) + expect(ir.helpers.size).toBe(0) + expect(ir.effect).toEqual([]) + + expect(ir.operation).toMatchObject([ + { + type: IRNodeTypes.SET_PROP, + element: 1, + runtimeCamelize: false, + key: { + type: NodeTypes.SIMPLE_EXPRESSION, + content: 'id', + isStatic: true, + }, + value: { + type: NodeTypes.SIMPLE_EXPRESSION, + content: 'foo', + isStatic: false, + }, + }, + ]) + + expect(code).toMatchSnapshot() + }) + + test.todo('on component') + test.todo('on slot outlet') + + test('inside v-once', () => { + const { ir, code } = compileWithOnce(`
`) + expect(ir.helpers.size).toBe(0) + expect(ir.effect).toMatchObject([]) + expect(ir.operation).toMatchObject([]) + + expect(code).toMatchSnapshot() + }) + + test.todo('with hoistStatic: true') + test.todo('with v-if/else') + test.todo('with v-for') })