@@ -13,7 +13,8 @@ import {
13
13
ExpressionNode ,
14
14
ElementTypes ,
15
15
PlainElementNode ,
16
- JSChildNode
16
+ JSChildNode ,
17
+ TextCallNode
17
18
} from '@vue/compiler-core'
18
19
import {
19
20
isVoidTag ,
@@ -32,13 +33,15 @@ export const enum StringifyThresholds {
32
33
NODE_COUNT = 20
33
34
}
34
35
36
+ type StringiableNode = PlainElementNode | TextCallNode
37
+
35
38
// Turn eligible hoisted static trees into stringied static nodes, e.g.
36
39
// const _hoisted_1 = createStaticVNode(`<div class="foo">bar</div>`)
37
40
// This is only performed in non-in-browser compilations.
38
41
export const stringifyStatic : HoistTransform = ( children , context ) => {
39
42
let nc = 0 // current node count
40
43
let ec = 0 // current element with binding count
41
- const currentChunk : PlainElementNode [ ] = [ ]
44
+ const currentChunk : StringiableNode [ ] = [ ]
42
45
43
46
const stringifyCurrentChunk = ( currentIndex : number ) : number => {
44
47
if (
@@ -48,7 +51,7 @@ export const stringifyStatic: HoistTransform = (children, context) => {
48
51
// combine all currently eligible nodes into a single static vnode call
49
52
const staticCall = createCallExpression ( context . helper ( CREATE_STATIC ) , [
50
53
JSON . stringify (
51
- currentChunk . map ( node => stringifyElement ( node , context ) ) . join ( '' )
54
+ currentChunk . map ( node => stringifyNode ( node , context ) ) . join ( '' )
52
55
) ,
53
56
// the 2nd argument indicates the number of DOM nodes this static vnode
54
57
// will insert / hydrate
@@ -77,8 +80,8 @@ export const stringifyStatic: HoistTransform = (children, context) => {
77
80
const child = children [ i ]
78
81
const hoisted = getHoistedNode ( child )
79
82
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
82
85
const result = analyzeNode ( node )
83
86
if ( result ) {
84
87
// node is stringifiable, record state
@@ -102,8 +105,8 @@ export const stringifyStatic: HoistTransform = (children, context) => {
102
105
}
103
106
104
107
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 ) &&
107
110
node . codegenNode &&
108
111
node . codegenNode . type === NodeTypes . SIMPLE_EXPRESSION &&
109
112
node . codegenNode . hoisted
@@ -114,7 +117,7 @@ const isStringifiableAttr = (name: string) => {
114
117
}
115
118
116
119
const replaceHoist = (
117
- node : PlainElementNode ,
120
+ node : StringiableNode ,
118
121
replacement : JSChildNode | null ,
119
122
context : TransformContext
120
123
) => {
@@ -125,11 +128,15 @@ const replaceHoist = (
125
128
/**
126
129
* for a hoisted node, analyze it and return:
127
130
* - 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
131
134
*/
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
+
133
140
let nc = 1 // node count
134
141
let ec = node . props . length > 0 ? 1 : 0 // element w/ binding count
135
142
let bailed = false
@@ -196,6 +203,35 @@ function analyzeNode(node: PlainElementNode): [number, number] | false {
196
203
return walk ( node ) ? [ nc , ec ] : false
197
204
}
198
205
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
+
199
235
function stringifyElement (
200
236
node : ElementNode ,
201
237
context : TransformContext
@@ -235,35 +271,6 @@ function stringifyElement(
235
271
return res
236
272
}
237
273
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
-
267
274
// __UNSAFE__
268
275
// Reason: eval.
269
276
// It's technically safe to eval because only constant expressions are possible
0 commit comments