]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(compiler-core): force <svg> into blocks for correct runtime isSVG
authorEvan You <yyx990803@gmail.com>
Mon, 20 Jan 2020 19:48:19 +0000 (14:48 -0500)
committerEvan You <yyx990803@gmail.com>
Mon, 20 Jan 2020 19:48:26 +0000 (14:48 -0500)
state during patch

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

index 92e2b3460028710c22d91f0c3b8c17d9744f631e..f411f4ff8ec9fa020f9eb164e5172072f5cdf5b1 100644 (file)
@@ -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('<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"`]
+        }
+      ]
+    })
+  })
 })
index 4261e7383452696e08170a506619ec5186a8a9e8..edd7918e7f8dec8c9e8e55b9082fd43d87221522 100644 (file)
@@ -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 {
index c13e9e4ce09abb04101eec56cf89749f0d95191d..09a865112dd18e0727a13455249487730192cca3 100644 (file)
@@ -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
+      ? // <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) {
       node.codegenNode = createCallExpression(
         context.helper(WITH_DIRECTIVES),