'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

var compilerDom = require('@vue/compiler-dom');
var shared = require('@vue/shared');

const SSR_INTERPOLATE = Symbol(`ssrInterpolate`);
const SSR_RENDER_VNODE = Symbol(`ssrRenderVNode`);
const SSR_RENDER_COMPONENT = Symbol(`ssrRenderComponent`);
const SSR_RENDER_SLOT = Symbol(`ssrRenderSlot`);
const SSR_RENDER_SLOT_INNER = Symbol(`ssrRenderSlotInner`);
const SSR_RENDER_CLASS = Symbol(`ssrRenderClass`);
const SSR_RENDER_STYLE = Symbol(`ssrRenderStyle`);
const SSR_RENDER_ATTRS = Symbol(`ssrRenderAttrs`);
const SSR_RENDER_ATTR = Symbol(`ssrRenderAttr`);
const SSR_RENDER_DYNAMIC_ATTR = Symbol(`ssrRenderDynamicAttr`);
const SSR_RENDER_LIST = Symbol(`ssrRenderList`);
const SSR_INCLUDE_BOOLEAN_ATTR = Symbol(`ssrIncludeBooleanAttr`);
const SSR_LOOSE_EQUAL = Symbol(`ssrLooseEqual`);
const SSR_LOOSE_CONTAIN = Symbol(`ssrLooseContain`);
const SSR_RENDER_DYNAMIC_MODEL = Symbol(`ssrRenderDynamicModel`);
const SSR_GET_DYNAMIC_MODEL_PROPS = Symbol(`ssrGetDynamicModelProps`);
const SSR_RENDER_TELEPORT = Symbol(`ssrRenderTeleport`);
const SSR_RENDER_SUSPENSE = Symbol(`ssrRenderSuspense`);
const SSR_GET_DIRECTIVE_PROPS = Symbol(`ssrGetDirectiveProps`);
const ssrHelpers = {
  [SSR_INTERPOLATE]: `ssrInterpolate`,
  [SSR_RENDER_VNODE]: `ssrRenderVNode`,
  [SSR_RENDER_COMPONENT]: `ssrRenderComponent`,
  [SSR_RENDER_SLOT]: `ssrRenderSlot`,
  [SSR_RENDER_SLOT_INNER]: `ssrRenderSlotInner`,
  [SSR_RENDER_CLASS]: `ssrRenderClass`,
  [SSR_RENDER_STYLE]: `ssrRenderStyle`,
  [SSR_RENDER_ATTRS]: `ssrRenderAttrs`,
  [SSR_RENDER_ATTR]: `ssrRenderAttr`,
  [SSR_RENDER_DYNAMIC_ATTR]: `ssrRenderDynamicAttr`,
  [SSR_RENDER_LIST]: `ssrRenderList`,
  [SSR_INCLUDE_BOOLEAN_ATTR]: `ssrIncludeBooleanAttr`,
  [SSR_LOOSE_EQUAL]: `ssrLooseEqual`,
  [SSR_LOOSE_CONTAIN]: `ssrLooseContain`,
  [SSR_RENDER_DYNAMIC_MODEL]: `ssrRenderDynamicModel`,
  [SSR_GET_DYNAMIC_MODEL_PROPS]: `ssrGetDynamicModelProps`,
  [SSR_RENDER_TELEPORT]: `ssrRenderTeleport`,
  [SSR_RENDER_SUSPENSE]: `ssrRenderSuspense`,
  [SSR_GET_DIRECTIVE_PROPS]: `ssrGetDirectiveProps`
};
compilerDom.registerRuntimeHelpers(ssrHelpers);

const ssrTransformIf = compilerDom.createStructuralDirectiveTransform(
  /^(if|else|else-if)$/,
  compilerDom.processIf
);
function ssrProcessIf(node, context, disableNestedFragments = false) {
  const [rootBranch] = node.branches;
  const ifStatement = compilerDom.createIfStatement(
    rootBranch.condition,
    processIfBranch(rootBranch, context, disableNestedFragments)
  );
  context.pushStatement(ifStatement);
  let currentIf = ifStatement;
  for (let i = 1; i < node.branches.length; i++) {
    const branch = node.branches[i];
    const branchBlockStatement = processIfBranch(
      branch,
      context,
      disableNestedFragments
    );
    if (branch.condition) {
      currentIf = currentIf.alternate = compilerDom.createIfStatement(
        branch.condition,
        branchBlockStatement
      );
    } else {
      currentIf.alternate = branchBlockStatement;
    }
  }
  if (!currentIf.alternate) {
    currentIf.alternate = compilerDom.createBlockStatement([
      compilerDom.createCallExpression(`_push`, ["`<!---->`"])
    ]);
  }
}
function processIfBranch(branch, context, disableNestedFragments = false) {
  const { children } = branch;
  const needFragmentWrapper = !disableNestedFragments && (children.length !== 1 || children[0].type !== 1) && // optimize away nested fragments when the only child is a ForNode
  !(children.length === 1 && children[0].type === 11);
  return processChildrenAsStatement(branch, context, needFragmentWrapper);
}

