This repository has been archived on 2026-09-15. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
OxideJS/crates/oxide_emit/src/closure.rs
T
爱特每羊队 6f80c12ac9 feat: 生成器基础支持(YIELD 帧快照挂起/恢复 + GeneratorPrototype next/return/throw)
- 新增 YIELD/SUSPEND_BODY opcode;function* 识别与 yield emit
- GeneratorState 全量快照 VM 执行上下文(regs/pc/bytecode/spill/save/try/cell 栈段/迭代器)
- 调用时参数初始化(默认值/解构副作用与异常在 g() 时刻生效)
- %GeneratorPrototype%/%GeneratorFunction.prototype% 内建对象与 next/return/throw
- session GC trace 生成器状态 JsValues;闭包捕获分析补 yield/赋值目标扫描
2026-08-09 18:02:08 +08:00

985 lines
48 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! 闭包捕获分析(AST 级,emit 前完成,时序无关)。
//!
//! 收集本函数绑定的名字(own_bindings)与被嵌套函数捕获的名字
//! (captured_bindings → cell_idx,按名排序稳定跨 run),为 MAKE_CELL /
//! CELL_GET / CELL_SET 与子函数 upvalue cell_idx 提供统一依据。
use std::collections::{BTreeMap, HashSet};
use oxide_bytecode::module::UpvalueCapture;
use oxide_parser::{ClassBody, ClassElement, Expression, Statement};
use crate::Emitter;
impl Emitter {
fn collect_fn_param_names(&self, params: &oxide_parser::FormalParameters) -> HashSet<String> {
let mut names = HashSet::new();
for p in &params.items {
if let oxide_parser::BindingPattern::BindingIdentifier(bi) = &p.pattern {
names.insert(bi.name.to_string());
}
}
names
}
/// 收集 for-in/for-of 头部声明(`var x` / 解构 pattern)绑定的名字。
fn collect_for_left_decl_names(&self, left: &oxide_parser::ForStatementLeft, out: &mut HashSet<String>) {
if let oxide_parser::ForStatementLeft::VariableDeclaration(vd) = left {
for d in &vd.declarations {
if let oxide_parser::BindingPattern::BindingIdentifier(bi) = &d.id {
out.insert(bi.name.to_string());
}
}
}
}
/// 收集当前函数作用域声明的绑定名(参数 + 变量/函数声明,含嵌套 block,不含嵌套函数体)。
pub(crate) fn collect_own_binding_names(&self, param_names: &[&str], stmts: &[Statement]) -> HashSet<String> {
let mut names = HashSet::new();
for p in param_names {
names.insert(p.to_string());
}
self.collect_decl_names_stmt(stmts, &mut names);
names
}
fn collect_decl_names_stmt(&self, stmts: &[Statement], out: &mut HashSet<String>) {
for stmt in stmts {
match stmt {
Statement::VariableDeclaration(vd) => {
for d in &vd.declarations {
if let oxide_parser::BindingPattern::BindingIdentifier(bi) = &d.id {
out.insert(bi.name.to_string());
}
}
}
Statement::FunctionDeclaration(fd) => {
if let Some(id) = &fd.id {
out.insert(id.name.to_string());
}
}
Statement::BlockStatement(b) => self.collect_decl_names_stmt(&b.body, out),
Statement::IfStatement(is) => {
self.collect_decl_names_stmt(std::slice::from_ref(&is.consequent), out);
if let Some(alt) = &is.alternate {
self.collect_decl_names_stmt(std::slice::from_ref(alt), out);
}
}
Statement::WhileStatement(w) => self.collect_decl_names_stmt(std::slice::from_ref(&w.body), out),
Statement::DoWhileStatement(d) => self.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());
}
}
}
self.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(vd) = &fi.left {
for d in &vd.declarations {
if let oxide_parser::BindingPattern::BindingIdentifier(bi) = &d.id {
out.insert(bi.name.to_string());
}
}
}
self.collect_decl_names_stmt(std::slice::from_ref(&fi.body), out);
}
Statement::ForOfStatement(fo) => {
if let oxide_parser::ForStatementLeft::VariableDeclaration(vd) = &fo.left {
for d in &vd.declarations {
if let oxide_parser::BindingPattern::BindingIdentifier(bi) = &d.id {
out.insert(bi.name.to_string());
}
}
}
self.collect_decl_names_stmt(std::slice::from_ref(&fo.body), out);
}
Statement::SwitchStatement(sw) => {
for case in &sw.cases {
self.collect_decl_names_stmt(&case.consequent, out);
}
}
Statement::TryStatement(ts) => {
self.collect_decl_names_stmt(&ts.block.body, out);
if let Some(h) = &ts.handler {
self.collect_decl_names_stmt(&h.body.body, out);
}
if let Some(f) = &ts.finalizer {
self.collect_decl_names_stmt(&f.body, out);
}
}
Statement::LabeledStatement(ls) => self.collect_decl_names_stmt(std::slice::from_ref(&ls.body), out),
Statement::WithStatement(ws) => self.collect_decl_names_stmt(std::slice::from_ref(&ws.body), out),
_ => {}
}
}
}
fn collect_capture_names_shadowed(
&self, stmts: &[Statement], ref_set: &HashSet<String>, shadow: &HashSet<String>, out: &mut HashSet<String>,
) {
for stmt in stmts {
self.collect_capture_names_stmt(stmt, ref_set, shadow, out);
}
}
fn collect_capture_names_stmt(
&self, stmt: &Statement, ref_set: &HashSet<String>, shadow: &HashSet<String>, out: &mut HashSet<String>,
) {
match stmt {
Statement::ExpressionStatement(es) => self.collect_capture_names_expr(&es.expression, ref_set, shadow, out),
Statement::ReturnStatement(rs) => {
if let Some(a) = &rs.argument {
self.collect_capture_names_expr(a, ref_set, shadow, out);
}
}
Statement::VariableDeclaration(vd) => {
for d in &vd.declarations {
if let Some(init) = &d.init {
self.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(self.collect_fn_param_names(&fd.params));
inner.extend(self.collect_own_binding_names(&[], body));
self.collect_fn_default_names(&fd.params, ref_set, shadow, out);
self.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());
}
self.collect_class_capture_names(&cd.body, ref_set, &class_shadow, out);
}
Statement::IfStatement(is) => {
self.collect_capture_names_expr(&is.test, ref_set, shadow, out);
self.collect_capture_names_stmt(&is.consequent, ref_set, shadow, out);
if let Some(alt) = &is.alternate {
self.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() {
self.collect_capture_names_expr(e, ref_set, shadow, out);
}
if let oxide_parser::ForStatementInit::VariableDeclaration(vd) = init {
for d in &vd.declarations {
if let Some(i) = &d.init {
self.collect_capture_names_expr(i, ref_set, shadow, out);
}
}
}
}
if let Some(t) = &fs.test {
self.collect_capture_names_expr(t, ref_set, shadow, out);
}
if let Some(u) = &fs.update {
self.collect_capture_names_expr(u, ref_set, shadow, out);
}
self.collect_capture_names_stmt(&fs.body, ref_set, shadow, out);
}
Statement::WhileStatement(w) => {
self.collect_capture_names_expr(&w.test, ref_set, shadow, out);
self.collect_capture_names_stmt(&w.body, ref_set, shadow, out);
}
Statement::DoWhileStatement(d) => {
self.collect_capture_names_stmt(&d.body, ref_set, shadow, out);
self.collect_capture_names_expr(&d.test, ref_set, shadow, out);
}
Statement::ForInStatement(fi) => {
self.collect_capture_names_expr(&fi.right, ref_set, shadow, out);
// left 的 var 声明遮蔽外层同名绑定,body 内引用不视为捕获外层。
let mut for_shadow = shadow.clone();
self.collect_for_left_decl_names(&fi.left, &mut for_shadow);
self.collect_capture_names_shadowed(std::slice::from_ref(&fi.body), ref_set, &for_shadow, out);
}
Statement::ForOfStatement(fo) => {
self.collect_capture_names_expr(&fo.right, ref_set, shadow, out);
let mut for_shadow = shadow.clone();
self.collect_for_left_decl_names(&fo.left, &mut for_shadow);
self.collect_capture_names_shadowed(std::slice::from_ref(&fo.body), ref_set, &for_shadow, out);
}
Statement::BlockStatement(b) => self.collect_capture_names_shadowed(&b.body, ref_set, shadow, out),
Statement::TryStatement(ts) => {
for s in &ts.block.body {
self.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 {
self.collect_capture_names_binding_pattern(
&param.pattern,
ref_set,
shadow,
out,
&mut catch_shadow,
);
}
for s in &h.body.body {
self.collect_capture_names_stmt(s, ref_set, &catch_shadow, out);
}
}
if let Some(f) = &ts.finalizer {
for s in &f.body {
self.collect_capture_names_stmt(s, ref_set, shadow, out);
}
}
}
Statement::ThrowStatement(ts) => self.collect_capture_names_expr(&ts.argument, ref_set, shadow, out),
Statement::SwitchStatement(sw) => {
self.collect_capture_names_expr(&sw.discriminant, ref_set, shadow, out);
for case in &sw.cases {
for s in &case.consequent {
self.collect_capture_names_stmt(s, ref_set, shadow, out);
}
}
}
Statement::LabeledStatement(ls) => self.collect_capture_names_stmt(&ls.body, ref_set, shadow, out),
Statement::WithStatement(ws) => {
self.collect_capture_names_expr(&ws.object, ref_set, shadow, out);
self.collect_capture_names_stmt(&ws.body, ref_set, shadow, out);
}
_ => {}
}
}
/// 收集类体对 `ref_set` 的引用:方法/构造器体、字段键与值、静态块。
/// 方法形参与方法体局部声明遮蔽外层绑定(捕获判定用)。
fn collect_class_capture_names(
&self, 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(self.collect_fn_param_names(&method.value.params));
let body: &[Statement] = method.value.body.as_ref().map(|b| &b.statements[..]).unwrap_or(&[]);
inner.extend(self.collect_own_binding_names(&[], body));
self.collect_fn_default_names(&method.value.params, ref_set, class_shadow, out);
self.collect_capture_names_shadowed(body, ref_set, &inner, out);
}
ClassElement::PropertyDefinition(prop) => {
if let Some(expr) = prop.key.as_expression() {
self.collect_capture_names_expr(expr, ref_set, class_shadow, out);
}
if let Some(value) = &prop.value {
self.collect_capture_names_expr(value, ref_set, class_shadow, out);
}
}
ClassElement::StaticBlock(block) => {
self.collect_capture_names_shadowed(&block.body, ref_set, class_shadow, out);
}
_ => {}
}
}
}
/// 遍历 catch 参数解构模式:收集模式内表达式引用(默认值等),声明名写入
/// `catch_shadow` 遮蔽 catch 作用域。
fn collect_capture_names_binding_pattern(
&self, 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 elem in &ap.elements {
if let Some(p) = elem {
self.collect_capture_names_binding_pattern(p, ref_set, shadow, out, catch_shadow);
}
}
if let Some(rest) = &ap.rest {
self.collect_capture_names_binding_pattern(&rest.argument, ref_set, shadow, out, catch_shadow);
}
}
oxide_parser::BindingPattern::ObjectPattern(op) => {
for prop in &op.properties {
self.collect_capture_names_binding_pattern(&prop.value, ref_set, shadow, out, catch_shadow);
}
if let Some(rest) = &op.rest {
self.collect_capture_names_binding_pattern(&rest.argument, ref_set, shadow, out, catch_shadow);
}
}
oxide_parser::BindingPattern::AssignmentPattern(ap) => {
self.collect_capture_names_expr(&ap.right, ref_set, shadow, out);
self.collect_capture_names_binding_pattern(&ap.left, ref_set, shadow, out, catch_shadow);
}
}
}
/// 扫描赋值目标中的引用(标识符写名,成员目标扫对象/键,解构目标递归元素)。
fn collect_capture_names_assign_target(
&self, 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) => {
self.collect_capture_names_expr(&m.object, ref_set, shadow, out);
}
oxide_parser::AssignmentTarget::ComputedMemberExpression(m) => {
self.collect_capture_names_expr(&m.object, ref_set, shadow, out);
self.collect_capture_names_expr(&m.expression, ref_set, shadow, out);
}
oxide_parser::AssignmentTarget::ArrayAssignmentTarget(a) => {
for elem in &a.elements {
if let Some(e) = elem {
self.collect_capture_names_maybe_default_target(e, ref_set, shadow, out);
}
}
if let Some(rest) = &a.rest {
self.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 {
self.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() {
self.collect_capture_names_expr(name_expr, ref_set, shadow, out);
}
self.collect_capture_names_maybe_default_target(&p.binding, ref_set, shadow, out);
}
}
if let Some(rest) = &o.rest {
self.collect_capture_names_assign_target(&rest.target, ref_set, shadow, out);
}
}
_ => {}
}
}
/// 解构赋值元素可能是 `AssignmentTarget` 或带默认值的包装(后者多一层 `init`)。
fn collect_capture_names_maybe_default_target(
&self, 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) => {
self.collect_capture_names_expr(&d.init, ref_set, shadow, out);
self.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) => {
self.collect_capture_names_expr(&m.object, ref_set, shadow, out);
}
MaybeDefault::ComputedMemberExpression(m) => {
self.collect_capture_names_expr(&m.object, ref_set, shadow, out);
self.collect_capture_names_expr(&m.expression, ref_set, shadow, out);
}
MaybeDefault::ArrayAssignmentTarget(a) => {
for elem in &a.elements {
if let Some(e) = elem {
self.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 {
self.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() {
self.collect_capture_names_expr(name_expr, ref_set, shadow, out);
}
self.collect_capture_names_maybe_default_target(&p.binding, ref_set, shadow, out);
}
}
}
_ => {}
}
}
/// 扫描一元更新目标(`++x` / `obj.x++`)中的引用。
fn collect_capture_names_simple_target(
&self, 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) => {
self.collect_capture_names_expr(&m.object, ref_set, shadow, out);
}
oxide_parser::SimpleAssignmentTarget::ComputedMemberExpression(m) => {
self.collect_capture_names_expr(&m.object, ref_set, shadow, out);
self.collect_capture_names_expr(&m.expression, ref_set, shadow, out);
}
_ => {}
}
}
/// `collect_captured_expr` 侧的赋值目标扫描:父绑定集合即 ref_set,无遮蔽。
fn collect_captured_assign_target(
&self, target: &oxide_parser::AssignmentTarget, own: &HashSet<String>, out: &mut HashSet<String>,
) {
let empty = HashSet::new();
self.collect_capture_names_assign_target(target, own, &empty, out);
}
/// `collect_captured_expr` 侧的一元更新目标扫描。
fn collect_captured_simple_target(
&self, target: &oxide_parser::SimpleAssignmentTarget, own: &HashSet<String>, out: &mut HashSet<String>,
) {
let empty = HashSet::new();
self.collect_capture_names_simple_target(target, own, &empty, out);
}
/// 收集函数参数默认值表达式里的引用(子层 upvalue 判定;参数名遮蔽)。
fn collect_fn_default_names(
&self, 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 {
self.collect_capture_names_expr(init, ref_set, shadow, out);
}
let mut param_shadow = shadow.clone();
self.collect_capture_names_binding_pattern(&p.pattern, ref_set, shadow, out, &mut param_shadow);
}
}
fn collect_capture_names_expr(
&self, 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) => {
// 赋值目标里的引用也须捕获:标识符目标写名,成员/解构目标扫描其对象/元素。
self.collect_capture_names_assign_target(&ae.left, ref_set, shadow, out);
self.collect_capture_names_expr(&ae.right, ref_set, shadow, out);
}
Expression::UpdateExpression(ue) => {
self.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(self.collect_fn_param_names(&fe.params));
inner.extend(self.collect_own_binding_names(&[], body));
self.collect_fn_default_names(&fe.params, ref_set, shadow, out);
self.collect_capture_names_shadowed(body, ref_set, &inner, out);
}
Expression::ArrowFunctionExpression(ae) => {
let mut inner = shadow.clone();
inner.extend(self.collect_fn_param_names(&ae.params));
inner.extend(self.collect_own_binding_names(&[], &ae.body.statements));
self.collect_fn_default_names(&ae.params, ref_set, shadow, out);
self.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());
}
self.collect_class_capture_names(&class.body, ref_set, &class_shadow, out);
}
Expression::BinaryExpression(be) => {
self.collect_capture_names_expr(&be.left, ref_set, shadow, out);
self.collect_capture_names_expr(&be.right, ref_set, shadow, out);
}
Expression::UnaryExpression(ue) => self.collect_capture_names_expr(&ue.argument, ref_set, shadow, out),
Expression::CallExpression(ce) => {
self.collect_capture_names_expr(&ce.callee, ref_set, shadow, out);
for a in &ce.arguments {
self.collect_capture_names_arg(a, ref_set, shadow, out);
}
}
Expression::NewExpression(ne) => {
self.collect_capture_names_expr(&ne.callee, ref_set, shadow, out);
for a in &ne.arguments {
self.collect_capture_names_arg(a, ref_set, shadow, out);
}
}
Expression::SequenceExpression(se) => {
for e in &se.expressions {
self.collect_capture_names_expr(e, ref_set, shadow, out);
}
}
Expression::ConditionalExpression(ce) => {
self.collect_capture_names_expr(&ce.test, ref_set, shadow, out);
self.collect_capture_names_expr(&ce.consequent, ref_set, shadow, out);
self.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() {
self.collect_capture_names_expr(e, ref_set, shadow, out);
}
}
}
Expression::LogicalExpression(le) => {
self.collect_capture_names_expr(&le.left, ref_set, shadow, out);
self.collect_capture_names_expr(&le.right, ref_set, shadow, out);
}
Expression::ComputedMemberExpression(m) => {
self.collect_capture_names_expr(&m.object, ref_set, shadow, out);
self.collect_capture_names_expr(&m.expression, ref_set, shadow, out);
}
Expression::StaticMemberExpression(m) => self.collect_capture_names_expr(&m.object, ref_set, shadow, out),
Expression::PrivateFieldExpression(m) => self.collect_capture_names_expr(&m.object, ref_set, shadow, out),
Expression::ParenthesizedExpression(p) => {
self.collect_capture_names_expr(&p.expression, ref_set, shadow, out)
}
Expression::TemplateLiteral(tl) => {
for e in &tl.expressions {
self.collect_capture_names_expr(e, ref_set, shadow, out);
}
}
Expression::TaggedTemplateExpression(tt) => {
self.collect_capture_names_expr(&tt.tag, ref_set, shadow, out);
for e in &tt.quasi.expressions {
self.collect_capture_names_expr(e, ref_set, shadow, out);
}
}
Expression::ObjectExpression(o) => {
for prop in &o.properties {
if let oxide_parser::ObjectPropertyKind::ObjectProperty(p) = prop {
self.collect_capture_names_expr(&p.value, ref_set, shadow, out);
}
}
}
// 生成器让出表达式:被让出的值里引用的父变量须纳入捕获,否则生成器体经
// LOAD_VAR 读调用方寄存器残留(挂起恢复后寄存器已被覆盖)。
Expression::YieldExpression(ye) => {
if let Some(a) = &ye.argument {
self.collect_capture_names_expr(a, ref_set, shadow, out);
}
}
Expression::ChainExpression(c) => self.collect_capture_names_chain(&c.expression, ref_set, shadow, out),
_ => {}
}
}
fn collect_capture_names_chain(
&self, element: &oxide_parser::ChainElement, ref_set: &HashSet<String>, shadow: &HashSet<String>,
out: &mut HashSet<String>,
) {
match element {
oxide_parser::ChainElement::StaticMemberExpression(m) => {
self.collect_capture_names_expr(&m.object, ref_set, shadow, out);
}
oxide_parser::ChainElement::ComputedMemberExpression(m) => {
self.collect_capture_names_expr(&m.object, ref_set, shadow, out);
self.collect_capture_names_expr(&m.expression, ref_set, shadow, out);
}
oxide_parser::ChainElement::PrivateFieldExpression(m) => {
self.collect_capture_names_expr(&m.object, ref_set, shadow, out);
}
oxide_parser::ChainElement::CallExpression(call) => {
self.collect_capture_names_expr(&call.callee, ref_set, shadow, out);
for a in &call.arguments {
self.collect_capture_names_arg(a, ref_set, shadow, out);
}
}
_ => {}
}
}
/// 遍历调用实参:静态实参与 spread 内部表达式都纳入捕获扫描。
fn collect_capture_names_arg(
&self, arg: &oxide_parser::Argument, ref_set: &HashSet<String>, shadow: &HashSet<String>,
out: &mut HashSet<String>,
) {
if let Some(e) = arg.as_expression() {
self.collect_capture_names_expr(e, ref_set, shadow, out);
} else if let oxide_parser::Argument::SpreadElement(sp) = arg {
self.collect_capture_names_expr(&sp.argument, ref_set, shadow, out);
}
}
/// 分析本函数:哪些绑定被任意深度嵌套函数捕获 → captured_bindings。
pub(crate) fn collect_captured_bindings(
&self, stmts: &[Statement], extra_exprs: &[&oxide_parser::Expression], own: &HashSet<String>,
) -> BTreeMap<String, u8> {
let mut names = HashSet::new();
for stmt in stmts {
self.collect_captured_stmt(stmt, own, &mut names);
}
// 参数默认值表达式(不在 body_stmts 内)里的嵌套函数引用也要纳入捕获,
// 否则默认值内 IIFE 引用全局/外层变量走 LOAD_VAR 读寄存器残留(B022 扩展)。
for expr in extra_exprs {
self.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 判定)。
fn collect_fn_default_captured(
&self, params: &oxide_parser::FormalParameters, own: &HashSet<String>, out: &mut HashSet<String>,
) {
for p in &params.items {
if let Some(init) = &p.initializer {
self.collect_captured_expr(init, own, out);
}
self.collect_captured_binding_pattern(&p.pattern, own, out);
}
}
/// 只从嵌套函数节点进入扫描(本函数直接引用不算捕获)。
fn collect_captured_stmt(&self, 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(&[]);
self.collect_fn_default_captured(&fd.params, own, out);
// 函数参数与体内部声明遮蔽父级绑定:体内对这些名字的引用不算捕获父级。
let mut fn_shadow = HashSet::new();
fn_shadow.extend(self.collect_fn_param_names(&fd.params));
fn_shadow.extend(self.collect_own_binding_names(&[], body));
self.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());
}
self.collect_class_capture_names(&cd.body, own, &class_shadow, out);
}
Statement::ExpressionStatement(es) => self.collect_captured_expr(&es.expression, own, out),
Statement::ReturnStatement(rs) => {
if let Some(a) = &rs.argument {
self.collect_captured_expr(a, own, out);
}
}
Statement::VariableDeclaration(vd) => {
for d in &vd.declarations {
if let Some(init) = &d.init {
self.collect_captured_expr(init, own, out);
}
}
}
Statement::IfStatement(is) => {
self.collect_captured_expr(&is.test, own, out);
self.collect_captured_stmt(&is.consequent, own, out);
if let Some(alt) = &is.alternate {
self.collect_captured_stmt(alt, own, out);
}
}
Statement::ForStatement(fs) => {
if let Some(init) = &fs.init {
if let Some(e) = init.as_expression() {
self.collect_captured_expr(e, own, out);
}
}
if let Some(t) = &fs.test {
self.collect_captured_expr(t, own, out);
}
if let Some(u) = &fs.update {
self.collect_captured_expr(u, own, out);
}
self.collect_captured_stmt(&fs.body, own, out);
}
Statement::WhileStatement(w) => {
self.collect_captured_expr(&w.test, own, out);
self.collect_captured_stmt(&w.body, own, out);
}
Statement::DoWhileStatement(d) => {
self.collect_captured_stmt(&d.body, own, out);
self.collect_captured_expr(&d.test, own, out);
}
Statement::ForInStatement(fi) => {
self.collect_captured_expr(&fi.right, own, out);
self.collect_captured_stmt(&fi.body, own, out);
}
Statement::ForOfStatement(fo) => {
self.collect_captured_expr(&fo.right, own, out);
self.collect_captured_stmt(&fo.body, own, out);
}
Statement::BlockStatement(b) => {
for s in &b.body {
self.collect_captured_stmt(s, own, out);
}
}
Statement::TryStatement(ts) => {
for s in &ts.block.body {
self.collect_captured_stmt(s, own, out);
}
if let Some(h) = &ts.handler {
if let Some(param) = &h.param {
self.collect_captured_binding_pattern(&param.pattern, own, out);
}
for s in &h.body.body {
self.collect_captured_stmt(s, own, out);
}
}
if let Some(f) = &ts.finalizer {
for s in &f.body {
self.collect_captured_stmt(s, own, out);
}
}
}
Statement::ThrowStatement(ts) => self.collect_captured_expr(&ts.argument, own, out),
Statement::SwitchStatement(sw) => {
self.collect_captured_expr(&sw.discriminant, own, out);
for case in &sw.cases {
for s in &case.consequent {
self.collect_captured_stmt(s, own, out);
}
}
}
Statement::LabeledStatement(ls) => self.collect_captured_stmt(&ls.body, own, out),
Statement::WithStatement(ws) => {
self.collect_captured_expr(&ws.object, own, out);
self.collect_captured_stmt(&ws.body, own, out);
}
_ => {}
}
}
/// 遍历 catch 参数解构模式内表达式引用(默认值等),供父层 MAKE_CELL 判定。
fn collect_captured_binding_pattern(
&self, pattern: &oxide_parser::BindingPattern, own: &HashSet<String>, out: &mut HashSet<String>,
) {
match pattern {
oxide_parser::BindingPattern::BindingIdentifier(_) => {}
oxide_parser::BindingPattern::ArrayPattern(ap) => {
for elem in &ap.elements {
if let Some(p) = elem {
self.collect_captured_binding_pattern(p, own, out);
}
}
if let Some(rest) = &ap.rest {
self.collect_captured_binding_pattern(&rest.argument, own, out);
}
}
oxide_parser::BindingPattern::ObjectPattern(op) => {
for prop in &op.properties {
self.collect_captured_binding_pattern(&prop.value, own, out);
}
if let Some(rest) = &op.rest {
self.collect_captured_binding_pattern(&rest.argument, own, out);
}
}
oxide_parser::BindingPattern::AssignmentPattern(ap) => {
self.collect_captured_expr(&ap.right, own, out);
self.collect_captured_binding_pattern(&ap.left, own, out);
}
}
}
fn collect_captured_expr(&self, 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 = self.collect_fn_param_names(&fe.params);
inner.extend(self.collect_own_binding_names(&[], body));
self.collect_fn_default_captured(&fe.params, own, out);
self.collect_capture_names_shadowed(body, own, &inner, out);
}
Expression::ArrowFunctionExpression(ae) => {
let mut inner = self.collect_fn_param_names(&ae.params);
inner.extend(self.collect_own_binding_names(&[], &ae.body.statements));
self.collect_fn_default_captured(&ae.params, own, out);
self.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());
}
self.collect_class_capture_names(&class.body, own, &class_shadow, out);
}
Expression::CallExpression(ce) => {
self.collect_captured_expr(&ce.callee, own, out);
for a in &ce.arguments {
self.collect_captured_arg(a, own, out);
}
}
Expression::BinaryExpression(be) => {
self.collect_captured_expr(&be.left, own, out);
self.collect_captured_expr(&be.right, own, out);
}
Expression::UnaryExpression(ue) => self.collect_captured_expr(&ue.argument, own, out),
Expression::LogicalExpression(le) => {
self.collect_captured_expr(&le.left, own, out);
self.collect_captured_expr(&le.right, own, out);
}
Expression::ConditionalExpression(ce) => {
self.collect_captured_expr(&ce.test, own, out);
self.collect_captured_expr(&ce.consequent, own, out);
self.collect_captured_expr(&ce.alternate, own, out);
}
Expression::SequenceExpression(se) => {
for e in &se.expressions {
self.collect_captured_expr(e, own, out);
}
}
Expression::AssignmentExpression(ae) => {
self.collect_captured_assign_target(&ae.left, own, out);
self.collect_captured_expr(&ae.right, own, out);
}
Expression::UpdateExpression(ue) => self.collect_captured_simple_target(&ue.argument, own, out),
Expression::ArrayExpression(ae) => {
for e in &ae.elements {
if let Some(e) = e.as_expression() {
self.collect_captured_expr(e, own, out);
}
}
}
Expression::ObjectExpression(o) => {
for prop in &o.properties {
if let oxide_parser::ObjectPropertyKind::ObjectProperty(p) = prop {
self.collect_captured_expr(&p.value, own, out);
}
}
}
Expression::NewExpression(ne) => {
self.collect_captured_expr(&ne.callee, own, out);
for a in &ne.arguments {
self.collect_captured_arg(a, own, out);
}
}
Expression::ComputedMemberExpression(m) => {
self.collect_captured_expr(&m.object, own, out);
self.collect_captured_expr(&m.expression, own, out);
}
Expression::StaticMemberExpression(m) => self.collect_captured_expr(&m.object, own, out),
Expression::PrivateFieldExpression(m) => self.collect_captured_expr(&m.object, own, out),
Expression::TemplateLiteral(tl) => {
for e in &tl.expressions {
self.collect_captured_expr(e, own, out);
}
}
Expression::TaggedTemplateExpression(tt) => {
self.collect_captured_expr(&tt.tag, own, out);
for e in &tt.quasi.expressions {
self.collect_captured_expr(e, own, out);
}
}
Expression::ParenthesizedExpression(p) => self.collect_captured_expr(&p.expression, own, out),
Expression::YieldExpression(ye) => {
if let Some(a) = &ye.argument {
self.collect_captured_expr(a, own, out);
}
}
Expression::ChainExpression(c) => self.collect_captured_chain(&c.expression, own, out),
_ => {}
}
}
fn collect_captured_chain(
&self, element: &oxide_parser::ChainElement, own: &HashSet<String>, out: &mut HashSet<String>,
) {
match element {
oxide_parser::ChainElement::StaticMemberExpression(m) => {
self.collect_captured_expr(&m.object, own, out);
}
oxide_parser::ChainElement::ComputedMemberExpression(m) => {
self.collect_captured_expr(&m.object, own, out);
self.collect_captured_expr(&m.expression, own, out);
}
oxide_parser::ChainElement::PrivateFieldExpression(m) => {
self.collect_captured_expr(&m.object, own, out);
}
oxide_parser::ChainElement::CallExpression(c) => {
self.collect_captured_expr(&c.callee, own, out);
for a in &c.arguments {
self.collect_captured_arg(a, own, out);
}
}
_ => {}
}
}
/// 遍历调用实参:静态实参与 spread 内部表达式都纳入捕获判定。
fn collect_captured_arg(&self, arg: &oxide_parser::Argument, own: &HashSet<String>, out: &mut HashSet<String>) {
if let Some(e) = arg.as_expression() {
self.collect_captured_expr(e, own, out);
} else if let oxide_parser::Argument::SpreadElement(sp) = arg {
self.collect_captured_expr(&sp.argument, own, out);
}
}
/// 分析子函数 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(
&self, 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();
self.collect_capture_names_shadowed(body_stmts, &parent_names, sub_own, &mut names);
// 参数默认值表达式(不在 body_stmts)里的嵌套函数引用也会捕获父变量。
for expr in extra_exprs {
self.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()
}
}