feat: try 语句压边界帧,空体内 break/continue 完成值物化 undefined

This commit is contained in:
2026-10-09 10:04:23 +00:00
parent 920dc0e7f7
commit 0c277aac10
4 changed files with 69 additions and 20 deletions
Generated
+19 -19
View File
@@ -1160,7 +1160,7 @@ dependencies = [
[[package]]
name = "oxide_builtins"
version = "0.8.97"
version = "0.8.98"
dependencies = [
"chrono",
"fast-float",
@@ -1185,7 +1185,7 @@ dependencies = [
[[package]]
name = "oxide_bytecode"
version = "0.8.97"
version = "0.8.98"
dependencies = [
"num-bigint",
"oxide_log",
@@ -1193,7 +1193,7 @@ dependencies = [
[[package]]
name = "oxide_cfg"
version = "0.8.97"
version = "0.8.98"
dependencies = [
"oxide_bytecode",
"oxide_emit",
@@ -1204,7 +1204,7 @@ dependencies = [
[[package]]
name = "oxide_cli"
version = "0.8.97"
version = "0.8.98"
dependencies = [
"ansi_term",
"bumpalo",
@@ -1226,7 +1226,7 @@ dependencies = [
[[package]]
name = "oxide_code_cache"
version = "0.8.97"
version = "0.8.98"
dependencies = [
"lru",
"oxide_bytecode",
@@ -1235,7 +1235,7 @@ dependencies = [
[[package]]
name = "oxide_compiler"
version = "0.8.97"
version = "0.8.98"
dependencies = [
"oxide_bytecode",
"oxide_cfg",
@@ -1255,7 +1255,7 @@ dependencies = [
[[package]]
name = "oxide_dce"
version = "0.8.97"
version = "0.8.98"
dependencies = [
"oxide_bytecode",
"oxide_cfg",
@@ -1269,7 +1269,7 @@ dependencies = [
[[package]]
name = "oxide_emit"
version = "0.8.97"
version = "0.8.98"
dependencies = [
"num-bigint",
"oxc_allocator",
@@ -1284,7 +1284,7 @@ dependencies = [
[[package]]
name = "oxide_engine"
version = "0.8.97"
version = "0.8.98"
dependencies = [
"oxide_bytecode",
"oxide_compiler",
@@ -1296,7 +1296,7 @@ dependencies = [
[[package]]
name = "oxide_ir"
version = "0.8.97"
version = "0.8.98"
dependencies = [
"oxide_bytecode",
"oxide_log",
@@ -1305,7 +1305,7 @@ dependencies = [
[[package]]
name = "oxide_kernel"
version = "0.8.97"
version = "0.8.98"
dependencies = [
"bumpalo",
"dashmap",
@@ -1319,7 +1319,7 @@ dependencies = [
[[package]]
name = "oxide_liveness"
version = "0.8.97"
version = "0.8.98"
dependencies = [
"oxide_bytecode",
"oxide_cfg",
@@ -1331,7 +1331,7 @@ dependencies = [
[[package]]
name = "oxide_log"
version = "0.8.97"
version = "0.8.98"
dependencies = [
"tracing",
"tracing-appender",
@@ -1340,7 +1340,7 @@ dependencies = [
[[package]]
name = "oxide_parser"
version = "0.8.97"
version = "0.8.98"
dependencies = [
"oxc_allocator",
"oxc_ast",
@@ -1355,7 +1355,7 @@ dependencies = [
[[package]]
name = "oxide_regalloc"
version = "0.8.97"
version = "0.8.98"
dependencies = [
"oxide_bytecode",
"oxide_cfg",
@@ -1371,7 +1371,7 @@ dependencies = [
[[package]]
name = "oxide_runtime_api"
version = "0.8.97"
version = "0.8.98"
dependencies = [
"num-bigint",
"num-traits",
@@ -1384,7 +1384,7 @@ dependencies = [
[[package]]
name = "oxide_test262"
version = "0.8.97"
version = "0.8.98"
dependencies = [
"oxide_bytecode",
"oxide_compiler",
@@ -1402,7 +1402,7 @@ dependencies = [
[[package]]
name = "oxide_types"
version = "0.8.97"
version = "0.8.98"
dependencies = [
"bumpalo",
"dashmap",
@@ -1415,7 +1415,7 @@ dependencies = [
[[package]]
name = "oxide_vm"
version = "0.8.97"
version = "0.8.98"
dependencies = [
"bumpalo",
"chrono",
+1 -1
View File
@@ -23,7 +23,7 @@ members = [
]
[workspace.package]
version = "0.8.97"
version = "0.8.98"
edition = "2021"
license = "MIT"
rust-version = "1.80"
@@ -19,6 +19,10 @@ impl Emitter {
let has_catch = ts.handler.is_some();
let has_finally = ts.finalizer.is_some();
let result_reg = ctx.alloc_reg();
// try 语句整体是 `UpdateEmpty(_, undefined)` 站点:压边界帧,位于
// try/catch/finally 三个体列表帧之外,非空内层列表值穿透、空内层体
// 携值物化 undefined。
ctx.push_completion_boundary();
if has_finally {
// finally 域跨整个语句(try 体 + catch 体 + finally 体):期间 break/continue
// 逃出语句时须穿越本 finally,词法上记录域深度供跨越计数。
@@ -144,6 +148,7 @@ impl Emitter {
ctx.pop_finally_domain();
}
ctx.labels.set_label_pos(try_end_label, ctx.insts.len());
ctx.pop_completion_boundary();
Ok(Some(result_reg))
}
}
+44
View File
@@ -328,6 +328,50 @@ fn compound_statement_completion_values() {
assert_num(result, 5.0);
let result = eval(&mut vm, "a: { try { throw 1; } catch (e) { 5; break a; } }").unwrap();
assert_num(result, 5.0);
// try 边界帧:空 catch/finally 体 break/continue 携值物化 undefined(无 if
// 守卫独立验收形),非空 finally 体值穿透。
let result = eval(
&mut vm,
"for (var i = 0; i < 2; ++i) { try { throw null; } catch (e) { break; } 'bad completion'; }",
)
.unwrap();
assert_eq!(result, JsValue::undefined());
let result = eval(
&mut vm,
"for (var i = 0; i < 2; ++i) { try { throw null; } catch (e) { continue; } 'bad completion'; }",
)
.unwrap();
assert_eq!(result, JsValue::undefined());
let result = eval(&mut vm, "for (var i = 0; i < 2; ++i) { try {} finally { break; } 'bad completion'; }").unwrap();
assert_eq!(result, JsValue::undefined());
let result =
eval(&mut vm, "for (var i = 0; i < 2; ++i) { try {} finally { continue; } 'bad completion'; }").unwrap();
assert_eq!(result, JsValue::undefined());
let result = eval(
&mut vm,
"for (var i = 0; i < 2; ++i) { try { throw null; } catch (e) {} finally { break; } 'bad completion'; }",
)
.unwrap();
assert_eq!(result, JsValue::undefined());
let result = eval(
&mut vm,
"for (var i = 0; i < 2; ++i) { try { throw null; } catch (e) {} finally { continue; } 'bad completion'; }",
)
.unwrap();
assert_eq!(result, JsValue::undefined());
// 跨 finally 值通道守卫:非空 finally 体值穿透,空 finally 体物化 undefined。
let result = eval(
&mut vm,
"99; do { -99; try { 39 } catch (e) { -1 } finally { 42; break; -2 }; } while (false);",
)
.unwrap();
assert_num(result, 42.0);
let result = eval(
&mut vm,
"99; do { -99; try { 39 } catch (e) { -1 } finally { break; -2 }; } while (false);",
)
.unwrap();
assert_eq!(result, JsValue::undefined());
// for 泄漏形完成值:体不读循环变量加常量尾,取末次迭代体值,前值不沿用。
let result = eval(&mut vm, "for (var i = 0; i < 2; ++i) { 42 }").unwrap();
assert_num(result, 42.0);