]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(compiler-core): fix expression transform for try...catch block params
authorEvan You <evan@vuejs.org>
Mon, 5 Aug 2024 05:46:51 +0000 (13:46 +0800)
committerEvan You <evan@vuejs.org>
Mon, 5 Aug 2024 05:46:51 +0000 (13:46 +0800)
close #11465
close #11467

packages/compiler-core/__tests__/transforms/__snapshots__/transformExpressions.spec.ts.snap
packages/compiler-core/__tests__/transforms/transformExpressions.spec.ts
packages/compiler-core/src/babelUtils.ts

index 9f4406864dbb31f3729848b93aa3fab938d5bb37..9ea502132ac24a279feb723d9e92caf297a6087c 100644 (file)
@@ -14,44 +14,74 @@ return function render(_ctx, _cache, $props, $setup, $data, $options) {
 }"
 `;
 
-exports[`compiler: expression transform > bindingMetadata > should not prefix temp variable of for loop 1`] = `
+exports[`compiler: expression transform > should not prefix catch block param 1`] = `
 "const { openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue
 
-return function render(_ctx, _cache, $props, $setup, $data, $options) {
+return function render(_ctx, _cache) {
+  return (_openBlock(), _createElementBlock("div", {
+    onClick: () => {
+         try {} catch (err) { console.error(err) }
+        console.log(_ctx.err)
+      }
+  }, null, 8 /* PROPS */, ["onClick"]))
+}"
+`;
+
+exports[`compiler: expression transform > should not prefix destructured catch block param 1`] = `
+"const { openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue
+
+return function render(_ctx, _cache) {
   return (_openBlock(), _createElementBlock("div", {
     onClick: () => {
-          for (let i = 0; i < _ctx.list.length; i++) {
-            _ctx.log(i)
-          }
+        try {
+          throw new Error('sup?')
+        } catch ({ message: { length } }) {
+          console.error(length)
         }
+        console.log(_ctx.length)
+      }
   }, null, 8 /* PROPS */, ["onClick"]))
 }"
 `;
 
-exports[`compiler: expression transform > bindingMetadata > should not prefix temp variable of for...in 1`] = `
+exports[`compiler: expression transform > should not prefix temp variable of for loop 1`] = `
 "const { openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue
 
