From 53fd09cbd7f559ea65dbcbf8c77eea1fcf67b691 Mon Sep 17 00:00:00 2001 From: magic-akari Date: Tue, 26 Mar 2024 12:20:44 +0800 Subject: [PATCH] fix(es/parser): Parse `await using` in for head (#8775) **Related issue:** - Closes #8774 --- .../fixture/issues-8xxx/8774/input/.swcrc | 20 +++ .../fixture/issues-8xxx/8774/input/index.js | 21 +++ .../fixture/issues-8xxx/8774/output/index.js | 53 +++++++ ...onsInForAwaitOf(target=es2015).1.normal.js | 62 +++++++-- ...sInForAwaitOf(target=es2015).2.minified.js | 12 +- ...onsInForAwaitOf(target=es2017).1.normal.js | 32 +++-- ...sInForAwaitOf(target=es2017).2.minified.js | 10 +- ...onsInForAwaitOf(target=es2022).1.normal.js | 32 +++-- ...sInForAwaitOf(target=es2022).2.minified.js | 10 +- ...ationsInForAwaitOf(target=es5).1.normal.js | 131 ++++++++++++++++-- ...ionsInForAwaitOf(target=es5).2.minified.js | 14 +- ...onsInForAwaitOf(target=esnext).1.normal.js | 32 +++-- ...sInForAwaitOf(target=esnext).2.minified.js | 10 +- ...ationsInForOf.1(target=es2015).1.normal.js | 42 ++++-- ...ionsInForOf.1(target=es2015).2.minified.js | 12 +- ...ationsInForOf.1(target=es2017).1.normal.js | 33 +++-- ...ionsInForOf.1(target=es2017).2.minified.js | 11 +- ...ationsInForOf.1(target=es2022).1.normal.js | 33 +++-- ...ionsInForOf.1(target=es2022).2.minified.js | 11 +- ...larationsInForOf.1(target=es5).1.normal.js | 53 +++++-- ...rationsInForOf.1(target=es5).2.minified.js | 14 +- ...ationsInForOf.1(target=esnext).1.normal.js | 33 +++-- ...ionsInForOf.1(target=esnext).2.minified.js | 11 +- crates/swc_ecma_parser/src/parser/stmt.rs | 38 +++-- .../tests/strip_correctness.rs | 2 + 25 files changed, 532 insertions(+), 200 deletions(-) create mode 100644 crates/swc/tests/fixture/issues-8xxx/8774/input/.swcrc create mode 100644 crates/swc/tests/fixture/issues-8xxx/8774/input/index.js create mode 100644 crates/swc/tests/fixture/issues-8xxx/8774/output/index.js diff --git a/crates/swc/tests/fixture/issues-8xxx/8774/input/.swcrc b/crates/swc/tests/fixture/issues-8xxx/8774/input/.swcrc new file mode 100644 index 00000000000..eb9185951de --- /dev/null +++ b/crates/swc/tests/fixture/issues-8xxx/8774/input/.swcrc @@ -0,0 +1,20 @@ +{ + "jsc": { + "parser": { + "explicitResourceManagement": true, + "syntax": "ecmascript", + "jsx": true, + }, + "target": "es2022", + "loose": false, + "minify": { + "compress": false, + "mangle": false + } + }, + "module": { + "type": "es6" + }, + "minify": false, + "isModule": true +} \ No newline at end of file diff --git a/crates/swc/tests/fixture/issues-8xxx/8774/input/index.js b/crates/swc/tests/fixture/issues-8xxx/8774/input/index.js new file mode 100644 index 00000000000..9a7c9ac452f --- /dev/null +++ b/crates/swc/tests/fixture/issues-8xxx/8774/input/index.js @@ -0,0 +1,21 @@ +const logClean = function () { + return { + [Symbol.dispose]() { + console.log("clean in sync"); + }, + [Symbol.asyncDispose]() { + console.log("clean in async"); + }, + }; +}; + +async function foo() { + using a = logClean(); + await using b = logClean(); + for (using a of [logClean(), logClean()]) { + } + for (await using a of [logClean(), logClean()]) { + } +} + +foo(); diff --git a/crates/swc/tests/fixture/issues-8xxx/8774/output/index.js b/crates/swc/tests/fixture/issues-8xxx/8774/output/index.js new file mode 100644 index 00000000000..15e70fb6315 --- /dev/null +++ b/crates/swc/tests/fixture/issues-8xxx/8774/output/index.js @@ -0,0 +1,53 @@ +import { _ as _dispose } from "@swc/helpers/_/_dispose"; +import { _ as _using } from "@swc/helpers/_/_using"; +const logClean = function() { + return { + [Symbol.dispose] () { + console.log("clean in sync"); + }, + [Symbol.asyncDispose] () { + console.log("clean in async"); + } + }; +}; +async function foo() { + try { + var _stack = []; + var a = _using(_stack, logClean()); + var b = _using(_stack, logClean(), true); + for (const a of [ + logClean(), + logClean() + ]){ + try { + var _stack1 = []; + {} + } catch (_) { + var _error = _; + var _hasError = true; + } finally{ + _dispose(_stack1, _error, _hasError); + } + } + for (const a of [ + logClean(), + logClean() + ]){ + try { + var _stack2 = []; + {} + } catch (_) { + var _error1 = _; + var _hasError1 = true; + } finally{ + _dispose(_stack2, _error1, _hasError1); + } + } + } catch (_) { + var _error2 = _; + var _hasError2 = true; + } finally{ + await _dispose(_stack, _error2, _hasError2); + } +} +foo(); diff --git a/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForAwaitOf(target=es2015).1.normal.js b/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForAwaitOf(target=es2015).1.normal.js index dfc5e46c104..1566d75ea6f 100644 --- a/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForAwaitOf(target=es2015).1.normal.js +++ b/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForAwaitOf(target=es2015).1.normal.js @@ -1,10 +1,54 @@ //// [awaitUsingDeclarationsInForAwaitOf.ts] -//! -//! x Expected ';', got 'd1' -//! ,-[1:1] -//! 1 | async function main() { -//! 2 | for await (await using d1 of [{ async [Symbol.asyncDispose]() {} }, { [Symbol.dispose]() {} }, null, undefined]) { -//! : ^^ -//! 3 | } -//! 4 | } -//! `---- +import { _ as _async_iterator } from "@swc/helpers/_/_async_iterator"; +import { _ as _async_to_generator } from "@swc/helpers/_/_async_to_generator"; +import { _ as _dispose } from "@swc/helpers/_/_dispose"; +function main() { + return _main.apply(this, arguments); +} +function _main() { + _main = _async_to_generator(function*() { + { + var _iteratorAbruptCompletion = false, _didIteratorError = false, _iteratorError; + try { + for(var _iterator = _async_iterator([ + { + [Symbol.asyncDispose] () { + return _async_to_generator(function*() {})(); + } + }, + { + [Symbol.dispose] () {} + }, + null, + undefined + ]), _step; _iteratorAbruptCompletion = !(_step = yield _iterator.next()).done; _iteratorAbruptCompletion = false){ + let _value = _step.value; + const d1 = _value; + try { + var _stack = []; + {} + } catch (_) { + var _error = _; + var _hasError = true; + } finally{ + _dispose(_stack, _error, _hasError); + } + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally{ + try { + if (_iteratorAbruptCompletion && _iterator.return != null) { + yield _iterator.return(); + } + } finally{ + if (_didIteratorError) { + throw _iteratorError; + } + } + } + } + }); + return _main.apply(this, arguments); +} diff --git a/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForAwaitOf(target=es2015).2.minified.js b/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForAwaitOf(target=es2015).2.minified.js index dfc5e46c104..aecf0b6155f 100644 --- a/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForAwaitOf(target=es2015).2.minified.js +++ b/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForAwaitOf(target=es2015).2.minified.js @@ -1,10 +1,4 @@ //// [awaitUsingDeclarationsInForAwaitOf.ts] -//! -//! x Expected ';', got 'd1' -//! ,-[1:1] -//! 1 | async function main() { -//! 2 | for await (await using d1 of [{ async [Symbol.asyncDispose]() {} }, { [Symbol.dispose]() {} }, null, undefined]) { -//! : ^^ -//! 3 | } -//! 4 | } -//! `---- +import "@swc/helpers/_/_async_iterator"; +import "@swc/helpers/_/_async_to_generator"; +import "@swc/helpers/_/_dispose"; diff --git a/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForAwaitOf(target=es2017).1.normal.js b/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForAwaitOf(target=es2017).1.normal.js index dfc5e46c104..34268ec9e78 100644 --- a/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForAwaitOf(target=es2017).1.normal.js +++ b/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForAwaitOf(target=es2017).1.normal.js @@ -1,10 +1,24 @@ //// [awaitUsingDeclarationsInForAwaitOf.ts] -//! -//! x Expected ';', got 'd1' -//! ,-[1:1] -//! 1 | async function main() { -//! 2 | for await (await using d1 of [{ async [Symbol.asyncDispose]() {} }, { [Symbol.dispose]() {} }, null, undefined]) { -//! : ^^ -//! 3 | } -//! 4 | } -//! `---- +import { _ as _dispose } from "@swc/helpers/_/_dispose"; +async function main() { + for await (const d1 of [ + { + async [Symbol.asyncDispose] () {} + }, + { + [Symbol.dispose] () {} + }, + null, + undefined + ]){ + try { + var _stack = []; + {} + } catch (_) { + var _error = _; + var _hasError = true; + } finally{ + _dispose(_stack, _error, _hasError); + } + } +} diff --git a/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForAwaitOf(target=es2017).2.minified.js b/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForAwaitOf(target=es2017).2.minified.js index dfc5e46c104..0c372bedeea 100644 --- a/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForAwaitOf(target=es2017).2.minified.js +++ b/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForAwaitOf(target=es2017).2.minified.js @@ -1,10 +1,2 @@ //// [awaitUsingDeclarationsInForAwaitOf.ts] -//! -//! x Expected ';', got 'd1' -//! ,-[1:1] -//! 1 | async function main() { -//! 2 | for await (await using d1 of [{ async [Symbol.asyncDispose]() {} }, { [Symbol.dispose]() {} }, null, undefined]) { -//! : ^^ -//! 3 | } -//! 4 | } -//! `---- +import "@swc/helpers/_/_dispose"; diff --git a/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForAwaitOf(target=es2022).1.normal.js b/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForAwaitOf(target=es2022).1.normal.js index dfc5e46c104..34268ec9e78 100644 --- a/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForAwaitOf(target=es2022).1.normal.js +++ b/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForAwaitOf(target=es2022).1.normal.js @@ -1,10 +1,24 @@ //// [awaitUsingDeclarationsInForAwaitOf.ts] -//! -//! x Expected ';', got 'd1' -//! ,-[1:1] -//! 1 | async function main() { -//! 2 | for await (await using d1 of [{ async [Symbol.asyncDispose]() {} }, { [Symbol.dispose]() {} }, null, undefined]) { -//! : ^^ -//! 3 | } -//! 4 | } -//! `---- +import { _ as _dispose } from "@swc/helpers/_/_dispose"; +async function main() { + for await (const d1 of [ + { + async [Symbol.asyncDispose] () {} + }, + { + [Symbol.dispose] () {} + }, + null, + undefined + ]){ + try { + var _stack = []; + {} + } catch (_) { + var _error = _; + var _hasError = true; + } finally{ + _dispose(_stack, _error, _hasError); + } + } +} diff --git a/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForAwaitOf(target=es2022).2.minified.js b/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForAwaitOf(target=es2022).2.minified.js index dfc5e46c104..0c372bedeea 100644 --- a/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForAwaitOf(target=es2022).2.minified.js +++ b/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForAwaitOf(target=es2022).2.minified.js @@ -1,10 +1,2 @@ //// [awaitUsingDeclarationsInForAwaitOf.ts] -//! -//! x Expected ';', got 'd1' -//! ,-[1:1] -//! 1 | async function main() { -//! 2 | for await (await using d1 of [{ async [Symbol.asyncDispose]() {} }, { [Symbol.dispose]() {} }, null, undefined]) { -//! : ^^ -//! 3 | } -//! 4 | } -//! `---- +import "@swc/helpers/_/_dispose"; diff --git a/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForAwaitOf(target=es5).1.normal.js b/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForAwaitOf(target=es5).1.normal.js index dfc5e46c104..9f4cd0d7b43 100644 --- a/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForAwaitOf(target=es5).1.normal.js +++ b/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForAwaitOf(target=es5).1.normal.js @@ -1,10 +1,123 @@ //// [awaitUsingDeclarationsInForAwaitOf.ts] -//! -//! x Expected ';', got 'd1' -//! ,-[1:1] -//! 1 | async function main() { -//! 2 | for await (await using d1 of [{ async [Symbol.asyncDispose]() {} }, { [Symbol.dispose]() {} }, null, undefined]) { -//! : ^^ -//! 3 | } -//! 4 | } -//! `---- +import { _ as _async_iterator } from "@swc/helpers/_/_async_iterator"; +import { _ as _async_to_generator } from "@swc/helpers/_/_async_to_generator"; +import { _ as _define_property } from "@swc/helpers/_/_define_property"; +import { _ as _ts_generator } from "@swc/helpers/_/_ts_generator"; +import { _ as _dispose } from "@swc/helpers/_/_dispose"; +function main() { + return _main.apply(this, arguments); +} +function _main() { + _main = _async_to_generator(function() { + var _iteratorAbruptCompletion, _didIteratorError, _iteratorError, _iterator, _step, _value, d1, _stack, _error, _hasError, err; + return _ts_generator(this, function(_state) { + switch(_state.label){ + case 0: + _iteratorAbruptCompletion = false, _didIteratorError = false; + _state.label = 1; + case 1: + _state.trys.push([ + 1, + 6, + 7, + 12 + ]); + _iterator = _async_iterator([ + _define_property({}, Symbol.asyncDispose, function() { + return _async_to_generator(function() { + return _ts_generator(this, function(_state) { + return [ + 2 + ]; + }); + })(); + }), + _define_property({}, Symbol.dispose, function() {}), + null, + undefined + ]); + _state.label = 2; + case 2: + return [ + 4, + _iterator.next() + ]; + case 3: + if (!(_iteratorAbruptCompletion = !(_step = _state.sent()).done)) return [ + 3, + 5 + ]; + _value = _step.value; + d1 = _value; + try { + _stack = []; + {} + } catch (_) { + _error = _; + _hasError = true; + } finally{ + _dispose(_stack, _error, _hasError); + } + _state.label = 4; + case 4: + _iteratorAbruptCompletion = false; + return [ + 3, + 2 + ]; + case 5: + return [ + 3, + 12 + ]; + case 6: + err = _state.sent(); + _didIteratorError = true; + _iteratorError = err; + return [ + 3, + 12 + ]; + case 7: + _state.trys.push([ + 7, + , + 10, + 11 + ]); + if (!(_iteratorAbruptCompletion && _iterator.return != null)) return [ + 3, + 9 + ]; + return [ + 4, + _iterator.return() + ]; + case 8: + _state.sent(); + _state.label = 9; + case 9: + return [ + 3, + 11 + ]; + case 10: + if (_didIteratorError) { + throw _iteratorError; + } + return [ + 7 + ]; + case 11: + return [ + 7 + ]; + case 12: + return [ + 2 + ]; + } + }); + }); + return _main.apply(this, arguments); +} diff --git a/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForAwaitOf(target=es5).2.minified.js b/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForAwaitOf(target=es5).2.minified.js index dfc5e46c104..3bf70bce4f9 100644 --- a/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForAwaitOf(target=es5).2.minified.js +++ b/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForAwaitOf(target=es5).2.minified.js @@ -1,10 +1,6 @@ //// [awaitUsingDeclarationsInForAwaitOf.ts] -//! -//! x Expected ';', got 'd1' -//! ,-[1:1] -//! 1 | async function main() { -//! 2 | for await (await using d1 of [{ async [Symbol.asyncDispose]() {} }, { [Symbol.dispose]() {} }, null, undefined]) { -//! : ^^ -//! 3 | } -//! 4 | } -//! `---- +import "@swc/helpers/_/_async_iterator"; +import "@swc/helpers/_/_async_to_generator"; +import "@swc/helpers/_/_define_property"; +import "@swc/helpers/_/_ts_generator"; +import "@swc/helpers/_/_dispose"; diff --git a/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForAwaitOf(target=esnext).1.normal.js b/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForAwaitOf(target=esnext).1.normal.js index dfc5e46c104..34268ec9e78 100644 --- a/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForAwaitOf(target=esnext).1.normal.js +++ b/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForAwaitOf(target=esnext).1.normal.js @@ -1,10 +1,24 @@ //// [awaitUsingDeclarationsInForAwaitOf.ts] -//! -//! x Expected ';', got 'd1' -//! ,-[1:1] -//! 1 | async function main() { -//! 2 | for await (await using d1 of [{ async [Symbol.asyncDispose]() {} }, { [Symbol.dispose]() {} }, null, undefined]) { -//! : ^^ -//! 3 | } -//! 4 | } -//! `---- +import { _ as _dispose } from "@swc/helpers/_/_dispose"; +async function main() { + for await (const d1 of [ + { + async [Symbol.asyncDispose] () {} + }, + { + [Symbol.dispose] () {} + }, + null, + undefined + ]){ + try { + var _stack = []; + {} + } catch (_) { + var _error = _; + var _hasError = true; + } finally{ + _dispose(_stack, _error, _hasError); + } + } +} diff --git a/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForAwaitOf(target=esnext).2.minified.js b/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForAwaitOf(target=esnext).2.minified.js index dfc5e46c104..0c372bedeea 100644 --- a/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForAwaitOf(target=esnext).2.minified.js +++ b/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForAwaitOf(target=esnext).2.minified.js @@ -1,10 +1,2 @@ //// [awaitUsingDeclarationsInForAwaitOf.ts] -//! -//! x Expected ';', got 'd1' -//! ,-[1:1] -//! 1 | async function main() { -//! 2 | for await (await using d1 of [{ async [Symbol.asyncDispose]() {} }, { [Symbol.dispose]() {} }, null, undefined]) { -//! : ^^ -//! 3 | } -//! 4 | } -//! `---- +import "@swc/helpers/_/_dispose"; diff --git a/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForOf.1(target=es2015).1.normal.js b/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForOf.1(target=es2015).1.normal.js index 6fef9708f9b..6f241e475a6 100644 --- a/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForOf.1(target=es2015).1.normal.js +++ b/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForOf.1(target=es2015).1.normal.js @@ -1,11 +1,33 @@ //// [awaitUsingDeclarationsInForOf.1.ts] -//! -//! x Expected ';', got 'd1' -//! ,-[1:1] -//! 1 | -//! 2 | async function main() { -//! 3 | for (await using d1 of [{ async [Symbol.asyncDispose]() {} }, { [Symbol.dispose]() {} }, null, undefined]) { -//! : ^^ -//! 4 | } -//! 5 | } -//! `---- +import { _ as _async_to_generator } from "@swc/helpers/_/_async_to_generator"; +import { _ as _dispose } from "@swc/helpers/_/_dispose"; +function main() { + return _main.apply(this, arguments); +} +function _main() { + _main = _async_to_generator(function*() { + for (const d1 of [ + { + [Symbol.asyncDispose] () { + return _async_to_generator(function*() {})(); + } + }, + { + [Symbol.dispose] () {} + }, + null, + undefined + ]){ + try { + var _stack = []; + {} + } catch (_) { + var _error = _; + var _hasError = true; + } finally{ + _dispose(_stack, _error, _hasError); + } + } + }); + return _main.apply(this, arguments); +} diff --git a/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForOf.1(target=es2015).2.minified.js b/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForOf.1(target=es2015).2.minified.js index 6fef9708f9b..e56fa25f934 100644 --- a/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForOf.1(target=es2015).2.minified.js +++ b/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForOf.1(target=es2015).2.minified.js @@ -1,11 +1,3 @@ //// [awaitUsingDeclarationsInForOf.1.ts] -//! -//! x Expected ';', got 'd1' -//! ,-[1:1] -//! 1 | -//! 2 | async function main() { -//! 3 | for (await using d1 of [{ async [Symbol.asyncDispose]() {} }, { [Symbol.dispose]() {} }, null, undefined]) { -//! : ^^ -//! 4 | } -//! 5 | } -//! `---- +import "@swc/helpers/_/_async_to_generator"; +import "@swc/helpers/_/_dispose"; diff --git a/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForOf.1(target=es2017).1.normal.js b/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForOf.1(target=es2017).1.normal.js index 6fef9708f9b..a9415bf9b80 100644 --- a/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForOf.1(target=es2017).1.normal.js +++ b/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForOf.1(target=es2017).1.normal.js @@ -1,11 +1,24 @@ //// [awaitUsingDeclarationsInForOf.1.ts] -//! -//! x Expected ';', got 'd1' -//! ,-[1:1] -//! 1 | -//! 2 | async function main() { -//! 3 | for (await using d1 of [{ async [Symbol.asyncDispose]() {} }, { [Symbol.dispose]() {} }, null, undefined]) { -//! : ^^ -//! 4 | } -//! 5 | } -//! `---- +import { _ as _dispose } from "@swc/helpers/_/_dispose"; +async function main() { + for (const d1 of [ + { + async [Symbol.asyncDispose] () {} + }, + { + [Symbol.dispose] () {} + }, + null, + undefined + ]){ + try { + var _stack = []; + {} + } catch (_) { + var _error = _; + var _hasError = true; + } finally{ + _dispose(_stack, _error, _hasError); + } + } +} diff --git a/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForOf.1(target=es2017).2.minified.js b/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForOf.1(target=es2017).2.minified.js index 6fef9708f9b..627c0b7e321 100644 --- a/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForOf.1(target=es2017).2.minified.js +++ b/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForOf.1(target=es2017).2.minified.js @@ -1,11 +1,2 @@ //// [awaitUsingDeclarationsInForOf.1.ts] -//! -//! x Expected ';', got 'd1' -//! ,-[1:1] -//! 1 | -//! 2 | async function main() { -//! 3 | for (await using d1 of [{ async [Symbol.asyncDispose]() {} }, { [Symbol.dispose]() {} }, null, undefined]) { -//! : ^^ -//! 4 | } -//! 5 | } -//! `---- +import "@swc/helpers/_/_dispose"; diff --git a/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForOf.1(target=es2022).1.normal.js b/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForOf.1(target=es2022).1.normal.js index 6fef9708f9b..a9415bf9b80 100644 --- a/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForOf.1(target=es2022).1.normal.js +++ b/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForOf.1(target=es2022).1.normal.js @@ -1,11 +1,24 @@ //// [awaitUsingDeclarationsInForOf.1.ts] -//! -//! x Expected ';', got 'd1' -//! ,-[1:1] -//! 1 | -//! 2 | async function main() { -//! 3 | for (await using d1 of [{ async [Symbol.asyncDispose]() {} }, { [Symbol.dispose]() {} }, null, undefined]) { -//! : ^^ -//! 4 | } -//! 5 | } -//! `---- +import { _ as _dispose } from "@swc/helpers/_/_dispose"; +async function main() { + for (const d1 of [ + { + async [Symbol.asyncDispose] () {} + }, + { + [Symbol.dispose] () {} + }, + null, + undefined + ]){ + try { + var _stack = []; + {} + } catch (_) { + var _error = _; + var _hasError = true; + } finally{ + _dispose(_stack, _error, _hasError); + } + } +} diff --git a/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForOf.1(target=es2022).2.minified.js b/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForOf.1(target=es2022).2.minified.js index 6fef9708f9b..627c0b7e321 100644 --- a/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForOf.1(target=es2022).2.minified.js +++ b/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForOf.1(target=es2022).2.minified.js @@ -1,11 +1,2 @@ //// [awaitUsingDeclarationsInForOf.1.ts] -//! -//! x Expected ';', got 'd1' -//! ,-[1:1] -//! 1 | -//! 2 | async function main() { -//! 3 | for (await using d1 of [{ async [Symbol.asyncDispose]() {} }, { [Symbol.dispose]() {} }, null, undefined]) { -//! : ^^ -//! 4 | } -//! 5 | } -//! `---- +import "@swc/helpers/_/_dispose"; diff --git a/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForOf.1(target=es5).1.normal.js b/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForOf.1(target=es5).1.normal.js index 6fef9708f9b..f23474fd18f 100644 --- a/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForOf.1(target=es5).1.normal.js +++ b/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForOf.1(target=es5).1.normal.js @@ -1,11 +1,44 @@ //// [awaitUsingDeclarationsInForOf.1.ts] -//! -//! x Expected ';', got 'd1' -//! ,-[1:1] -//! 1 | -//! 2 | async function main() { -//! 3 | for (await using d1 of [{ async [Symbol.asyncDispose]() {} }, { [Symbol.dispose]() {} }, null, undefined]) { -//! : ^^ -//! 4 | } -//! 5 | } -//! `---- +import { _ as _async_to_generator } from "@swc/helpers/_/_async_to_generator"; +import { _ as _define_property } from "@swc/helpers/_/_define_property"; +import { _ as _ts_generator } from "@swc/helpers/_/_ts_generator"; +import { _ as _dispose } from "@swc/helpers/_/_dispose"; +function main() { + return _main.apply(this, arguments); +} +function _main() { + _main = _async_to_generator(function() { + var _i, _iter, d1, _stack, _error, _hasError; + return _ts_generator(this, function(_state) { + for(_i = 0, _iter = [ + _define_property({}, Symbol.asyncDispose, function() { + return _async_to_generator(function() { + return _ts_generator(this, function(_state) { + return [ + 2 + ]; + }); + })(); + }), + _define_property({}, Symbol.dispose, function() {}), + null, + undefined + ]; _i < _iter.length; _i++){ + d1 = _iter[_i]; + try { + _stack = []; + {} + } catch (_) { + _error = _; + _hasError = true; + } finally{ + _dispose(_stack, _error, _hasError); + } + } + return [ + 2 + ]; + }); + }); + return _main.apply(this, arguments); +} diff --git a/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForOf.1(target=es5).2.minified.js b/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForOf.1(target=es5).2.minified.js index 6fef9708f9b..abedd580b28 100644 --- a/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForOf.1(target=es5).2.minified.js +++ b/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForOf.1(target=es5).2.minified.js @@ -1,11 +1,5 @@ //// [awaitUsingDeclarationsInForOf.1.ts] -//! -//! x Expected ';', got 'd1' -//! ,-[1:1] -//! 1 | -//! 2 | async function main() { -//! 3 | for (await using d1 of [{ async [Symbol.asyncDispose]() {} }, { [Symbol.dispose]() {} }, null, undefined]) { -//! : ^^ -//! 4 | } -//! 5 | } -//! `---- +import "@swc/helpers/_/_async_to_generator"; +import "@swc/helpers/_/_define_property"; +import "@swc/helpers/_/_ts_generator"; +import "@swc/helpers/_/_dispose"; diff --git a/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForOf.1(target=esnext).1.normal.js b/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForOf.1(target=esnext).1.normal.js index 6fef9708f9b..a9415bf9b80 100644 --- a/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForOf.1(target=esnext).1.normal.js +++ b/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForOf.1(target=esnext).1.normal.js @@ -1,11 +1,24 @@ //// [awaitUsingDeclarationsInForOf.1.ts] -//! -//! x Expected ';', got 'd1' -//! ,-[1:1] -//! 1 | -//! 2 | async function main() { -//! 3 | for (await using d1 of [{ async [Symbol.asyncDispose]() {} }, { [Symbol.dispose]() {} }, null, undefined]) { -//! : ^^ -//! 4 | } -//! 5 | } -//! `---- +import { _ as _dispose } from "@swc/helpers/_/_dispose"; +async function main() { + for (const d1 of [ + { + async [Symbol.asyncDispose] () {} + }, + { + [Symbol.dispose] () {} + }, + null, + undefined + ]){ + try { + var _stack = []; + {} + } catch (_) { + var _error = _; + var _hasError = true; + } finally{ + _dispose(_stack, _error, _hasError); + } + } +} diff --git a/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForOf.1(target=esnext).2.minified.js b/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForOf.1(target=esnext).2.minified.js index 6fef9708f9b..627c0b7e321 100644 --- a/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForOf.1(target=esnext).2.minified.js +++ b/crates/swc/tests/tsc-references/awaitUsingDeclarationsInForOf.1(target=esnext).2.minified.js @@ -1,11 +1,2 @@ //// [awaitUsingDeclarationsInForOf.1.ts] -//! -//! x Expected ';', got 'd1' -//! ,-[1:1] -//! 1 | -//! 2 | async function main() { -//! 3 | for (await using d1 of [{ async [Symbol.asyncDispose]() {} }, { [Symbol.dispose]() {} }, null, undefined]) { -//! : ^^ -//! 4 | } -//! 5 | } -//! `---- +import "@swc/helpers/_/_dispose"; diff --git a/crates/swc_ecma_parser/src/parser/stmt.rs b/crates/swc_ecma_parser/src/parser/stmt.rs index 0564527bf21..f414f795f74 100644 --- a/crates/swc_ecma_parser/src/parser/stmt.rs +++ b/crates/swc_ecma_parser/src/parser/stmt.rs @@ -1286,15 +1286,33 @@ impl<'a, I: Tokens> Parser { let start = cur_pos!(self); let init = self.include_in_expr(false).parse_for_head_prefix()?; - let is_using_decl = self.input.syntax().explicit_resource_management() - && match *init { - _ if init.is_ident_ref_to("using") => { - is!(self, BindingIdent) - && !is!(self, "of") - && (peeked_is!(self, "of") || peeked_is!(self, "in")) - } - _ => false, - }; + let mut is_using_decl = false; + let mut is_await_using_decl = false; + + if self.input.syntax().explicit_resource_management() { + // using foo + let mut maybe_using_decl = init.is_ident_ref_to("using"); + let mut maybe_await_using_decl = false; + + // await using foo + if !maybe_using_decl + && init + .as_await_expr() + .filter(|e| e.arg.is_ident_ref_to("using")) + .is_some() + { + maybe_using_decl = true; + maybe_await_using_decl = true; + } + + if maybe_using_decl + && !is!(self, "of") + && (peeked_is!(self, "of") || peeked_is!(self, "in")) + { + is_using_decl = maybe_using_decl; + is_await_using_decl = maybe_await_using_decl; + } + } if is_using_decl { let name = self.parse_binding_ident()?; @@ -1307,7 +1325,7 @@ impl<'a, I: Tokens> Parser { let pat = Box::new(UsingDecl { span: span!(self, start), - is_await: false, + is_await: is_await_using_decl, decls: vec![decl], }); diff --git a/crates/swc_ecma_transforms_typescript/tests/strip_correctness.rs b/crates/swc_ecma_transforms_typescript/tests/strip_correctness.rs index 01d7d531765..4a6dcfc8e29 100644 --- a/crates/swc_ecma_transforms_typescript/tests/strip_correctness.rs +++ b/crates/swc_ecma_transforms_typescript/tests/strip_correctness.rs @@ -48,6 +48,8 @@ fn identity(entry: PathBuf) { "constEnum4.ts", "decoratorOnClassMethod11.ts", "elementAccessChain.3.ts", + "awaitUsingDeclarationsInForAwaitOf.ts", + "awaitUsingDeclarationsInForOf.1.ts", "usingDeclarationsInForOf.1.ts", "usingDeclarationsInForAwaitOf.ts", "tsxReactEmitNesting.tsx",