const ssrTransformFor = compilerDom.createStructuralDirectiveTransform(
  "for",
  compilerDom.processFor
);
function ssrProcessFor(node, context, disableNestedFragments = false) {
  const needFragmentWrapper = !disableNestedFragments && (node.children.length !== 1 || node.children[0].type !== 1);
  const renderLoop = compilerDom.createFunctionExpression(
    compilerDom.createForLoopParams(node.parseResult)
  );
  renderLoop.body = processChildrenAsStatement(
    node,
    context,
    needFragmentWrapper
  );
  if (!disableNestedFragments) {
    context.pushStringPart(`<!--[-->`);
  }
  context.pushStatement(
    compilerDom.createCallExpression(context.helper(SSR_RENDER_LIST), [
      node.source,
      renderLoop
    ])
  );
  if (!disableNestedFragments) {
    context.pushStringPart(`<!--]-->`);
  }
}

const ssrTransformSlotOutlet = (node, context) => {
  if (compilerDom.isSlotOutlet(node)) {
    const { slotName, slotProps } = compilerDom.processSlotOutlet(node, context);
    const args = [
      `_ctx.$slots`,
      slotName,
      slotProps || `{}`,
      // fallback content placeholder. will be replaced in the process phase
      `null`,
      `_push`,
      `_parent`
    ];
    if (context.scopeId && context.slotted !== false) {
      args.push(`"${context.scopeId}-s"`);
    }
    let method = SSR_RENDER_SLOT;
    const parent = context.parent;
    if (parent && parent.type === 1 && parent.tagType === 1 && compilerDom.resolveComponentType(parent, context, true) === compilerDom.TRANSITION && parent.children.filter((c) => c.type === 1).length === 1) {
      method = SSR_RENDER_SLOT_INNER;
      if (!(context.scopeId && context.slotted !== false)) {
        args.push("null");
      }
      args.push("true");
    }
    node.ssrCodegenNode = compilerDom.createCallExpression(context.helper(method), args);
  }
};
function ssrProcessSlotOutlet(node, context) {
  const renderCall = node.ssrCodegenNode;
  if (node.children.length) {
    const fallbackRenderFn = compilerDom.createFunctionExpression([]);
    fallbackRenderFn.body = processChildrenAsStatement(node, context);
    renderCall.arguments[3] = fallbackRenderFn;
  }
  if (context.withSlotScopeId) {
    const slotScopeId = renderCall.arguments[6];
    renderCall.arguments[6] = slotScopeId ? `${slotScopeId} + _scopeId` : `_scopeId`;
  }
  context.pushStatement(node.ssrCodegenNode);
}

function createSSRCompilerError(code, loc) {
  return compilerDom.createCompilerError(code, loc, SSRErrorMessages);
}
const SSRErrorMessages = {
  [65]: `Unsafe attribute name for SSR.`,
  [66]: `Missing the 'to' prop on teleport element.`,
  [67]: `Invalid AST node during SSR transform.`
};

function ssrProcessTeleport(node, context) {
  const targetProp = compilerDom.findProp(node, "to");
  if (!targetProp) {
    context.onError(
      createSSRCompilerError(66, node.loc)
    );
    return;
  }
  let target;
  if (targetProp.type === 6) {
    target = targetProp.value && compilerDom.createSimpleExpression(targetProp.value.content, true);
  } else {
    target = targetProp.exp;
  }
  if (!target) {
    context.onError(
      createSSRCompilerError(
        66,
        targetProp.loc
      )
    );
    return;
  }
  const disabledProp = compilerDom.findProp(
    node,
    "disabled",
    false,
    true
    /* allow empty */
  );
  const disabled = disabledProp ? disabledProp.type === 6 ? `true` : disabledProp.exp || `false` : `false`;
  const contentRenderFn = compilerDom.createFunctionExpression(
    [`_push`],
    void 0,
    // Body is added later
    true,
    // newline
    false,
    // isSlot
    node.loc
  );
  contentRenderFn.body = processChildrenAsStatement(node, context);
  context.pushStatement(
    compilerDom.createCallExpression(context.helper(SSR_RENDER_TELEPORT), [
      `_push`,
      contentRenderFn,
      target,
      disabled,
      `_parent`
    ])
  );
}

const wipMap$2 = /* @__PURE__ */ new WeakMap();
function ssrTransformSuspense(node, context) {
  return () => {
    if (node.children.length) {
      const wipEntry = {
        slotsExp: null,
        // to be immediately set
        wipSlots: []
      };
      wipMap$2.set(node, wipEntry);
      wipEntry.slotsExp = compilerDom.buildSlots(node, context, (_props, children, loc) => {
        const fn = compilerDom.createFunctionExpression(
          [],
          void 0,
          // no return, assign body later
          true,
          // newline
          false,
          // suspense slots are not treated as normal slots
          loc
        );
        wipEntry.wipSlots.push({
          fn,
          children
        });
        return fn;
      }).slots;
    }
  };
}
function ssrProcessSuspense(node, context) {
  const wipEntry = wipMap$2.get(node);
  if (!wipEntry) {
    return;
  }
  const { slotsExp, wipSlots } = wipEntry;
  for (let i = 0; i < wipSlots.length; i++) {
    const slot = wipSlots[i];
    slot.fn.body = processChildrenAsStatement(slot, context);
  }
  context.pushStatement(
    compilerDom.createCallExpression(context.helper(SSR_RENDER_SUSPENSE), [
      `_push`,
      slotsExp
    ])
  );
}

