Skip to content

Commit

Permalink
fix(compiler-ssr): handle comments codegen + refactor ssr codegen tra…
Browse files Browse the repository at this point in the history
…nsform
  • Loading branch information
yyx990803 committed May 1, 2020
1 parent 0e730c0 commit 6c60ce1
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 27 deletions.
6 changes: 6 additions & 0 deletions packages/compiler-ssr/__tests__/ssrText.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ describe('ssr: text', () => {
expect(getCompiledString(`foo`)).toMatchInlineSnapshot(`"\`foo\`"`)
})

test('comments', () => {
expect(getCompiledString(`<!--bar-->`)).toMatchInlineSnapshot(
`"\`<!--bar-->\`"`
)
})

test('static text escape', () => {
expect(getCompiledString(`&lt;foo&gt;`)).toMatchInlineSnapshot(
`"\`&lt;foo&gt;\`"`
Expand Down
6 changes: 4 additions & 2 deletions packages/compiler-ssr/src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@ export function createSSRCompilerError(
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`
}
83 changes: 65 additions & 18 deletions packages/compiler-ssr/src/ssrCodegenTransform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { ssrProcessFor } from './transforms/ssrVFor'
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
Expand Down Expand Up @@ -115,24 +116,70 @@ export function processChildren(
}
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) {
Expand Down
10 changes: 3 additions & 7 deletions packages/server-renderer/src/renderToString.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ import {
isVoidTag,
escapeHtml,
NO,
generateCodeFrame
generateCodeFrame,
escapeHtmlComment
} from '@vue/shared'
import { compile } from '@vue/compiler-ssr'
import { ssrRenderAttrs } from './helpers/ssrRenderAttrs'
Expand Down Expand Up @@ -230,9 +231,6 @@ function ssrCompile(
return (compileCache[template] = Function('require', code)(require))
}

// https://www.w3.org/TR/html52/syntax.html#comments
const commentStripRE = /^-?>|<!--|-->|--!>|<!-$/g

function renderVNode(
push: PushFn,
vnode: VNode,
Expand All @@ -245,9 +243,7 @@ function renderVNode(
break
case Comment:
push(
children
? `<!--${(children as string).replace(commentStripRE, '')}-->`
: `<!---->`
children ? `<!--${escapeHtmlComment(children as string)}-->` : `<!---->`
)
break
case Static:
Expand Down
7 changes: 7 additions & 0 deletions packages/shared/src/escapeHtml.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,10 @@ export function escapeHtml(string: unknown) {

return lastIndex !== index ? html + str.substring(lastIndex, index) : html
}

// https://www.w3.org/TR/html52/syntax.html#comments
const commentStripRE = /^-?>|<!--|-->|--!>|<!-$/g

export function escapeHtmlComment(src: string): string {
return src.replace(commentStripRE, '')
}

0 comments on commit 6c60ce1

Please sign in to comment.