refactor: 闭包捕获分析拆目录并自由函数化去除接收者

This commit is contained in:
2026-09-15 23:02:03 +00:00
parent 985c27e5bb
commit fa4c9edb81
12 changed files with 1453 additions and 1408 deletions
+424
View File
@@ -0,0 +1,424 @@
//! 闭包捕获分析,父层捕获分析:本函数哪些绑定被任意深度嵌套函数捕获
//! → BTreeMap<String, u8>(cell_idx 按名字序,稳定跨 run)。
use std::collections::{BTreeMap, HashSet};
use oxide_parser::{Expression, Statement};
use super::collect_fn_param_names;
use super::names::collect_own_binding_names;
use super::scanner::{collect_capture_names_expr, collect_capture_names_shadowed, collect_class_capture_names};
/// 分析本函数:哪些绑定被任意深度嵌套函数捕获 → captured_bindings。
pub(crate) fn collect_captured_bindings(
stmts: &[Statement], extra_exprs: &[&oxide_parser::Expression], own: &HashSet<String>,
) -> BTreeMap<String, u8> {
let mut names = HashSet::new();
for stmt in stmts {
collect_captured_stmt(stmt, own, &mut names);
}
// 参数默认值表达式(不在 body_stmts 内)里的嵌套函数引用也要纳入捕获,
// 否则默认值内 IIFE 引用全局/外层变量走 LOAD_VAR 读寄存器残留(B022 扩展)。
for expr in extra_exprs {
collect_captured_expr(expr, own, &mut names);
}
// 名字排序分配 cell_idx(稳定跨 run,父 MAKE_CELL 与子 upvalue 统一引用)
let mut sorted: Vec<String> = names.into_iter().collect();
sorted.sort();
sorted.into_iter().enumerate().map(|(i, n)| (n, i as u8)).collect()
}
/// 收集函数参数默认值表达式里的嵌套函数引用(父层 captured/子层 upvalue 判定)。
pub(crate) fn collect_fn_default_captured(
params: &oxide_parser::FormalParameters, own: &HashSet<String>, out: &mut HashSet<String>,
) {
let empty_shadow = HashSet::new();
for p in &params.items {
if let Some(init) = &p.initializer {
collect_capture_names_expr(init, own, &empty_shadow, out);
}
// 形参模式的运行时求值表达式(计算键/内嵌默认值)在子作用域求值,
// 其标识符引用须纳入父层 MAKE_CELL 判定。
collect_captured_pattern_runtime_exprs(&p.pattern, own, out);
}
}
/// 遍历绑定 pattern 内全部运行时求值表达式(计算键与 AssignmentPattern 默认值):
/// 这些表达式在子作用域(嵌套函数形参绑定时)求值,引用的父层绑定须建 cell 供
/// 子函数 upvalue 读取——与 `collect_capture_names_expr` 同口径(标识符比对)。
pub(crate) fn collect_captured_pattern_runtime_exprs(
pattern: &oxide_parser::BindingPattern, own: &HashSet<String>, out: &mut HashSet<String>,
) {
let empty_shadow = HashSet::new();
match pattern {
oxide_parser::BindingPattern::BindingIdentifier(_) => {}
oxide_parser::BindingPattern::ArrayPattern(ap) => {
for p in ap.elements.iter().flatten() {
collect_captured_pattern_runtime_exprs(p, own, out);
}
if let Some(rest) = &ap.rest {
collect_captured_pattern_runtime_exprs(&rest.argument, own, out);
}
}
oxide_parser::BindingPattern::ObjectPattern(op) => {
for prop in &op.properties {
if prop.computed {
collect_capture_names_expr(prop.key.to_expression(), own, &empty_shadow, out);
}
collect_captured_pattern_runtime_exprs(&prop.value, own, out);
}
if let Some(rest) = &op.rest {
collect_captured_pattern_runtime_exprs(&rest.argument, own, out);
}
}
oxide_parser::BindingPattern::AssignmentPattern(ap) => {
collect_capture_names_expr(&ap.right, own, &empty_shadow, out);
collect_captured_pattern_runtime_exprs(&ap.left, own, out);
}
}
}
/// 只从嵌套函数节点进入扫描(本函数直接引用不算捕获)。
pub(crate) fn collect_captured_stmt(stmt: &Statement, own: &HashSet<String>, out: &mut HashSet<String>) {
match stmt {
Statement::FunctionDeclaration(fd) => {
let body: &[Statement] = fd.body.as_ref().map(|b| &b.statements[..]).unwrap_or(&[]);
collect_fn_default_captured(&fd.params, own, out);
// 函数参数与体内部声明遮蔽父级绑定:体内对这些名字的引用不算捕获父级。
let mut fn_shadow = HashSet::new();
fn_shadow.extend(collect_fn_param_names(&fd.params));
fn_shadow.extend(collect_own_binding_names(&[], body));
collect_capture_names_shadowed(body, own, &fn_shadow, out);
}
Statement::ClassDeclaration(cd) => {
// 类构造器/方法体与字段表达式引用的父级绑定须建 cell,供子模块 upvalue 捕获。
let mut class_shadow = HashSet::new();
if let Some(id) = &cd.id {
class_shadow.insert(id.name.as_str().to_string());
}
collect_class_capture_names(&cd.body, own, &class_shadow, out);
}
Statement::ExpressionStatement(es) => collect_captured_expr(&es.expression, own, out),
Statement::ReturnStatement(rs) => {
if let Some(a) = &rs.argument {
collect_captured_expr(a, own, out);
}
}
Statement::VariableDeclaration(vd) => {
for d in &vd.declarations {
// 绑定 pattern 的计算键是运行时求值表达式,其引用须纳入捕获判定。
collect_captured_binding_keys(&d.id, own, out);
if let Some(init) = &d.init {
collect_captured_expr(init, own, out);
}
}
}
Statement::IfStatement(is) => {
collect_captured_expr(&is.test, own, out);
collect_captured_stmt(&is.consequent, own, out);
if let Some(alt) = &is.alternate {
collect_captured_stmt(alt, own, out);
}
}
Statement::ForStatement(fs) => {
if let Some(init) = &fs.init {
if let Some(e) = init.as_expression() {
collect_captured_expr(e, own, out);
}
if let oxide_parser::ForStatementInit::VariableDeclaration(vd) = init {
for d in &vd.declarations {
collect_captured_binding_keys(&d.id, own, out);
if let Some(i) = &d.init {
collect_captured_expr(i, own, out);
}
}
}
}
if let Some(t) = &fs.test {
collect_captured_expr(t, own, out);
}
if let Some(u) = &fs.update {
collect_captured_expr(u, own, out);
}
collect_captured_stmt(&fs.body, own, out);
}
Statement::WhileStatement(w) => {
collect_captured_expr(&w.test, own, out);
collect_captured_stmt(&w.body, own, out);
}
Statement::DoWhileStatement(d) => {
collect_captured_stmt(&d.body, own, out);
collect_captured_expr(&d.test, own, out);
}
Statement::ForInStatement(fi) => {
collect_captured_expr(&fi.right, own, out);
if let oxide_parser::ForStatementLeft::VariableDeclaration(vd) = &fi.left {
for d in &vd.declarations {
collect_captured_binding_keys(&d.id, own, out);
}
}
collect_captured_stmt(&fi.body, own, out);
}
Statement::ForOfStatement(fo) => {
collect_captured_expr(&fo.right, own, out);
if let oxide_parser::ForStatementLeft::VariableDeclaration(vd) = &fo.left {
for d in &vd.declarations {
collect_captured_binding_keys(&d.id, own, out);
}
}
collect_captured_stmt(&fo.body, own, out);
}
Statement::BlockStatement(b) => {
for s in &b.body {
collect_captured_stmt(s, own, out);
}
}
Statement::TryStatement(ts) => {
for s in &ts.block.body {
collect_captured_stmt(s, own, out);
}
if let Some(h) = &ts.handler {
if let Some(param) = &h.param {
collect_captured_binding_pattern(&param.pattern, own, out);
}
for s in &h.body.body {
collect_captured_stmt(s, own, out);
}
}
if let Some(f) = &ts.finalizer {
for s in &f.body {
collect_captured_stmt(s, own, out);
}
}
}
Statement::ThrowStatement(ts) => collect_captured_expr(&ts.argument, own, out),
Statement::SwitchStatement(sw) => {
collect_captured_expr(&sw.discriminant, own, out);
for case in &sw.cases {
for s in &case.consequent {
collect_captured_stmt(s, own, out);
}
}
}
Statement::LabeledStatement(ls) => collect_captured_stmt(&ls.body, own, out),
Statement::WithStatement(ws) => {
collect_captured_expr(&ws.object, own, out);
collect_captured_stmt(&ws.body, own, out);
}
_ => {}
}
}
/// 遍历 catch 参数解构模式内表达式引用(默认值等),供父层 MAKE_CELL 判定。
pub(crate) fn collect_captured_binding_pattern(
pattern: &oxide_parser::BindingPattern, own: &HashSet<String>, out: &mut HashSet<String>,
) {
match pattern {
oxide_parser::BindingPattern::BindingIdentifier(_) => {}
oxide_parser::BindingPattern::ArrayPattern(ap) => {
for p in ap.elements.iter().flatten() {
collect_captured_binding_pattern(p, own, out);
}
if let Some(rest) = &ap.rest {
collect_captured_binding_pattern(&rest.argument, own, out);
}
}
oxide_parser::BindingPattern::ObjectPattern(op) => {
for prop in &op.properties {
// 计算键表达式(本作用域 catch 参数求值,含 IIFE 等嵌套函数)引用
// 本函数绑定走寄存器,只须扫描键内嵌套函数表达式。
if prop.computed {
collect_captured_expr(prop.key.to_expression(), own, out);
}
collect_captured_binding_pattern(&prop.value, own, out);
}
if let Some(rest) = &op.rest {
collect_captured_binding_pattern(&rest.argument, own, out);
}
}
oxide_parser::BindingPattern::AssignmentPattern(ap) => {
collect_captured_expr(&ap.right, own, out);
collect_captured_binding_pattern(&ap.left, own, out);
}
}
}
/// 遍历绑定 pattern 的运行时求值表达式引用:计算键(`{[k]: a}` 的键)与内嵌
/// 默认值(`{a = x}` 的 x),供父层捕获判定(声明语句/for 头的模式与 catch/
/// 默认值路径同口径)。
pub(crate) fn collect_captured_binding_keys(
pattern: &oxide_parser::BindingPattern, own: &HashSet<String>, out: &mut HashSet<String>,
) {
match pattern {
oxide_parser::BindingPattern::BindingIdentifier(_) => {}
oxide_parser::BindingPattern::ArrayPattern(ap) => {
for p in ap.elements.iter().flatten() {
collect_captured_binding_keys(p, own, out);
}
if let Some(rest) = &ap.rest {
collect_captured_binding_keys(&rest.argument, own, out);
}
}
oxide_parser::BindingPattern::ObjectPattern(op) => {
for prop in &op.properties {
if prop.computed {
collect_captured_expr(prop.key.to_expression(), own, out);
}
collect_captured_binding_keys(&prop.value, own, out);
}
if let Some(rest) = &op.rest {
collect_captured_binding_keys(&rest.argument, own, out);
}
}
oxide_parser::BindingPattern::AssignmentPattern(ap) => {
// 内嵌默认值表达式引用外层绑定须建 cell(与 captured_binding_pattern
// 同口径);left 继续递归模式键。
collect_captured_expr(&ap.right, own, out);
collect_captured_binding_keys(&ap.left, own, out);
}
}
}
pub(crate) fn collect_captured_expr(expr: &Expression, own: &HashSet<String>, out: &mut HashSet<String>) {
match expr {
Expression::FunctionExpression(fe) => {
let body: &[Statement] = fe.body.as_ref().map(|b| &b.statements[..]).unwrap_or(&[]);
let mut inner = collect_fn_param_names(&fe.params);
inner.extend(collect_own_binding_names(&[], body));
collect_fn_default_captured(&fe.params, own, out);
collect_capture_names_shadowed(body, own, &inner, out);
}
Expression::ArrowFunctionExpression(ae) => {
let mut inner = collect_fn_param_names(&ae.params);
inner.extend(collect_own_binding_names(&[], &ae.body.statements));
collect_fn_default_captured(&ae.params, own, out);
collect_capture_names_shadowed(&ae.body.statements, own, &inner, out);
}
Expression::ClassExpression(class) => {
// 类表达式:构造器/方法体与字段表达式引用的父级绑定须建 cell。
let mut class_shadow = HashSet::new();
if let Some(id) = &class.id {
class_shadow.insert(id.name.as_str().to_string());
}
collect_class_capture_names(&class.body, own, &class_shadow, out);
}
Expression::CallExpression(ce) => {
collect_captured_expr(&ce.callee, own, out);
for a in &ce.arguments {
collect_captured_arg(a, own, out);
}
}
Expression::BinaryExpression(be) => {
collect_captured_expr(&be.left, own, out);
collect_captured_expr(&be.right, own, out);
}
Expression::UnaryExpression(ue) => collect_captured_expr(&ue.argument, own, out),
Expression::LogicalExpression(le) => {
collect_captured_expr(&le.left, own, out);
collect_captured_expr(&le.right, own, out);
}
Expression::ConditionalExpression(ce) => {
collect_captured_expr(&ce.test, own, out);
collect_captured_expr(&ce.consequent, own, out);
collect_captured_expr(&ce.alternate, own, out);
}
Expression::SequenceExpression(se) => {
for e in &se.expressions {
collect_captured_expr(e, own, out);
}
}
Expression::AssignmentExpression(ae) => {
// 只扫右侧:左侧赋值目标是本函数绑定,不引用嵌套函数;
// 若目标含嵌套函数表达式(如 `[f()] = ...`),由其自身递归处理。
collect_captured_expr(&ae.right, own, out);
}
Expression::UpdateExpression(_ue) => {} // 一元更新目标不引用嵌套函数,无需捕获
Expression::ArrayExpression(ae) => {
for e in &ae.elements {
if let Some(e) = e.as_expression() {
collect_captured_expr(e, own, out);
}
}
}
Expression::ObjectExpression(o) => {
for prop in &o.properties {
match prop {
oxide_parser::ObjectPropertyKind::ObjectProperty(p) => {
if p.computed {
collect_captured_expr(p.key.to_expression(), own, out);
}
collect_captured_expr(&p.value, own, out);
}
oxide_parser::ObjectPropertyKind::SpreadProperty(spread) => {
collect_captured_expr(&spread.argument, own, out);
}
}
}
}
Expression::NewExpression(ne) => {
collect_captured_expr(&ne.callee, own, out);
for a in &ne.arguments {
collect_captured_arg(a, own, out);
}
}
Expression::ComputedMemberExpression(m) => {
collect_captured_expr(&m.object, own, out);
collect_captured_expr(&m.expression, own, out);
}
Expression::StaticMemberExpression(m) => collect_captured_expr(&m.object, own, out),
Expression::PrivateFieldExpression(m) => collect_captured_expr(&m.object, own, out),
Expression::TemplateLiteral(tl) => {
for e in &tl.expressions {
collect_captured_expr(e, own, out);
}
}
Expression::TaggedTemplateExpression(tt) => {
collect_captured_expr(&tt.tag, own, out);
for e in &tt.quasi.expressions {
collect_captured_expr(e, own, out);
}
}
Expression::ParenthesizedExpression(p) => collect_captured_expr(&p.expression, own, out),
Expression::YieldExpression(ye) => {
if let Some(a) = &ye.argument {
collect_captured_expr(a, own, out);
}
}
Expression::AwaitExpression(ae) => collect_captured_expr(&ae.argument, own, out),
Expression::ChainExpression(c) => collect_captured_chain(&c.expression, own, out),
_ => {}
}
}
pub(crate) fn collect_captured_chain(
element: &oxide_parser::ChainElement, own: &HashSet<String>, out: &mut HashSet<String>,
) {
match element {
oxide_parser::ChainElement::StaticMemberExpression(m) => {
collect_captured_expr(&m.object, own, out);
}
oxide_parser::ChainElement::ComputedMemberExpression(m) => {
collect_captured_expr(&m.object, own, out);
collect_captured_expr(&m.expression, own, out);
}
oxide_parser::ChainElement::PrivateFieldExpression(m) => {
collect_captured_expr(&m.object, own, out);
}
oxide_parser::ChainElement::CallExpression(c) => {
collect_captured_expr(&c.callee, own, out);
for a in &c.arguments {
collect_captured_arg(a, own, out);
}
}
_ => {}
}
}
/// 遍历调用实参:静态实参与 spread 内部表达式都纳入捕获判定。
pub(crate) fn collect_captured_arg(arg: &oxide_parser::Argument, own: &HashSet<String>, out: &mut HashSet<String>) {
if let Some(e) = arg.as_expression() {
collect_captured_expr(e, own, out);
} else if let oxide_parser::Argument::SpreadElement(sp) = arg {
collect_captured_expr(&sp.argument, own, out);
}
}
+71
View File
@@ -0,0 +1,71 @@
//! 闭包捕获分析(AST 级,emit 前完成,时序无关)。
//!
//! 收集本函数绑定的名字(own_bindings)与被嵌套函数捕获的名字
//! (captured_bindings → cell_idx,按名排序稳定跨 run),为 MAKE_CELL /
//! CELL_GET / CELL_SET 与子函数 upvalue cell_idx 提供统一依据。
//!
//! 五区严格单向分层(本文件 ← names ← scanner ← captured ← upvalues):
//! 跨区调用单向、无共享局部状态、无接收者状态。
mod captured;
mod names;
mod scanner;
mod upvalues;
use std::collections::HashSet;
pub(crate) use captured::collect_captured_bindings;
pub(crate) use names::collect_own_binding_names;
pub(crate) use names::collect_top_level_function_names;
pub(crate) use names::collect_top_level_function_names_ordered;
pub(crate) use names::collect_var_binding_names;
pub(crate) use upvalues::collect_upvalue_names;
pub(crate) fn collect_fn_param_names(params: &oxide_parser::FormalParameters) -> HashSet<String> {
let mut names = HashSet::new();
for p in &params.items {
collect_binding_pattern_names(&p.pattern, &mut names);
}
// rest 形参也是本函数作用域绑定,遮蔽外层同名变量。
if let Some(rest) = &params.rest {
collect_binding_pattern_names(&rest.rest.argument, &mut names);
}
names
}
/// 递归收集 binding pattern 内全部绑定标识符名(解构 `[a, b]` / `{x: y}` 嵌套)。
pub(crate) fn collect_binding_pattern_names(pattern: &oxide_parser::BindingPattern, out: &mut HashSet<String>) {
match pattern {
oxide_parser::BindingPattern::BindingIdentifier(bi) => {
out.insert(bi.name.to_string());
}
oxide_parser::BindingPattern::ArrayPattern(ap) => {
for p in ap.elements.iter().flatten() {
collect_binding_pattern_names(p, out);
}
if let Some(rest) = &ap.rest {
collect_binding_pattern_names(&rest.argument, out);
}
}
oxide_parser::BindingPattern::ObjectPattern(op) => {
for prop in &op.properties {
collect_binding_pattern_names(&prop.value, out);
}
if let Some(rest) = &op.rest {
collect_binding_pattern_names(&rest.argument, out);
}
}
oxide_parser::BindingPattern::AssignmentPattern(ap) => {
collect_binding_pattern_names(&ap.left, out);
}
}
}
/// 收集 for-in/for-of 头部声明(`var x` / 解构 pattern)绑定的名字。
pub(crate) fn collect_for_left_decl_names(left: &oxide_parser::ForStatementLeft, out: &mut HashSet<String>) {
if let oxide_parser::ForStatementLeft::VariableDeclaration(vd) = left {
for d in &vd.declarations {
collect_binding_pattern_names(&d.id, out);
}
}
}
+261
View File
@@ -0,0 +1,261 @@
//! 闭包捕获分析,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
}
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
/// (供 GDI 检查阶段逆序遍历逐名去重,规范"逆序首见 = 源序最后声明")。
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
}
/// 收集当前函数作用域声明的绑定名(参数 + 变量/函数声明,含嵌套 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
}
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 {
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),
_ => {}
}
}
}
+614
View File
@@ -0,0 +1,614 @@
//! 闭包捕获分析,遮蔽感知引用收集:ref_set × shadow 双集驱动,遍历
//! 语句/表达式/赋值目标/类体 AST,嵌套函数/类/for 头/catch 参数逐层
//! 遮蔽,收集任意深度嵌套函数引用的名字。
use std::collections::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};
pub(crate) fn collect_capture_names_shadowed(
stmts: &[Statement], ref_set: &HashSet<String>, shadow: &HashSet<String>, out: &mut HashSet<String>,
) {
for stmt in stmts {
collect_capture_names_stmt(stmt, ref_set, shadow, out);
}
}
pub(crate) fn collect_capture_names_stmt(
stmt: &Statement, ref_set: &HashSet<String>, shadow: &HashSet<String>, out: &mut HashSet<String>,
) {
match stmt {
Statement::ExpressionStatement(es) => collect_capture_names_expr(&es.expression, ref_set, shadow, out),
Statement::ReturnStatement(rs) => {
if let Some(a) = &rs.argument {
collect_capture_names_expr(a, ref_set, shadow, out);
}
}
Statement::VariableDeclaration(vd) => {
for d in &vd.declarations {
// 绑定 pattern 的计算键是运行时求值表达式,其引用须纳入捕获。
collect_capture_names_binding_keys(&d.id, ref_set, shadow, out);
if let Some(init) = &d.init {
collect_capture_names_expr(init, ref_set, shadow, out);
}
}
}
Statement::FunctionDeclaration(fd) => {
let body: &[Statement] = fd.body.as_ref().map(|b| &b.statements[..]).unwrap_or(&[]);
let mut inner = shadow.clone();
inner.extend(collect_fn_param_names(&fd.params));
inner.extend(collect_own_binding_names(&[], body));
collect_fn_default_names(&fd.params, ref_set, shadow, out);
collect_capture_names_shadowed(body, ref_set, &inner, out);
}
Statement::ClassDeclaration(cd) => {
// 类体(构造器/方法体、字段键与值、静态块)是嵌套作用域:
// 类名遮蔽外层绑定,方法形参与方法体局部进一步遮蔽。
let mut class_shadow = shadow.clone();
if let Some(id) = &cd.id {
class_shadow.insert(id.name.as_str().to_string());
}
collect_class_capture_names(&cd.body, ref_set, &class_shadow, out);
}
Statement::IfStatement(is) => {
collect_capture_names_expr(&is.test, ref_set, shadow, out);
collect_capture_names_stmt(&is.consequent, ref_set, shadow, out);
if let Some(alt) = &is.alternate {
collect_capture_names_stmt(alt, ref_set, shadow, out);
}
}
Statement::ForStatement(fs) => {
if let Some(init) = &fs.init {
if let Some(e) = init.as_expression() {
collect_capture_names_expr(e, ref_set, shadow, out);
}
if let oxide_parser::ForStatementInit::VariableDeclaration(vd) = init {
for d in &vd.declarations {
collect_capture_names_binding_keys(&d.id, ref_set, shadow, out);
if let Some(i) = &d.init {
collect_capture_names_expr(i, ref_set, shadow, out);
}
}
}
}
if let Some(t) = &fs.test {
collect_capture_names_expr(t, ref_set, shadow, out);
}
if let Some(u) = &fs.update {
collect_capture_names_expr(u, ref_set, shadow, out);
}
collect_capture_names_stmt(&fs.body, ref_set, shadow, out);
}
Statement::WhileStatement(w) => {
collect_capture_names_expr(&w.test, ref_set, shadow, out);
collect_capture_names_stmt(&w.body, ref_set, shadow, out);
}
Statement::DoWhileStatement(d) => {
collect_capture_names_stmt(&d.body, ref_set, shadow, out);
collect_capture_names_expr(&d.test, ref_set, shadow, out);
}
Statement::ForInStatement(fi) => {
collect_capture_names_expr(&fi.right, ref_set, shadow, out);
// left 的 var 声明遮蔽外层同名绑定,body 内引用不视为捕获外层。
let mut for_shadow = shadow.clone();
collect_for_left_decl_names(&fi.left, &mut for_shadow);
if let oxide_parser::ForStatementLeft::VariableDeclaration(vd) = &fi.left {
for d in &vd.declarations {
collect_capture_names_binding_keys(&d.id, ref_set, shadow, out);
}
}
collect_capture_names_shadowed(std::slice::from_ref(&fi.body), ref_set, &for_shadow, out);
}
Statement::ForOfStatement(fo) => {
collect_capture_names_expr(&fo.right, ref_set, shadow, out);
let mut for_shadow = shadow.clone();
collect_for_left_decl_names(&fo.left, &mut for_shadow);
if let oxide_parser::ForStatementLeft::VariableDeclaration(vd) = &fo.left {
for d in &vd.declarations {
collect_capture_names_binding_keys(&d.id, ref_set, shadow, out);
}
}
collect_capture_names_shadowed(std::slice::from_ref(&fo.body), ref_set, &for_shadow, out);
}
Statement::BlockStatement(b) => collect_capture_names_shadowed(&b.body, ref_set, shadow, out),
Statement::TryStatement(ts) => {
for s in &ts.block.body {
collect_capture_names_stmt(s, ref_set, shadow, out);
}
if let Some(h) = &ts.handler {
// catch 参数解构模式内的表达式引用(默认值等)也会被内部闭包捕获;
// 参数声明名遮蔽 catch 作用域。
let mut catch_shadow = shadow.clone();
if let Some(param) = &h.param {
collect_capture_names_binding_pattern(&param.pattern, ref_set, shadow, out, &mut catch_shadow);
}
for s in &h.body.body {
collect_capture_names_stmt(s, ref_set, &catch_shadow, out);
}
}
if let Some(f) = &ts.finalizer {
for s in &f.body {
collect_capture_names_stmt(s, ref_set, shadow, out);
}
}
}
Statement::ExportNamedDeclaration(exp) => {
if let Some(decl) = &exp.declaration {
match decl {
oxide_parser::Declaration::VariableDeclaration(vd) => {
for d in &vd.declarations {
collect_capture_names_binding_keys(&d.id, ref_set, shadow, out);
if let Some(init) = &d.init {
collect_capture_names_expr(init, ref_set, shadow, out);
}
}
}
oxide_parser::Declaration::FunctionDeclaration(fd) => {
let body: &[Statement] = fd.body.as_ref().map(|b| &b.statements[..]).unwrap_or(&[]);
let mut inner = shadow.clone();
inner.extend(collect_fn_param_names(&fd.params));
inner.extend(collect_own_binding_names(&[], body));
collect_fn_default_names(&fd.params, ref_set, shadow, out);
collect_capture_names_shadowed(body, ref_set, &inner, out);
}
oxide_parser::Declaration::ClassDeclaration(cd) => {
let mut class_shadow = shadow.clone();
if let Some(id) = &cd.id {
class_shadow.insert(id.name.as_str().to_string());
}
collect_class_capture_names(&cd.body, ref_set, &class_shadow, out);
}
_ => {}
}
}
}
Statement::ExportDefaultDeclaration(exp) => match &exp.declaration {
oxide_parser::ExportDefaultDeclarationKind::FunctionDeclaration(fd) => {
let body: &[Statement] = fd.body.as_ref().map(|b| &b.statements[..]).unwrap_or(&[]);
let mut inner = shadow.clone();
inner.extend(collect_fn_param_names(&fd.params));
inner.extend(collect_own_binding_names(&[], body));
collect_fn_default_names(&fd.params, ref_set, shadow, out);
collect_capture_names_shadowed(body, ref_set, &inner, out);
}
oxide_parser::ExportDefaultDeclarationKind::ClassDeclaration(cd) => {
let mut class_shadow = shadow.clone();
if let Some(id) = &cd.id {
class_shadow.insert(id.name.as_str().to_string());
}
collect_class_capture_names(&cd.body, ref_set, &class_shadow, out);
}
other => {
if let Some(e) = other.as_expression() {
collect_capture_names_expr(e, ref_set, shadow, out);
}
}
},
Statement::ThrowStatement(ts) => collect_capture_names_expr(&ts.argument, ref_set, shadow, out),
Statement::SwitchStatement(sw) => {
collect_capture_names_expr(&sw.discriminant, ref_set, shadow, out);
for case in &sw.cases {
for s in &case.consequent {
collect_capture_names_stmt(s, ref_set, shadow, out);
}
}
}
Statement::LabeledStatement(ls) => collect_capture_names_stmt(&ls.body, ref_set, shadow, out),
Statement::WithStatement(ws) => {
collect_capture_names_expr(&ws.object, ref_set, shadow, out);
collect_capture_names_stmt(&ws.body, ref_set, shadow, out);
}
_ => {}
}
}
/// 收集类体对 `ref_set` 的引用:方法/构造器体、字段键与值、静态块。
/// 方法形参与方法体局部声明遮蔽外层绑定(捕获判定用)。
pub(crate) fn collect_class_capture_names(
class_body: &ClassBody, ref_set: &HashSet<String>, class_shadow: &HashSet<String>, out: &mut HashSet<String>,
) {
for element in &class_body.body {
match element {
ClassElement::MethodDefinition(method) => {
let mut inner = class_shadow.clone();
inner.extend(collect_fn_param_names(&method.value.params));
let body: &[Statement] = method.value.body.as_ref().map(|b| &b.statements[..]).unwrap_or(&[]);
inner.extend(collect_own_binding_names(&[], body));
collect_fn_default_names(&method.value.params, ref_set, class_shadow, out);
collect_capture_names_shadowed(body, ref_set, &inner, out);
}
ClassElement::PropertyDefinition(prop) => {
if let Some(expr) = prop.key.as_expression() {
collect_capture_names_expr(expr, ref_set, class_shadow, out);
}
if let Some(value) = &prop.value {
collect_capture_names_expr(value, ref_set, class_shadow, out);
}
}
ClassElement::StaticBlock(block) => {
collect_capture_names_shadowed(&block.body, ref_set, class_shadow, out);
}
_ => {}
}
}
}
/// 遍历 catch 参数解构模式:收集模式内表达式引用(默认值等),声明名写入
/// `catch_shadow` 遮蔽 catch 作用域。
pub(crate) fn collect_capture_names_binding_pattern(
pattern: &oxide_parser::BindingPattern, ref_set: &HashSet<String>, shadow: &HashSet<String>,
out: &mut HashSet<String>, catch_shadow: &mut HashSet<String>,
) {
match pattern {
oxide_parser::BindingPattern::BindingIdentifier(bi) => {
catch_shadow.insert(bi.name.as_str().to_string());
}
oxide_parser::BindingPattern::ArrayPattern(ap) => {
for p in ap.elements.iter().flatten() {
collect_capture_names_binding_pattern(p, ref_set, shadow, out, catch_shadow);
}
if let Some(rest) = &ap.rest {
collect_capture_names_binding_pattern(&rest.argument, ref_set, shadow, out, catch_shadow);
}
}
oxide_parser::BindingPattern::ObjectPattern(op) => {
for prop in &op.properties {
// 计算键是运行时求值表达式,其引用须纳入捕获。
if prop.computed {
collect_capture_names_expr(prop.key.to_expression(), ref_set, shadow, out);
}
collect_capture_names_binding_pattern(&prop.value, ref_set, shadow, out, catch_shadow);
}
if let Some(rest) = &op.rest {
collect_capture_names_binding_pattern(&rest.argument, ref_set, shadow, out, catch_shadow);
}
}
oxide_parser::BindingPattern::AssignmentPattern(ap) => {
collect_capture_names_expr(&ap.right, ref_set, shadow, out);
collect_capture_names_binding_pattern(&ap.left, ref_set, shadow, out, catch_shadow);
}
}
}
/// 遍历绑定 pattern 的运行时求值表达式引用:计算键(`{[k]: a}` 的键)与内嵌
/// 默认值(`{a = x}` 的 x)都是模式内求值的表达式,嵌套函数引用外层绑定时须
/// 纳入捕获(与赋值侧/对象字面量/类字段键遍历同口径)。
pub(crate) fn collect_capture_names_binding_keys(
pattern: &oxide_parser::BindingPattern, ref_set: &HashSet<String>, shadow: &HashSet<String>,
out: &mut HashSet<String>,
) {
match pattern {
oxide_parser::BindingPattern::BindingIdentifier(_) => {}
oxide_parser::BindingPattern::ArrayPattern(ap) => {
for p in ap.elements.iter().flatten() {
collect_capture_names_binding_keys(p, ref_set, shadow, out);
}
if let Some(rest) = &ap.rest {
collect_capture_names_binding_keys(&rest.argument, ref_set, shadow, out);
}
}
oxide_parser::BindingPattern::ObjectPattern(op) => {
for prop in &op.properties {
if prop.computed {
collect_capture_names_expr(prop.key.to_expression(), ref_set, shadow, out);
}
collect_capture_names_binding_keys(&prop.value, ref_set, shadow, out);
}
if let Some(rest) = &op.rest {
collect_capture_names_binding_keys(&rest.argument, ref_set, shadow, out);
}
}
oxide_parser::BindingPattern::AssignmentPattern(ap) => {
// 内嵌默认值表达式引用外层绑定须捕获(与 binding_pattern/赋值侧
// maybe_default 的 init 扫描同口径);left 继续递归模式键。
collect_capture_names_expr(&ap.right, ref_set, shadow, out);
collect_capture_names_binding_keys(&ap.left, ref_set, shadow, out);
}
}
}
/// 扫描赋值目标中的引用(标识符写名,成员目标扫对象/键,解构目标递归元素)。
pub(crate) fn collect_capture_names_assign_target(
target: &oxide_parser::AssignmentTarget, ref_set: &HashSet<String>, shadow: &HashSet<String>,
out: &mut HashSet<String>,
) {
match target {
oxide_parser::AssignmentTarget::AssignmentTargetIdentifier(ati) => {
let name = ati.name.as_str();
if ref_set.contains(name) && !shadow.contains(name) {
out.insert(ati.name.to_string());
}
}
oxide_parser::AssignmentTarget::StaticMemberExpression(m) => {
collect_capture_names_expr(&m.object, ref_set, shadow, out);
}
oxide_parser::AssignmentTarget::ComputedMemberExpression(m) => {
collect_capture_names_expr(&m.object, ref_set, shadow, out);
collect_capture_names_expr(&m.expression, ref_set, shadow, out);
}
oxide_parser::AssignmentTarget::ArrayAssignmentTarget(a) => {
for e in a.elements.iter().flatten() {
collect_capture_names_maybe_default_target(e, ref_set, shadow, out);
}
if let Some(rest) = &a.rest {
collect_capture_names_assign_target(&rest.target, ref_set, shadow, out);
}
}
oxide_parser::AssignmentTarget::ObjectAssignmentTarget(o) => {
for prop in &o.properties {
if let oxide_parser::AssignmentTargetProperty::AssignmentTargetPropertyIdentifier(id) = prop {
if ref_set.contains(id.binding.name.as_str()) && !shadow.contains(id.binding.name.as_str()) {
out.insert(id.binding.name.to_string());
}
if let Some(init) = &id.init {
collect_capture_names_expr(init, ref_set, shadow, out);
}
} else if let oxide_parser::AssignmentTargetProperty::AssignmentTargetPropertyProperty(p) = prop {
if let Some(name_expr) = p.name.as_expression() {
collect_capture_names_expr(name_expr, ref_set, shadow, out);
}
collect_capture_names_maybe_default_target(&p.binding, ref_set, shadow, out);
}
}
if let Some(rest) = &o.rest {
collect_capture_names_assign_target(&rest.target, ref_set, shadow, out);
}
}
_ => {}
}
}
/// 解构赋值元素可能是 `AssignmentTarget` 或带默认值的包装(后者多一层 `init`)。
pub(crate) fn collect_capture_names_maybe_default_target(
target: &oxide_parser::AssignmentTargetMaybeDefault, ref_set: &HashSet<String>, shadow: &HashSet<String>,
out: &mut HashSet<String>,
) {
use oxide_parser::AssignmentTargetMaybeDefault as MaybeDefault;
match target {
MaybeDefault::AssignmentTargetWithDefault(d) => {
collect_capture_names_expr(&d.init, ref_set, shadow, out);
collect_capture_names_assign_target(&d.binding, ref_set, shadow, out);
}
MaybeDefault::AssignmentTargetIdentifier(ati) => {
let name = ati.name.as_str();
if ref_set.contains(name) && !shadow.contains(name) {
out.insert(ati.name.to_string());
}
}
MaybeDefault::StaticMemberExpression(m) => {
collect_capture_names_expr(&m.object, ref_set, shadow, out);
}
MaybeDefault::ComputedMemberExpression(m) => {
collect_capture_names_expr(&m.object, ref_set, shadow, out);
collect_capture_names_expr(&m.expression, ref_set, shadow, out);
}
MaybeDefault::ArrayAssignmentTarget(a) => {
for e in a.elements.iter().flatten() {
collect_capture_names_maybe_default_target(e, ref_set, shadow, out);
}
}
MaybeDefault::ObjectAssignmentTarget(o) => {
for prop in &o.properties {
if let oxide_parser::AssignmentTargetProperty::AssignmentTargetPropertyIdentifier(id) = prop {
if ref_set.contains(id.binding.name.as_str()) && !shadow.contains(id.binding.name.as_str()) {
out.insert(id.binding.name.to_string());
}
if let Some(init) = &id.init {
collect_capture_names_expr(init, ref_set, shadow, out);
}
} else if let oxide_parser::AssignmentTargetProperty::AssignmentTargetPropertyProperty(p) = prop {
if let Some(name_expr) = p.name.as_expression() {
collect_capture_names_expr(name_expr, ref_set, shadow, out);
}
collect_capture_names_maybe_default_target(&p.binding, ref_set, shadow, out);
}
}
}
_ => {}
}
}
/// 扫描一元更新目标(`++x` / `obj.x++`)中的引用。
pub(crate) fn collect_capture_names_simple_target(
target: &oxide_parser::SimpleAssignmentTarget, ref_set: &HashSet<String>, shadow: &HashSet<String>,
out: &mut HashSet<String>,
) {
match target {
oxide_parser::SimpleAssignmentTarget::AssignmentTargetIdentifier(ati) => {
let name = ati.name.as_str();
if ref_set.contains(name) && !shadow.contains(name) {
out.insert(ati.name.to_string());
}
}
oxide_parser::SimpleAssignmentTarget::StaticMemberExpression(m) => {
collect_capture_names_expr(&m.object, ref_set, shadow, out);
}
oxide_parser::SimpleAssignmentTarget::ComputedMemberExpression(m) => {
collect_capture_names_expr(&m.object, ref_set, shadow, out);
collect_capture_names_expr(&m.expression, ref_set, shadow, out);
}
_ => {}
}
}
/// 收集函数参数默认值表达式里的引用(子层 upvalue 判定;参数名遮蔽)。
pub(crate) fn collect_fn_default_names(
params: &oxide_parser::FormalParameters, ref_set: &HashSet<String>, shadow: &HashSet<String>,
out: &mut HashSet<String>,
) {
for p in &params.items {
if let Some(init) = &p.initializer {
collect_capture_names_expr(init, ref_set, shadow, out);
}
let mut param_shadow = shadow.clone();
collect_capture_names_binding_pattern(&p.pattern, ref_set, shadow, out, &mut param_shadow);
}
}
pub(crate) fn collect_capture_names_expr(
expr: &Expression, ref_set: &HashSet<String>, shadow: &HashSet<String>, out: &mut HashSet<String>,
) {
match expr {
Expression::Identifier(id) => {
let name = id.name.as_str();
if ref_set.contains(name) && !shadow.contains(name) {
out.insert(id.name.to_string());
}
}
Expression::AssignmentExpression(ae) => {
// 赋值目标里的引用也须捕获:标识符目标写名,成员/解构目标扫描其对象/元素。
collect_capture_names_assign_target(&ae.left, ref_set, shadow, out);
collect_capture_names_expr(&ae.right, ref_set, shadow, out);
}
Expression::UpdateExpression(ue) => {
collect_capture_names_simple_target(&ue.argument, ref_set, shadow, out);
}
Expression::FunctionExpression(fe) => {
let body: &[Statement] = fe.body.as_ref().map(|b| &b.statements[..]).unwrap_or(&[]);
let mut inner = shadow.clone();
inner.extend(collect_fn_param_names(&fe.params));
inner.extend(collect_own_binding_names(&[], body));
collect_fn_default_names(&fe.params, ref_set, shadow, out);
collect_capture_names_shadowed(body, ref_set, &inner, out);
}
Expression::ArrowFunctionExpression(ae) => {
let mut inner = shadow.clone();
inner.extend(collect_fn_param_names(&ae.params));
inner.extend(collect_own_binding_names(&[], &ae.body.statements));
collect_fn_default_names(&ae.params, ref_set, shadow, out);
collect_capture_names_shadowed(&ae.body.statements, ref_set, &inner, out);
}
Expression::ClassExpression(class) => {
// 类表达式:方法/构造器体与字段表达式是嵌套作用域,引用须捕获。
let mut class_shadow = shadow.clone();
if let Some(id) = &class.id {
class_shadow.insert(id.name.as_str().to_string());
}
collect_class_capture_names(&class.body, ref_set, &class_shadow, out);
}
Expression::BinaryExpression(be) => {
collect_capture_names_expr(&be.left, ref_set, shadow, out);
collect_capture_names_expr(&be.right, ref_set, shadow, out);
}
Expression::UnaryExpression(ue) => collect_capture_names_expr(&ue.argument, ref_set, shadow, out),
Expression::CallExpression(ce) => {
collect_capture_names_expr(&ce.callee, ref_set, shadow, out);
for a in &ce.arguments {
collect_capture_names_arg(a, ref_set, shadow, out);
}
}
Expression::NewExpression(ne) => {
collect_capture_names_expr(&ne.callee, ref_set, shadow, out);
for a in &ne.arguments {
collect_capture_names_arg(a, ref_set, shadow, out);
}
}
Expression::SequenceExpression(se) => {
for e in &se.expressions {
collect_capture_names_expr(e, ref_set, shadow, out);
}
}
Expression::ConditionalExpression(ce) => {
collect_capture_names_expr(&ce.test, ref_set, shadow, out);
collect_capture_names_expr(&ce.consequent, ref_set, shadow, out);
collect_capture_names_expr(&ce.alternate, ref_set, shadow, out);
}
Expression::ArrayExpression(ae) => {
for e in &ae.elements {
if let Some(e) = e.as_expression() {
collect_capture_names_expr(e, ref_set, shadow, out);
}
}
}
Expression::LogicalExpression(le) => {
collect_capture_names_expr(&le.left, ref_set, shadow, out);
collect_capture_names_expr(&le.right, ref_set, shadow, out);
}
Expression::ComputedMemberExpression(m) => {
collect_capture_names_expr(&m.object, ref_set, shadow, out);
collect_capture_names_expr(&m.expression, ref_set, shadow, out);
}
Expression::StaticMemberExpression(m) => collect_capture_names_expr(&m.object, ref_set, shadow, out),
Expression::PrivateFieldExpression(m) => collect_capture_names_expr(&m.object, ref_set, shadow, out),
Expression::ParenthesizedExpression(p) => collect_capture_names_expr(&p.expression, ref_set, shadow, out),
Expression::TemplateLiteral(tl) => {
for e in &tl.expressions {
collect_capture_names_expr(e, ref_set, shadow, out);
}
}
Expression::TaggedTemplateExpression(tt) => {
collect_capture_names_expr(&tt.tag, ref_set, shadow, out);
for e in &tt.quasi.expressions {
collect_capture_names_expr(e, ref_set, shadow, out);
}
}
Expression::ObjectExpression(o) => {
for prop in &o.properties {
match prop {
oxide_parser::ObjectPropertyKind::ObjectProperty(p) => {
if p.computed {
collect_capture_names_expr(p.key.to_expression(), ref_set, shadow, out);
}
collect_capture_names_expr(&p.value, ref_set, shadow, out);
}
oxide_parser::ObjectPropertyKind::SpreadProperty(spread) => {
collect_capture_names_expr(&spread.argument, ref_set, shadow, out);
}
}
}
}
// 生成器让出表达式:被让出的值里引用的父变量须纳入捕获,否则生成器体经
// LOAD_VAR 读调用方寄存器残留(挂起恢复后寄存器已被覆盖)。
Expression::YieldExpression(ye) => {
if let Some(a) = &ye.argument {
collect_capture_names_expr(a, ref_set, shadow, out);
}
}
// await 表达式:被等待的值里引用的父变量须纳入捕获(与 yield 同因——
// 异步体挂起恢复后寄存器已被覆盖,只能经 cell 读取)。
Expression::AwaitExpression(ae) => {
collect_capture_names_expr(&ae.argument, ref_set, shadow, out);
}
Expression::ChainExpression(c) => collect_capture_names_chain(&c.expression, ref_set, shadow, out),
_ => {}
}
}
pub(crate) fn collect_capture_names_chain(
element: &oxide_parser::ChainElement, ref_set: &HashSet<String>, shadow: &HashSet<String>,
out: &mut HashSet<String>,
) {
match element {
oxide_parser::ChainElement::StaticMemberExpression(m) => {
collect_capture_names_expr(&m.object, ref_set, shadow, out);
}
oxide_parser::ChainElement::ComputedMemberExpression(m) => {
collect_capture_names_expr(&m.object, ref_set, shadow, out);
collect_capture_names_expr(&m.expression, ref_set, shadow, out);
}
oxide_parser::ChainElement::PrivateFieldExpression(m) => {
collect_capture_names_expr(&m.object, ref_set, shadow, out);
}
oxide_parser::ChainElement::CallExpression(call) => {
collect_capture_names_expr(&call.callee, ref_set, shadow, out);
for a in &call.arguments {
collect_capture_names_arg(a, ref_set, shadow, out);
}
}
_ => {}
}
}
/// 遍历调用实参:静态实参与 spread 内部表达式都纳入捕获扫描。
pub(crate) fn collect_capture_names_arg(
arg: &oxide_parser::Argument, ref_set: &HashSet<String>, shadow: &HashSet<String>, out: &mut HashSet<String>,
) {
if let Some(e) = arg.as_expression() {
collect_capture_names_expr(e, ref_set, shadow, out);
} else if let oxide_parser::Argument::SpreadElement(sp) = arg {
collect_capture_names_expr(&sp.argument, ref_set, shadow, out);
}
}
+48
View File
@@ -0,0 +1,48 @@
//! 闭包捕获分析,子函数 upvalue 分析:子函数体对父被捕获绑定的引用
//! → Vec<UpvalueCapture>(排序对齐 cell_idx,enclosing_reg 留 0 待
//! assemble_ir 填充)。
use std::collections::{BTreeMap, HashSet};
use oxide_bytecode::module::UpvalueCapture;
use oxide_parser::Statement;
use super::scanner::{collect_capture_names_expr, collect_capture_names_shadowed};
/// 分析子函数 body:引用父级被捕获绑定的名字 → upvalue_captures。
/// 名字若在父 `captured_bindings`(父 own cell)则 `cell_idx` 索引定义方表;
/// 若在父 `upvalue_captures`(父自身从更外层捕获)则链式标记 `parent_uv_idx`,
/// 运行时从父闭包 upvalues 取 cell。enclosing_reg 由父 emit 完成后填充。
pub(crate) fn collect_upvalue_names(
body_stmts: &[Statement], extra_exprs: &[&oxide_parser::Expression], parent_captured: &BTreeMap<String, u8>,
parent_upvalues: &[UpvalueCapture], sub_own: &HashSet<String>,
) -> Vec<UpvalueCapture> {
let mut parent_names: HashSet<String> = parent_captured.keys().cloned().collect();
for u in parent_upvalues {
parent_names.insert(u.name.clone());
}
let mut names = HashSet::new();
collect_capture_names_shadowed(body_stmts, &parent_names, sub_own, &mut names);
// 参数默认值表达式(不在 body_stmts)里的嵌套函数引用也会捕获父变量。
for expr in extra_exprs {
collect_capture_names_expr(expr, &parent_names, sub_own, &mut names);
}
// HashSet 迭代序带随机种子(进程级非确定),必须排序使 upvalue_captures 的顺序与
// 父 captured_bindings 的 cell_idx(BTreeMap 名字序)对齐——否则 LOAD_UPVALUE 的
// a 槽 uv_idx 编码与 cell_idx 错位,读错 upvalue。
let mut names: Vec<String> = names.into_iter().collect();
names.sort();
names
.into_iter()
.map(|name| {
let parent_uv_idx = parent_upvalues.iter().position(|u| u.name == name).map(|i| i as u8);
let cell_idx = parent_captured.get(&name).copied().unwrap_or(0);
UpvalueCapture {
name,
enclosing_reg: 0, // assemble_ir 时从父符号表填充
cell_idx,
parent_uv_idx,
}
})
.collect()
}
File diff suppressed because it is too large Load Diff
+11 -8
View File
@@ -2,7 +2,7 @@
//! (参数 prologue、参数默认值与闭包捕获分析、双 sub-pass 语句发射)。 //! (参数 prologue、参数默认值与闭包捕获分析、双 sub-pass 语句发射)。
//! //!
//! 两类型经 lib.rs 重导出供各语法域构造实参;编译链为 `Emitter` 方法, //! 两类型经 lib.rs 重导出供各语法域构造实参;编译链为 `Emitter` 方法,
//! 捕获分析经 `self.*` 调用 closure 族,与所在文件无关。 //! 捕获分析经自由函数调用 capture 族,与所在文件无关。
use std::collections::HashSet; use std::collections::HashSet;
@@ -13,6 +13,10 @@ use oxide_ir::operand::{LabelId, Operand};
use oxide_ir::IRFunction; use oxide_ir::IRFunction;
use oxide_parser::{Expression, Statement, VariableDeclarationKind}; use oxide_parser::{Expression, Statement, VariableDeclarationKind};
use crate::capture::{
collect_binding_pattern_names, collect_captured_bindings, collect_own_binding_names, collect_upvalue_names,
collect_var_binding_names,
};
use crate::compile_ctx::{CompileCtx, FieldBuffer}; use crate::compile_ctx::{CompileCtx, FieldBuffer};
use crate::symbol_table::{Binding, ScopeKind}; use crate::symbol_table::{Binding, ScopeKind};
use crate::Emitter; use crate::Emitter;
@@ -299,7 +303,7 @@ impl Emitter {
for spec in param_specs { for spec in param_specs {
param_names.insert(spec.register_name().to_string()); param_names.insert(spec.register_name().to_string());
if let ParamSpec::Pattern { pattern, .. } = spec { if let ParamSpec::Pattern { pattern, .. } = spec {
self.collect_binding_pattern_names(pattern, &mut param_names); collect_binding_pattern_names(pattern, &mut param_names);
} }
} }
ctx.param_names = param_names; ctx.param_names = param_names;
@@ -527,10 +531,10 @@ impl Emitter {
ParamSpec::Rest { .. } => {} ParamSpec::Rest { .. } => {}
} }
} }
ctx.own_bindings = self.collect_own_binding_names(&param_names, body_stmts); ctx.own_bindings = collect_own_binding_names(&param_names, body_stmts);
for spec in param_specs { for spec in param_specs {
if let ParamSpec::Pattern { pattern, .. } = spec { if let ParamSpec::Pattern { pattern, .. } = spec {
self.collect_binding_pattern_names(pattern, &mut ctx.own_bindings); collect_binding_pattern_names(pattern, &mut ctx.own_bindings);
} }
} }
@@ -548,13 +552,13 @@ impl Emitter {
// 字段初始化表达式(值表达式)与参数默认值一并纳入捕获分析。 // 字段初始化表达式(值表达式)与参数默认值一并纳入捕获分析。
let mut capture_exprs: Vec<&oxide_parser::Expression> = param_defaults.clone(); let mut capture_exprs: Vec<&oxide_parser::Expression> = param_defaults.clone();
capture_exprs.extend_from_slice(extra_capture_exprs); capture_exprs.extend_from_slice(extra_capture_exprs);
ctx.captured_bindings = self.collect_captured_bindings(body_stmts, &capture_exprs, &ctx.own_bindings); ctx.captured_bindings = collect_captured_bindings(body_stmts, &capture_exprs, &ctx.own_bindings);
// 自由变量分析:收集 upvalue 捕获(类方法也是普通函数,可捕获外层变量)。 // 自由变量分析:收集 upvalue 捕获(类方法也是普通函数,可捕获外层变量)。
if matches!( if matches!(
body_context, body_context,
FunctionBodyContext::Ordinary | FunctionBodyContext::Arrow | FunctionBodyContext::ClassElement FunctionBodyContext::Ordinary | FunctionBodyContext::Arrow | FunctionBodyContext::ClassElement
) { ) {
ctx.current_upvalue_captures = self.collect_upvalue_names( ctx.current_upvalue_captures = collect_upvalue_names(
body_stmts, body_stmts,
&capture_exprs, &capture_exprs,
&parent_ctx.captured_bindings, &parent_ctx.captured_bindings,
@@ -659,8 +663,7 @@ impl Emitter {
// 只是赋值;否则声明语句前创建的闭包读取占位 cell → TDZ 误报。参数与 // 只是赋值;否则声明语句前创建的闭包读取占位 cell → TDZ 误报。参数与
// arguments 已在上方初始化(跳过以免覆盖参数值);let/const/class 保持 // arguments 已在上方初始化(跳过以免覆盖参数值);let/const/class 保持
// TDZ 语义不动。声明语句的 MAKE_CELL 按占位更新语义覆盖此初值。 // TDZ 语义不动。声明语句的 MAKE_CELL 按占位更新语义覆盖此初值。
let var_names: Vec<String> = self let var_names: Vec<String> = collect_var_binding_names(body_stmts)
.collect_var_binding_names(body_stmts)
.into_iter() .into_iter()
.filter(|n| !param_names.contains(&n.as_str()) && n != "arguments") .filter(|n| !param_names.contains(&n.as_str()) && n != "arguments")
.filter(|n| ctx.captured_bindings.contains_key(n)) .filter(|n| ctx.captured_bindings.contains_key(n))
+1 -1
View File
@@ -5,8 +5,8 @@
//! `oxide_ir::lower` 降为 bytecode。语法按域拆分:`expr/`、`stmt/`、`class/`、 //! `oxide_ir::lower` 降为 bytecode。语法按域拆分:`expr/`、`stmt/`、`class/`、
//! `shared/`;作用域与闭包捕获分析在 emit 前完成,消除符号表时序依赖。 //! `shared/`;作用域与闭包捕获分析在 emit 前完成,消除符号表时序依赖。
mod capture;
pub mod class; pub mod class;
pub mod closure;
mod compile_ctx; mod compile_ctx;
pub mod emit; pub mod emit;
pub mod emit_ctx; pub mod emit_ctx;
+3 -2
View File
@@ -7,6 +7,7 @@
use std::collections::HashSet; use std::collections::HashSet;
use std::path::Path; use std::path::Path;
use crate::capture::{collect_captured_bindings, collect_own_binding_names};
use crate::expr::call::pack_arg_regs; use crate::expr::call::pack_arg_regs;
use crate::{CompileCtx, Emitter}; use crate::{CompileCtx, Emitter};
use oxc_allocator::Box; use oxc_allocator::Box;
@@ -171,8 +172,8 @@ impl Emitter {
let _ = self.predeclare_lexical_declarations(body, ctx, false); let _ = self.predeclare_lexical_declarations(body, ctx, false);
// 闭包捕获分析(import 绑定名纳入 own_bindings,供嵌套函数 cell 捕获)。 // 闭包捕获分析(import 绑定名纳入 own_bindings,供嵌套函数 cell 捕获)。
ctx.own_bindings = self.collect_own_binding_names(&[], body); ctx.own_bindings = collect_own_binding_names(&[], body);
ctx.captured_bindings = self.collect_captured_bindings(body, &[], &ctx.own_bindings); ctx.captured_bindings = collect_captured_bindings(body, &[], &ctx.own_bindings);
// —— 模块命名空间对象 —— // —— 模块命名空间对象 ——
let ns_reg = self.emit_module_call(ctx, "__moduleObject", &[])?; let ns_reg = self.emit_module_call(ctx, "__moduleObject", &[])?;
+7 -6
View File
@@ -4,6 +4,7 @@
use std::collections::HashSet; use std::collections::HashSet;
use crate::capture::collect_binding_pattern_names;
use crate::Emitter; use crate::Emitter;
use oxide_parser::{Declaration, Statement, VariableDeclarationKind}; use oxide_parser::{Declaration, Statement, VariableDeclarationKind};
@@ -98,7 +99,7 @@ impl Emitter {
Statement::VariableDeclaration(vd) => { Statement::VariableDeclaration(vd) => {
if !matches!(vd.kind, VariableDeclarationKind::Var) { if !matches!(vd.kind, VariableDeclarationKind::Var) {
for d in &vd.declarations { for d in &vd.declarations {
self.collect_binding_pattern_names(&d.id, names); collect_binding_pattern_names(&d.id, names);
} }
} }
} }
@@ -111,7 +112,7 @@ impl Emitter {
if let Some(oxide_parser::ForStatementInit::VariableDeclaration(decl)) = &fs.init { if let Some(oxide_parser::ForStatementInit::VariableDeclaration(decl)) = &fs.init {
if !matches!(decl.kind, VariableDeclarationKind::Var) { if !matches!(decl.kind, VariableDeclarationKind::Var) {
for d in &decl.declarations { for d in &decl.declarations {
self.collect_binding_pattern_names(&d.id, names); collect_binding_pattern_names(&d.id, names);
} }
} }
} }
@@ -121,7 +122,7 @@ impl Emitter {
if let oxide_parser::ForStatementLeft::VariableDeclaration(decl) = &fi.left { if let oxide_parser::ForStatementLeft::VariableDeclaration(decl) = &fi.left {
if !matches!(decl.kind, VariableDeclarationKind::Var) { if !matches!(decl.kind, VariableDeclarationKind::Var) {
for d in &decl.declarations { for d in &decl.declarations {
self.collect_binding_pattern_names(&d.id, names); collect_binding_pattern_names(&d.id, names);
} }
} }
} }
@@ -131,7 +132,7 @@ impl Emitter {
if let oxide_parser::ForStatementLeft::VariableDeclaration(decl) = &fo.left { if let oxide_parser::ForStatementLeft::VariableDeclaration(decl) = &fo.left {
if !matches!(decl.kind, VariableDeclarationKind::Var) { if !matches!(decl.kind, VariableDeclarationKind::Var) {
for d in &decl.declarations { for d in &decl.declarations {
self.collect_binding_pattern_names(&d.id, names); collect_binding_pattern_names(&d.id, names);
} }
} }
} }
@@ -141,7 +142,7 @@ impl Emitter {
// catch 参数是 handler 环境的词法绑定。 // catch 参数是 handler 环境的词法绑定。
if let Some(handler) = &ts.handler { if let Some(handler) = &ts.handler {
if let Some(param) = &handler.param { if let Some(param) = &handler.param {
self.collect_binding_pattern_names(&param.pattern, names); collect_binding_pattern_names(&param.pattern, names);
} }
self.collect_lexical_name_suppressions(&handler.body.body, names); self.collect_lexical_name_suppressions(&handler.body.body, names);
} }
@@ -178,7 +179,7 @@ impl Emitter {
if let Some(Declaration::VariableDeclaration(vd)) = &exp.declaration { if let Some(Declaration::VariableDeclaration(vd)) = &exp.declaration {
if !matches!(vd.kind, VariableDeclarationKind::Var) { if !matches!(vd.kind, VariableDeclarationKind::Var) {
for d in &vd.declarations { for d in &vd.declarations {
self.collect_binding_pattern_names(&d.id, names); collect_binding_pattern_names(&d.id, names);
} }
} }
} }
+11 -7
View File
@@ -16,6 +16,10 @@ use oxide_ir::operand::Operand;
use oxide_ir::IRFunction; use oxide_ir::IRFunction;
use oxide_parser::Statement; use oxide_parser::Statement;
use crate::capture::{
collect_captured_bindings, collect_own_binding_names, collect_top_level_function_names,
collect_top_level_function_names_ordered, collect_var_binding_names,
};
use crate::compile_ctx::CompileCtx; use crate::compile_ctx::CompileCtx;
use crate::Emitter; use crate::Emitter;
@@ -220,7 +224,7 @@ impl Emitter {
/// - 仅遍历语句列表直接子级具名函数声明(生成器/异步声明同节点类型,天然 /// - 仅遍历语句列表直接子级具名函数声明(生成器/异步声明同节点类型,天然
/// 覆盖);块内函数声明与 `export default function` 不入全局检查面。 /// 覆盖);块内函数声明与 `export default function` 不入全局检查面。
pub(crate) fn emit_gdi_func_decl_checks(&self, stmts: &[Statement], ctx: &mut CompileCtx) { pub(crate) fn emit_gdi_func_decl_checks(&self, stmts: &[Statement], ctx: &mut CompileCtx) {
let names = self.collect_top_level_function_names_ordered(stmts); let names = collect_top_level_function_names_ordered(stmts);
let mut seen = HashSet::new(); let mut seen = HashSet::new();
for name in names.iter().rev() { for name in names.iter().rev() {
// 逆序首见即源序最后声明者(规范去重口径),重名只查一次。 // 逆序首见即源序最后声明者(规范去重口径),重名只查一次。
@@ -262,7 +266,7 @@ impl Emitter {
// 严格 eval 代码函数声明绑定 eval 自身 lexical 环境、不触全局、不抛,门禁 // 严格 eval 代码函数声明绑定 eval 自身 lexical 环境、不触全局、不抛,门禁
// 随 !is_strict 关闭,其写点抑制在声明发射处。 // 随 !is_strict 关闭,其写点抑制在声明发射处。
if ctx.is_eval_script && !ctx.is_strict { if ctx.is_eval_script && !ctx.is_strict {
for name in self.collect_top_level_function_names(&program.body) { for name in collect_top_level_function_names(&program.body) {
if NON_WRITABLE_GLOBAL_BUILTINS.contains(&name.as_str()) { if NON_WRITABLE_GLOBAL_BUILTINS.contains(&name.as_str()) {
let _ = self.emit_throw_error( let _ = self.emit_throw_error(
"TypeError", "TypeError",
@@ -312,15 +316,15 @@ impl Emitter {
} }
// 闭包捕获分析(AST 级,emit 前确定) // 闭包捕获分析(AST 级,emit 前确定)
ctx.own_bindings = self.collect_own_binding_names(&[], &program.body); ctx.own_bindings = collect_own_binding_names(&[], &program.body);
// 顶层已声明名(A 侧单一真值):裸读走全局对象属性、裸写走描述符感知 // 顶层已声明名(A 侧单一真值):裸读走全局对象属性、裸写走描述符感知
// A 侧写,不落镜像 cell——从捕获集剔除,使嵌套函数经继承 scope-0 直连全局。 // A 侧写,不落镜像 cell——从捕获集剔除,使嵌套函数经继承 scope-0 直连全局。
// 集 = 顶层 var 名 ∪ 顶层函数声明名:函数值是编译闭包,编译期不可得, // 集 = 顶层 var 名 ∪ 顶层函数声明名:函数值是编译闭包,编译期不可得,
// 其 A 侧值由首 sub-pass 以真闭包建立,先于任何用户代码。 // 其 A 侧值由首 sub-pass 以真闭包建立,先于任何用户代码。
// 仅在此顶层调用点过滤:嵌套函数的局部同名遮蔽是独立绑定,其调用点不过滤。 // 仅在此顶层调用点过滤:嵌套函数的局部同名遮蔽是独立绑定,其调用点不过滤。
let var_names = self.collect_var_binding_names(&program.body); let var_names = collect_var_binding_names(&program.body);
let mut tier_names = var_names.clone(); let mut tier_names = var_names.clone();
tier_names.extend(self.collect_top_level_function_names(&program.body)); tier_names.extend(collect_top_level_function_names(&program.body));
// 块级函数泄漏名并入:求值期写回与头写同走全局对象属性(A 侧单一真值)。 // 块级函数泄漏名并入:求值期写回与头写同走全局对象属性(A 侧单一真值)。
for name in &block_fn_names { for name in &block_fn_names {
if !ctx.block_fn_suppressed.contains(name) && !CompileCtx::is_non_writable_global_builtin(name) { if !ctx.block_fn_suppressed.contains(name) && !CompileCtx::is_non_writable_global_builtin(name) {
@@ -328,7 +332,7 @@ impl Emitter {
} }
} }
ctx.global_tier_names = tier_names; ctx.global_tier_names = tier_names;
ctx.captured_bindings = self.collect_captured_bindings(&program.body, &[], &ctx.own_bindings); ctx.captured_bindings = collect_captured_bindings(&program.body, &[], &ctx.own_bindings);
ctx.captured_bindings.retain(|n, _| !ctx.global_tier_names.contains(n)); ctx.captured_bindings.retain(|n, _| !ctx.global_tier_names.contains(n));
// 顶层 var 入口实例化:被捕获的 var 名统一 MAKE_CELL(undefined),使 var // 顶层 var 入口实例化:被捕获的 var 名统一 MAKE_CELL(undefined),使 var
@@ -364,7 +368,7 @@ impl Emitter {
// 预载全局属性值),既有属性零动作,值幂等保留。 // 预载全局属性值),既有属性零动作,值幂等保留。
// 序言名集 = 顶层 var 名 ∪ 顶层块级函数泄漏名(web-compat 外层绑定同样 // 序言名集 = 顶层 var 名 ∪ 顶层块级函数泄漏名(web-compat 外层绑定同样
// 在求值前实例化,同走 define-if-absent)。 // 在求值前实例化,同走 define-if-absent)。
let mut gdi_var_names = self.collect_var_binding_names(&program.body); let mut gdi_var_names = collect_var_binding_names(&program.body);
gdi_var_names.extend( gdi_var_names.extend(
block_fn_names block_fn_names
.iter() .iter()
@@ -6,6 +6,7 @@
use std::collections::HashSet; use std::collections::HashSet;
use crate::capture::collect_binding_pattern_names;
use crate::{CompileCtx, Emitter}; use crate::{CompileCtx, Emitter};
use oxide_bytecode::opcode::OpCode; use oxide_bytecode::opcode::OpCode;
use oxide_ir::inst::Inst; use oxide_ir::inst::Inst;
@@ -30,7 +31,7 @@ impl Emitter {
} }
let mut names = HashSet::new(); let mut names = HashSet::new();
for d in &decl.declarations { for d in &decl.declarations {
self.collect_binding_pattern_names(&d.id, &mut names); collect_binding_pattern_names(&d.id, &mut names);
} }
let mut v: Vec<String> = names.into_iter().collect(); let mut v: Vec<String> = names.into_iter().collect();
v.sort(); v.sort();