const rawChildrenMap = /* @__PURE__ */ new WeakMap();
const ssrTransformElement = (node, context) => {
  if (node.type !== 1 || node.tagType !== 0) {
    return;
  }
  return function ssrPostTransformElement() {
    const openTag = [`<${node.tag}`];
    const needTagForRuntime = node.tag === "textarea" || node.tag.indexOf("-") > 0;
    const hasDynamicVBind = compilerDom.hasDynamicKeyVBind(node);
    const hasCustomDir = node.props.some(
      (p) => p.type === 7 && !shared.isBuiltInDirective(p.name)
    );
    const needMergeProps = hasDynamicVBind || hasCustomDir;
    if (needMergeProps) {
      const { props, directives } = compilerDom.buildProps(
        node,
        context,
        node.props,
        false,
        false,
        true
        /* ssr */
      );
      if (props || directives.length) {
        const mergedProps = buildSSRProps(props, directives, context);
        const propsExp = compilerDom.createCallExpression(
          context.helper(SSR_RENDER_ATTRS),
          [mergedProps]
        );
        if (node.tag === "textarea") {
          const existingText = node.children[0];
          if (!existingText || existingText.type !== 5) {
            const tempId = `_temp${context.temps++}`;
            propsExp.arguments = [
              compilerDom.createAssignmentExpression(
                compilerDom.createSimpleExpression(tempId, false),
                mergedProps
              )
            ];
            rawChildrenMap.set(
              node,
              compilerDom.createCallExpression(context.helper(SSR_INTERPOLATE), [
                compilerDom.createConditionalExpression(
                  compilerDom.createSimpleExpression(`"value" in ${tempId}`, false),
                  compilerDom.createSimpleExpression(`${tempId}.value`, false),
                  compilerDom.createSimpleExpression(
                    existingText ? existingText.content : ``,
                    true
                  ),
                  false
                )
              ])
            );
          }
        } else if (node.tag === "input") {
          const vModel = findVModel(node);
          if (vModel) {
            const tempId = `_temp${context.temps++}`;
            const tempExp = compilerDom.createSimpleExpression(tempId, false);
            propsExp.arguments = [
              compilerDom.createSequenceExpression([
                compilerDom.createAssignmentExpression(tempExp, mergedProps),
                compilerDom.createCallExpression(context.helper(compilerDom.MERGE_PROPS), [
                  tempExp,
                  compilerDom.createCallExpression(
                    context.helper(SSR_GET_DYNAMIC_MODEL_PROPS),
                    [
                      tempExp,
                      // existing props
                      vModel.exp
                      // model
                    ]
                  )
                ])
              ])
            ];
          }
        }
        if (needTagForRuntime) {
          propsExp.arguments.push(`"${node.tag}"`);
        }
        openTag.push(propsExp);
      }
    }
    let dynamicClassBinding = void 0;
    let staticClassBinding = void 0;
    let dynamicStyleBinding = void 0;
    for (let i = 0; i < node.props.length; i++) {
      const prop = node.props[i];
      if (node.tag === "input" && isTrueFalseValue(prop)) {
        continue;
      }
      if (prop.type === 7) {
        if (prop.name === "html" && prop.exp) {
          rawChildrenMap.set(node, prop.exp);
        } else if (prop.name === "text" && prop.exp) {
          node.children = [compilerDom.createInterpolation(prop.exp, prop.loc)];
        } else if (prop.name === "slot") {
          context.onError(
            compilerDom.createCompilerError(40, prop.loc)
          );
        } else if (isTextareaWithValue(node, prop) && prop.exp) {
          if (!needMergeProps) {
            node.children = [compilerDom.createInterpolation(prop.exp, prop.loc)];
          }
        } else if (!needMergeProps && prop.name !== "on") {
          const directiveTransform = context.directiveTransforms[prop.name];
          if (directiveTransform) {
            const { props, ssrTagParts } = directiveTransform(
              prop,
              node,
              context
            );
            if (ssrTagParts) {
              openTag.push(...ssrTagParts);
            }
            for (let j = 0; j < props.length; j++) {
              const { key, value } = props[j];
              if (compilerDom.isStaticExp(key)) {
                let attrName = key.content;
                if (attrName === "key" || attrName === "ref") {
                  continue;
                }
                if (attrName === "class") {
                  openTag.push(
                    ` class="`,
                    dynamicClassBinding = compilerDom.createCallExpression(
                      context.helper(SSR_RENDER_CLASS),
                      [value]
                    ),
                    `"`
                  );
                } else if (attrName === "style") {
                  if (dynamicStyleBinding) {
                    mergeCall(dynamicStyleBinding, value);
                  } else {
                    openTag.push(
                      ` style="`,
                      dynamicStyleBinding = compilerDom.createCallExpression(
                        context.helper(SSR_RENDER_STYLE),
                        [value]
                      ),
                      `"`
                    );
                  }
                } else {
                  attrName = node.tag.indexOf("-") > 0 ? attrName : shared.propsToAttrMap[attrName] || attrName.toLowerCase();
                  if (shared.isBooleanAttr(attrName)) {
                    openTag.push(
                      compilerDom.createConditionalExpression(
                        compilerDom.createCallExpression(
                          context.helper(SSR_INCLUDE_BOOLEAN_ATTR),
                          [value]
                        ),
                        compilerDom.createSimpleExpression(" " + attrName, true),
                        compilerDom.createSimpleExpression("", true),
                        false
                        /* no newline */
                      )
                    );
                  } else if (shared.isSSRSafeAttrName(attrName)) {
                    openTag.push(
                      compilerDom.createCallExpression(context.helper(SSR_RENDER_ATTR), [
                        key,
                        value
                      ])
                    );
                  } else {
                    context.onError(
                      createSSRCompilerError(
                        65,
                        key.loc
                      )
                    );
                  }
                }
              } else {
                const args = [key, value];
                if (needTagForRuntime) {
                  args.push(`"${node.tag}"`);
                }
                openTag.push(
                  compilerDom.createCallExpression(
                    context.helper(SSR_RENDER_DYNAMIC_ATTR),
                    args
                  )
                );
              }
            }
          }
        }
      } else {
        if (node.tag === "textarea" && prop.name === "value" && prop.value) {
          rawChildrenMap.set(node, shared.escapeHtml(prop.value.content));
        } else if (!needMergeProps) {
          if (prop.name === "key" || prop.name === "ref") {
            continue;
          }
          if (prop.name === "class" && prop.value) {
            staticClassBinding = JSON.stringify(prop.value.content);
          }
          openTag.push(
            ` ${prop.name}` + (prop.value ? `="${shared.escapeHtml(prop.value.content)}"` : ``)
          );
        }
      }
    }
    if (dynamicClassBinding && staticClassBinding) {
      mergeCall(dynamicClassBinding, staticClassBinding);
      removeStaticBinding(openTag, "class");
    }
    if (context.scopeId) {
      openTag.push(` ${context.scopeId}`);
    }
    node.ssrCodegenNode = compilerDom.createTemplateLiteral(openTag);
  };
};
function buildSSRProps(props, directives, context) {
  let mergePropsArgs = [];
  if (props) {
    if (props.type === 14) {
      mergePropsArgs = props.arguments;
    } else {
      mergePropsArgs.push(props);
    }
  }
  if (directives.length) {
    for (const dir of directives) {
      mergePropsArgs.push(
        compilerDom.createCallExpression(context.helper(SSR_GET_DIRECTIVE_PROPS), [
          `_ctx`,
          ...compilerDom.buildDirectiveArgs(dir, context).elements
        ])
      );
    }
  }
  return mergePropsArgs.length > 1 ? compilerDom.createCallExpression(context.helper(compilerDom.MERGE_PROPS), mergePropsArgs) : mergePropsArgs[0];
}
function isTrueFalseValue(prop) {
  if (prop.type === 7) {
    return prop.name === "bind" && prop.arg && compilerDom.isStaticExp(prop.arg) && (prop.arg.content === "true-value" || prop.arg.content === "false-value");
  } else {
    return prop.name === "true-value" || prop.name === "false-value";
  }
}
function isTextareaWithValue(node, prop) {
  return !!(node.tag === "textarea" && prop.name === "bind" && compilerDom.isStaticArgOf(prop.arg, "value"));
}
function mergeCall(call, arg) {
  const existing = call.arguments[0];
  if (existing.type === 17) {
    existing.elements.push(arg);
  } else {
    call.arguments[0] = compilerDom.createArrayExpression([existing, arg]);
  }
}
function removeStaticBinding(tag, binding) {
  const regExp = new RegExp(`^ ${binding}=".+"$`);
  const i = tag.findIndex((e) => typeof e === "string" && regExp.test(e));
  if (i > -1) {
    tag.splice(i, 1);
  }
}
function findVModel(node) {
  return node.props.find(
    (p) => p.type === 7 && p.name === "model" && p.exp
  );
}
function ssrProcessElement(node, context) {
  const isVoidTag = context.options.isVoidTag || shared.NO;
  const elementsToAdd = node.ssrCodegenNode.elements;
  for (let j = 0; j < elementsToAdd.length; j++) {
    context.pushStringPart(elementsToAdd[j]);
  }
  if (context.withSlotScopeId) {
    context.pushStringPart(compilerDom.createSimpleExpression(`_scopeId`, false));
  }
  context.pushStringPart(`>`);
  const rawChildren = rawChildrenMap.get(node);
  if (rawChildren) {
    context.pushStringPart(rawChildren);
  } else if (node.children.length) {
    processChildren(node, context);
  }
  if (!isVoidTag(node.tag)) {
    context.pushStringPart(`</${node.tag}>`);
  }
}

