fix(ssr): fix hydration error on falsy v-if inside transition/keep-alive
fix #5352
This commit is contained in:
		
							parent
							
								
									c65b805ef1
								
							
						
					
					
						commit
						ee4186ef9e
					
				@ -280,46 +280,92 @@ describe('ssr: components', () => {
 | 
				
			|||||||
      `)
 | 
					      `)
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    test('built-in fallthroughs', () => {
 | 
					    describe('built-in fallthroughs', () => {
 | 
				
			||||||
      expect(compile(`<transition><div/></transition>`).code)
 | 
					      test('transition', () => {
 | 
				
			||||||
        .toMatchInlineSnapshot(`
 | 
					        expect(compile(`<transition><div/></transition>`).code)
 | 
				
			||||||
        "const { ssrRenderAttrs: _ssrRenderAttrs } = require(\\"vue/server-renderer\\")
 | 
					          .toMatchInlineSnapshot(`
 | 
				
			||||||
 | 
					                  "const { ssrRenderAttrs: _ssrRenderAttrs } = require(\\"vue/server-renderer\\")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return function ssrRender(_ctx, _push, _parent, _attrs) {
 | 
					                  return function ssrRender(_ctx, _push, _parent, _attrs) {
 | 
				
			||||||
          _push(\`<div\${_ssrRenderAttrs(_attrs)}></div>\`)
 | 
					                    _push(\`<div\${_ssrRenderAttrs(_attrs)}></div>\`)
 | 
				
			||||||
        }"
 | 
					                  }"
 | 
				
			||||||
      `)
 | 
					              `)
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // should inject attrs if root with coomments
 | 
					      test('keep-alive', () => {
 | 
				
			||||||
      expect(compile(`<!--root--><transition><div/></transition>`).code)
 | 
					        expect(compile(`<keep-alive><foo/></keep-alive>`).code)
 | 
				
			||||||
        .toMatchInlineSnapshot(`
 | 
					          .toMatchInlineSnapshot(`
 | 
				
			||||||
        "const { ssrRenderAttrs: _ssrRenderAttrs } = require(\\"vue/server-renderer\\")
 | 
					                  "const { resolveComponent: _resolveComponent } = require(\\"vue\\")
 | 
				
			||||||
 | 
					                  const { ssrRenderComponent: _ssrRenderComponent } = require(\\"vue/server-renderer\\")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return function ssrRender(_ctx, _push, _parent, _attrs) {
 | 
					                  return function ssrRender(_ctx, _push, _parent, _attrs) {
 | 
				
			||||||
          _push(\`<!--[--><!--root--><div\${_ssrRenderAttrs(_attrs)}></div><!--]-->\`)
 | 
					                    const _component_foo = _resolveComponent(\\"foo\\")
 | 
				
			||||||
        }"
 | 
					 | 
				
			||||||
      `)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // should not inject attrs if not root
 | 
					                    _push(_ssrRenderComponent(_component_foo, _attrs, null, _parent))
 | 
				
			||||||
      expect(compile(`<div/><transition><div/></transition>`).code)
 | 
					                  }"
 | 
				
			||||||
        .toMatchInlineSnapshot(`
 | 
					              `)
 | 
				
			||||||
        "
 | 
					      })
 | 
				
			||||||
        return function ssrRender(_ctx, _push, _parent, _attrs) {
 | 
					 | 
				
			||||||
          _push(\`<!--[--><div></div><div></div><!--]-->\`)
 | 
					 | 
				
			||||||
        }"
 | 
					 | 
				
			||||||
      `)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      expect(compile(`<keep-alive><foo/></keep-alive>`).code)
 | 
					      test('should inject attrs if root with coomments', () => {
 | 
				
			||||||
        .toMatchInlineSnapshot(`
 | 
					        expect(compile(`<!--root--><transition><div/></transition>`).code)
 | 
				
			||||||
        "const { resolveComponent: _resolveComponent } = require(\\"vue\\")
 | 
					          .toMatchInlineSnapshot(`
 | 
				
			||||||
        const { ssrRenderComponent: _ssrRenderComponent } = require(\\"vue/server-renderer\\")
 | 
					                  "const { ssrRenderAttrs: _ssrRenderAttrs } = require(\\"vue/server-renderer\\")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return function ssrRender(_ctx, _push, _parent, _attrs) {
 | 
					                  return function ssrRender(_ctx, _push, _parent, _attrs) {
 | 
				
			||||||
          const _component_foo = _resolveComponent(\\"foo\\")
 | 
					                    _push(\`<!--[--><!--root--><div\${_ssrRenderAttrs(_attrs)}></div><!--]-->\`)
 | 
				
			||||||
 | 
					                  }"
 | 
				
			||||||
 | 
					              `)
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          _push(_ssrRenderComponent(_component_foo, _attrs, null, _parent))
 | 
					      test('should not inject attrs if not root', () => {
 | 
				
			||||||
        }"
 | 
					        expect(compile(`<div/><transition><div/></transition>`).code)
 | 
				
			||||||
      `)
 | 
					          .toMatchInlineSnapshot(`
 | 
				
			||||||
 | 
					                  "
 | 
				
			||||||
 | 
					                  return function ssrRender(_ctx, _push, _parent, _attrs) {
 | 
				
			||||||
 | 
					                    _push(\`<!--[--><div></div><div></div><!--]-->\`)
 | 
				
			||||||
 | 
					                  }"
 | 
				
			||||||
 | 
					              `)
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // #5352
 | 
				
			||||||
 | 
					      test('should push marker string if is slot root', () => {
 | 
				
			||||||
 | 
					        expect(
 | 
				
			||||||
 | 
					          compile(`<foo><transition><div v-if="false"/></transition></foo>`)
 | 
				
			||||||
 | 
					            .code
 | 
				
			||||||
 | 
					        ).toMatchInlineSnapshot(`
 | 
				
			||||||
 | 
					          "const { resolveComponent: _resolveComponent, withCtx: _withCtx, openBlock: _openBlock, createBlock: _createBlock, createCommentVNode: _createCommentVNode, Transition: _Transition, createVNode: _createVNode } = require(\\"vue\\")
 | 
				
			||||||
 | 
					          const { ssrRenderComponent: _ssrRenderComponent } = require(\\"vue/server-renderer\\")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          return function ssrRender(_ctx, _push, _parent, _attrs) {
 | 
				
			||||||
 | 
					            const _component_foo = _resolveComponent(\\"foo\\")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            _push(_ssrRenderComponent(_component_foo, _attrs, {
 | 
				
			||||||
 | 
					              default: _withCtx((_, _push, _parent, _scopeId) => {
 | 
				
			||||||
 | 
					                if (_push) {
 | 
				
			||||||
 | 
					                  _push(\`\`)
 | 
				
			||||||
 | 
					                  if (false) {
 | 
				
			||||||
 | 
					                    _push(\`<div\${_scopeId}></div>\`)
 | 
				
			||||||
 | 
					                  } else {
 | 
				
			||||||
 | 
					                    _push(\`<!---->\`)
 | 
				
			||||||
 | 
					                  }
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                  return [
 | 
				
			||||||
 | 
					                    _createVNode(_Transition, null, {
 | 
				
			||||||
 | 
					                      default: _withCtx(() => [
 | 
				
			||||||
 | 
					                        false
 | 
				
			||||||
 | 
					                          ? (_openBlock(), _createBlock(\\"div\\", { key: 0 }))
 | 
				
			||||||
 | 
					                          : _createCommentVNode(\\"v-if\\", true)
 | 
				
			||||||
 | 
					                      ]),
 | 
				
			||||||
 | 
					                      _: 1 /* STABLE */
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
 | 
					                  ]
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					              }),
 | 
				
			||||||
 | 
					              _: 1 /* STABLE */
 | 
				
			||||||
 | 
					            }, _parent))
 | 
				
			||||||
 | 
					          }"
 | 
				
			||||||
 | 
					        `)
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // transition-group should flatten and concat its children fragments into
 | 
					    // transition-group should flatten and concat its children fragments into
 | 
				
			||||||
 | 
				
			|||||||
@ -51,7 +51,7 @@ export function ssrCodegenTransform(ast: RootNode, options: CompilerOptions) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  const isFragment =
 | 
					  const isFragment =
 | 
				
			||||||
    ast.children.length > 1 && ast.children.some(c => !isText(c))
 | 
					    ast.children.length > 1 && ast.children.some(c => !isText(c))
 | 
				
			||||||
  processChildren(ast.children, context, isFragment)
 | 
					  processChildren(ast, context, isFragment)
 | 
				
			||||||
  ast.codegenNode = createBlockStatement(context.body)
 | 
					  ast.codegenNode = createBlockStatement(context.body)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Finalize helpers.
 | 
					  // Finalize helpers.
 | 
				
			||||||
@ -125,8 +125,12 @@ function createChildContext(
 | 
				
			|||||||
  )
 | 
					  )
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface Container {
 | 
				
			||||||
 | 
					  children: TemplateChildNode[]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function processChildren(
 | 
					export function processChildren(
 | 
				
			||||||
  children: TemplateChildNode[],
 | 
					  parent: Container,
 | 
				
			||||||
  context: SSRTransformContext,
 | 
					  context: SSRTransformContext,
 | 
				
			||||||
  asFragment = false,
 | 
					  asFragment = false,
 | 
				
			||||||
  disableNestedFragments = false
 | 
					  disableNestedFragments = false
 | 
				
			||||||
@ -134,6 +138,7 @@ export function processChildren(
 | 
				
			|||||||
  if (asFragment) {
 | 
					  if (asFragment) {
 | 
				
			||||||
    context.pushStringPart(`<!--[-->`)
 | 
					    context.pushStringPart(`<!--[-->`)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  const { children } = parent
 | 
				
			||||||
  for (let i = 0; i < children.length; i++) {
 | 
					  for (let i = 0; i < children.length; i++) {
 | 
				
			||||||
    const child = children[i]
 | 
					    const child = children[i]
 | 
				
			||||||
    switch (child.type) {
 | 
					    switch (child.type) {
 | 
				
			||||||
@ -143,7 +148,7 @@ export function processChildren(
 | 
				
			|||||||
            ssrProcessElement(child, context)
 | 
					            ssrProcessElement(child, context)
 | 
				
			||||||
            break
 | 
					            break
 | 
				
			||||||
          case ElementTypes.COMPONENT:
 | 
					          case ElementTypes.COMPONENT:
 | 
				
			||||||
            ssrProcessComponent(child, context)
 | 
					            ssrProcessComponent(child, context, parent)
 | 
				
			||||||
            break
 | 
					            break
 | 
				
			||||||
          case ElementTypes.SLOT:
 | 
					          case ElementTypes.SLOT:
 | 
				
			||||||
            ssrProcessSlotOutlet(child, context)
 | 
					            ssrProcessSlotOutlet(child, context)
 | 
				
			||||||
@ -208,12 +213,12 @@ export function processChildren(
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function processChildrenAsStatement(
 | 
					export function processChildrenAsStatement(
 | 
				
			||||||
  children: TemplateChildNode[],
 | 
					  parent: Container,
 | 
				
			||||||
  parentContext: SSRTransformContext,
 | 
					  parentContext: SSRTransformContext,
 | 
				
			||||||
  asFragment = false,
 | 
					  asFragment = false,
 | 
				
			||||||
  withSlotScopeId = parentContext.withSlotScopeId
 | 
					  withSlotScopeId = parentContext.withSlotScopeId
 | 
				
			||||||
): BlockStatement {
 | 
					): BlockStatement {
 | 
				
			||||||
  const childContext = createChildContext(parentContext, withSlotScopeId)
 | 
					  const childContext = createChildContext(parentContext, withSlotScopeId)
 | 
				
			||||||
  processChildren(children, childContext, asFragment)
 | 
					  processChildren(parent, childContext, asFragment)
 | 
				
			||||||
  return createBlockStatement(childContext.body)
 | 
					  return createBlockStatement(childContext.body)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -58,7 +58,10 @@ import { buildSSRProps } from './ssrTransformElement'
 | 
				
			|||||||
// pass and complete them in the 2nd pass.
 | 
					// pass and complete them in the 2nd pass.
 | 
				
			||||||
const wipMap = new WeakMap<ComponentNode, WIPSlotEntry[]>()
 | 
					const wipMap = new WeakMap<ComponentNode, WIPSlotEntry[]>()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const WIP_SLOT = Symbol()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface WIPSlotEntry {
 | 
					interface WIPSlotEntry {
 | 
				
			||||||
 | 
					  type: typeof WIP_SLOT
 | 
				
			||||||
  fn: FunctionExpression
 | 
					  fn: FunctionExpression
 | 
				
			||||||
  children: TemplateChildNode[]
 | 
					  children: TemplateChildNode[]
 | 
				
			||||||
  vnodeBranch: ReturnStatement
 | 
					  vnodeBranch: ReturnStatement
 | 
				
			||||||
@ -143,6 +146,7 @@ export const ssrTransformComponent: NodeTransform = (node, context) => {
 | 
				
			|||||||
        loc
 | 
					        loc
 | 
				
			||||||
      )
 | 
					      )
 | 
				
			||||||
      wipEntries.push({
 | 
					      wipEntries.push({
 | 
				
			||||||
 | 
					        type: WIP_SLOT,
 | 
				
			||||||
        fn,
 | 
					        fn,
 | 
				
			||||||
        children,
 | 
					        children,
 | 
				
			||||||
        // also collect the corresponding vnode branch built earlier
 | 
					        // also collect the corresponding vnode branch built earlier
 | 
				
			||||||
@ -182,7 +186,8 @@ export const ssrTransformComponent: NodeTransform = (node, context) => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
export function ssrProcessComponent(
 | 
					export function ssrProcessComponent(
 | 
				
			||||||
  node: ComponentNode,
 | 
					  node: ComponentNode,
 | 
				
			||||||
  context: SSRTransformContext
 | 
					  context: SSRTransformContext,
 | 
				
			||||||
 | 
					  parent: { children: TemplateChildNode[] }
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
  const component = componentTypeMap.get(node)!
 | 
					  const component = componentTypeMap.get(node)!
 | 
				
			||||||
  if (!node.ssrCodegenNode) {
 | 
					  if (!node.ssrCodegenNode) {
 | 
				
			||||||
@ -196,13 +201,19 @@ export function ssrProcessComponent(
 | 
				
			|||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      // real fall-through: Transition / KeepAlive
 | 
					      // real fall-through: Transition / KeepAlive
 | 
				
			||||||
      // just render its children.
 | 
					      // just render its children.
 | 
				
			||||||
      processChildren(node.children, context)
 | 
					      // #5352: if is at root level of a slot, push an empty string.
 | 
				
			||||||
 | 
					      // this does not affect the final output, but avoids all-comment slot
 | 
				
			||||||
 | 
					      // content of being treated as empty by ssrRenderSlot().
 | 
				
			||||||
 | 
					      if ((parent as WIPSlotEntry).type === WIP_SLOT) {
 | 
				
			||||||
 | 
					        context.pushStringPart(``)
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      processChildren(node, context)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    // finish up slot function expressions from the 1st pass.
 | 
					    // finish up slot function expressions from the 1st pass.
 | 
				
			||||||
    const wipEntries = wipMap.get(node) || []
 | 
					    const wipEntries = wipMap.get(node) || []
 | 
				
			||||||
    for (let i = 0; i < wipEntries.length; i++) {
 | 
					    for (let i = 0; i < wipEntries.length; i++) {
 | 
				
			||||||
      const { fn, children, vnodeBranch } = wipEntries[i]
 | 
					      const { fn, vnodeBranch } = wipEntries[i]
 | 
				
			||||||
      // For each slot, we generate two branches: one SSR-optimized branch and
 | 
					      // For each slot, we generate two branches: one SSR-optimized branch and
 | 
				
			||||||
      // one normal vnode-based branch. The branches are taken based on the
 | 
					      // one normal vnode-based branch. The branches are taken based on the
 | 
				
			||||||
      // presence of the 2nd `_push` argument (which is only present if the slot
 | 
					      // presence of the 2nd `_push` argument (which is only present if the slot
 | 
				
			||||||
@ -210,7 +221,7 @@ export function ssrProcessComponent(
 | 
				
			|||||||
      fn.body = createIfStatement(
 | 
					      fn.body = createIfStatement(
 | 
				
			||||||
        createSimpleExpression(`_push`, false),
 | 
					        createSimpleExpression(`_push`, false),
 | 
				
			||||||
        processChildrenAsStatement(
 | 
					        processChildrenAsStatement(
 | 
				
			||||||
          children,
 | 
					          wipEntries[i],
 | 
				
			||||||
          context,
 | 
					          context,
 | 
				
			||||||
          false,
 | 
					          false,
 | 
				
			||||||
          true /* withSlotScopeId */
 | 
					          true /* withSlotScopeId */
 | 
				
			||||||
 | 
				
			|||||||
@ -428,7 +428,7 @@ export function ssrProcessElement(
 | 
				
			|||||||
  if (rawChildren) {
 | 
					  if (rawChildren) {
 | 
				
			||||||
    context.pushStringPart(rawChildren)
 | 
					    context.pushStringPart(rawChildren)
 | 
				
			||||||
  } else if (node.children.length) {
 | 
					  } else if (node.children.length) {
 | 
				
			||||||
    processChildren(node.children, context)
 | 
					    processChildren(node, context)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (!isVoidTag(node.tag)) {
 | 
					  if (!isVoidTag(node.tag)) {
 | 
				
			||||||
 | 
				
			|||||||
@ -65,7 +65,7 @@ export function ssrProcessSlotOutlet(
 | 
				
			|||||||
  // has fallback content
 | 
					  // has fallback content
 | 
				
			||||||
  if (node.children.length) {
 | 
					  if (node.children.length) {
 | 
				
			||||||
    const fallbackRenderFn = createFunctionExpression([])
 | 
					    const fallbackRenderFn = createFunctionExpression([])
 | 
				
			||||||
    fallbackRenderFn.body = processChildrenAsStatement(node.children, context)
 | 
					    fallbackRenderFn.body = processChildrenAsStatement(node, context)
 | 
				
			||||||
    // _renderSlot(slots, name, props, fallback, ...)
 | 
					    // _renderSlot(slots, name, props, fallback, ...)
 | 
				
			||||||
    renderCall.arguments[3] = fallbackRenderFn
 | 
					    renderCall.arguments[3] = fallbackRenderFn
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
				
			|||||||
@ -66,8 +66,8 @@ export function ssrProcessSuspense(
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
  const { slotsExp, wipSlots } = wipEntry
 | 
					  const { slotsExp, wipSlots } = wipEntry
 | 
				
			||||||
  for (let i = 0; i < wipSlots.length; i++) {
 | 
					  for (let i = 0; i < wipSlots.length; i++) {
 | 
				
			||||||
    const { fn, children } = wipSlots[i]
 | 
					    const slot = wipSlots[i]
 | 
				
			||||||
    fn.body = processChildrenAsStatement(children, context)
 | 
					    slot.fn.body = processChildrenAsStatement(slot, context)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  // _push(ssrRenderSuspense(slots))
 | 
					  // _push(ssrRenderSuspense(slots))
 | 
				
			||||||
  context.pushStatement(
 | 
					  context.pushStatement(
 | 
				
			||||||
 | 
				
			|||||||
@ -58,7 +58,7 @@ export function ssrProcessTeleport(
 | 
				
			|||||||
    false, // isSlot
 | 
					    false, // isSlot
 | 
				
			||||||
    node.loc
 | 
					    node.loc
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
  contentRenderFn.body = processChildrenAsStatement(node.children, context)
 | 
					  contentRenderFn.body = processChildrenAsStatement(node, context)
 | 
				
			||||||
  context.pushStatement(
 | 
					  context.pushStatement(
 | 
				
			||||||
    createCallExpression(context.helper(SSR_RENDER_TELEPORT), [
 | 
					    createCallExpression(context.helper(SSR_RENDER_TELEPORT), [
 | 
				
			||||||
      `_push`,
 | 
					      `_push`,
 | 
				
			||||||
 | 
				
			|||||||
@ -14,7 +14,7 @@ export function ssrProcessTransitionGroup(
 | 
				
			|||||||
      context.pushStringPart(`>`)
 | 
					      context.pushStringPart(`>`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      processChildren(
 | 
					      processChildren(
 | 
				
			||||||
        node.children,
 | 
					        node,
 | 
				
			||||||
        context,
 | 
					        context,
 | 
				
			||||||
        false,
 | 
					        false,
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
@ -31,11 +31,11 @@ export function ssrProcessTransitionGroup(
 | 
				
			|||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      // static tag
 | 
					      // static tag
 | 
				
			||||||
      context.pushStringPart(`<${tag.value!.content}>`)
 | 
					      context.pushStringPart(`<${tag.value!.content}>`)
 | 
				
			||||||
      processChildren(node.children, context, false, true)
 | 
					      processChildren(node, context, false, true)
 | 
				
			||||||
      context.pushStringPart(`</${tag.value!.content}>`)
 | 
					      context.pushStringPart(`</${tag.value!.content}>`)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    // fragment
 | 
					    // fragment
 | 
				
			||||||
    processChildren(node.children, context, true, true)
 | 
					    processChildren(node, context, true, true)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -33,7 +33,7 @@ export function ssrProcessFor(
 | 
				
			|||||||
    createForLoopParams(node.parseResult)
 | 
					    createForLoopParams(node.parseResult)
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
  renderLoop.body = processChildrenAsStatement(
 | 
					  renderLoop.body = processChildrenAsStatement(
 | 
				
			||||||
    node.children,
 | 
					    node,
 | 
				
			||||||
    context,
 | 
					    context,
 | 
				
			||||||
    needFragmentWrapper
 | 
					    needFragmentWrapper
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
 | 
				
			|||||||
@ -72,5 +72,5 @@ function processIfBranch(
 | 
				
			|||||||
    (children.length !== 1 || children[0].type !== NodeTypes.ELEMENT) &&
 | 
					    (children.length !== 1 || children[0].type !== NodeTypes.ELEMENT) &&
 | 
				
			||||||
    // optimize away nested fragments when the only child is a ForNode
 | 
					    // optimize away nested fragments when the only child is a ForNode
 | 
				
			||||||
    !(children.length === 1 && children[0].type === NodeTypes.FOR)
 | 
					    !(children.length === 1 && children[0].type === NodeTypes.FOR)
 | 
				
			||||||
  return processChildrenAsStatement(children, context, needFragmentWrapper)
 | 
					  return processChildrenAsStatement(branch, context, needFragmentWrapper)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -84,5 +84,9 @@ export function ssrRenderSlotInner(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const commentRE = /<!--.*?-->/g
 | 
					const commentRE = /<!--.*?-->/g
 | 
				
			||||||
function isComment(item: SSRBufferItem) {
 | 
					function isComment(item: SSRBufferItem) {
 | 
				
			||||||
  return typeof item === 'string' && !item.replace(commentRE, '').trim()
 | 
					  return (
 | 
				
			||||||
 | 
					    typeof item === 'string' &&
 | 
				
			||||||
 | 
					    commentRE.test(item) &&
 | 
				
			||||||
 | 
					    !item.replace(commentRE, '').trim()
 | 
				
			||||||
 | 
					  )
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user