mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-24 02:31:13 +08:00
perf: 影子集改计次映射消每边界集合分配
This commit is contained in:
@@ -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 ¶ms.items {
|
||||
collect_binding_pattern_names(&p.pattern, &mut names);
|
||||
collect_binding_pattern_names_into(&p.pattern, shadow);
|
||||
}
|
||||
// rest 形参也是本函数作用域绑定,遮蔽外层同名变量。
|
||||
if let Some(rest) = ¶ms.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}` 嵌套)。
|
||||
|
||||
@@ -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(¶m.pattern, out);
|
||||
collect_binding_pattern_names_into(¶m.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),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(¶m.pattern, eng);
|
||||
collect_binding_pattern_exprs(¶m.pattern, eng);
|
||||
collect_binding_pattern_names_into(¶m.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);
|
||||
|
||||
Reference in New Issue
Block a user