Skip to content

Commit f2ac28b

Browse files
committed
fix(compiler-core): force <svg> into blocks for correct runtime isSVG
state during patch
1 parent 0c42a6d commit f2ac28b

File tree

3 files changed

+48
-7
lines changed

3 files changed

+48
-7
lines changed

packages/compiler-core/__tests__/transforms/transformElement.spec.ts

+24-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ import {
1616
RESOLVE_DYNAMIC_COMPONENT,
1717
SUSPENSE,
1818
KEEP_ALIVE,
19-
BASE_TRANSITION
19+
BASE_TRANSITION,
20+
OPEN_BLOCK,
21+
CREATE_BLOCK
2022
} from '../../src/runtimeHelpers'
2123
import {
2224
CallExpression,
@@ -821,4 +823,25 @@ describe('compiler: element transform', () => {
821823
])
822824
})
823825
})
826+
827+
test('<svg> should be forced into blocks', () => {
828+
const ast = parse(`<div><svg/></div>`)
829+
transform(ast, {
830+
nodeTransforms: [transformElement]
831+
})
832+
expect((ast as any).children[0].children[0].codegenNode).toMatchObject({
833+
type: NodeTypes.JS_SEQUENCE_EXPRESSION,
834+
expressions: [
835+
{
836+
type: NodeTypes.JS_CALL_EXPRESSION,
837+
callee: OPEN_BLOCK
838+
},
839+
{
840+
type: NodeTypes.JS_CALL_EXPRESSION,
841+
callee: CREATE_BLOCK,
842+
arguments: [`"svg"`]
843+
}
844+
]
845+
})
846+
})
824847
})

packages/compiler-core/src/ast.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -118,21 +118,26 @@ export interface BaseElementNode extends Node {
118118
| CallExpression
119119
| SimpleExpressionNode
120120
| CacheExpression
121+
| SequenceExpression
121122
| undefined
122123
}
123124

124125
export interface PlainElementNode extends BaseElementNode {
125126
tagType: ElementTypes.ELEMENT
126127
codegenNode:
127128
| ElementCodegenNode
128-
| undefined
129129
| SimpleExpressionNode // when hoisted
130130
| CacheExpression // when cached by v-once
131+
| SequenceExpression // when turned into a block
132+
| undefined
131133
}
132134

133135
export interface ComponentNode extends BaseElementNode {
134136
tagType: ElementTypes.COMPONENT
135-
codegenNode: ComponentCodegenNode | undefined | CacheExpression // when cached by v-once
137+
codegenNode:
138+
| ComponentCodegenNode
139+
| CacheExpression // when cached by v-once
140+
| undefined
136141
}
137142

138143
export interface SlotOutletNode extends BaseElementNode {

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

+17-4
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ import {
1313
createObjectProperty,
1414
createSimpleExpression,
1515
createObjectExpression,
16-
Property
16+
Property,
17+
createSequenceExpression
1718
} from '../ast'
1819
import { PatchFlags, PatchFlagNames, isSymbol } from '@vue/shared'
1920
import { createCompilerError, ErrorCodes } from '../errors'
@@ -26,7 +27,9 @@ import {
2627
MERGE_PROPS,
2728
TO_HANDLERS,
2829
PORTAL,
29-
KEEP_ALIVE
30+
KEEP_ALIVE,
31+
OPEN_BLOCK,
32+
CREATE_BLOCK
3033
} from '../runtimeHelpers'
3134
import {
3235
getInnerRange,
@@ -67,6 +70,9 @@ export const transformElement: NodeTransform = (node, context) => {
6770
let runtimeDirectives: DirectiveNode[] | undefined
6871
let dynamicPropNames: string[] | undefined
6972
let dynamicComponent: string | CallExpression | undefined
73+
// technically this is web specific but we are keeping it in core to avoid
74+
// extra complexity
75+
let isSVG = false
7076

7177
// handle dynamic component
7278
const isProp = findProp(node, 'is')
@@ -105,6 +111,7 @@ export const transformElement: NodeTransform = (node, context) => {
105111
} else {
106112
// plain element
107113
nodeType = `"${node.tag}"`
114+
isSVG = node.tag === 'svg'
108115
}
109116

110117
const args: CallExpression['arguments'] = [nodeType]
@@ -190,8 +197,14 @@ export const transformElement: NodeTransform = (node, context) => {
190197
}
191198

192199
const { loc } = node
193-
const vnode = createCallExpression(context.helper(CREATE_VNODE), args, loc)
194-
200+
const vnode = isSVG
201+
? // <svg> must be forced into blocks so that block updates inside retain
202+
// isSVG flag at runtime. (#639, #643)
203+
createSequenceExpression([
204+
createCallExpression(context.helper(OPEN_BLOCK)),
205+
createCallExpression(context.helper(CREATE_BLOCK), args, loc)
206+
])
207+
: createCallExpression(context.helper(CREATE_VNODE), args, loc)
195208
if (runtimeDirectives && runtimeDirectives.length) {
196209
node.codegenNode = createCallExpression(
197210
context.helper(WITH_DIRECTIVES),

0 commit comments

Comments
 (0)