fix(compiler-core): force <svg> into blocks for correct runtime isSVG
state during patch
This commit is contained in:
parent
0c42a6d8fa
commit
f2ac28b31e
@ -16,7 +16,9 @@ import {
|
|||||||
RESOLVE_DYNAMIC_COMPONENT,
|
RESOLVE_DYNAMIC_COMPONENT,
|
||||||
SUSPENSE,
|
SUSPENSE,
|
||||||
KEEP_ALIVE,
|
KEEP_ALIVE,
|
||||||
BASE_TRANSITION
|
BASE_TRANSITION,
|
||||||
|
OPEN_BLOCK,
|
||||||
|
CREATE_BLOCK
|
||||||
} from '../../src/runtimeHelpers'
|
} from '../../src/runtimeHelpers'
|
||||||
import {
|
import {
|
||||||
CallExpression,
|
CallExpression,
|
||||||
@ -821,4 +823,25 @@ describe('compiler: element transform', () => {
|
|||||||
])
|
])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('<svg> should be forced into blocks', () => {
|
||||||
|
const ast = parse(`<div><svg/></div>`)
|
||||||
|
transform(ast, {
|
||||||
|
nodeTransforms: [transformElement]
|
||||||
|
})
|
||||||
|
expect((ast as any).children[0].children[0].codegenNode).toMatchObject({
|
||||||
|
type: NodeTypes.JS_SEQUENCE_EXPRESSION,
|
||||||
|
expressions: [
|
||||||
|
{
|
||||||
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
|
callee: OPEN_BLOCK
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
|
callee: CREATE_BLOCK,
|
||||||
|
arguments: [`"svg"`]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -118,6 +118,7 @@ export interface BaseElementNode extends Node {
|
|||||||
| CallExpression
|
| CallExpression
|
||||||
| SimpleExpressionNode
|
| SimpleExpressionNode
|
||||||
| CacheExpression
|
| CacheExpression
|
||||||
|
| SequenceExpression
|
||||||
| undefined
|
| undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,14 +126,18 @@ export interface PlainElementNode extends BaseElementNode {
|
|||||||
tagType: ElementTypes.ELEMENT
|
tagType: ElementTypes.ELEMENT
|
||||||
codegenNode:
|
codegenNode:
|
||||||
| ElementCodegenNode
|
| ElementCodegenNode
|
||||||
| undefined
|
|
||||||
| SimpleExpressionNode // when hoisted
|
| SimpleExpressionNode // when hoisted
|
||||||
| CacheExpression // when cached by v-once
|
| CacheExpression // when cached by v-once
|
||||||
|
| SequenceExpression // when turned into a block
|
||||||
|
| undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ComponentNode extends BaseElementNode {
|
export interface ComponentNode extends BaseElementNode {
|
||||||
tagType: ElementTypes.COMPONENT
|
tagType: ElementTypes.COMPONENT
|
||||||
codegenNode: ComponentCodegenNode | undefined | CacheExpression // when cached by v-once
|
codegenNode:
|
||||||
|
| ComponentCodegenNode
|
||||||
|
| CacheExpression // when cached by v-once
|
||||||
|
| undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SlotOutletNode extends BaseElementNode {
|
export interface SlotOutletNode extends BaseElementNode {
|
||||||
|
@ -13,7 +13,8 @@ import {
|
|||||||
createObjectProperty,
|
createObjectProperty,
|
||||||
createSimpleExpression,
|
createSimpleExpression,
|
||||||
createObjectExpression,
|
createObjectExpression,
|
||||||
Property
|
Property,
|
||||||
|
createSequenceExpression
|
||||||
} from '../ast'
|
} from '../ast'
|
||||||
import { PatchFlags, PatchFlagNames, isSymbol } from '@vue/shared'
|
import { PatchFlags, PatchFlagNames, isSymbol } from '@vue/shared'
|
||||||
import { createCompilerError, ErrorCodes } from '../errors'
|
import { createCompilerError, ErrorCodes } from '../errors'
|
||||||
@ -26,7 +27,9 @@ import {
|
|||||||
MERGE_PROPS,
|
MERGE_PROPS,
|
||||||
TO_HANDLERS,
|
TO_HANDLERS,
|
||||||
PORTAL,
|
PORTAL,
|
||||||
KEEP_ALIVE
|
KEEP_ALIVE,
|
||||||
|
OPEN_BLOCK,
|
||||||
|
CREATE_BLOCK
|
||||||
} from '../runtimeHelpers'
|
} from '../runtimeHelpers'
|
||||||
import {
|
import {
|
||||||
getInnerRange,
|
getInnerRange,
|
||||||
@ -67,6 +70,9 @@ export const transformElement: NodeTransform = (node, context) => {
|
|||||||
let runtimeDirectives: DirectiveNode[] | undefined
|
let runtimeDirectives: DirectiveNode[] | undefined
|
||||||
let dynamicPropNames: string[] | undefined
|
let dynamicPropNames: string[] | undefined
|
||||||
let dynamicComponent: string | CallExpression | undefined
|
let dynamicComponent: string | CallExpression | undefined
|
||||||
|
// technically this is web specific but we are keeping it in core to avoid
|
||||||
|
// extra complexity
|
||||||
|
let isSVG = false
|
||||||
|
|
||||||
// handle dynamic component
|
// handle dynamic component
|
||||||
const isProp = findProp(node, 'is')
|
const isProp = findProp(node, 'is')
|
||||||
@ -105,6 +111,7 @@ export const transformElement: NodeTransform = (node, context) => {
|
|||||||
} else {
|
} else {
|
||||||
// plain element
|
// plain element
|
||||||
nodeType = `"${node.tag}"`
|
nodeType = `"${node.tag}"`
|
||||||
|
isSVG = node.tag === 'svg'
|
||||||
}
|
}
|
||||||
|
|
||||||
const args: CallExpression['arguments'] = [nodeType]
|
const args: CallExpression['arguments'] = [nodeType]
|
||||||
@ -190,8 +197,14 @@ export const transformElement: NodeTransform = (node, context) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { loc } = node
|
const { loc } = node
|
||||||
const vnode = createCallExpression(context.helper(CREATE_VNODE), args, loc)
|
const vnode = isSVG
|
||||||
|
? // <svg> must be forced into blocks so that block updates inside retain
|
||||||
|
// isSVG flag at runtime. (#639, #643)
|
||||||
|
createSequenceExpression([
|
||||||
|
createCallExpression(context.helper(OPEN_BLOCK)),
|
||||||
|
createCallExpression(context.helper(CREATE_BLOCK), args, loc)
|
||||||
|
])
|
||||||
|
: createCallExpression(context.helper(CREATE_VNODE), args, loc)
|
||||||
if (runtimeDirectives && runtimeDirectives.length) {
|
if (runtimeDirectives && runtimeDirectives.length) {
|
||||||
node.codegenNode = createCallExpression(
|
node.codegenNode = createCallExpression(
|
||||||
context.helper(WITH_DIRECTIVES),
|
context.helper(WITH_DIRECTIVES),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user