export const enum SSRErrorCodes {
X_SSR_CUSTOM_DIRECTIVE_NO_TRANSFORM = DOMErrorCodes.__EXTEND_POINT__,
X_SSR_UNSAFE_ATTR_NAME,
- X_SSR_NO_TELEPORT_TARGET
+ X_SSR_NO_TELEPORT_TARGET,
+ X_SSR_INVALID_AST_NODE
}
export const SSRErrorMessages: { [code: number]: string } = {
[SSRErrorCodes.X_SSR_CUSTOM_DIRECTIVE_NO_TRANSFORM]: `Custom directive is missing corresponding SSR transform and will be ignored.`,
[SSRErrorCodes.X_SSR_UNSAFE_ATTR_NAME]: `Unsafe attribute name for SSR.`,
- [SSRErrorCodes.X_SSR_NO_TELEPORT_TARGET]: `No target prop on teleport element.`
+ [SSRErrorCodes.X_SSR_NO_TELEPORT_TARGET]: `No target prop on teleport element.`,
+ [SSRErrorCodes.X_SSR_INVALID_AST_NODE]: `Invalid AST node during ssr transform`
}
import { ssrProcessSlotOutlet } from './transforms/ssrTransformSlotOutlet'
import { ssrProcessComponent } from './transforms/ssrTransformComponent'
import { ssrProcessElement } from './transforms/ssrTransformElement'
+import { createSSRCompilerError, SSRErrorCodes } from './errors'
// Because SSR codegen output is completely different from client-side output
// (e.g. multiple elements can be concatenated into a single template literal
}
for (let i = 0; i < children.length; i++) {
const child = children[i]
- if (child.type === NodeTypes.ELEMENT) {
- if (child.tagType === ElementTypes.ELEMENT) {
- ssrProcessElement(child, context)
- } else if (child.tagType === ElementTypes.COMPONENT) {
- ssrProcessComponent(child, context)
- } else if (child.tagType === ElementTypes.SLOT) {
- ssrProcessSlotOutlet(child, context)
- }
- } else if (child.type === NodeTypes.TEXT) {
- context.pushStringPart(escapeHtml(child.content))
- } else if (child.type === NodeTypes.INTERPOLATION) {
- context.pushStringPart(
- createCallExpression(context.helper(SSR_INTERPOLATE), [child.content])
- )
- } else if (child.type === NodeTypes.IF) {
- ssrProcessIf(child, context)
- } else if (child.type === NodeTypes.FOR) {
- ssrProcessFor(child, context)
+ switch (child.type) {
+ case NodeTypes.ELEMENT:
+ switch (child.tagType) {
+ case ElementTypes.ELEMENT:
+ ssrProcessElement(child, context)
+ break
+ case ElementTypes.COMPONENT:
+ ssrProcessComponent(child, context)
+ break
+ case ElementTypes.SLOT:
+ ssrProcessSlotOutlet(child, context)
+ break
+ case ElementTypes.TEMPLATE:
+ // TODO
+ break
+ default:
+ context.onError(
+ createSSRCompilerError(
+ SSRErrorCodes.X_SSR_INVALID_AST_NODE,
+ (child as any).loc
+ )
+ )
+ // make sure we exhaust all possible types
+ const exhaustiveCheck: never = child
+ return exhaustiveCheck
+ }
+ break
+ case NodeTypes.TEXT:
+ context.pushStringPart(escapeHtml(child.content))
+ break
+ case NodeTypes.COMMENT:
+ // no need to escape comment here because the AST can only
+ // contain valid comments.
+ context.pushStringPart(`<!--${child.content}-->`)
+ break
+ case NodeTypes.INTERPOLATION:
+ context.pushStringPart(
+ createCallExpression(context.helper(SSR_INTERPOLATE), [child.content])
+ )
+ break
+ case NodeTypes.IF:
+ ssrProcessIf(child, context)
+ break
+ case NodeTypes.FOR:
+ ssrProcessFor(child, context)
+ break
+ case NodeTypes.IF_BRANCH:
+ // no-op - handled by ssrProcessIf
+ break
+ case NodeTypes.TEXT_CALL:
+ case NodeTypes.COMPOUND_EXPRESSION:
+ // no-op - these two types can never appear as template child node since
+ // `transformText` is not used during SSR compile.
+ break
+ default:
+ context.onError(
+ createSSRCompilerError(
+ SSRErrorCodes.X_SSR_INVALID_AST_NODE,
+ (child as any).loc
+ )
+ )
+ // make sure we exhaust all possible types
+ const exhaustiveCheck: never = child
+ return exhaustiveCheck
}
}
if (asFragment) {