diff --git a/packages/compiler-core/__tests__/__snapshots__/compile.spec.ts.snap b/packages/compiler-core/__tests__/__snapshots__/compile.spec.ts.snap index efbeb1be1..4748ed19d 100644 --- a/packages/compiler-core/__tests__/__snapshots__/compile.spec.ts.snap +++ b/packages/compiler-core/__tests__/__snapshots__/compile.spec.ts.snap @@ -15,11 +15,11 @@ return function render() { (_openBlock(), ok ? _createBlock(\\"div\\", { key: 0 }, \\"yes\\") : _createBlock(_Fragment, { key: 1 }, \\"no\\")), - (_openBlock(), _createBlock(_Fragment, null, _renderList(list, (value, index) => { - return _createVNode(\\"div\\", null, [ + _createVNode(_Fragment, null, _renderList(list, (value, index) => { + return (_openBlock(), _createBlock(\\"div\\", null, [ _createVNode(\\"span\\", null, _toString(value + index)) - ]) - }))) + ])) + }), 128 /* UNKEYED_FRAGMENT */) ], 2 /* CLASS */) } }" @@ -38,11 +38,11 @@ return function render() { (openBlock(), (_ctx.ok) ? createBlock(\\"div\\", { key: 0 }, \\"yes\\") : createBlock(Fragment, { key: 1 }, \\"no\\")), - (openBlock(), createBlock(Fragment, null, renderList(_ctx.list, (value, index) => { - return createVNode(\\"div\\", null, [ + createVNode(Fragment, null, renderList(_ctx.list, (value, index) => { + return (openBlock(), createBlock(\\"div\\", null, [ createVNode(\\"span\\", null, toString(value + index)) - ]) - }))) + ])) + }), 128 /* UNKEYED_FRAGMENT */) ], 2 /* CLASS */) }" `; @@ -60,11 +60,11 @@ export default function render() { (openBlock(), (_ctx.ok) ? createBlock(\\"div\\", { key: 0 }, \\"yes\\") : createBlock(Fragment, { key: 1 }, \\"no\\")), - (openBlock(), createBlock(Fragment, null, renderList(_ctx.list, (value, index) => { - return createVNode(\\"div\\", null, [ + createVNode(Fragment, null, renderList(_ctx.list, (value, index) => { + return (openBlock(), createBlock(\\"div\\", null, [ createVNode(\\"span\\", null, _toString(value + index)) - ]) - }))) + ])) + }), 128 /* UNKEYED_FRAGMENT */) ], 2 /* CLASS */) }" `; diff --git a/packages/compiler-core/__tests__/transforms/__snapshots__/vFor.spec.ts.snap b/packages/compiler-core/__tests__/transforms/__snapshots__/vFor.spec.ts.snap index d9ce98eb3..352f0f62b 100644 --- a/packages/compiler-core/__tests__/transforms/__snapshots__/vFor.spec.ts.snap +++ b/packages/compiler-core/__tests__/transforms/__snapshots__/vFor.spec.ts.snap @@ -5,11 +5,42 @@ exports[`compiler: v-for codegen basic v-for 1`] = ` return function render() { with (this) { - const { openBlock: _openBlock, createVNode: _createVNode, createBlock: _createBlock, Fragment: _Fragment, renderList: _renderList } = _Vue + const { renderList: _renderList, createVNode: _createVNode, Fragment: _Fragment, createBlock: _createBlock, openBlock: _openBlock } = _Vue - return (_openBlock(), _createBlock(_Fragment, null, _renderList(items, (item) => { - return _createVNode(\\"span\\") - }))) + return _createVNode(_Fragment, null, _renderList(items, (item) => { + return (_openBlock(), _createBlock(\\"span\\")) + }), 128 /* UNKEYED_FRAGMENT */) + } +}" +`; + +exports[`compiler: v-for codegen keyed template v-for 1`] = ` +"const _Vue = Vue + +return function render() { + with (this) { + const { renderList: _renderList, createVNode: _createVNode, Fragment: _Fragment, openBlock: _openBlock, createBlock: _createBlock } = _Vue + + return _createVNode(_Fragment, null, _renderList(items, (item) => { + return (_openBlock(), _createBlock(_Fragment, { key: item }, [ + \\"hello\\", + _createVNode(\\"span\\") + ])) + }), 64 /* KEYED_FRAGMENT */) + } +}" +`; + +exports[`compiler: v-for codegen keyed v-for 1`] = ` +"const _Vue = Vue + +return function render() { + with (this) { + const { renderList: _renderList, createVNode: _createVNode, Fragment: _Fragment, createBlock: _createBlock, openBlock: _openBlock } = _Vue + + return _createVNode(_Fragment, null, _renderList(items, (item) => { + return (_openBlock(), _createBlock(\\"span\\", { key: item })) + }), 64 /* KEYED_FRAGMENT */) } }" `; @@ -19,11 +50,11 @@ exports[`compiler: v-for codegen skipped key 1`] = ` return function render() { with (this) { - const { openBlock: _openBlock, createVNode: _createVNode, createBlock: _createBlock, Fragment: _Fragment, renderList: _renderList } = _Vue + const { renderList: _renderList, createVNode: _createVNode, Fragment: _Fragment, createBlock: _createBlock, openBlock: _openBlock } = _Vue - return (_openBlock(), _createBlock(_Fragment, null, _renderList(items, (value, __, index) => { - return _createVNode(\\"span\\") - }))) + return _createVNode(_Fragment, null, _renderList(items, (item, __, index) => { + return (_openBlock(), _createBlock(\\"span\\")) + }), 128 /* UNKEYED_FRAGMENT */) } }" `; @@ -33,11 +64,11 @@ exports[`compiler: v-for codegen skipped value & key 1`] = ` return function render() { with (this) { - const { openBlock: _openBlock, createVNode: _createVNode, createBlock: _createBlock, Fragment: _Fragment, renderList: _renderList } = _Vue + const { renderList: _renderList, createVNode: _createVNode, Fragment: _Fragment, createBlock: _createBlock, openBlock: _openBlock } = _Vue - return (_openBlock(), _createBlock(_Fragment, null, _renderList(items, (_, __, index) => { - return _createVNode(\\"span\\") - }))) + return _createVNode(_Fragment, null, _renderList(items, (_, __, index) => { + return (_openBlock(), _createBlock(\\"span\\")) + }), 128 /* UNKEYED_FRAGMENT */) } }" `; @@ -47,11 +78,11 @@ exports[`compiler: v-for codegen skipped value 1`] = ` return function render() { with (this) { - const { openBlock: _openBlock, createVNode: _createVNode, createBlock: _createBlock, Fragment: _Fragment, renderList: _renderList } = _Vue + const { renderList: _renderList, createVNode: _createVNode, Fragment: _Fragment, createBlock: _createBlock, openBlock: _openBlock } = _Vue - return (_openBlock(), _createBlock(_Fragment, null, _renderList(items, (_, key, index) => { - return _createVNode(\\"span\\") - }))) + return _createVNode(_Fragment, null, _renderList(items, (_, key, index) => { + return (_openBlock(), _createBlock(\\"span\\")) + }), 128 /* UNKEYED_FRAGMENT */) } }" `; @@ -61,14 +92,14 @@ exports[`compiler: v-for codegen template v-for 1`] = ` return function render() { with (this) { - const { openBlock: _openBlock, createVNode: _createVNode, createBlock: _createBlock, Fragment: _Fragment, renderList: _renderList } = _Vue + const { renderList: _renderList, createVNode: _createVNode, Fragment: _Fragment, openBlock: _openBlock, createBlock: _createBlock } = _Vue - return (_openBlock(), _createBlock(_Fragment, null, _renderList(items, (item) => { - return [ + return _createVNode(_Fragment, null, _renderList(items, (item) => { + return (_openBlock(), _createBlock(_Fragment, null, [ \\"hello\\", _createVNode(\\"span\\") - ] - }))) + ])) + }), 128 /* UNKEYED_FRAGMENT */) } }" `; @@ -78,12 +109,12 @@ exports[`compiler: v-for codegen v-if + v-for 1`] = ` return function render() { with (this) { - const { openBlock: _openBlock, createVNode: _createVNode, createBlock: _createBlock, Fragment: _Fragment, renderList: _renderList, Empty: _Empty } = _Vue + const { openBlock: _openBlock, renderList: _renderList, createVNode: _createVNode, Fragment: _Fragment, createBlock: _createBlock, Empty: _Empty } = _Vue return (_openBlock(), ok ? _createBlock(_Fragment, { key: 0 }, _renderList(list, (i) => { - return _createVNode(\\"div\\") - })) + return (_openBlock(), _createBlock(\\"div\\")) + }), 128 /* UNKEYED_FRAGMENT */) : _createBlock(_Empty)) } }" @@ -94,11 +125,11 @@ exports[`compiler: v-for codegen value + key + index 1`] = ` return function render() { with (this) { - const { openBlock: _openBlock, createVNode: _createVNode, createBlock: _createBlock, Fragment: _Fragment, renderList: _renderList } = _Vue + const { renderList: _renderList, createVNode: _createVNode, Fragment: _Fragment, createBlock: _createBlock, openBlock: _openBlock } = _Vue - return (_openBlock(), _createBlock(_Fragment, null, _renderList(items, (item, key, index) => { - return _createVNode(\\"span\\") - }))) + return _createVNode(_Fragment, null, _renderList(items, (item, key, index) => { + return (_openBlock(), _createBlock(\\"span\\")) + }), 128 /* UNKEYED_FRAGMENT */) } }" `; diff --git a/packages/compiler-core/__tests__/transforms/__snapshots__/vIf.spec.ts.snap b/packages/compiler-core/__tests__/transforms/__snapshots__/vIf.spec.ts.snap index 6509aa12c..bbd8a8d30 100644 --- a/packages/compiler-core/__tests__/transforms/__snapshots__/vIf.spec.ts.snap +++ b/packages/compiler-core/__tests__/transforms/__snapshots__/vIf.spec.ts.snap @@ -19,7 +19,7 @@ exports[`compiler: v-if codegen template v-if 1`] = ` return function render() { with (this) { - const { openBlock: _openBlock, createVNode: _createVNode, createBlock: _createBlock, Fragment: _Fragment, Empty: _Empty } = _Vue + const { openBlock: _openBlock, createVNode: _createVNode, Fragment: _Fragment, createBlock: _createBlock, Empty: _Empty } = _Vue return (_openBlock(), ok ? _createBlock(_Fragment, { key: 0 }, [ diff --git a/packages/compiler-core/__tests__/transforms/vFor.spec.ts b/packages/compiler-core/__tests__/transforms/vFor.spec.ts index 0fa36d5bc..389560959 100644 --- a/packages/compiler-core/__tests__/transforms/vFor.spec.ts +++ b/packages/compiler-core/__tests__/transforms/vFor.spec.ts @@ -2,25 +2,29 @@ import { parse } from '../../src/parse' import { transform } from '../../src/transform' import { transformIf } from '../../src/transforms/vIf' import { transformFor } from '../../src/transforms/vFor' +import { transformBind } from '../../src/transforms/vBind' import { transformElement } from '../../src/transforms/transformElement' +import { transformExpression } from '../../src/transforms/transformExpression' import { ForNode, NodeTypes, SimpleExpressionNode, ElementNode, InterpolationNode, - SequenceExpression, CallExpression } from '../../src/ast' import { ErrorCodes } from '../../src/errors' import { CompilerOptions, generate } from '../../src' -import { transformExpression } from '../../src/transforms/transformExpression' import { OPEN_BLOCK, CREATE_BLOCK, FRAGMENT, - RENDER_LIST + RENDER_LIST, + CREATE_VNODE } from '../../src/runtimeConstants' +import { PatchFlags } from '@vue/runtime-dom' +import { PatchFlagNames } from '@vue/shared' +import { createObjectMatcher } from '../testUtils' function parseWithForTransform( template: string, @@ -34,6 +38,9 @@ function parseWithForTransform( ...(options.prefixIdentifiers ? [transformExpression] : []), transformElement ], + directiveTransforms: { + bind: transformBind + }, ...options }) return { @@ -555,31 +562,51 @@ describe('compiler: v-for', () => { }) describe('codegen', () => { - function assertSharedCodegen(node: SequenceExpression) { + function assertSharedCodegen(node: CallExpression, keyed: boolean = false) { expect(node).toMatchObject({ - type: NodeTypes.JS_SEQUENCE_EXPRESSION, - expressions: [ + type: NodeTypes.JS_CALL_EXPRESSION, + callee: `_${CREATE_VNODE}`, + arguments: [ + `_${FRAGMENT}`, + `null`, { type: NodeTypes.JS_CALL_EXPRESSION, - callee: `_${OPEN_BLOCK}`, - arguments: [] - }, - { - type: NodeTypes.JS_CALL_EXPRESSION, - callee: `_${CREATE_BLOCK}`, + callee: `_${RENDER_LIST}`, arguments: [ - `_${FRAGMENT}`, - `null`, + {}, // to be asserted by each test { - type: NodeTypes.JS_CALL_EXPRESSION, - callee: `_${RENDER_LIST}` + type: NodeTypes.JS_FUNCTION_EXPRESSION, + returns: { + type: NodeTypes.JS_SEQUENCE_EXPRESSION, + expressions: [ + { + type: NodeTypes.JS_CALL_EXPRESSION, + callee: `_${OPEN_BLOCK}` + }, + { + type: NodeTypes.JS_CALL_EXPRESSION, + callee: `_${CREATE_BLOCK}` + } + ] + } } ] - } + }, + keyed + ? `${PatchFlags.KEYED_FRAGMENT} /* ${ + PatchFlagNames[PatchFlags.KEYED_FRAGMENT] + } */` + : `${PatchFlags.UNKEYED_FRAGMENT} /* ${ + PatchFlagNames[PatchFlags.UNKEYED_FRAGMENT] + } */` ] }) - return (node.expressions[1] as CallExpression) - .arguments[2] as CallExpression + const renderListArgs = (node.arguments[2] as CallExpression).arguments + return { + source: renderListArgs[0] as SimpleExpressionNode, + params: (renderListArgs[1] as any).params, + blockArgs: (renderListArgs[1] as any).returns.expressions[1].arguments + } } test('basic v-for', () => { @@ -587,17 +614,11 @@ describe('compiler: v-for', () => { root, node: { codegenNode } } = parseWithForTransform('') - expect(assertSharedCodegen(codegenNode).arguments).toMatchObject([ - { content: `items` }, - { - type: NodeTypes.JS_FUNCTION_EXPRESSION, - params: [{ content: `item` }], - returns: { - type: NodeTypes.ELEMENT, - tag: `span` - } - } - ]) + expect(assertSharedCodegen(codegenNode)).toMatchObject({ + source: { content: `items` }, + params: [{ content: `item` }], + blockArgs: [`"span"`] + }) expect(generate(root).code).toMatchSnapshot() }) @@ -606,17 +627,10 @@ describe('compiler: v-for', () => { root, node: { codegenNode } } = parseWithForTransform('') - expect(assertSharedCodegen(codegenNode).arguments).toMatchObject([ - { content: `items` }, - { - type: NodeTypes.JS_FUNCTION_EXPRESSION, - params: [ - { content: `item` }, - { content: `key` }, - { content: `index` } - ] - } - ]) + expect(assertSharedCodegen(codegenNode)).toMatchObject({ + source: { content: `items` }, + params: [{ content: `item` }, { content: `key` }, { content: `index` }] + }) expect(generate(root).code).toMatchSnapshot() }) @@ -624,14 +638,11 @@ describe('compiler: v-for', () => { const { root, node: { codegenNode } - } = parseWithForTransform('') - expect(assertSharedCodegen(codegenNode).arguments).toMatchObject([ - { content: `items` }, - { - type: NodeTypes.JS_FUNCTION_EXPRESSION, - params: [{ content: `_` }, { content: `key` }, { content: `index` }] - } - ]) + } = parseWithForTransform('') + expect(assertSharedCodegen(codegenNode)).toMatchObject({ + source: { content: `items` }, + params: [{ content: `_` }, { content: `key` }, { content: `index` }] + }) expect(generate(root).code).toMatchSnapshot() }) @@ -639,18 +650,11 @@ describe('compiler: v-for', () => { const { root, node: { codegenNode } - } = parseWithForTransform('') - expect(assertSharedCodegen(codegenNode).arguments).toMatchObject([ - { content: `items` }, - { - type: NodeTypes.JS_FUNCTION_EXPRESSION, - params: [ - { content: `value` }, - { content: `__` }, - { content: `index` } - ] - } - ]) + } = parseWithForTransform('') + expect(assertSharedCodegen(codegenNode)).toMatchObject({ + source: { content: `items` }, + params: [{ content: `item` }, { content: `__` }, { content: `index` }] + }) expect(generate(root).code).toMatchSnapshot() }) @@ -659,13 +663,10 @@ describe('compiler: v-for', () => { root, node: { codegenNode } } = parseWithForTransform('') - expect(assertSharedCodegen(codegenNode).arguments).toMatchObject([ - { content: `items` }, - { - type: NodeTypes.JS_FUNCTION_EXPRESSION, - params: [{ content: `_` }, { content: `__` }, { content: `index` }] - } - ]) + expect(assertSharedCodegen(codegenNode)).toMatchObject({ + source: { content: `items` }, + params: [{ content: `_` }, { content: `__` }, { content: `index` }] + }) expect(generate(root).code).toMatchSnapshot() }) @@ -676,17 +677,60 @@ describe('compiler: v-for', () => { } = parseWithForTransform( '' ) - expect(assertSharedCodegen(codegenNode).arguments).toMatchObject([ - { content: `items` }, - { - type: NodeTypes.JS_FUNCTION_EXPRESSION, - params: [{ content: `item` }], - returns: [ + expect(assertSharedCodegen(codegenNode)).toMatchObject({ + source: { content: `items` }, + params: [{ content: `item` }], + blockArgs: [ + `_${FRAGMENT}`, + `null`, + [ { type: NodeTypes.TEXT, content: `hello` }, { type: NodeTypes.ELEMENT, tag: `span` } ] - } - ]) + ] + }) + expect(generate(root).code).toMatchSnapshot() + }) + + test('keyed v-for', () => { + const { + root, + node: { codegenNode } + } = parseWithForTransform('') + expect(assertSharedCodegen(codegenNode, true)).toMatchObject({ + source: { content: `items` }, + params: [{ content: `item` }], + blockArgs: [ + `"span"`, + createObjectMatcher({ + key: `[item]` + }) + ] + }) + expect(generate(root).code).toMatchSnapshot() + }) + + test('keyed template v-for', () => { + const { + root, + node: { codegenNode } + } = parseWithForTransform( + '' + ) + expect(assertSharedCodegen(codegenNode, true)).toMatchObject({ + source: { content: `items` }, + params: [{ content: `item` }], + blockArgs: [ + `_${FRAGMENT}`, + createObjectMatcher({ + key: `[item]` + }), + [ + { type: NodeTypes.TEXT, content: `hello` }, + { type: NodeTypes.ELEMENT, tag: `span` } + ] + ] + }) expect(generate(root).code).toMatchSnapshot() }) @@ -722,12 +766,25 @@ describe('compiler: v-for', () => { type: NodeTypes.JS_FUNCTION_EXPRESSION, params: [{ content: `i` }], returns: { - type: NodeTypes.ELEMENT, - tag: `div` + type: NodeTypes.JS_SEQUENCE_EXPRESSION, + expressions: [ + { + type: NodeTypes.JS_CALL_EXPRESSION, + callee: `_${OPEN_BLOCK}` + }, + { + type: NodeTypes.JS_CALL_EXPRESSION, + callee: `_${CREATE_BLOCK}`, + arguments: [`"div"`] + } + ] } } ] - } + }, + `${PatchFlags.UNKEYED_FRAGMENT} /* ${ + PatchFlagNames[PatchFlags.UNKEYED_FRAGMENT] + } */` ] } } diff --git a/packages/compiler-core/src/ast.ts b/packages/compiler-core/src/ast.ts index cc8f4296a..999c875a7 100644 --- a/packages/compiler-core/src/ast.ts +++ b/packages/compiler-core/src/ast.ts @@ -158,7 +158,7 @@ export interface ForNode extends Node { keyAlias: ExpressionNode | undefined objectIndexAlias: ExpressionNode | undefined children: TemplateChildNode[] - codegenNode: SequenceExpression + codegenNode: CallExpression } // We also include a number of JavaScript AST nodes for code generation. @@ -198,7 +198,7 @@ export interface ArrayExpression extends Node { export interface FunctionExpression extends Node { type: NodeTypes.JS_FUNCTION_EXPRESSION params: ExpressionNode | ExpressionNode[] | undefined - returns: TemplateChildNode | TemplateChildNode[] + returns: TemplateChildNode | TemplateChildNode[] | JSChildNode newline: boolean } diff --git a/packages/compiler-core/src/codegen.ts b/packages/compiler-core/src/codegen.ts index c25518c14..81b7cb3f9 100644 --- a/packages/compiler-core/src/codegen.ts +++ b/packages/compiler-core/src/codegen.ts @@ -261,7 +261,6 @@ function genHoists(hoists: JSChildNode[], context: CodegenContext) { // - The target position explicitly allows a single node (root, if, for) // - The list has length === 1, AND The only child is a: // - text -// - expression // - outlet, which always produces an array function genChildren( children: TemplateChildNode[], diff --git a/packages/compiler-core/src/transforms/transformElement.ts b/packages/compiler-core/src/transforms/transformElement.ts index ae9155a24..de6d1ffbe 100644 --- a/packages/compiler-core/src/transforms/transformElement.ts +++ b/packages/compiler-core/src/transforms/transformElement.ts @@ -163,7 +163,7 @@ export function buildProps( // patchFlag analysis let patchFlag = 0 const dynamicPropNames: string[] = [] - let hasDynammicKeys = false + let hasDynamicKeys = false let hasClassBinding = false let hasStyleBinding = false let hasRef = false @@ -207,7 +207,7 @@ export function buildProps( // special case for v-bind and v-on with no argument const isBind = name === 'bind' if (!arg && (isBind || name === 'on')) { - hasDynammicKeys = true + hasDynamicKeys = true if (exp) { if (properties.length) { mergeArgs.push( @@ -249,11 +249,11 @@ export function buildProps( hasClassBinding = true } else if (name === 'style') { hasStyleBinding = true - } else { + } else if (name !== 'key') { dynamicPropNames.push(name) } } else { - hasDynammicKeys = true + hasDynamicKeys = true } } @@ -303,7 +303,7 @@ export function buildProps( } // determine the flags to add - if (hasDynammicKeys) { + if (hasDynamicKeys) { patchFlag |= PatchFlags.FULL_PROPS } else { if (hasClassBinding) { diff --git a/packages/compiler-core/src/transforms/vFor.ts b/packages/compiler-core/src/transforms/vFor.ts index aefd6f087..3af7f8619 100644 --- a/packages/compiler-core/src/transforms/vFor.ts +++ b/packages/compiler-core/src/transforms/vFor.ts @@ -11,17 +11,22 @@ import { createSequenceExpression, createCallExpression, createFunctionExpression, - ElementTypes + ElementTypes, + ObjectExpression, + createObjectExpression, + createObjectProperty } from '../ast' import { createCompilerError, ErrorCodes } from '../errors' -import { getInnerRange } from '../utils' +import { getInnerRange, findProp } from '../utils' import { RENDER_LIST, OPEN_BLOCK, CREATE_BLOCK, - FRAGMENT + FRAGMENT, + CREATE_VNODE } from '../runtimeConstants' import { processExpression } from './transformExpression' +import { PatchFlags, PatchFlagNames } from '@vue/shared' export const transformFor = createStructuralDirectiveTransform( 'for', @@ -38,9 +43,19 @@ export const transformFor = createStructuralDirectiveTransform( const { helper, addIdentifiers, removeIdentifiers } = context const { source, value, key, index } = parseResult - const codegenNode = createSequenceExpression([ - createCallExpression(helper(OPEN_BLOCK)) - // to be filled in on exit after children traverse + // create the loop render function expression now, and add the + // iterator on exit after all children have been traversed + const renderExp = createCallExpression(helper(RENDER_LIST), [source]) + const keyProp = findProp(node.props, `key`) + const fragmentFlag = keyProp + ? PatchFlags.KEYED_FRAGMENT + : PatchFlags.UNKEYED_FRAGMENT + const codegenNode = createCallExpression(helper(CREATE_VNODE), [ + helper(FRAGMENT), + `null`, + renderExp, + fragmentFlag + + (__DEV__ ? ` /* ${PatchFlagNames[fragmentFlag]} */` : ``) ]) context.replaceNode({ @@ -63,6 +78,13 @@ export const transformFor = createStructuralDirectiveTransform( } return () => { + if (!__BROWSER__ && context.prefixIdentifiers) { + value && removeIdentifiers(value) + key && removeIdentifiers(key) + index && removeIdentifiers(index) + } + + // finish the codegen now that all children have been traversed const params: ExpressionNode[] = [] if (value) { params.push(value) @@ -83,26 +105,46 @@ export const transformFor = createStructuralDirectiveTransform( params.push(index) } - codegenNode.expressions.push( - createCallExpression(helper(CREATE_BLOCK), [ - helper(FRAGMENT), - `null`, - createCallExpression(helper(RENDER_LIST), [ - source, - createFunctionExpression( - params, - node.tagType === ElementTypes.TEMPLATE ? node.children : node, - true /* force newline to make it more readable */ + let childBlock + if (node.tagType === ElementTypes.TEMPLATE) { + //