const wipMap$1 = /* @__PURE__ */ new WeakMap();
function ssrTransformTransitionGroup(node, context) {
  return () => {
    const tag = compilerDom.findProp(node, "tag");
    if (tag) {
      const otherProps = node.props.filter((p) => p !== tag);
      const { props, directives } = compilerDom.buildProps(
        node,
        context,
        otherProps,
        true,
        false,
        true
        /* ssr (skip event listeners) */
      );
      let propsExp = null;
      if (props || directives.length) {
        propsExp = compilerDom.createCallExpression(context.helper(SSR_RENDER_ATTRS), [
          buildSSRProps(props, directives, context)
        ]);
      }
      wipMap$1.set(node, {
        tag,
        propsExp
      });
    }
  };
}
function ssrProcessTransitionGroup(node, context) {
  const entry = wipMap$1.get(node);
  if (entry) {
    const { tag, propsExp } = entry;
    if (tag.type === 7) {
      context.pushStringPart(`<`);
      context.pushStringPart(tag.exp);
      if (propsExp) {
        context.pushStringPart(propsExp);
      }
      context.pushStringPart(`>`);
      processChildren(
        node,
        context,
        false,
        /**
         * TransitionGroup has the special runtime behavior of flattening and
         * concatenating all children into a single fragment (in order for them to
         * be patched using the same key map) so we need to account for that here
         * by disabling nested fragment wrappers from being generated.
         */
        true
      );
      context.pushStringPart(`</`);
      context.pushStringPart(tag.exp);
      context.pushStringPart(`>`);
    } else {
      context.pushStringPart(`<${tag.value.content}`);
      if (propsExp) {
        context.pushStringPart(propsExp);
      }
      context.pushStringPart(`>`);
      processChildren(node, context, false, true);
      context.pushStringPart(`</${tag.value.content}>`);
    }
  } else {
    processChildren(node, context, true, true);
  }
}

