fix(es/parser): Parse await using in for head (#8775)

**Related issue:**
 
 - Closes #8774
This commit is contained in:
magic-akari 2024-03-26 12:20:44 +08:00 committed by GitHub
parent cd06af3ef7
commit 53fd09cbd7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
25 changed files with 532 additions and 200 deletions

View File

@ -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
}

View File

@ -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();

View File

@ -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();

View File

@ -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);
}

View File

@ -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";

View File

@ -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);
}
}
}

View File

@ -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";

View File

@ -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);
}
}
}

View File

@ -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";

View File

@ -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);
}

View File

@ -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";

View File

@ -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);
}
}
}

View File

@ -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";

View File

@ -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);
}

View File

@ -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";

View File

@ -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);
}
}
}

View File

@ -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";

View File

@ -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);
}
}
}

View File

@ -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";

View File

@ -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);
}

View File

@ -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";

View File

@ -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);
}
}
}

View File

@ -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";

View File

@ -1286,15 +1286,33 @@ impl<'a, I: Tokens> Parser<I> {
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)
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;
}
}
_ => false,
};
if is_using_decl {
let name = self.parse_binding_ident()?;
@ -1307,7 +1325,7 @@ impl<'a, I: Tokens> Parser<I> {
let pat = Box::new(UsingDecl {
span: span!(self, start),
is_await: false,
is_await: is_await_using_decl,
decls: vec![decl],
});

View File

@ -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",