From 077a1aeb3c222b729a7e190f46864656ecc65325 Mon Sep 17 00:00:00 2001 From: Evan You Date: Mon, 5 Aug 2024 13:46:51 +0800 Subject: [PATCH] fix(compiler-core): fix expression transform for try...catch block params close #11465 close #11467 --- .../transformExpressions.spec.ts.snap | 60 +++++++--- .../transforms/transformExpressions.spec.ts | 105 ++++++++++++------ packages/compiler-core/src/babelUtils.ts | 4 + 3 files changed, 118 insertions(+), 51 deletions(-) diff --git a/packages/compiler-core/__tests__/transforms/__snapshots__/transformExpressions.spec.ts.snap b/packages/compiler-core/__tests__/transforms/__snapshots__/transformExpressions.spec.ts.snap index 9f4406864db..9ea502132ac 100644 --- a/packages/compiler-core/__tests__/transforms/__snapshots__/transformExpressions.spec.ts.snap +++ b/packages/compiler-core/__tests__/transforms/__snapshots__/transformExpressions.spec.ts.snap @@ -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"])) }" `; diff --git a/packages/compiler-core/__tests__/transforms/transformExpressions.spec.ts b/packages/compiler-core/__tests__/transforms/transformExpressions.spec.ts index 7ca831f0ce8..af14265e27a 100644 --- a/packages/compiler-core/__tests__/transforms/transformExpressions.spec.ts +++ b/packages/compiler-core/__tests__/transforms/transformExpressions.spec.ts @@ -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( + `
`, + ) + expect(code).not.toMatch(`_ctx.x`) + expect(code).toMatchSnapshot() + }) + + test('should not prefix temp variable of for...of', () => { + const { code } = compile( + `
`, + ) + expect(code).not.toMatch(`_ctx.x`) + expect(code).toMatchSnapshot() + }) + + test('should not prefix temp variable of for loop', () => { + const { code } = compile( + `
`, + ) + expect(code).not.toMatch(`_ctx.i`) + expect(code).toMatchSnapshot() + }) + + test('should not prefix catch block param', () => { + const { code } = compile( + `
`, + ) + 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( + `
`, + ) + 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( - `
`, - ) - expect(code).not.toMatch(`_ctx.x`) - expect(code).toMatchSnapshot() - }) - - test('should not prefix temp variable of for...of', () => { - const { code } = compileWithBindingMetadata( - `
`, - ) - expect(code).not.toMatch(`_ctx.x`) - expect(code).toMatchSnapshot() - }) - - test('should not prefix temp variable of for loop', () => { - const { code } = compileWithBindingMetadata( - `
`, - ) - expect(code).not.toMatch(`_ctx.i`) - expect(code).toMatchSnapshot() - }) - test('inline mode', () => { const { code } = compileWithBindingMetadata( `
{{ props }} {{ setup }} {{ setupConst }} {{ data }} {{ options }} {{ isNaN }}
`, diff --git a/packages/compiler-core/src/babelUtils.ts b/packages/compiler-core/src/babelUtils.ts index 67997798864..3144ed595b4 100644 --- a/packages/compiler-core/src/babelUtils.ts +++ b/packages/compiler-core/src/babelUtils.ts @@ -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 }, parent: Node | null) {