const wipMap = /* @__PURE__ */ new WeakMap();
const WIP_SLOT = Symbol();
const componentTypeMap = /* @__PURE__ */ new WeakMap();
const ssrTransformComponent = (node, context) => {
  if (node.type !== 1 || node.tagType !== 1) {
    return;
  }
  const component = compilerDom.resolveComponentType(
    node,
    context,
    true
    /* ssr */
  );
  const isDynamicComponent = shared.isObject(component) && component.callee === compilerDom.RESOLVE_DYNAMIC_COMPONENT;
  componentTypeMap.set(node, component);
  if (shared.isSymbol(component)) {
    if (component === compilerDom.SUSPENSE) {
      return ssrTransformSuspense(node, context);
    }
    if (component === compilerDom.TRANSITION_GROUP) {
      return ssrTransformTransitionGroup(node, context);
    }
    return;
  }
  const vnodeBranches = [];
  const clonedNode = clone(node);
  return function ssrPostTransformComponent() {
    if (clonedNode.children.length) {
      compilerDom.buildSlots(clonedNode, context, (props, children) => {
        vnodeBranches.push(createVNodeSlotBranch(props, children, context));
        return compilerDom.createFunctionExpression(void 0);
      });
    }
    let propsExp = `null`;
    if (node.props.length) {
      const { props, directives } = compilerDom.buildProps(
        node,
        context,
        void 0,
        true,
        isDynamicComponent
      );
      if (props || directives.length) {
        propsExp = buildSSRProps(props, directives, context);
      }
    }
    const wipEntries = [];
    wipMap.set(node, wipEntries);
    const buildSSRSlotFn = (props, children, loc) => {
      const param0 = props && compilerDom.stringifyExpression(props) || `_`;
      const fn = compilerDom.createFunctionExpression(
        [param0, `_push`, `_parent`, `_scopeId`],
        void 0,
        // no return, assign body later
        true,
        // newline
        true,
        // isSlot
        loc
      );
      wipEntries.push({
        type: WIP_SLOT,
        fn,
        children,
        // also collect the corresponding vnode branch built earlier
        vnodeBranch: vnodeBranches[wipEntries.length]
      });
      return fn;
    };
    const slots = node.children.length ? compilerDom.buildSlots(node, context, buildSSRSlotFn).slots : `null`;
    if (typeof component !== "string") {
      node.ssrCodegenNode = compilerDom.createCallExpression(
        context.helper(SSR_RENDER_VNODE),
        [
          `_push`,
          compilerDom.createCallExpression(context.helper(compilerDom.CREATE_VNODE), [
            component,
            propsExp,
            slots
          ]),
          `_parent`
        ]
      );
    } else {
      node.ssrCodegenNode = compilerDom.createCallExpression(
        context.helper(SSR_RENDER_COMPONENT),
        [component, propsExp, slots, `_parent`]
      );
    }
  };
};
function ssrProcessComponent(node, context, parent) {
  const component = componentTypeMap.get(node);
  if (!node.ssrCodegenNode) {
    if (component === compilerDom.TELEPORT) {
      return ssrProcessTeleport(node, context);
    } else if (component === compilerDom.SUSPENSE) {
      return ssrProcessSuspense(node, context);
    } else if (component === compilerDom.TRANSITION_GROUP) {
      return ssrProcessTransitionGroup(node, context);
    } else {
      if (parent.type === WIP_SLOT) {
        context.pushStringPart(``);
      }
      if (component === compilerDom.TRANSITION) {
        node.children = node.children.filter((c) => c.type !== 3);
      }
      processChildren(node, context);
    }
  } else {
    const wipEntries = wipMap.get(node) || [];
    for (let i = 0; i < wipEntries.length; i++) {
      const { fn, vnodeBranch } = wipEntries[i];
      fn.body = compilerDom.createIfStatement(
        compilerDom.createSimpleExpression(`_push`, false),
        processChildrenAsStatement(
          wipEntries[i],
          context,
          false,
          true
          /* withSlotScopeId */
        ),
        vnodeBranch
      );
    }
    if (context.withSlotScopeId) {
      node.ssrCodegenNode.arguments.push(`_scopeId`);
    }
    if (typeof component === "string") {
      context.pushStatement(
        compilerDom.createCallExpression(`_push`, [node.ssrCodegenNode])
      );
    } else {
      context.pushStatement(node.ssrCodegenNode);
    }
  }
}
const rawOptionsMap = /* @__PURE__ */ new WeakMap();
const [baseNodeTransforms, baseDirectiveTransforms] = compilerDom.getBaseTransformPreset(true);
const vnodeNodeTransforms = [...baseNodeTransforms, ...compilerDom.DOMNodeTransforms];
const vnodeDirectiveTransforms = {
  ...baseDirectiveTransforms,
  ...compilerDom.DOMDirectiveTransforms
};
function createVNodeSlotBranch(props, children, parentContext) {
  const rawOptions = rawOptionsMap.get(parentContext.root);
  const subOptions = {
    ...rawOptions,
    // overwrite with vnode-based transforms
    nodeTransforms: [
      ...vnodeNodeTransforms,
      ...rawOptions.nodeTransforms || []
    ],
    directiveTransforms: {
      ...vnodeDirectiveTransforms,
      ...rawOptions.directiveTransforms || {}
    }
  };
  const wrapperNode = {
    type: 1,
    ns: 0,
    tag: "template",
    tagType: 3,
    isSelfClosing: false,
    // important: provide v-slot="props" on the wrapper for proper
    // scope analysis
    props: [
      {
        type: 7,
        name: "slot",
        exp: props,
        arg: void 0,
        modifiers: [],
        loc: compilerDom.locStub
      }
    ],
    children,
    loc: compilerDom.locStub,
    codegenNode: void 0
  };
  subTransform(wrapperNode, subOptions, parentContext);
  return compilerDom.createReturnStatement(children);
}
function subTransform(node, options, parentContext) {
  const childRoot = compilerDom.createRoot([node]);
  const childContext = compilerDom.createTransformContext(childRoot, options);
  childContext.ssr = false;
  childContext.scopes = { ...parentContext.scopes };
  childContext.identifiers = { ...parentContext.identifiers };
  childContext.imports = parentContext.imports;
  compilerDom.traverseNode(childRoot, childContext);
  ["helpers", "components", "directives"].forEach((key) => {
    childContext[key].forEach((value, helperKey) => {
      if (key === "helpers") {
        const parentCount = parentContext.helpers.get(helperKey);
        if (parentCount === void 0) {
          parentContext.helpers.set(helperKey, value);
        } else {
          parentContext.helpers.set(helperKey, value + parentCount);
        }
      } else {
        parentContext[key].add(value);
      }
    });
  });
}
function clone(v) {
  if (shared.isArray(v)) {
    return v.map(clone);
  } else if (shared.isObject(v)) {
    const res = {};
    for (const key in v) {
      res[key] = clone(v[key]);
    }
    return res;
  } else {
    return v;
  }
}

