perf: 影子集改计次映射消每边界集合分配

This commit is contained in:
2026-10-12 09:46:34 +00:00
parent ff8e28fa06
commit 8babf99f3f
5 changed files with 238 additions and 140 deletions
Generated
+20 -20
View File
@@ -1160,7 +1160,7 @@ dependencies = [
[[package]]
name = "oxide_builtins"
version = "0.16.9"
version = "0.16.10"
dependencies = [
"chrono",
"fast-float",
@@ -1185,7 +1185,7 @@ dependencies = [
[[package]]
name = "oxide_bytecode"
version = "0.16.9"
version = "0.16.10"
dependencies = [
"num-bigint",
"oxide_log",
@@ -1193,7 +1193,7 @@ dependencies = [
[[package]]
name = "oxide_cfg"
version = "0.16.9"
version = "0.16.10"
dependencies = [
"oxide_bytecode",
"oxide_emit",
@@ -1204,7 +1204,7 @@ dependencies = [
[[package]]
name = "oxide_cli"
version = "0.16.9"
version = "0.16.10"
dependencies = [
"ansi_term",
"bumpalo",
@@ -1228,7 +1228,7 @@ dependencies = [
[[package]]
name = "oxide_code_cache"
version = "0.16.9"
version = "0.16.10"
dependencies = [
"lru",
"oxide_bytecode",
@@ -1237,7 +1237,7 @@ dependencies = [
[[package]]
name = "oxide_compiler"
version = "0.16.9"
version = "0.16.10"
dependencies = [
"oxide_bytecode",
"oxide_cfg",
@@ -1257,7 +1257,7 @@ dependencies = [
[[package]]
name = "oxide_dce"
version = "0.16.9"
version = "0.16.10"
dependencies = [
"oxide_bytecode",
"oxide_cfg",
@@ -1271,7 +1271,7 @@ dependencies = [
[[package]]
name = "oxide_emit"
version = "0.16.9"
version = "0.16.10"
dependencies = [
"num-bigint",
"oxc_allocator",
@@ -1286,7 +1286,7 @@ dependencies = [
[[package]]
name = "oxide_engine"
version = "0.16.9"
version = "0.16.10"
dependencies = [
"oxide_bytecode",
"oxide_compiler",
@@ -1298,7 +1298,7 @@ dependencies = [
[[package]]
name = "oxide_ir"
version = "0.16.9"
version = "0.16.10"
dependencies = [
"oxide_bytecode",
"oxide_log",
@@ -1307,7 +1307,7 @@ dependencies = [
[[package]]
name = "oxide_kernel"
version = "0.16.9"
version = "0.16.10"
dependencies = [
"bumpalo",
"dashmap",
@@ -1321,7 +1321,7 @@ dependencies = [
[[package]]
name = "oxide_liveness"
version = "0.16.9"
version = "0.16.10"
dependencies = [
"oxide_bytecode",
"oxide_cfg",
@@ -1333,7 +1333,7 @@ dependencies = [
[[package]]
name = "oxide_log"
version = "0.16.9"
version = "0.16.10"
dependencies = [
"tracing",
"tracing-appender",
@@ -1342,11 +1342,11 @@ dependencies = [
[[package]]
name = "oxide_net"
version = "0.16.9"
version = "0.16.10"
[[package]]
name = "oxide_parser"
version = "0.16.9"
version = "0.16.10"
dependencies = [
"oxc_allocator",
"oxc_ast",
@@ -1361,7 +1361,7 @@ dependencies = [
[[package]]
name = "oxide_regalloc"
version = "0.16.9"
version = "0.16.10"
dependencies = [
"oxide_bytecode",
"oxide_cfg",
@@ -1377,7 +1377,7 @@ dependencies = [
[[package]]
name = "oxide_runtime_api"
version = "0.16.9"
version = "0.16.10"
dependencies = [
"num-bigint",
"num-traits",
@@ -1390,7 +1390,7 @@ dependencies = [
[[package]]
name = "oxide_test262"
version = "0.16.9"
version = "0.16.10"
dependencies = [
"oxide_bytecode",
"oxide_compiler",
@@ -1410,7 +1410,7 @@ dependencies = [
[[package]]
name = "oxide_types"
version = "0.16.9"
version = "0.16.10"
dependencies = [
"bumpalo",
"dashmap",
@@ -1423,7 +1423,7 @@ dependencies = [
[[package]]
name = "oxide_vm"
version = "0.16.9"
version = "0.16.10"
dependencies = [
"bumpalo",
"chrono",
+1 -1
View File
@@ -24,7 +24,7 @@ members = [
]
[workspace.package]
version = "0.16.9"
version = "0.16.10"
edition = "2021"
license = "MIT"
rust-version = "1.80"
+94 -7
View File
@@ -12,24 +12,111 @@ mod names;
mod scanner;
mod upvalues;
use std::collections::HashSet;
use std::collections::{HashMap, HashSet};
pub(crate) use names::collect_fn_scope_names;
pub(crate) use names::FnScopeNames;
pub(crate) use upvalues::collect_captured_bindings;
pub(crate) use upvalues::collect_captures_and_upvalues;
/// 收集形参(含 rest)绑定的名字集,作为本函数作用域的遮蔽集。
pub(crate) fn collect_fn_param_names(params: &oxide_parser::FormalParameters) -> HashSet<String> {
let mut names = HashSet::new();
/// 收集形参(含 rest)绑定的名字写入影子计次映射(计次加一),
/// 作为本函数作用域的遮蔽集。
pub(crate) fn collect_fn_param_names_into(params: &oxide_parser::FormalParameters, shadow: &mut HashMap<String, u32>) {
for p in &params.items {
collect_binding_pattern_names(&p.pattern, &mut names);
collect_binding_pattern_names_into(&p.pattern, shadow);
}
// rest 形参也是本函数作用域绑定,遮蔽外层同名变量。
if let Some(rest) = &params.rest {
collect_binding_pattern_names(&rest.rest.argument, &mut names);
collect_binding_pattern_names_into(&rest.rest.argument, shadow);
}
}
/// 递归收集 binding pattern 内全部绑定标识符名(解构 `[a, b]` / `{x: y}` 嵌套),
/// 写入影子计次映射(计次加一),作用域进入时遮蔽外层同名绑定。
pub(crate) fn collect_binding_pattern_names_into(pattern: &oxide_parser::BindingPattern, shadow: &mut HashMap<String, u32>) {
match pattern {
oxide_parser::BindingPattern::BindingIdentifier(bi) => {
*shadow.entry(bi.name.as_str().to_string()).or_insert(0) += 1;
}
oxide_parser::BindingPattern::ArrayPattern(ap) => {
for p in ap.elements.iter().flatten() {
collect_binding_pattern_names_into(p, shadow);
}
if let Some(rest) = &ap.rest {
collect_binding_pattern_names_into(&rest.argument, shadow);
}
}
oxide_parser::BindingPattern::ObjectPattern(op) => {
for prop in &op.properties {
collect_binding_pattern_names_into(&prop.value, shadow);
}
if let Some(rest) = &op.rest {
collect_binding_pattern_names_into(&rest.argument, shadow);
}
}
oxide_parser::BindingPattern::AssignmentPattern(ap) => {
collect_binding_pattern_names_into(&ap.left, shadow);
}
}
}
/// 递归收集 binding pattern 内全部绑定标识符名并解除影子计次映射(计次减一,
/// 归零删项),作用域退出时解除遮蔽,与 `collect_binding_pattern_names_into` 配对。
fn collect_binding_pattern_names_remove(pattern: &oxide_parser::BindingPattern, shadow: &mut HashMap<String, u32>) {
match pattern {
oxide_parser::BindingPattern::BindingIdentifier(bi) => {
shadow_dec(shadow, bi.name.as_str().to_string());
}
oxide_parser::BindingPattern::ArrayPattern(ap) => {
for p in ap.elements.iter().flatten() {
collect_binding_pattern_names_remove(p, shadow);
}
if let Some(rest) = &ap.rest {
collect_binding_pattern_names_remove(&rest.argument, shadow);
}
}
oxide_parser::BindingPattern::ObjectPattern(op) => {
for prop in &op.properties {
collect_binding_pattern_names_remove(&prop.value, shadow);
}
if let Some(rest) = &op.rest {
collect_binding_pattern_names_remove(&rest.argument, shadow);
}
}
oxide_parser::BindingPattern::AssignmentPattern(ap) => {
collect_binding_pattern_names_remove(&ap.left, shadow);
}
}
}
/// 影子计次映射中某名字计次减一,归零删项。
pub(crate) fn shadow_dec(shadow: &mut HashMap<String, u32>, name: String) {
if let Some(count) = shadow.get_mut(&name) {
*count -= 1;
if *count == 0 {
shadow.remove(&name);
}
}
}
/// 收集 for-in/for-of 头部声明(`var x` / 解构 pattern)绑定的名字写入影子计次
/// 映射(计次加一),作用域进入时遮蔽外层同名绑定。
pub(crate) fn collect_for_left_decl_names_into(left: &oxide_parser::ForStatementLeft, shadow: &mut HashMap<String, u32>) {
if let oxide_parser::ForStatementLeft::VariableDeclaration(vd) = left {
for d in &vd.declarations {
collect_binding_pattern_names_into(&d.id, shadow);
}
}
}
/// 收集 for-in/for-of 头部声明绑定的名字并解除影子计次映射(计次减一,归零删项),
/// 作用域退出时解除遮蔽,与 `collect_for_left_decl_names_into` 配对。
pub(crate) fn collect_for_left_decl_names_remove(left: &oxide_parser::ForStatementLeft, shadow: &mut HashMap<String, u32>) {
if let oxide_parser::ForStatementLeft::VariableDeclaration(vd) = left {
for d in &vd.declarations {
collect_binding_pattern_names_remove(&d.id, shadow);
}
}
names
}
/// 递归收集 binding pattern 内全部绑定标识符名(解构 `[a, b]` / `{x: y}` 嵌套)。
+42 -40
View File
@@ -2,22 +2,24 @@
//! 块级声明名 / 直接子词法名 / 顶层函数名集 / 顶层函数声明序 / 块级函数名 /
//! 块函数抑制集),供各入口(程序/模块/函数体)的 GDI 检查、builtin 排除、
//! 入口实例化与块函数 web-compat 各调用点共用;另保留捕获扫描器内部依赖的
//! own 绑定名集收集(`collect_own_binding_names`)。
//! own 绑定名集收集(`collect_own_binding_names_into`)。
use std::collections::HashSet;
use std::collections::{HashMap, HashSet};
use oxide_parser::{Statement, VariableDeclarationKind};
use super::{collect_binding_pattern_names, collect_for_left_decl_names};
use super::{
collect_binding_pattern_names, collect_binding_pattern_names_into, collect_for_left_decl_names,
collect_for_left_decl_names_into,
};
/// 收集当前函数作用域声明的绑定名(参数 + 变量/函数声明,含嵌套 block,不含嵌套函数体)。
pub(crate) fn collect_own_binding_names(param_names: &[&str], stmts: &[Statement]) -> HashSet<String> {
let mut names = HashSet::new();
/// 收集当前函数作用域声明的绑定名(参数 + 变量/函数声明,含嵌套 block,不含嵌套函数体),
/// 写入影子计次映射(计次加一)。
pub(crate) fn collect_own_binding_names_into(param_names: &[&str], stmts: &[Statement], out: &mut HashMap<String, u32>) {
for p in param_names {
names.insert(p.to_string());
*out.entry(p.to_string()).or_insert(0) += 1;
}
collect_decl_names_stmt(stmts, &mut names);
names
collect_decl_names_into(stmts, out);
}
/// 函数作用域名收集结果:单趟遍历同时填八个输出,与各旧独立收集函数逐位一致。
@@ -335,25 +337,25 @@ fn collect_fn_scope_names_impl(stmts: &[Statement], out: &mut FnScopeNames, top:
}
/// 递归遍历语句树收集当前函数作用域声明的绑定名(变量/函数/类/import/export,
/// 含嵌套块,不进嵌套函数体)。
pub(crate) fn collect_decl_names_stmt(stmts: &[Statement], out: &mut HashSet<String>) {
/// 含嵌套块,不进嵌套函数体),写入影子计次映射(计次加一)。
pub(crate) fn collect_decl_names_into(stmts: &[Statement], out: &mut HashMap<String, u32>) {
for stmt in stmts {
match stmt {
Statement::VariableDeclaration(vd) => {
for d in &vd.declarations {
collect_binding_pattern_names(&d.id, out);
collect_binding_pattern_names_into(&d.id, out);
}
}
Statement::FunctionDeclaration(fd) => {
if let Some(id) = &fd.id {
out.insert(id.name.to_string());
*out.entry(id.name.to_string()).or_insert(0) += 1;
}
}
// class 名是本作用域 const 绑定:须计入 own_bindings,否则嵌套函数
// 引用类名时捕获分析缺失 → 落符号表兜底(TDZ 误报或读父寄存器残留)。
Statement::ClassDeclaration(cd) => {
if let Some(id) = &cd.id {
out.insert(id.name.to_string());
*out.entry(id.name.to_string()).or_insert(0) += 1;
}
}
// import 绑定是模块作用域 const 绑定,须计入 own_bindings 供
@@ -363,13 +365,13 @@ pub(crate) fn collect_decl_names_stmt(stmts: &[Statement], out: &mut HashSet<Str
for sp in specifiers {
match sp {
oxide_parser::ImportDeclarationSpecifier::ImportSpecifier(s) => {
out.insert(s.local.name.to_string());
*out.entry(s.local.name.to_string()).or_insert(0) += 1;
}
oxide_parser::ImportDeclarationSpecifier::ImportDefaultSpecifier(s) => {
out.insert(s.local.name.to_string());
*out.entry(s.local.name.to_string()).or_insert(0) += 1;
}
oxide_parser::ImportDeclarationSpecifier::ImportNamespaceSpecifier(s) => {
out.insert(s.local.name.to_string());
*out.entry(s.local.name.to_string()).or_insert(0) += 1;
}
}
}
@@ -380,17 +382,17 @@ pub(crate) fn collect_decl_names_stmt(stmts: &[Statement], out: &mut HashSet<Str
match decl {
oxide_parser::Declaration::VariableDeclaration(vd) => {
for d in &vd.declarations {
collect_binding_pattern_names(&d.id, out);
collect_binding_pattern_names_into(&d.id, out);
}
}
oxide_parser::Declaration::FunctionDeclaration(fd) => {
if let Some(id) = &fd.id {
out.insert(id.name.to_string());
*out.entry(id.name.to_string()).or_insert(0) += 1;
}
}
oxide_parser::Declaration::ClassDeclaration(cd) => {
if let Some(id) = &cd.id {
out.insert(id.name.to_string());
*out.entry(id.name.to_string()).or_insert(0) += 1;
}
}
_ => {}
@@ -400,70 +402,70 @@ pub(crate) fn collect_decl_names_stmt(stmts: &[Statement], out: &mut HashSet<Str
Statement::ExportDefaultDeclaration(exp) => match &exp.declaration {
oxide_parser::ExportDefaultDeclarationKind::FunctionDeclaration(fd) => {
if let Some(id) = &fd.id {
out.insert(id.name.to_string());
*out.entry(id.name.to_string()).or_insert(0) += 1;
}
}
oxide_parser::ExportDefaultDeclarationKind::ClassDeclaration(cd) => {
if let Some(id) = &cd.id {
out.insert(id.name.to_string());
*out.entry(id.name.to_string()).or_insert(0) += 1;
}
}
_ => {}
},
Statement::BlockStatement(b) => collect_decl_names_stmt(&b.body, out),
Statement::BlockStatement(b) => collect_decl_names_into(&b.body, out),
Statement::IfStatement(is) => {
collect_decl_names_stmt(std::slice::from_ref(&is.consequent), out);
collect_decl_names_into(std::slice::from_ref(&is.consequent), out);
if let Some(alt) = &is.alternate {
collect_decl_names_stmt(std::slice::from_ref(alt), out);
collect_decl_names_into(std::slice::from_ref(alt), out);
}
}
Statement::WhileStatement(w) => collect_decl_names_stmt(std::slice::from_ref(&w.body), out),
Statement::DoWhileStatement(d) => collect_decl_names_stmt(std::slice::from_ref(&d.body), out),
Statement::WhileStatement(w) => collect_decl_names_into(std::slice::from_ref(&w.body), out),
Statement::DoWhileStatement(d) => collect_decl_names_into(std::slice::from_ref(&d.body), out),
Statement::ForStatement(f) => {
if let Some(oxide_parser::ForStatementInit::VariableDeclaration(vd)) = &f.init {
for d in &vd.declarations {
if let oxide_parser::BindingPattern::BindingIdentifier(bi) = &d.id {
out.insert(bi.name.to_string());
*out.entry(bi.name.to_string()).or_insert(0) += 1;
}
}
}
collect_decl_names_stmt(std::slice::from_ref(&f.body), out);
collect_decl_names_into(std::slice::from_ref(&f.body), out);
}
// for-in / for-of 头部的 var 声明是本函数局部绑定(遮蔽外层同名),
// 须计入 own_bindings,否则闭包捕获分析会误判为捕获外层变量。
Statement::ForInStatement(fi) => {
if let oxide_parser::ForStatementLeft::VariableDeclaration(_) = &fi.left {
collect_for_left_decl_names(&fi.left, out);
collect_for_left_decl_names_into(&fi.left, out);
}
collect_decl_names_stmt(std::slice::from_ref(&fi.body), out);
collect_decl_names_into(std::slice::from_ref(&fi.body), out);
}
Statement::ForOfStatement(fo) => {
if let oxide_parser::ForStatementLeft::VariableDeclaration(_) = &fo.left {
collect_for_left_decl_names(&fo.left, out);
collect_for_left_decl_names_into(&fo.left, out);
}
collect_decl_names_stmt(std::slice::from_ref(&fo.body), out);
collect_decl_names_into(std::slice::from_ref(&fo.body), out);
}
Statement::SwitchStatement(sw) => {
for case in &sw.cases {
collect_decl_names_stmt(&case.consequent, out);
collect_decl_names_into(&case.consequent, out);
}
}
Statement::TryStatement(ts) => {
collect_decl_names_stmt(&ts.block.body, out);
collect_decl_names_into(&ts.block.body, out);
if let Some(h) = &ts.handler {
// catch 参数是本函数作用域的词法绑定:计入 own_bindings,
// 嵌套函数引用它时捕获分析才会建 cell 供 upvalue 读取。
if let Some(param) = &h.param {
collect_binding_pattern_names(&param.pattern, out);
collect_binding_pattern_names_into(&param.pattern, out);
}
collect_decl_names_stmt(&h.body.body, out);
collect_decl_names_into(&h.body.body, out);
}
if let Some(f) = &ts.finalizer {
collect_decl_names_stmt(&f.body, out);
collect_decl_names_into(&f.body, out);
}
}
Statement::LabeledStatement(ls) => collect_decl_names_stmt(std::slice::from_ref(&ls.body), out),
Statement::WithStatement(ws) => collect_decl_names_stmt(std::slice::from_ref(&ws.body), out),
Statement::LabeledStatement(ls) => collect_decl_names_into(std::slice::from_ref(&ls.body), out),
Statement::WithStatement(ws) => collect_decl_names_into(std::slice::from_ref(&ws.body), out),
_ => {}
}
}
+81 -72
View File
@@ -1,19 +1,23 @@
//! 闭包捕获分析,遮蔽感知引用收集:`CaptureEngine` 捆绑双引用集(own ×
//! parent_names)× shadow(遮蔽名集)× 双输出累加器(captured_out ×
//! parent_names)× shadow(遮蔽名计次映射)× 双输出累加器(captured_out ×
//! upvalue_out)× depth(嵌套深度),遍历语句/表达式/赋值目标/类体 AST,嵌套
//! 函数/类/for 头/catch 参数逐层遮蔽,按深度分区写两输出。
use std::collections::HashSet;
use std::collections::{HashMap, HashSet};
use oxide_parser::{ClassBody, ClassElement, Expression, Statement};
use super::names::collect_own_binding_names;
use super::{collect_fn_param_names, collect_for_left_decl_names};
use super::names::collect_own_binding_names_into;
use super::{
collect_binding_pattern_names_into, collect_fn_param_names_into, collect_for_left_decl_names_into,
collect_for_left_decl_names_remove, shadow_dec,
};
/// 双引用集引擎:捆绑 own(深度 ≥ 1 引用集)、parent_names(全深度引用集)、
/// sub_own(upvalue 显式排除集)、shadow(遮蔽名集)、depth(嵌套深度)与双输出
/// sub_own(upvalue 显式排除集)、shadow(遮蔽名计次映射)、depth(嵌套深度)与双输出
/// 累加器,本族十五个收集函数共享单一 `&mut CaptureEngine` 参数。作用域边界(嵌套
/// 函数/类/for 头/catch 参数)对 shadow 集做保存/恢复,逐层遮蔽外层绑定;函数/类
/// 函数/类/for 头/catch 参数)对 shadow 计次映射做计次增减(函数边界清空重建,
/// catch 参数只增不减),逐层遮蔽外层绑定;函数/类
/// 边界对 depth 做增减,区分本函数体层与嵌套层。
pub(crate) struct CaptureEngine<'a> {
/// 深度 ≥ 1 的引用集:本函数 own 绑定集(父层捕获判定)。
@@ -22,8 +26,9 @@ pub(crate) struct CaptureEngine<'a> {
parent_names: &'a HashSet<String>,
/// upvalue 判定的显式排除集:本函数 own 绑定集。
sub_own: &'a HashSet<String>,
/// 遮蔽名集:当前作用域内被遮蔽、须排除的名字;作用域边界保存/恢复。
shadow: HashSet<String>,
/// 遮蔽名计次映射:当前作用域内被遮蔽的名字及其计次;作用域边界计次增减,
/// 函数边界清空重建,每边界零分配。
shadow: HashMap<String, u32>,
/// 嵌套深度:0 = 本函数体层,≥ 1 = 嵌套函数/类内。
depth: u32,
/// 输出累加器:被嵌套函数捕获的名字(父层捕获判定)。
@@ -44,7 +49,7 @@ impl<'a> CaptureEngine<'a> {
own,
parent_names,
sub_own,
shadow: HashSet::new(),
shadow: HashMap::new(),
depth: 0,
captured_out,
upvalue_out,
@@ -55,13 +60,18 @@ impl<'a> CaptureEngine<'a> {
/// 深度 ≥ 1 且名字在 own 且不在 shadow → captured_out;
/// 名字在 parent_names 且不在 shadow 且不在 sub_own → upvalue_out。
fn check_identifier(&mut self, name: &str) {
if self.depth >= 1 && self.own.contains(name) && !self.shadow.contains(name) {
if self.depth >= 1 && self.own.contains(name) && !self.shadow_contains(name) {
self.captured_out.insert(name.to_string());
}
if self.parent_names.contains(name) && !self.shadow.contains(name) && !self.sub_own.contains(name) {
if self.parent_names.contains(name) && !self.shadow_contains(name) && !self.sub_own.contains(name) {
self.upvalue_out.insert(name.to_string());
}
}
/// 遮蔽判定:名字在计次映射中的计次大于零即被遮蔽。
fn shadow_contains(&self, name: &str) -> bool {
self.shadow.get(name).is_some_and(|&c| c > 0)
}
}
/// 以引擎的 ref_set × shadow 双集驱动,收集被任意深度嵌套函数引用、且未被遮蔽的
@@ -94,10 +104,11 @@ pub(crate) fn collect_capture_names_stmt(stmt: &Statement, eng: &mut CaptureEngi
Statement::FunctionDeclaration(fd) => {
let body: &[Statement] = fd.body.as_ref().map(|b| &b.statements[..]).unwrap_or(&[]);
collect_fn_default_names(&fd.params, eng);
// 函数形参与体内声明遮蔽外层绑定:影子集保存/恢复,深度增一。
// 函数形参与体内声明遮蔽外层绑定:影子计次映射保存/恢复,清空重建为
// 本函数自身名,深度增一。
let saved = std::mem::take(&mut eng.shadow);
eng.shadow.extend(collect_fn_param_names(&fd.params));
eng.shadow.extend(collect_own_binding_names(&[], body));
collect_fn_param_names_into(&fd.params, &mut eng.shadow);
collect_own_binding_names_into(&[], body, &mut eng.shadow);
eng.depth += 1;
collect_capture_names_shadowed(body, eng);
eng.depth -= 1;
@@ -106,14 +117,15 @@ pub(crate) fn collect_capture_names_stmt(stmt: &Statement, eng: &mut CaptureEngi
Statement::ClassDeclaration(cd) => {
// 类体(构造器/方法体、字段键与值、静态块)是嵌套作用域:
// 类名遮蔽外层绑定,方法形参与方法体局部进一步遮蔽。深度增一。
let saved = std::mem::take(&mut eng.shadow);
if let Some(id) = &cd.id {
eng.shadow.insert(id.name.as_str().to_string());
*eng.shadow.entry(id.name.as_str().to_string()).or_insert(0) += 1;
}
eng.depth += 1;
collect_class_capture_names(&cd.body, eng);
eng.depth -= 1;
eng.shadow = saved;
if let Some(id) = &cd.id {
shadow_dec(&mut eng.shadow, id.name.as_str().to_string());
}
}
Statement::IfStatement(is) => {
collect_capture_names_expr(&is.test, eng);
@@ -164,10 +176,9 @@ pub(crate) fn collect_capture_names_stmt(stmt: &Statement, eng: &mut CaptureEngi
collect_capture_names_for_left(&fi.left, eng);
}
// left 的 var 声明遮蔽外层同名绑定,body 内引用不视为捕获外层。
let saved = std::mem::take(&mut eng.shadow);
collect_for_left_decl_names(&fi.left, &mut eng.shadow);
collect_for_left_decl_names_into(&fi.left, &mut eng.shadow);
collect_capture_names_shadowed(std::slice::from_ref(&fi.body), eng);
eng.shadow = saved;
collect_for_left_decl_names_remove(&fi.left, &mut eng.shadow);
}
Statement::ForOfStatement(fo) => {
collect_capture_names_expr(&fo.right, eng);
@@ -178,10 +189,9 @@ pub(crate) fn collect_capture_names_stmt(stmt: &Statement, eng: &mut CaptureEngi
} else {
collect_capture_names_for_left(&fo.left, eng);
}
let saved = std::mem::take(&mut eng.shadow);
collect_for_left_decl_names(&fo.left, &mut eng.shadow);
collect_for_left_decl_names_into(&fo.left, &mut eng.shadow);
collect_capture_names_shadowed(std::slice::from_ref(&fo.body), eng);
eng.shadow = saved;
collect_for_left_decl_names_remove(&fo.left, &mut eng.shadow);
}
Statement::BlockStatement(b) => collect_capture_names_shadowed(&b.body, eng),
Statement::TryStatement(ts) => {
@@ -190,9 +200,11 @@ pub(crate) fn collect_capture_names_stmt(stmt: &Statement, eng: &mut CaptureEngi
}
if let Some(h) = &ts.handler {
// catch 参数解构模式内的表达式引用(默认值等)也会被内部闭包捕获;
// 参数声明名合并进引擎影子集后遮蔽 catch 作用域。
// 先以外层影子集扫模式内表达式,再将参数声明名合并进引擎影子计次
// 映射遮蔽 catch 作用域(只增不减,与旧代码一致)。
if let Some(param) = &h.param {
collect_capture_names_binding_pattern(&param.pattern, eng);
collect_binding_pattern_exprs(&param.pattern, eng);
collect_binding_pattern_names_into(&param.pattern, &mut eng.shadow);
}
for s in &h.body.body {
collect_capture_names_stmt(s, eng);
@@ -219,22 +231,23 @@ pub(crate) fn collect_capture_names_stmt(stmt: &Statement, eng: &mut CaptureEngi
let body: &[Statement] = fd.body.as_ref().map(|b| &b.statements[..]).unwrap_or(&[]);
collect_fn_default_names(&fd.params, eng);
let saved = std::mem::take(&mut eng.shadow);
eng.shadow.extend(collect_fn_param_names(&fd.params));
eng.shadow.extend(collect_own_binding_names(&[], body));
collect_fn_param_names_into(&fd.params, &mut eng.shadow);
collect_own_binding_names_into(&[], body, &mut eng.shadow);
eng.depth += 1;
collect_capture_names_shadowed(body, eng);
eng.depth -= 1;
eng.shadow = saved;
}
oxide_parser::Declaration::ClassDeclaration(cd) => {
let saved = std::mem::take(&mut eng.shadow);
if let Some(id) = &cd.id {
eng.shadow.insert(id.name.as_str().to_string());
*eng.shadow.entry(id.name.as_str().to_string()).or_insert(0) += 1;
}
eng.depth += 1;
collect_class_capture_names(&cd.body, eng);
eng.depth -= 1;
eng.shadow = saved;
if let Some(id) = &cd.id {
shadow_dec(&mut eng.shadow, id.name.as_str().to_string());
}
}
_ => {}
}
@@ -245,22 +258,23 @@ pub(crate) fn collect_capture_names_stmt(stmt: &Statement, eng: &mut CaptureEngi
let body: &[Statement] = fd.body.as_ref().map(|b| &b.statements[..]).unwrap_or(&[]);
collect_fn_default_names(&fd.params, eng);
let saved = std::mem::take(&mut eng.shadow);
eng.shadow.extend(collect_fn_param_names(&fd.params));
eng.shadow.extend(collect_own_binding_names(&[], body));
collect_fn_param_names_into(&fd.params, &mut eng.shadow);
collect_own_binding_names_into(&[], body, &mut eng.shadow);
eng.depth += 1;
collect_capture_names_shadowed(body, eng);
eng.depth -= 1;
eng.shadow = saved;
}
oxide_parser::ExportDefaultDeclarationKind::ClassDeclaration(cd) => {
let saved = std::mem::take(&mut eng.shadow);
if let Some(id) = &cd.id {
eng.shadow.insert(id.name.as_str().to_string());
*eng.shadow.entry(id.name.as_str().to_string()).or_insert(0) += 1;
}
eng.depth += 1;
collect_class_capture_names(&cd.body, eng);
eng.depth -= 1;
eng.shadow = saved;
if let Some(id) = &cd.id {
shadow_dec(&mut eng.shadow, id.name.as_str().to_string());
}
}
other => {
if let Some(e) = other.as_expression() {
@@ -307,11 +321,12 @@ pub(crate) fn collect_class_capture_names(class_body: &ClassBody, eng: &mut Capt
match element {
ClassElement::MethodDefinition(method) => {
collect_fn_default_names(&method.value.params, eng);
// 方法形参与方法体局部遮蔽外层绑定:影子集保存/恢复。
// 方法形参与方法体局部遮蔽外层绑定:影子计次映射保存/恢复,
// 清空重建为本方法自身名。
let saved = std::mem::take(&mut eng.shadow);
eng.shadow.extend(collect_fn_param_names(&method.value.params));
collect_fn_param_names_into(&method.value.params, &mut eng.shadow);
let body: &[Statement] = method.value.body.as_ref().map(|b| &b.statements[..]).unwrap_or(&[]);
eng.shadow.extend(collect_own_binding_names(&[], body));
collect_own_binding_names_into(&[], body, &mut eng.shadow);
collect_capture_names_shadowed(body, eng);
eng.shadow = saved;
}
@@ -333,29 +348,20 @@ pub(crate) fn collect_class_capture_names(class_body: &ClassBody, eng: &mut Capt
}
}
/// 遍历 catch 参数解构模式:收集模式内表达式引用(默认值等),声明名合并进引擎
/// 影子集遮蔽 catch 作用域。模式内表达式扫描走外层影子集,不受本模式声明名影响。
pub(crate) fn collect_capture_names_binding_pattern(pattern: &oxide_parser::BindingPattern, eng: &mut CaptureEngine) {
let mut declared = HashSet::new();
collect_binding_pattern_refs(pattern, eng, &mut declared);
eng.shadow.extend(declared);
}
/// 递归遍历 catch 参数解构模式:收集模式内表达式引用(默认值等)写入引擎输出,
/// 声明名累积进 `declared` 供调用方合并进影子集。
fn collect_binding_pattern_refs(
pattern: &oxide_parser::BindingPattern, eng: &mut CaptureEngine, declared: &mut HashSet<String>,
) {
/// 遍历绑定 pattern 的运行时求值表达式引用:计算键(`{[k]: a}` 的键)与内嵌
/// 默认值(`{a = x}` 的 x)都是模式内求值的表达式,嵌套函数引用外层绑定时须
/// 纳入捕获(与赋值侧/对象字面量/类字段键遍历同口径)。模式声明名不进影子计次
/// 映射:catch 与形参默认值边界都先以外层影子集扫完表达式、再写声明名,声明名
/// 不参与模式内表达式扫描。
pub(crate) fn collect_binding_pattern_exprs(pattern: &oxide_parser::BindingPattern, eng: &mut CaptureEngine) {
match pattern {
oxide_parser::BindingPattern::BindingIdentifier(bi) => {
declared.insert(bi.name.as_str().to_string());
}
oxide_parser::BindingPattern::BindingIdentifier(_) => {}
oxide_parser::BindingPattern::ArrayPattern(ap) => {
for p in ap.elements.iter().flatten() {
collect_binding_pattern_refs(p, eng, declared);
collect_binding_pattern_exprs(p, eng);
}
if let Some(rest) = &ap.rest {
collect_binding_pattern_refs(&rest.argument, eng, declared);
collect_binding_pattern_exprs(&rest.argument, eng);
}
}
oxide_parser::BindingPattern::ObjectPattern(op) => {
@@ -364,15 +370,15 @@ fn collect_binding_pattern_refs(
if prop.computed {
collect_capture_names_expr(prop.key.to_expression(), eng);
}
collect_binding_pattern_refs(&prop.value, eng, declared);
collect_binding_pattern_exprs(&prop.value, eng);
}
if let Some(rest) = &op.rest {
collect_binding_pattern_refs(&rest.argument, eng, declared);
collect_binding_pattern_exprs(&rest.argument, eng);
}
}
oxide_parser::BindingPattern::AssignmentPattern(ap) => {
collect_capture_names_expr(&ap.right, eng);
collect_binding_pattern_refs(&ap.left, eng, declared);
collect_binding_pattern_exprs(&ap.left, eng);
}
}
}
@@ -576,10 +582,10 @@ pub(crate) fn collect_fn_default_names(params: &oxide_parser::FormalParameters,
if let Some(init) = &p.initializer {
collect_capture_names_expr(init, eng);
}
// 形参模式声明名只遮蔽本形参模式,不渗入后续形参默认值扫描。
let saved = std::mem::take(&mut eng.shadow);
collect_capture_names_binding_pattern(&p.pattern, eng);
eng.shadow = saved;
// 形参模式内表达式(计算键、嵌套默认值)在外层作用域求值,须纳入捕获
// 判定;模式声明名不进影子计次映射(旧代码扩展后立即恢复,净效果为空,
// 保持逐位一致)。
collect_binding_pattern_exprs(&p.pattern, eng);
}
eng.depth -= 1;
}
@@ -603,10 +609,11 @@ pub(crate) fn collect_capture_names_expr(expr: &Expression, eng: &mut CaptureEng
Expression::FunctionExpression(fe) => {
let body: &[Statement] = fe.body.as_ref().map(|b| &b.statements[..]).unwrap_or(&[]);
collect_fn_default_names(&fe.params, eng);
// 函数形参与体内声明遮蔽外层绑定:影子集保存/恢复,深度增一。
// 函数形参与体内声明遮蔽外层绑定:影子计次映射保存/恢复,清空重建为
// 本函数自身名,深度增一。
let saved = std::mem::take(&mut eng.shadow);
eng.shadow.extend(collect_fn_param_names(&fe.params));
eng.shadow.extend(collect_own_binding_names(&[], body));
collect_fn_param_names_into(&fe.params, &mut eng.shadow);
collect_own_binding_names_into(&[], body, &mut eng.shadow);
eng.depth += 1;
collect_capture_names_shadowed(body, eng);
eng.depth -= 1;
@@ -614,10 +621,11 @@ pub(crate) fn collect_capture_names_expr(expr: &Expression, eng: &mut CaptureEng
}
Expression::ArrowFunctionExpression(ae) => {
collect_fn_default_names(&ae.params, eng);
// 函数形参与体内声明遮蔽外层绑定:影子集保存/恢复,深度增一。
// 函数形参与体内声明遮蔽外层绑定:影子计次映射保存/恢复,清空重建为
// 本函数自身名,深度增一。
let saved = std::mem::take(&mut eng.shadow);
eng.shadow.extend(collect_fn_param_names(&ae.params));
eng.shadow.extend(collect_own_binding_names(&[], &ae.body.statements));
collect_fn_param_names_into(&ae.params, &mut eng.shadow);
collect_own_binding_names_into(&[], &ae.body.statements, &mut eng.shadow);
eng.depth += 1;
collect_capture_names_shadowed(&ae.body.statements, eng);
eng.depth -= 1;
@@ -625,14 +633,15 @@ pub(crate) fn collect_capture_names_expr(expr: &Expression, eng: &mut CaptureEng
}
Expression::ClassExpression(class) => {
// 类表达式:方法/构造器体与字段表达式是嵌套作用域,引用须捕获。深度增一。
let saved = std::mem::take(&mut eng.shadow);
if let Some(id) = &class.id {
eng.shadow.insert(id.name.as_str().to_string());
*eng.shadow.entry(id.name.as_str().to_string()).or_insert(0) += 1;
}
eng.depth += 1;
collect_class_capture_names(&class.body, eng);
eng.depth -= 1;
eng.shadow = saved;
if let Some(id) = &class.id {
shadow_dec(&mut eng.shadow, id.name.as_str().to_string());
}
}
Expression::BinaryExpression(be) => {
collect_capture_names_expr(&be.left, eng);