Skip to content

Commit 9b5d13e

Browse files
committed
fix: bail stringification for slots
fix #1281, close #1286
1 parent fbaf52a commit 9b5d13e

File tree

4 files changed

+59
-12
lines changed

4 files changed

+59
-12
lines changed

packages/compiler-core/src/options.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ElementNode, Namespace, TemplateChildNode } from './ast'
1+
import { ElementNode, Namespace, TemplateChildNode, ParentNode } from './ast'
22
import { TextModes } from './parse'
33
import { CompilerError } from './errors'
44
import {
@@ -53,7 +53,8 @@ export interface ParserOptions {
5353

5454
export type HoistTransform = (
5555
children: TemplateChildNode[],
56-
context: TransformContext
56+
context: TransformContext,
57+
parent: ParentNode
5758
) => void
5859

5960
export interface TransformOptions {

packages/compiler-core/src/transforms/hoistStatic.ts

+14-8
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,16 @@ import {
88
ComponentNode,
99
TemplateNode,
1010
ElementNode,
11-
VNodeCall
11+
VNodeCall,
12+
ParentNode
1213
} from '../ast'
1314
import { TransformContext } from '../transform'
1415
import { PatchFlags, isString, isSymbol } from '@vue/shared'
1516
import { isSlotOutlet, findProp } from '../utils'
1617

1718
export function hoistStatic(root: RootNode, context: TransformContext) {
1819
walk(
19-
root.children,
20+
root,
2021
context,
2122
new Map(),
2223
// Root node is unfortunately non-hoistable due to potential parent
@@ -44,7 +45,7 @@ const enum StaticType {
4445
}
4546

4647
function walk(
47-
children: TemplateChildNode[],
48+
node: ParentNode,
4849
context: TransformContext,
4950
resultCache: Map<TemplateChildNode, StaticType>,
5051
doNotHoistNode: boolean = false
@@ -60,6 +61,7 @@ function walk(
6061
// stringficiation threshold is met.
6162
let hasRuntimeConstant = false
6263

64+
const { children } = node
6365
for (let i = 0; i < children.length; i++) {
6466
const child = children[i]
6567
// only plain elements & text calls are eligible for hoisting.
@@ -114,21 +116,25 @@ function walk(
114116

115117
// walk further
116118
if (child.type === NodeTypes.ELEMENT) {
117-
walk(child.children, context, resultCache)
119+
walk(child, context, resultCache)
118120
} else if (child.type === NodeTypes.FOR) {
119121
// Do not hoist v-for single child because it has to be a block
120-
walk(child.children, context, resultCache, child.children.length === 1)
122+
walk(child, context, resultCache, child.children.length === 1)
121123
} else if (child.type === NodeTypes.IF) {
122124
for (let i = 0; i < child.branches.length; i++) {
123-
const branchChildren = child.branches[i].children
124125
// Do not hoist v-if single child because it has to be a block
125-
walk(branchChildren, context, resultCache, branchChildren.length === 1)
126+
walk(
127+
child.branches[i],
128+
context,
129+
resultCache,
130+
child.branches[i].children.length === 1
131+
)
126132
}
127133
}
128134
}
129135

130136
if (!hasRuntimeConstant && hasHoistedNode && context.transformHoist) {
131-
context.transformHoist(children, context)
137+
context.transformHoist(children, context, node)
132138
}
133139
}
134140

packages/compiler-dom/__tests__/transforms/stringifyStatic.spec.ts

+33-1
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ describe('stringify static html', () => {
250250
})
251251
})
252252

253-
test('should bail on break content with innerHTML (eg.tables related tags)', () => {
253+
test('should bail on tags that has placement constraints (eg.tables related tags)', () => {
254254
const { ast } = compileWithStringify(
255255
`<table><tbody>${repeat(
256256
`<tr class="foo"><td>foo</td></tr>`,
@@ -262,4 +262,36 @@ describe('stringify static html', () => {
262262
type: NodeTypes.VNODE_CALL // not CALL_EXPRESSION
263263
})
264264
})
265+
266+
test('should bail inside slots', () => {
267+
const { ast } = compileWithStringify(
268+
`<foo>${repeat(
269+
`<div class="foo"></div>`,
270+
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
271+
)}</foo>`
272+
)
273+
expect(ast.hoists.length).toBe(
274+
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
275+
)
276+
ast.hoists.forEach(node => {
277+
expect(node).toMatchObject({
278+
type: NodeTypes.VNODE_CALL // not CALL_EXPRESSION
279+
})
280+
})
281+
282+
const { ast: ast2 } = compileWithStringify(
283+
`<foo><template #foo>${repeat(
284+
`<div class="foo"></div>`,
285+
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
286+
)}</template></foo>`
287+
)
288+
expect(ast2.hoists.length).toBe(
289+
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
290+
)
291+
ast2.hoists.forEach(node => {
292+
expect(node).toMatchObject({
293+
type: NodeTypes.VNODE_CALL // not CALL_EXPRESSION
294+
})
295+
})
296+
})
265297
})

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

+9-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,15 @@ type StringifiableNode = PlainElementNode | TextCallNode
5959
*
6060
* This optimization is only performed in Node.js.
6161
*/
62-
export const stringifyStatic: HoistTransform = (children, context) => {
62+
export const stringifyStatic: HoistTransform = (children, context, parent) => {
63+
if (
64+
parent.type === NodeTypes.ELEMENT &&
65+
(parent.tagType === ElementTypes.COMPONENT ||
66+
parent.tagType === ElementTypes.TEMPLATE)
67+
) {
68+
return
69+
}
70+
6371
let nc = 0 // current node count
6472
let ec = 0 // current element with binding count
6573
const currentChunk: StringifiableNode[] = []

0 commit comments

Comments
 (0)