function ssrCodegenTransform(ast, options) {
  const context = createSSRTransformContext(ast, options);
  if (options.ssrCssVars) {
    const cssContext = compilerDom.createTransformContext(compilerDom.createRoot([]), options);
    const varsExp = compilerDom.processExpression(
      compilerDom.createSimpleExpression(options.ssrCssVars, false),
      cssContext
    );
    context.body.push(
      compilerDom.createCompoundExpression([`const _cssVars = { style: `, varsExp, `}`])
    );
    Array.from(cssContext.helpers.keys()).forEach((helper) => {
      ast.helpers.add(helper);
    });
  }
  const isFragment = ast.children.length > 1 && ast.children.some((c) => !compilerDom.isText(c));
  processChildren(ast, context, isFragment);
  ast.codegenNode = compilerDom.createBlockStatement(context.body);
  ast.ssrHelpers = Array.from(
    /* @__PURE__ */ new Set([
      ...Array.from(ast.helpers).filter((h) => h in ssrHelpers),
      ...context.helpers
    ])
  );
  ast.helpers = new Set(Array.from(ast.helpers).filter((h) => !(h in ssrHelpers)));
}
function createSSRTransformContext(root, options, helpers = /* @__PURE__ */ new Set(), withSlotScopeId = false) {
  const body = [];
  let currentString = null;
  return {
    root,
    options,
    body,
    helpers,
    withSlotScopeId,
    onError: options.onError || ((e) => {
      throw e;
    }),
    helper(name) {
      helpers.add(name);
      return name;
    },
    pushStringPart(part) {
      if (!currentString) {
        const currentCall = compilerDom.createCallExpression(`_push`);
        body.push(currentCall);
        currentString = compilerDom.createTemplateLiteral([]);
        currentCall.arguments.push(currentString);
      }
      const bufferedElements = currentString.elements;
      const lastItem = bufferedElements[bufferedElements.length - 1];
      if (shared.isString(part) && shared.isString(lastItem)) {
        bufferedElements[bufferedElements.length - 1] += part;
      } else {
        bufferedElements.push(part);
      }
    },
    pushStatement(statement) {
      currentString = null;
      body.push(statement);
    }
  };
}
function createChildContext(parent, withSlotScopeId = parent.withSlotScopeId) {
  return createSSRTransformContext(
    parent.root,
    parent.options,
    parent.helpers,
    withSlotScopeId
  );
}
function processChildren(parent, context, asFragment = false, disableNestedFragments = false) {
  if (asFragment) {
    context.pushStringPart(`<!--[-->`);
  }
  const { children } = parent;
  for (let i = 0; i < children.length; i++) {
    const child = children[i];
    switch (child.type) {
      case 1:
        switch (child.tagType) {
          case 0:
            ssrProcessElement(child, context);
            break;
          case 1:
            ssrProcessComponent(child, context, parent);
            break;
          case 2:
            ssrProcessSlotOutlet(child, context);
            break;
          case 3:
            break;
          default:
            context.onError(
              createSSRCompilerError(
                67,
                child.loc
              )
            );
            const exhaustiveCheck2 = child;
            return exhaustiveCheck2;
        }
        break;
      case 2:
        context.pushStringPart(shared.escapeHtml(child.content));
        break;
      case 3:
        context.pushStringPart(`<!--${child.content}-->`);
        break;
      case 5:
        context.pushStringPart(
          compilerDom.createCallExpression(context.helper(SSR_INTERPOLATE), [child.content])
        );
        break;
      case 9:
        ssrProcessIf(child, context, disableNestedFragments);
        break;
      case 11:
        ssrProcessFor(child, context, disableNestedFragments);
        break;
      case 10:
        break;
      case 12:
      case 8:
        break;
      default:
        context.onError(
          createSSRCompilerError(
            67,
            child.loc
          )
        );
        const exhaustiveCheck = child;
        return exhaustiveCheck;
    }
  }
  if (asFragment) {
    context.pushStringPart(`<!--]-->`);
  }
}
function processChildrenAsStatement(parent, parentContext, asFragment = false, withSlotScopeId = parentContext.withSlotScopeId) {
  const childContext = createChildContext(parentContext, withSlotScopeId);
  processChildren(parent, childContext, asFragment);
  return compilerDom.createBlockStatement(childContext.body);
}