-return function render(_ctx, _cache, $props, $setup, $data, $options) {
+return function render(_ctx, _cache) {
   return (_openBlock(), _createElementBlock("div", {
     onClick: () => {
-          for (const x in _ctx.list) {
-            _ctx.log(x)
-          }
+        for (let i = 0; i < _ctx.list.length; i++) {
+          _ctx.log(i)
         }
+      }
   }, null, 8 /* PROPS */, ["onClick"]))
 }"
 `;
 
-exports[`compiler: expression transform > bindingMetadata > should not prefix temp variable of for...of 1`] = `
+exports[`compiler: expression transform > should not prefix temp variable of for...in 1`] = `
 "const { openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue
 
-return function render(_ctx, _cache, $props, $setup, $data, $options) {
+return function render(_ctx, _cache) {
+  return (_openBlock(), _createElementBlock("div", {
+    onClick: () => {
+        for (const x in _ctx.list) {
+          _ctx.log(x)
+        }
+      }
+  }, null, 8 /* PROPS */, ["onClick"]))
+}"
+`;
+
+exports[`compiler: expression transform > should not prefix temp variable of for...of 1`] = `
+"const { openBlock: _openBlock, createElementBlock: _createElementBlock } = Vue
+
+return function render(_ctx, _cache) {
   return (_openBlock(), _createElementBlock("div", {
     onClick: () => {
-          for (const x of _ctx.list) {
-            _ctx.log(x)
-          }
+        for (const x of _ctx.list) {
+          _ctx.log(x)
         }
+      }
   }, null, 8 /* PROPS */, ["onClick"]))
 }"
 `;
index 7ca831f0ce8da29b431af861cf6383813af00ff8..af14265e27aea63b74b14aefb6d581759298d4e8 100644 (file)
@@ -27,6 +27,10 @@ function parseWithExpressionTransform(
   return ast.children[0]
 }
 
+function compile(template: string) {
+  return baseCompile(template, { prefixIdentifiers: true })
+}
+
 describe('compiler: expression transform', () => {
   test('interpolation (root)', () => {
     const node = parseWithExpressionTransform(`{{ foo }}`) as InterpolationNode
@@ -291,6 +295,7 @@ describe('compiler: expression transform', () => {
       ],
     })
   })
+
   test('should not prefix an object property key', () => {
     const node = parseWithExpressionTransform(
       `{{ { foo() { baz() }, value: bar } }}`,
@@ -457,6 +462,70 @@ describe('compiler: expression transform', () => {
     })
   })
 
+  test('should not prefix temp variable of for...in', () => {
+    const { code } = compile(
+      `<div @click="() => {
+        for (const x in list) {
+          log(x)
+        }
+      }"/>`,
+    )
+    expect(code).not.toMatch(`_ctx.x`)
+    expect(code).toMatchSnapshot()
+  })
+
+  test('should not prefix temp variable of for...of', () => {
+    const { code } = compile(
+      `<div @click="() => {
+        for (const x of list) {
+          log(x)
+        }
+      }"/>`,
+    )
+    expect(code).not.toMatch(`_ctx.x`)
+    expect(code).toMatchSnapshot()
+  })
+
+  test('should not prefix temp variable of for loop', () => {
+    const { code } = compile(
+      `<div @click="() => {
+        for (let i = 0; i < list.length; i++) {
+          log(i)
+        }
+      }"/>`,
+    )
+    expect(code).not.toMatch(`_ctx.i`)
+    expect(code).toMatchSnapshot()
+  })
+
+  test('should not prefix catch block param', () => {
+    const { code } = compile(
+      `<div @click="() => {
+         try {} catch (err) { console.error(err) }
+        console.log(err)
+      }"/>`,
+    )
+    expect(code).not.toMatch(`console.error(_ctx.err)`)
+    expect(code).toMatch(`console.log(_ctx.err)`)
+    expect(code).toMatchSnapshot()
+  })
+
+  test('should not prefix destructured catch block param', () => {
+    const { code } = compile(
+      `<div @click="() => {
+        try {
+          throw new Error('sup?')
+        } catch ({ message: { length } }) {
+          console.error(length)
+        }
+        console.log(length)
+      }"/>`,
+    )
+    expect(code).not.toMatch(`console.error(_ctx.length)`)
+    expect(code).toMatch(`console.log(_ctx.length)`)
+    expect(code).toMatchSnapshot()
+  })
+
   describe('ES Proposals support', () => {
     test('bigInt', () => {
       const node = parseWithExpressionTransform(
@@ -555,42 +624,6 @@ describe('compiler: expression transform', () => {
       expect(code).toMatchSnapshot()
     })
 
-    test('should not prefix temp variable of for...in', () => {
-      const { code } = compileWithBindingMetadata(
-        `<div @click="() => {
-          for (const x in list) {
-            log(x)
-          }
-        }"/>`,
-      )
-      expect(code).not.toMatch(`_ctx.x`)
-      expect(code).toMatchSnapshot()
-    })
-
-    test('should not prefix temp variable of for...of', () => {
-      const { code } = compileWithBindingMetadata(
-        `<div @click="() => {
-          for (const x of list) {
-            log(x)
-          }
-        }"/>`,
-      )
-      expect(code).not.toMatch(`_ctx.x`)
-      expect(code).toMatchSnapshot()
-    })
-
-    test('should not prefix temp variable of for loop', () => {
-      const { code } = compileWithBindingMetadata(
-        `<div @click="() => {
-          for (let i = 0; i < list.length; i++) {
-            log(i)
-          }
-        }"/>`,
-      )
-      expect(code).not.toMatch(`_ctx.i`)
-      expect(code).toMatchSnapshot()
-    })
-
     test('inline mode', () => {
       const { code } = compileWithBindingMetadata(
         `<div>{{ props }} {{ setup }} {{ setupConst }} {{ data }} {{ options }} {{ isNaN }}</div>`,
index 67997798864cb7ce1f8eaaaaaa677230454f5691..3144ed595b475ced83a84ea79c03f2bef8af8fa1 100644 (file)
@@ -77,6 +77,10 @@ export function walkIdentifiers(
             markScopeIdentifier(node, id, knownIds),
           )
         }
+      } else if (node.type === 'CatchClause' && node.param) {
+        for (const id of extractIdentifiers(node.param)) {
+          markScopeIdentifier(node, id, knownIds)
+        }
       }
     },
     leave(node: Node & { scopeIds?: Set<string> }, parent: Node | null) {