diff --git a/packages/compiler-core/__tests__/transforms/transformElement.spec.ts b/packages/compiler-core/__tests__/transforms/transformElement.spec.ts index 92e2b346..f411f4ff 100644 --- a/packages/compiler-core/__tests__/transforms/transformElement.spec.ts +++ b/packages/compiler-core/__tests__/transforms/transformElement.spec.ts @@ -16,7 +16,9 @@ import { RESOLVE_DYNAMIC_COMPONENT, SUSPENSE, KEEP_ALIVE, - BASE_TRANSITION + BASE_TRANSITION, + OPEN_BLOCK, + CREATE_BLOCK } from '../../src/runtimeHelpers' import { CallExpression, @@ -821,4 +823,25 @@ describe('compiler: element transform', () => { ]) }) }) + + test(' should be forced into blocks', () => { + const ast = parse(`
`) + 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"`] + } + ] + }) + }) }) diff --git a/packages/compiler-core/src/ast.ts b/packages/compiler-core/src/ast.ts index 4261e738..edd7918e 100644 --- a/packages/compiler-core/src/ast.ts +++ b/packages/compiler-core/src/ast.ts @@ -118,6 +118,7 @@ export interface BaseElementNode extends Node { | CallExpression | SimpleExpressionNode | CacheExpression + | SequenceExpression | undefined } @@ -125,14 +126,18 @@ export interface PlainElementNode extends BaseElementNode { tagType: ElementTypes.ELEMENT codegenNode: | ElementCodegenNode - | undefined | SimpleExpressionNode // when hoisted | CacheExpression // when cached by v-once + | SequenceExpression // when turned into a block + | undefined } export interface ComponentNode extends BaseElementNode { 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 { diff --git a/packages/compiler-core/src/transforms/transformElement.ts b/packages/compiler-core/src/transforms/transformElement.ts index c13e9e4c..09a86511 100644 --- a/packages/compiler-core/src/transforms/transformElement.ts +++ b/packages/compiler-core/src/transforms/transformElement.ts @@ -13,7 +13,8 @@ import { createObjectProperty, createSimpleExpression, createObjectExpression, - Property + Property, + createSequenceExpression } from '../ast' import { PatchFlags, PatchFlagNames, isSymbol } from '@vue/shared' import { createCompilerError, ErrorCodes } from '../errors' @@ -26,7 +27,9 @@ import { MERGE_PROPS, TO_HANDLERS, PORTAL, - KEEP_ALIVE + KEEP_ALIVE, + OPEN_BLOCK, + CREATE_BLOCK } from '../runtimeHelpers' import { getInnerRange, @@ -67,6 +70,9 @@ export const transformElement: NodeTransform = (node, context) => { let runtimeDirectives: DirectiveNode[] | undefined let dynamicPropNames: string[] | 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 const isProp = findProp(node, 'is') @@ -105,6 +111,7 @@ export const transformElement: NodeTransform = (node, context) => { } else { // plain element nodeType = `"${node.tag}"` + isSVG = node.tag === 'svg' } const args: CallExpression['arguments'] = [nodeType] @@ -190,8 +197,14 @@ export const transformElement: NodeTransform = (node, context) => { } const { loc } = node - const vnode = createCallExpression(context.helper(CREATE_VNODE), args, loc) - + const vnode = isSVG + ? // 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) { node.codegenNode = createCallExpression( context.helper(WITH_DIRECTIVES),