const ssrTransformModel = (dir, node, context) => {
  const model = dir.exp;
  function checkDuplicatedValue() {
    const value = compilerDom.findProp(node, "value");
    if (value) {
      context.onError(
        compilerDom.createDOMCompilerError(
          60,
          value.loc
        )
      );
    }
  }
  if (node.tagType === 0) {
    const res = { props: [] };
    const defaultProps = [
      // default value binding for text type inputs
      compilerDom.createObjectProperty(`value`, model)
    ];
    if (node.tag === "input") {
      const type = compilerDom.findProp(node, "type");
      if (type) {
        const value = findValueBinding(node);
        if (type.type === 7) {
          res.ssrTagParts = [
            compilerDom.createCallExpression(context.helper(SSR_RENDER_DYNAMIC_MODEL), [
              type.exp,
              model,
              value
            ])
          ];
        } else if (type.value) {
          switch (type.value.content) {
            case "radio":
              res.props = [
                compilerDom.createObjectProperty(
                  `checked`,
                  compilerDom.createCallExpression(context.helper(SSR_LOOSE_EQUAL), [
                    model,
                    value
                  ])
                )
              ];
              break;
            case "checkbox":
              const trueValueBinding = compilerDom.findProp(node, "true-value");
              if (trueValueBinding) {
                const trueValue = trueValueBinding.type === 6 ? JSON.stringify(trueValueBinding.value.content) : trueValueBinding.exp;
                res.props = [
                  compilerDom.createObjectProperty(
                    `checked`,
                    compilerDom.createCallExpression(context.helper(SSR_LOOSE_EQUAL), [
                      model,
                      trueValue
                    ])
                  )
                ];
              } else {
                res.props = [
                  compilerDom.createObjectProperty(
                    `checked`,
                    compilerDom.createConditionalExpression(
                      compilerDom.createCallExpression(`Array.isArray`, [model]),
                      compilerDom.createCallExpression(context.helper(SSR_LOOSE_CONTAIN), [
                        model,
                        value
                      ]),
                      model
                    )
                  )
                ];
              }
              break;
            case "file":
              context.onError(
                compilerDom.createDOMCompilerError(
                  59,
                  dir.loc
                )
              );
              break;
            default:
              checkDuplicatedValue();
              res.props = defaultProps;
              break;
          }
        }
      } else if (compilerDom.hasDynamicKeyVBind(node)) ; else {
        checkDuplicatedValue();
        res.props = defaultProps;
      }
    } else if (node.tag === "textarea") {
      checkDuplicatedValue();
      node.children = [compilerDom.createInterpolation(model, model.loc)];
    } else if (node.tag === "select") ; else {
      context.onError(
        compilerDom.createDOMCompilerError(
          57,
          dir.loc
        )
      );
    }
    return res;
  } else {
    return compilerDom.transformModel(dir, node, context);
  }
};
function findValueBinding(node) {
  const valueBinding = compilerDom.findProp(node, "value");
  return valueBinding ? valueBinding.type === 7 ? valueBinding.exp : compilerDom.createSimpleExpression(valueBinding.value.content, true) : compilerDom.createSimpleExpression(`null`, false);
}

