fix: TLA 游走器补 if 测试臂与类声明 extends 臂

This commit is contained in:
2026-10-13 18:43:45 +00:00
parent cfd00db9f0
commit 1ad4c63c94
4 changed files with 74 additions and 30 deletions
Generated
+21 -21
View File
@@ -1160,7 +1160,7 @@ dependencies = [
[[package]]
name = "oxide_builtins"
version = "0.18.8"
version = "0.18.9"
dependencies = [
"chrono",
"fast-float",
@@ -1185,7 +1185,7 @@ dependencies = [
[[package]]
name = "oxide_bytecode"
version = "0.18.8"
version = "0.18.9"
dependencies = [
"num-bigint",
"oxide_log",
@@ -1193,7 +1193,7 @@ dependencies = [
[[package]]
name = "oxide_cfg"
version = "0.18.8"
version = "0.18.9"
dependencies = [
"oxide_bytecode",
"oxide_emit",
@@ -1204,7 +1204,7 @@ dependencies = [
[[package]]
name = "oxide_cli"
version = "0.18.8"
version = "0.18.9"
dependencies = [
"ansi_term",
"bumpalo",
@@ -1228,7 +1228,7 @@ dependencies = [
[[package]]
name = "oxide_code_cache"
version = "0.18.8"
version = "0.18.9"
dependencies = [
"lru",
"oxide_bytecode",
@@ -1237,7 +1237,7 @@ dependencies = [
[[package]]
name = "oxide_compiler"
version = "0.18.8"
version = "0.18.9"
dependencies = [
"oxide_bytecode",
"oxide_cfg",
@@ -1258,7 +1258,7 @@ dependencies = [
[[package]]
name = "oxide_dce"
version = "0.18.8"
version = "0.18.9"
dependencies = [
"oxide_bytecode",
"oxide_cfg",
@@ -1272,7 +1272,7 @@ dependencies = [
[[package]]
name = "oxide_emit"
version = "0.18.8"
version = "0.18.9"
dependencies = [
"num-bigint",
"oxc_allocator",
@@ -1288,7 +1288,7 @@ dependencies = [
[[package]]
name = "oxide_engine"
version = "0.18.8"
version = "0.18.9"
dependencies = [
"oxide_bytecode",
"oxide_compiler",
@@ -1300,7 +1300,7 @@ dependencies = [
[[package]]
name = "oxide_fold"
version = "0.18.8"
version = "0.18.9"
dependencies = [
"num-bigint",
"oxide_bytecode",
@@ -1312,7 +1312,7 @@ dependencies = [
[[package]]
name = "oxide_ir"
version = "0.18.8"
version = "0.18.9"
dependencies = [
"oxide_bytecode",
"oxide_log",
@@ -1321,7 +1321,7 @@ dependencies = [
[[package]]
name = "oxide_kernel"
version = "0.18.8"
version = "0.18.9"
dependencies = [
"bumpalo",
"dashmap",
@@ -1335,7 +1335,7 @@ dependencies = [
[[package]]
name = "oxide_liveness"
version = "0.18.8"
version = "0.18.9"
dependencies = [
"oxide_bytecode",
"oxide_cfg",
@@ -1347,7 +1347,7 @@ dependencies = [
[[package]]
name = "oxide_log"
version = "0.18.8"
version = "0.18.9"
dependencies = [
"tracing",
"tracing-appender",
@@ -1356,11 +1356,11 @@ dependencies = [
[[package]]
name = "oxide_net"
version = "0.18.8"
version = "0.18.9"
[[package]]
name = "oxide_parser"
version = "0.18.8"
version = "0.18.9"
dependencies = [
"oxc_allocator",
"oxc_ast",
@@ -1375,7 +1375,7 @@ dependencies = [
[[package]]
name = "oxide_regalloc"
version = "0.18.8"
version = "0.18.9"
dependencies = [
"oxide_bytecode",
"oxide_cfg",
@@ -1391,7 +1391,7 @@ dependencies = [
[[package]]
name = "oxide_runtime_api"
version = "0.18.8"
version = "0.18.9"
dependencies = [
"num-bigint",
"num-traits",
@@ -1404,7 +1404,7 @@ dependencies = [
[[package]]
name = "oxide_test262"
version = "0.18.8"
version = "0.18.9"
dependencies = [
"oxide_bytecode",
"oxide_compiler",
@@ -1424,7 +1424,7 @@ dependencies = [
[[package]]
name = "oxide_types"
version = "0.18.8"
version = "0.18.9"
dependencies = [
"bumpalo",
"dashmap",
@@ -1437,7 +1437,7 @@ dependencies = [
[[package]]
name = "oxide_vm"
version = "0.18.8"
version = "0.18.9"
dependencies = [
"bumpalo",
"chrono",
+1 -1
View File
@@ -25,7 +25,7 @@ members = [
]
[workspace.package]
version = "0.18.8"
version = "0.18.9"
edition = "2021"
license = "MIT"
rust-version = "1.80"
+20 -8
View File
@@ -356,7 +356,8 @@ fn stmt_has_top_level_await(stmt: &Statement) -> bool {
match stmt {
Statement::BlockStatement(block) => block.body.iter().any(|s| stmt_has_top_level_await(s)),
Statement::IfStatement(if_stmt) => {
stmt_has_top_level_await(&if_stmt.consequent)
expr_has_top_level_await(&if_stmt.test)
|| stmt_has_top_level_await(&if_stmt.consequent)
|| if_stmt.alternate.as_ref().is_some_and(|alt| stmt_has_top_level_await(alt))
}
Statement::ForStatement(for_stmt) => {
@@ -419,21 +420,32 @@ fn stmt_has_top_level_await(stmt: &Statement) -> bool {
.declarations
.iter()
.any(|d| d.init.as_ref().is_some_and(|i| expr_has_top_level_await(i))),
// 函数/类声明:体不进入(函数体是独立异步语义边界)。
Statement::FunctionDeclaration(_) | Statement::ClassDeclaration(_) => false,
// 函数声明:体不进入(函数体是独立异步语义边界)。
Statement::FunctionDeclaration(_) => false,
// 类声明:类体不进入(独立异步语义边界),extends 表达式是顶层 await
// (如 `export class A extends (await x) {}`)。
Statement::ClassDeclaration(cls) => cls.super_class.as_ref().is_some_and(expr_has_top_level_await),
// `export const/let/var x = await ...` 是顶层 await;
// 函数/类声明形态不进入(体是独立异步语义边界,与裸声明臂同口径)。
// 函数/类声明形态不进入(体是独立异步语义边界,与裸声明臂同口径),
// 但类声明的 extends 表达式照常游走。
Statement::ExportNamedDeclaration(exp) => exp.declaration.as_ref().is_some_and(|decl| match decl {
Declaration::VariableDeclaration(vd) => vd
.declarations
.iter()
.any(|d| d.init.as_ref().is_some_and(|i| expr_has_top_level_await(i))),
Declaration::ClassDeclaration(cls) => {
cls.super_class.as_ref().is_some_and(expr_has_top_level_await)
}
_ => false,
}),
// `export default await ...` 是顶层 await;函数/类声明形态不进入(同口径)。
Statement::ExportDefaultDeclaration(exp) => {
exp.declaration.as_expression().is_some_and(expr_has_top_level_await)
}
// `export default await ...` 是顶层 await;函数/类声明形态体不进入(同口径),
// 但类声明的 extends 表达式照常游走。
Statement::ExportDefaultDeclaration(exp) => match &exp.declaration {
ExportDefaultDeclarationKind::ClassDeclaration(cls) => {
cls.super_class.as_ref().is_some_and(expr_has_top_level_await)
}
_ => exp.declaration.as_expression().is_some_and(expr_has_top_level_await),
},
// import、`export *`、`export { x }`(无声明)与无子表达式的语句
// (break/continue/debugger/empty)不含顶层 await。
_ => false,
@@ -584,3 +584,35 @@ fn export_named_async_fn_expr_not_tla() {
assert!(!ir.is_async, "异步函数表达式体不得使模块标记异步");
assert_eq!(ir.insts.iter().filter(|i| i.op == OpCode::AWAIT).count(), 0, "主身不得含 AWAIT");
}
/// 面 28:`if (await ...)`(IfStatement 的 test 表达式)是顶层 await,
/// 模块标记异步、体 await 编译为 AWAIT。
#[test]
fn if_test_await_makes_module_async() {
let (ir, _) = emit_module("if (await Promise.resolve(1)) { globalThis.v = 1; }", "./entry.js", &[])
.expect("if (await ...) 模块应编译成功");
assert!(ir.is_async, "if (await ...) 应标记模块异步求值");
assert_eq!(
ir.insts.iter().filter(|i| i.op == OpCode::AWAIT).count(),
1,
"顶层 await 应编译为一条 AWAIT"
);
}
/// 面 29:`export class A extends (await ...)`(ClassDeclaration 的 extends
/// 表达式)是顶层 await,模块标记异步、体 await 编译为 AWAIT;类体不进入游走。
#[test]
fn extends_await_makes_module_async() {
let (ir, _) = emit_module(
"export class A extends (await Promise.resolve(1)) {}",
"./entry.js",
&[],
)
.expect("extends (await ...) 模块应编译成功");
assert!(ir.is_async, "extends (await ...) 应标记模块异步求值");
assert_eq!(
ir.insts.iter().filter(|i| i.op == OpCode::AWAIT).count(),
1,
"顶层 await 应编译为一条 AWAIT"
);
}