mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-23 18:21:13 +08:00
438 lines
20 KiB
Rust
438 lines
20 KiB
Rust
//! 闭包捕获分析,own/var/顶层声明名收集:本函数 own_bindings 名集
|
||
//! (参数名 + 变量/函数/import/export 声明,含嵌套块)、var 提升入口
|
||
//! 名集、顶层函数声明名集(无序集 + 声明序列表)。
|
||
|
||
use std::collections::HashSet;
|
||
|
||
use oxide_parser::{Statement, VariableDeclarationKind};
|
||
|
||
use super::{collect_binding_pattern_names, collect_for_left_decl_names};
|
||
|
||
/// 收集语句树中全部 `var` 声明名(var 提升到函数/程序作用域,递归进嵌套块)。
|
||
/// 供函数/程序入口批量 MAKE_CELL(undefined) 使用(var 入口实例化语义)。
|
||
pub(crate) fn collect_var_binding_names(stmts: &[Statement]) -> HashSet<String> {
|
||
let mut names = HashSet::new();
|
||
collect_var_names_stmt(stmts, &mut names);
|
||
names
|
||
}
|
||
|
||
/// 递归遍历语句树收集 `var` 声明名(函数/程序级提升目标),含嵌套块与控制流各分支。
|
||
pub(crate) fn collect_var_names_stmt(stmts: &[Statement], out: &mut HashSet<String>) {
|
||
for stmt in stmts {
|
||
match stmt {
|
||
Statement::VariableDeclaration(vd) => {
|
||
if matches!(vd.kind, VariableDeclarationKind::Var) {
|
||
for d in &vd.declarations {
|
||
collect_binding_pattern_names(&d.id, out);
|
||
}
|
||
}
|
||
}
|
||
Statement::BlockStatement(b) => collect_var_names_stmt(&b.body, out),
|
||
Statement::IfStatement(is) => {
|
||
collect_var_names_stmt(std::slice::from_ref(&is.consequent), out);
|
||
if let Some(alt) = &is.alternate {
|
||
collect_var_names_stmt(std::slice::from_ref(alt), out);
|
||
}
|
||
}
|
||
Statement::WhileStatement(w) => collect_var_names_stmt(std::slice::from_ref(&w.body), out),
|
||
Statement::DoWhileStatement(d) => collect_var_names_stmt(std::slice::from_ref(&d.body), out),
|
||
Statement::ForStatement(f) => {
|
||
if let Some(oxide_parser::ForStatementInit::VariableDeclaration(vd)) = &f.init {
|
||
if matches!(vd.kind, VariableDeclarationKind::Var) {
|
||
for d in &vd.declarations {
|
||
collect_binding_pattern_names(&d.id, out);
|
||
}
|
||
}
|
||
}
|
||
collect_var_names_stmt(std::slice::from_ref(&f.body), out);
|
||
}
|
||
Statement::ForInStatement(fi) => {
|
||
if let oxide_parser::ForStatementLeft::VariableDeclaration(vd) = &fi.left {
|
||
// 仅 var 头名提升到函数作用域,let/const 头名是迭代级绑定。
|
||
if matches!(vd.kind, VariableDeclarationKind::Var) {
|
||
collect_for_left_decl_names(&fi.left, out);
|
||
}
|
||
}
|
||
collect_var_names_stmt(std::slice::from_ref(&fi.body), out);
|
||
}
|
||
Statement::ForOfStatement(fo) => {
|
||
if let oxide_parser::ForStatementLeft::VariableDeclaration(vd) = &fo.left {
|
||
// 仅 var 头名提升到函数作用域,let/const 头名是迭代级绑定。
|
||
if matches!(vd.kind, VariableDeclarationKind::Var) {
|
||
collect_for_left_decl_names(&fo.left, out);
|
||
}
|
||
}
|
||
collect_var_names_stmt(std::slice::from_ref(&fo.body), out);
|
||
}
|
||
Statement::SwitchStatement(sw) => {
|
||
for case in &sw.cases {
|
||
collect_var_names_stmt(&case.consequent, out);
|
||
}
|
||
}
|
||
Statement::TryStatement(ts) => {
|
||
collect_var_names_stmt(&ts.block.body, out);
|
||
if let Some(h) = &ts.handler {
|
||
collect_var_names_stmt(&h.body.body, out);
|
||
}
|
||
if let Some(f) = &ts.finalizer {
|
||
collect_var_names_stmt(&f.body, out);
|
||
}
|
||
}
|
||
Statement::LabeledStatement(ls) => collect_var_names_stmt(std::slice::from_ref(&ls.body), out),
|
||
Statement::WithStatement(ws) => collect_var_names_stmt(std::slice::from_ref(&ws.body), out),
|
||
Statement::ExportNamedDeclaration(exp) => {
|
||
if let Some(oxide_parser::Declaration::VariableDeclaration(vd)) = &exp.declaration {
|
||
if matches!(vd.kind, VariableDeclarationKind::Var) {
|
||
for d in &vd.declarations {
|
||
collect_binding_pattern_names(&d.id, out);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
_ => {}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// 收集语句列表**直接子级**函数声明的绑定名(顶层函数声明是全局 var 绑定,
|
||
/// 裸读/裸写与 var 名同路由全局对象属性)。不递归进块:块内函数声明是块
|
||
/// 作用域,不参与全局对象同步;`export default function` 是 lexical 绑定,不纳。
|
||
pub(crate) fn collect_top_level_function_names(stmts: &[Statement]) -> HashSet<String> {
|
||
let mut names = HashSet::new();
|
||
for stmt in stmts {
|
||
if let Statement::FunctionDeclaration(fd) = stmt {
|
||
if let Some(id) = &fd.id {
|
||
names.insert(id.name.to_string());
|
||
}
|
||
}
|
||
}
|
||
names
|
||
}
|
||
|
||
/// 同 [`collect_top_level_function_names`] 的收集面,但按**声明序**返回 Vec
|
||
/// (供 GlobalDeclarationInstantiation(脚本顶层声明实例化)检查阶段逆序遍历逐名
|
||
/// 去重,规范"逆序首见 = 源序最后声明";重名只查一次,取源序最后一次声明)。
|
||
pub(crate) fn collect_top_level_function_names_ordered(stmts: &[Statement]) -> Vec<String> {
|
||
let mut names = Vec::new();
|
||
for stmt in stmts {
|
||
if let Statement::FunctionDeclaration(fd) = stmt {
|
||
if let Some(id) = &fd.id {
|
||
names.push(id.name.to_string());
|
||
}
|
||
}
|
||
}
|
||
names
|
||
}
|
||
|
||
/// 收集语句列表**直接子级**词法声明名(let/const,含解构 pattern 叶):
|
||
/// 入口 TDZ 占位 cell 名集(被捕获的词法绑定在入口未初始化)。
|
||
///
|
||
/// 遍历面与 `predeclare_lexical_declarations` 一致——只走直接子级,不递归块/
|
||
/// if/for/switch case/try 区(块级名不提升到函数/程序作用域,不建入口
|
||
/// cell);for 头声明是循环作用域绑定,不纳;var 声明不纳(var 入口实例化
|
||
/// 独立覆盖);import 绑定由模块导入初始化的发射点建 cell,不纳。
|
||
pub(crate) fn collect_direct_lexical_names(stmts: &[Statement]) -> HashSet<String> {
|
||
let mut names = HashSet::new();
|
||
for stmt in stmts {
|
||
match stmt {
|
||
Statement::VariableDeclaration(decl) => {
|
||
if matches!(decl.kind, VariableDeclarationKind::Var) {
|
||
continue;
|
||
}
|
||
for d in &decl.declarations {
|
||
collect_binding_pattern_names(&d.id, &mut names);
|
||
}
|
||
}
|
||
Statement::ClassDeclaration(cd) => {
|
||
if let Some(id) = &cd.id {
|
||
names.insert(id.name.to_string());
|
||
}
|
||
}
|
||
Statement::ExportNamedDeclaration(exp) => {
|
||
if let Some(decl) = &exp.declaration {
|
||
match decl {
|
||
oxide_parser::Declaration::VariableDeclaration(vd) => {
|
||
if matches!(vd.kind, VariableDeclarationKind::Var) {
|
||
continue;
|
||
}
|
||
for d in &vd.declarations {
|
||
collect_binding_pattern_names(&d.id, &mut names);
|
||
}
|
||
}
|
||
oxide_parser::Declaration::ClassDeclaration(cd) => {
|
||
if let Some(id) = &cd.id {
|
||
names.insert(id.name.to_string());
|
||
}
|
||
}
|
||
_ => {}
|
||
}
|
||
}
|
||
}
|
||
Statement::ExportDefaultDeclaration(exp) => {
|
||
if let oxide_parser::ExportDefaultDeclarationKind::ClassDeclaration(cd) = &exp.declaration {
|
||
if let Some(id) = &cd.id {
|
||
names.insert(id.name.to_string());
|
||
}
|
||
}
|
||
}
|
||
_ => {}
|
||
}
|
||
}
|
||
names
|
||
}
|
||
|
||
/// 收集块级声明名(块内 let/const/class、catch 参数、for 头 let/const):
|
||
/// 这些名字是块作用域绑定,遮蔽同名顶层 tier 名时,tier 名须保留在捕获集,
|
||
/// 块级绑定才能追加新索引供闭包捕获。顶层直接子级 let/const/class 是顶层
|
||
/// 词法绑定,不纳;var 声明不纳(var 是函数/全局作用域)。
|
||
pub(crate) fn collect_block_level_decl_names(stmts: &[Statement]) -> HashSet<String> {
|
||
let mut names = HashSet::new();
|
||
collect_block_level_names_stmt(stmts, &mut names, true);
|
||
names
|
||
}
|
||
|
||
/// 递归遍历语句树收集块级声明名。`top` 标记当前层是否为顶层(顶层直接子级
|
||
/// let/const/class 是顶层词法绑定,非块级)。
|
||
fn collect_block_level_names_stmt(stmts: &[Statement], out: &mut HashSet<String>, top: bool) {
|
||
for stmt in stmts {
|
||
match stmt {
|
||
Statement::VariableDeclaration(vd) => {
|
||
if matches!(vd.kind, VariableDeclarationKind::Var) || top {
|
||
continue;
|
||
}
|
||
for d in &vd.declarations {
|
||
collect_binding_pattern_names(&d.id, out);
|
||
}
|
||
}
|
||
Statement::ClassDeclaration(cd) => {
|
||
if !top {
|
||
if let Some(id) = &cd.id {
|
||
out.insert(id.name.to_string());
|
||
}
|
||
}
|
||
}
|
||
Statement::BlockStatement(b) => collect_block_level_names_stmt(&b.body, out, false),
|
||
Statement::IfStatement(is) => {
|
||
collect_block_level_names_stmt(std::slice::from_ref(&is.consequent), out, false);
|
||
if let Some(alt) = &is.alternate {
|
||
collect_block_level_names_stmt(std::slice::from_ref(alt), out, false);
|
||
}
|
||
}
|
||
Statement::WhileStatement(w) => collect_block_level_names_stmt(std::slice::from_ref(&w.body), out, false),
|
||
Statement::DoWhileStatement(d) => collect_block_level_names_stmt(std::slice::from_ref(&d.body), out, false),
|
||
Statement::ForStatement(f) => {
|
||
if let Some(oxide_parser::ForStatementInit::VariableDeclaration(vd)) = &f.init {
|
||
if !matches!(vd.kind, VariableDeclarationKind::Var) {
|
||
for d in &vd.declarations {
|
||
collect_binding_pattern_names(&d.id, out);
|
||
}
|
||
}
|
||
}
|
||
collect_block_level_names_stmt(std::slice::from_ref(&f.body), out, false);
|
||
}
|
||
Statement::ForInStatement(fi) => {
|
||
if let oxide_parser::ForStatementLeft::VariableDeclaration(vd) = &fi.left {
|
||
if !matches!(vd.kind, VariableDeclarationKind::Var) {
|
||
collect_for_left_decl_names(&fi.left, out);
|
||
}
|
||
}
|
||
collect_block_level_names_stmt(std::slice::from_ref(&fi.body), out, false);
|
||
}
|
||
Statement::ForOfStatement(fo) => {
|
||
if let oxide_parser::ForStatementLeft::VariableDeclaration(vd) = &fo.left {
|
||
if !matches!(vd.kind, VariableDeclarationKind::Var) {
|
||
collect_for_left_decl_names(&fo.left, out);
|
||
}
|
||
}
|
||
collect_block_level_names_stmt(std::slice::from_ref(&fo.body), out, false);
|
||
}
|
||
Statement::SwitchStatement(sw) => {
|
||
for case in &sw.cases {
|
||
collect_block_level_names_stmt(&case.consequent, out, false);
|
||
}
|
||
}
|
||
Statement::TryStatement(ts) => {
|
||
collect_block_level_names_stmt(&ts.block.body, out, false);
|
||
if let Some(h) = &ts.handler {
|
||
if let Some(param) = &h.param {
|
||
collect_binding_pattern_names(¶m.pattern, out);
|
||
}
|
||
collect_block_level_names_stmt(&h.body.body, out, false);
|
||
}
|
||
if let Some(f) = &ts.finalizer {
|
||
collect_block_level_names_stmt(&f.body, out, false);
|
||
}
|
||
}
|
||
Statement::LabeledStatement(ls) => {
|
||
collect_block_level_names_stmt(std::slice::from_ref(&ls.body), out, false)
|
||
}
|
||
Statement::WithStatement(ws) => collect_block_level_names_stmt(std::slice::from_ref(&ws.body), out, false),
|
||
Statement::ExportNamedDeclaration(exp) => {
|
||
if let Some(decl) = &exp.declaration {
|
||
match decl {
|
||
oxide_parser::Declaration::VariableDeclaration(vd) => {
|
||
if !matches!(vd.kind, VariableDeclarationKind::Var) && !top {
|
||
for d in &vd.declarations {
|
||
collect_binding_pattern_names(&d.id, out);
|
||
}
|
||
}
|
||
}
|
||
oxide_parser::Declaration::ClassDeclaration(cd) if !top => {
|
||
if let Some(id) = &cd.id {
|
||
out.insert(id.name.to_string());
|
||
}
|
||
}
|
||
_ => {}
|
||
}
|
||
}
|
||
}
|
||
_ => {}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// 收集当前函数作用域声明的绑定名(参数 + 变量/函数声明,含嵌套 block,不含嵌套函数体)。
|
||
pub(crate) fn collect_own_binding_names(param_names: &[&str], stmts: &[Statement]) -> HashSet<String> {
|
||
let mut names = HashSet::new();
|
||
for p in param_names {
|
||
names.insert(p.to_string());
|
||
}
|
||
collect_decl_names_stmt(stmts, &mut names);
|
||
names
|
||
}
|
||
|
||
/// 递归遍历语句树收集当前函数作用域声明的绑定名(变量/函数/类/import/export,
|
||
/// 含嵌套块,不进嵌套函数体)。
|
||
pub(crate) fn collect_decl_names_stmt(stmts: &[Statement], out: &mut HashSet<String>) {
|
||
for stmt in stmts {
|
||
match stmt {
|
||
Statement::VariableDeclaration(vd) => {
|
||
for d in &vd.declarations {
|
||
collect_binding_pattern_names(&d.id, out);
|
||
}
|
||
}
|
||
Statement::FunctionDeclaration(fd) => {
|
||
if let Some(id) = &fd.id {
|
||
out.insert(id.name.to_string());
|
||
}
|
||
}
|
||
// class 名是本作用域 const 绑定:须计入 own_bindings,否则嵌套函数
|
||
// 引用类名时捕获分析缺失 → 落符号表兜底(TDZ 误报或读父寄存器残留)。
|
||
Statement::ClassDeclaration(cd) => {
|
||
if let Some(id) = &cd.id {
|
||
out.insert(id.name.to_string());
|
||
}
|
||
}
|
||
// import 绑定是模块作用域 const 绑定,须计入 own_bindings 供
|
||
// 嵌套函数 cell 捕获。
|
||
Statement::ImportDeclaration(imp) => {
|
||
if let Some(specifiers) = &imp.specifiers {
|
||
for sp in specifiers {
|
||
match sp {
|
||
oxide_parser::ImportDeclarationSpecifier::ImportSpecifier(s) => {
|
||
out.insert(s.local.name.to_string());
|
||
}
|
||
oxide_parser::ImportDeclarationSpecifier::ImportDefaultSpecifier(s) => {
|
||
out.insert(s.local.name.to_string());
|
||
}
|
||
oxide_parser::ImportDeclarationSpecifier::ImportNamespaceSpecifier(s) => {
|
||
out.insert(s.local.name.to_string());
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
Statement::ExportNamedDeclaration(exp) => {
|
||
if let Some(decl) = &exp.declaration {
|
||
match decl {
|
||
oxide_parser::Declaration::VariableDeclaration(vd) => {
|
||
for d in &vd.declarations {
|
||
collect_binding_pattern_names(&d.id, out);
|
||
}
|
||
}
|
||
oxide_parser::Declaration::FunctionDeclaration(fd) => {
|
||
if let Some(id) = &fd.id {
|
||
out.insert(id.name.to_string());
|
||
}
|
||
}
|
||
oxide_parser::Declaration::ClassDeclaration(cd) => {
|
||
if let Some(id) = &cd.id {
|
||
out.insert(id.name.to_string());
|
||
}
|
||
}
|
||
_ => {}
|
||
}
|
||
}
|
||
}
|
||
Statement::ExportDefaultDeclaration(exp) => match &exp.declaration {
|
||
oxide_parser::ExportDefaultDeclarationKind::FunctionDeclaration(fd) => {
|
||
if let Some(id) = &fd.id {
|
||
out.insert(id.name.to_string());
|
||
}
|
||
}
|
||
oxide_parser::ExportDefaultDeclarationKind::ClassDeclaration(cd) => {
|
||
if let Some(id) = &cd.id {
|
||
out.insert(id.name.to_string());
|
||
}
|
||
}
|
||
_ => {}
|
||
},
|
||
Statement::BlockStatement(b) => collect_decl_names_stmt(&b.body, out),
|
||
Statement::IfStatement(is) => {
|
||
collect_decl_names_stmt(std::slice::from_ref(&is.consequent), out);
|
||
if let Some(alt) = &is.alternate {
|
||
collect_decl_names_stmt(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::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());
|
||
}
|
||
}
|
||
}
|
||
collect_decl_names_stmt(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_decl_names_stmt(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_decl_names_stmt(std::slice::from_ref(&fo.body), out);
|
||
}
|
||
Statement::SwitchStatement(sw) => {
|
||
for case in &sw.cases {
|
||
collect_decl_names_stmt(&case.consequent, out);
|
||
}
|
||
}
|
||
Statement::TryStatement(ts) => {
|
||
collect_decl_names_stmt(&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_decl_names_stmt(&h.body.body, out);
|
||
}
|
||
if let Some(f) = &ts.finalizer {
|
||
collect_decl_names_stmt(&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),
|
||
_ => {}
|
||
}
|
||
}
|
||
}
|