mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-23 18:21:13 +08:00
fix: 闭包捕获/upvalue 分析纳入参数默认值表达式(含嵌套函数声明)
This commit is contained in:
@@ -123,6 +123,7 @@ impl Emitter {
|
||||
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::IfStatement(is) => {
|
||||
@@ -240,6 +241,20 @@ impl Emitter {
|
||||
}
|
||||
}
|
||||
|
||||
/// 收集函数参数默认值表达式里的引用(子层 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 ¶ms.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>,
|
||||
) {
|
||||
@@ -272,12 +287,14 @@ impl Emitter {
|
||||
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::BinaryExpression(be) => {
|
||||
@@ -382,21 +399,41 @@ impl Emitter {
|
||||
}
|
||||
|
||||
/// 分析本函数:哪些绑定被任意深度嵌套函数捕获 → captured_bindings。
|
||||
pub(crate) fn collect_captured_bindings(&self, stmts: &[Statement], own: &HashSet<String>) -> BTreeMap<String, u8> {
|
||||
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 ¶ms.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);
|
||||
self.collect_capture_names(body, own, out);
|
||||
}
|
||||
Statement::ExpressionStatement(es) => self.collect_captured_expr(&es.expression, own, out),
|
||||
@@ -523,11 +560,13 @@ impl Emitter {
|
||||
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::CallExpression(ce) => {
|
||||
@@ -634,7 +673,7 @@ impl Emitter {
|
||||
/// 若在父 `upvalue_captures`(父自身从更外层捕获)则链式标记 `parent_uv_idx`,
|
||||
/// 运行时从父闭包 upvalues 取 cell。enclosing_reg 由父 emit 完成后填充。
|
||||
pub(crate) fn collect_upvalue_names(
|
||||
&self, body_stmts: &[Statement], parent_captured: &BTreeMap<String, u8>,
|
||||
&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();
|
||||
@@ -643,6 +682,10 @@ impl Emitter {
|
||||
}
|
||||
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。
|
||||
|
||||
@@ -523,6 +523,39 @@ impl Emitter {
|
||||
Self
|
||||
}
|
||||
|
||||
/// 遍历解构 pattern 收集内嵌默认值表达式(AssignmentPattern.right)。
|
||||
fn collect_pattern_default_exprs<'a>(
|
||||
&self, pattern: &'a oxide_parser::BindingPattern<'a>, out: &mut Vec<&'a oxide_parser::Expression<'a>>,
|
||||
) {
|
||||
use oxide_parser::BindingPattern;
|
||||
match pattern {
|
||||
BindingPattern::AssignmentPattern(ap) => {
|
||||
out.push(&ap.right);
|
||||
self.collect_pattern_default_exprs(&ap.left, out);
|
||||
}
|
||||
BindingPattern::ArrayPattern(ap) => {
|
||||
for elem in &ap.elements {
|
||||
if let Some(p) = elem {
|
||||
self.collect_pattern_default_exprs(p, out);
|
||||
}
|
||||
}
|
||||
if let Some(rest) = &ap.rest {
|
||||
self.collect_pattern_default_exprs(&rest.argument, out);
|
||||
}
|
||||
}
|
||||
BindingPattern::ObjectPattern(op) => {
|
||||
for prop in &op.properties {
|
||||
self.collect_pattern_default_exprs(&prop.value, out);
|
||||
}
|
||||
if let Some(rest) = &op.rest {
|
||||
self.collect_pattern_default_exprs(&rest.argument, out);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ── 闭包捕获分析(AST 级,时序无关)──
|
||||
|
||||
/// 收集函数参数的绑定名(BindingIdentifier 形态)。
|
||||
@@ -759,8 +792,26 @@ impl Emitter {
|
||||
|
||||
// 闭包捕获分析(AST 级,emit 前确定,时序无关)
|
||||
let param_names: Vec<&str> = param_specs.iter().map(|s| s.register_name()).collect();
|
||||
let mut param_defaults: Vec<&oxide_parser::Expression> = Vec::new();
|
||||
for spec in param_specs {
|
||||
match spec {
|
||||
ParamSpec::Identifier { initializer, .. } => {
|
||||
if let Some(init) = initializer {
|
||||
param_defaults.push(init);
|
||||
}
|
||||
}
|
||||
ParamSpec::Pattern { pattern, initializer, .. } => {
|
||||
if let Some(init) = initializer {
|
||||
param_defaults.push(init);
|
||||
}
|
||||
// 模式内嵌默认值(`[x = expr]` 的 AssignmentPattern.right)也会被
|
||||
// 内部闭包引用,需纳入捕获分析。
|
||||
self.collect_pattern_default_exprs(pattern, &mut param_defaults);
|
||||
}
|
||||
}
|
||||
}
|
||||
ctx.own_bindings = self.collect_own_binding_names(¶m_names, body_stmts);
|
||||
ctx.captured_bindings = self.collect_captured_bindings(body_stmts, &ctx.own_bindings);
|
||||
ctx.captured_bindings = self.collect_captured_bindings(body_stmts, ¶m_defaults, &ctx.own_bindings);
|
||||
|
||||
// 被捕获的参数也必须建 cell(MAKE_CELL):否则子函数经 lazy upvalue 路径读
|
||||
// 自身寄存器(依赖调用者寄存器残留),vreg 化/RegAlloc 移动寄存器后读到垃圾。
|
||||
@@ -782,6 +833,7 @@ impl Emitter {
|
||||
if matches!(body_context, FunctionBodyContext::Ordinary | FunctionBodyContext::Arrow) {
|
||||
ctx.current_upvalue_captures = self.collect_upvalue_names(
|
||||
body_stmts,
|
||||
¶m_defaults,
|
||||
&parent_ctx.captured_bindings,
|
||||
&parent_ctx.current_upvalue_captures,
|
||||
&ctx.own_bindings,
|
||||
@@ -888,7 +940,7 @@ impl Emitter {
|
||||
|
||||
// 闭包捕获分析(AST 级,emit 前确定)
|
||||
ctx.own_bindings = self.collect_own_binding_names(&[], &program.body);
|
||||
ctx.captured_bindings = self.collect_captured_bindings(&program.body, &ctx.own_bindings);
|
||||
ctx.captured_bindings = self.collect_captured_bindings(&program.body, &[], &ctx.own_bindings);
|
||||
|
||||
// 首个 sub-pass:发函数声明(hoisting),保证任何代码运行前函数对象已就绪。
|
||||
for stmt in &program.body {
|
||||
|
||||
Reference in New Issue
Block a user