Skip to content

Commit 59d50da

Browse files
committed
wip: account for text call nodes in stringify chunks
1 parent b26976b commit 59d50da

File tree

1 file changed

+48
-41
lines changed

1 file changed

+48
-41
lines changed

packages/compiler-dom/src/transforms/stringifyStatic.ts

+48-41
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ import {
1313
ExpressionNode,
1414
ElementTypes,
1515
PlainElementNode,
16-
JSChildNode
16+
JSChildNode,
17+
TextCallNode
1718
} from '@vue/compiler-core'
1819
import {
1920
isVoidTag,
@@ -32,13 +33,15 @@ export const enum StringifyThresholds {
3233
NODE_COUNT = 20
3334
}
3435

36+
type StringiableNode = PlainElementNode | TextCallNode
37+
3538
// Turn eligible hoisted static trees into stringied static nodes, e.g.
3639
// const _hoisted_1 = createStaticVNode(`<div class="foo">bar</div>`)
3740
// This is only performed in non-in-browser compilations.
3841
export const stringifyStatic: HoistTransform = (children, context) => {
3942
let nc = 0 // current node count
4043
let ec = 0 // current element with binding count
41-
const currentChunk: PlainElementNode[] = []
44+
const currentChunk: StringiableNode[] = []
4245

4346
const stringifyCurrentChunk = (currentIndex: number): number => {
4447
if (
@@ -48,7 +51,7 @@ export const stringifyStatic: HoistTransform = (children, context) => {
4851
// combine all currently eligible nodes into a single static vnode call
4952
const staticCall = createCallExpression(context.helper(CREATE_STATIC), [
5053
JSON.stringify(
51-
currentChunk.map(node => stringifyElement(node, context)).join('')
54+
currentChunk.map(node => stringifyNode(node, context)).join('')
5255
),
5356
// the 2nd argument indicates the number of DOM nodes this static vnode
5457
// will insert / hydrate
@@ -77,8 +80,8 @@ export const stringifyStatic: HoistTransform = (children, context) => {
7780
const child = children[i]
7881
const hoisted = getHoistedNode(child)
7982
if (hoisted) {
80-
// presence of hoisted means child must be a plain element Node
81-
const node = child as PlainElementNode
83+
// presence of hoisted means child must be a stringifiable node
84+
const node = child as StringiableNode
8285
const result = analyzeNode(node)
8386
if (result) {
8487
// node is stringifiable, record state
@@ -102,8 +105,8 @@ export const stringifyStatic: HoistTransform = (children, context) => {
102105
}
103106

104107
const getHoistedNode = (node: TemplateChildNode) =>
105-
node.type === NodeTypes.ELEMENT &&
106-
node.tagType === ElementTypes.ELEMENT &&
108+
((node.type === NodeTypes.ELEMENT && node.tagType === ElementTypes.ELEMENT) ||
109+
node.type == NodeTypes.TEXT_CALL) &&
107110
node.codegenNode &&
108111
node.codegenNode.type === NodeTypes.SIMPLE_EXPRESSION &&
109112
node.codegenNode.hoisted
@@ -114,7 +117,7 @@ const isStringifiableAttr = (name: string) => {
114117
}
115118

116119
const replaceHoist = (
117-
node: PlainElementNode,
120+
node: StringiableNode,
118121
replacement: JSChildNode | null,
119122
context: TransformContext
120123
) => {
@@ -125,11 +128,15 @@ const replaceHoist = (
125128
/**
126129
* for a hoisted node, analyze it and return:
127130
* - false: bailed (contains runtime constant)
128-
* - [x, y] where
129-
* - x is the number of nodes inside
130-
* - y is the number of element with bindings inside
131+
* - [nc, ec] where
132+
* - nc is the number of nodes inside
133+
* - ec is the number of element with bindings inside
131134
*/
132-
function analyzeNode(node: PlainElementNode): [number, number] | false {
135+
function analyzeNode(node: StringiableNode): [number, number] | false {
136+
if (node.type === NodeTypes.TEXT_CALL) {
137+
return [1, 0]
138+
}
139+
133140
let nc = 1 // node count
134141
let ec = node.props.length > 0 ? 1 : 0 // element w/ binding count
135142
let bailed = false
@@ -196,6 +203,35 @@ function analyzeNode(node: PlainElementNode): [number, number] | false {
196203
return walk(node) ? [nc, ec] : false
197204
}
198205

206+
function stringifyNode(
207+
node: string | TemplateChildNode,
208+
context: TransformContext
209+
): string {
210+
if (isString(node)) {
211+
return node
212+
}
213+
if (isSymbol(node)) {
214+
return ``
215+
}
216+
switch (node.type) {
217+
case NodeTypes.ELEMENT:
218+
return stringifyElement(node, context)
219+
case NodeTypes.TEXT:
220+
return escapeHtml(node.content)
221+
case NodeTypes.COMMENT:
222+
return `<!--${escapeHtml(node.content)}-->`
223+
case NodeTypes.INTERPOLATION:
224+
return escapeHtml(toDisplayString(evaluateConstant(node.content)))
225+
case NodeTypes.COMPOUND_EXPRESSION:
226+
return escapeHtml(evaluateConstant(node))
227+
case NodeTypes.TEXT_CALL:
228+
return stringifyNode(node.content, context)
229+
default:
230+
// static trees will not contain if/for nodes
231+
return ''
232+
}
233+
}
234+
199235
function stringifyElement(
200236
node: ElementNode,
201237
context: TransformContext
@@ -235,35 +271,6 @@ function stringifyElement(
235271
return res
236272
}
237273

238-
function stringifyNode(
239-
node: string | TemplateChildNode,
240-
context: TransformContext
241-
): string {
242-
if (isString(node)) {
243-
return node
244-
}
245-
if (isSymbol(node)) {
246-
return ``
247-
}
248-
switch (node.type) {
249-
case NodeTypes.ELEMENT:
250-
return stringifyElement(node, context)
251-
case NodeTypes.TEXT:
252-
return escapeHtml(node.content)
253-
case NodeTypes.COMMENT:
254-
return `<!--${escapeHtml(node.content)}-->`
255-
case NodeTypes.INTERPOLATION:
256-
return escapeHtml(toDisplayString(evaluateConstant(node.content)))
257-
case NodeTypes.COMPOUND_EXPRESSION:
258-
return escapeHtml(evaluateConstant(node))
259-
case NodeTypes.TEXT_CALL:
260-
return stringifyNode(node.content, context)
261-
default:
262-
// static trees will not contain if/for nodes
263-
return ''
264-
}
265-
}
266-
267274
// __UNSAFE__
268275
// Reason: eval.
269276
// It's technically safe to eval because only constant expressions are possible

0 commit comments

Comments
 (0)