const ssrTransformShow = (dir, node, context) => {
  if (!dir.exp) {
    context.onError(
      compilerDom.createDOMCompilerError(61)
    );
  }
  return {
    props: [
      compilerDom.createObjectProperty(
        `style`,
        compilerDom.createConditionalExpression(
          dir.exp,
          compilerDom.createSimpleExpression(`null`, false),
          compilerDom.createObjectExpression([
            compilerDom.createObjectProperty(
              `display`,
              compilerDom.createSimpleExpression(`none`, true)
            )
          ]),
          false
          /* no newline */
        )
      )
    ]
  };
};

const filterChild = (node) => node.children.filter((n) => n.type !== 3);
const hasSingleChild = (node) => filterChild(node).length === 1;
const ssrInjectFallthroughAttrs = (node, context) => {
  if (node.type === 0) {
    context.identifiers._attrs = 1;
  }
  if (node.type === 1 && node.tagType === 1 && (compilerDom.isBuiltInType(node.tag, "Transition") || compilerDom.isBuiltInType(node.tag, "KeepAlive"))) {
    const rootChildren = filterChild(context.root);
    if (rootChildren.length === 1 && rootChildren[0] === node) {
      if (hasSingleChild(node)) {
        injectFallthroughAttrs(node.children[0]);
      }
      return;
    }
  }
  const parent = context.parent;
  if (!parent || parent.type !== 0) {
    return;
  }
  if (node.type === 10 && hasSingleChild(node)) {
    let hasEncounteredIf = false;
    for (const c of filterChild(parent)) {
      if (c.type === 9 || c.type === 1 && compilerDom.findDir(c, "if")) {
        if (hasEncounteredIf)
          return;
        hasEncounteredIf = true;
      } else if (
        // node before v-if
        !hasEncounteredIf || // non else nodes
        !(c.type === 1 && compilerDom.findDir(c, /else/, true))
      ) {
        return;
      }
    }
    injectFallthroughAttrs(node.children[0]);
  } else if (hasSingleChild(parent)) {
    injectFallthroughAttrs(node);
  }
};
function injectFallthroughAttrs(node) {
  if (node.type === 1 && (node.tagType === 0 || node.tagType === 1) && !compilerDom.findDir(node, "for")) {
    node.props.push({
      type: 7,
      name: "bind",
      arg: void 0,
      exp: compilerDom.createSimpleExpression(`_attrs`, false),
      modifiers: [],
      loc: compilerDom.locStub
    });
  }
}

const ssrInjectCssVars = (node, context) => {
  if (!context.ssrCssVars) {
    return;
  }
  if (node.type === 0) {
    context.identifiers._cssVars = 1;
  }
  const parent = context.parent;
  if (!parent || parent.type !== 0) {
    return;
  }
  if (node.type === 10) {
    for (const child of node.children) {
      injectCssVars(child);
    }
  } else {
    injectCssVars(node);
  }
};
function injectCssVars(node) {
  if (node.type === 1 && (node.tagType === 0 || node.tagType === 1) && !compilerDom.findDir(node, "for")) {
    if (compilerDom.isBuiltInType(node.tag, "Suspense")) {
      for (const child of node.children) {
        if (child.type === 1 && child.tagType === 3) {
          child.children.forEach(injectCssVars);
        } else {
          injectCssVars(child);
        }
      }
    } else {
      node.props.push({
        type: 7,
        name: "bind",
        arg: void 0,
        exp: compilerDom.createSimpleExpression(`_cssVars`, false),
        modifiers: [],
        loc: compilerDom.locStub
      });
    }
  }
}

function compile(template, options = {}) {
  options = {
    ...options,
    // apply DOM-specific parsing options
    ...compilerDom.parserOptions,
    ssr: true,
    inSSR: true,
    scopeId: options.mode === "function" ? null : options.scopeId,
    // always prefix since compiler-ssr doesn't have size concern
    prefixIdentifiers: true,
    // disable optimizations that are unnecessary for ssr
    cacheHandlers: false,
    hoistStatic: false
  };
  const ast = compilerDom.baseParse(template, options);
  rawOptionsMap.set(ast, options);
  compilerDom.transform(ast, {
    ...options,
    hoistStatic: false,
    nodeTransforms: [
      ssrTransformIf,
      ssrTransformFor,
      compilerDom.trackVForSlotScopes,
      compilerDom.transformExpression,
      ssrTransformSlotOutlet,
      ssrInjectFallthroughAttrs,
      ssrInjectCssVars,
      ssrTransformElement,
      ssrTransformComponent,
      compilerDom.trackSlotScopes,
      compilerDom.transformStyle,
      ...options.nodeTransforms || []
      // user transforms
    ],
    directiveTransforms: {
      // reusing core v-bind
      bind: compilerDom.transformBind,
      on: compilerDom.transformOn,
      // model and show has dedicated SSR handling
      model: ssrTransformModel,
      show: ssrTransformShow,
      // the following are ignored during SSR
      // on: noopDirectiveTransform,
      cloak: compilerDom.noopDirectiveTransform,
      once: compilerDom.noopDirectiveTransform,
      memo: compilerDom.noopDirectiveTransform,
      ...options.directiveTransforms || {}
      // user transforms
    }
  });
  ssrCodegenTransform(ast, options);
  return compilerDom.generate(ast, options);
}

exports.compile = compile;
