]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(compiler-core): properly transform replaced nodes (#2927)
authorCalvin Liang <calvin34585@gmail.com>
Mon, 29 Mar 2021 22:08:10 +0000 (15:08 -0700)
committerGitHub <noreply@github.com>
Mon, 29 Mar 2021 22:08:10 +0000 (18:08 -0400)
packages/compiler-core/__tests__/transforms/transformElement.spec.ts
packages/compiler-core/src/transforms/transformElement.ts

index 1258398d4656147d3f743305300892eb3c7d802e..33fdb7dba19720083f188a8bc38b41d1b9f94c14 100644 (file)
@@ -3,7 +3,8 @@ import {
   baseParse as parse,
   transform,
   ErrorCodes,
-  BindingTypes
+  BindingTypes,
+  NodeTransform
 } from '../../src'
 import {
   RESOLVE_COMPONENT,
@@ -939,4 +940,35 @@ describe('compiler: element transform', () => {
       isBlock: true
     })
   })
+
+  test('should process node when node has been replaced', () => {
+    // a NodeTransform that swaps out <div id="foo" /> with <span id="foo" />
+    const customNodeTransform: NodeTransform = (node, context) => {
+      if (
+        node.type === NodeTypes.ELEMENT &&
+        node.tag === 'div' &&
+        node.props.some(
+          prop =>
+            prop.type === NodeTypes.ATTRIBUTE &&
+            prop.name === 'id' &&
+            prop.value &&
+            prop.value.content === 'foo'
+        )
+      ) {
+        context.replaceNode({
+          ...node,
+          tag: 'span'
+        })
+      }
+    }
+    const ast = parse(`<div><div id="foo" /></div>`)
+    transform(ast, {
+      nodeTransforms: [transformElement, transformText, customNodeTransform]
+    })
+    expect((ast as any).children[0].children[0].codegenNode).toMatchObject({
+      type: NodeTypes.VNODE_CALL,
+      tag: '"span"',
+      isBlock: false
+    })
+  })
 })
index 9f4f338956499d814f7f3452049a2d6dde183bd4..113b03dd8564f83d20316f87e15bd36d7b18e507 100644 (file)
@@ -62,18 +62,21 @@ const directiveImportMap = new WeakMap<DirectiveNode, symbol>()
 
 // generate a JavaScript AST for this element's codegen
 export const transformElement: NodeTransform = (node, context) => {
-  if (
-    !(
-      node.type === NodeTypes.ELEMENT &&
-      (node.tagType === ElementTypes.ELEMENT ||
-        node.tagType === ElementTypes.COMPONENT)
-    )
-  ) {
-    return
-  }
   // perform the work on exit, after all child expressions have been
   // processed and merged.
   return function postTransformElement() {
+    node = context.currentNode!
+
+    if (
+      !(
+        node.type === NodeTypes.ELEMENT &&
+        (node.tagType === ElementTypes.ELEMENT ||
+          node.tagType === ElementTypes.COMPONENT)
+      )
+    ) {
+      return
+    }
+
     const { tag, props } = node
     const isComponent = node.tagType === ElementTypes.COMPONENT