fix: capture destructured function parameters
This commit is contained in:
@@ -15,21 +15,19 @@ impl Emitter {
|
|||||||
fn collect_fn_param_names(&self, params: &oxide_parser::FormalParameters) -> HashSet<String> {
|
fn collect_fn_param_names(&self, params: &oxide_parser::FormalParameters) -> HashSet<String> {
|
||||||
let mut names = HashSet::new();
|
let mut names = HashSet::new();
|
||||||
for p in ¶ms.items {
|
for p in ¶ms.items {
|
||||||
if let oxide_parser::BindingPattern::BindingIdentifier(bi) = &p.pattern {
|
self.collect_binding_pattern_names(&p.pattern, &mut names);
|
||||||
names.insert(bi.name.to_string());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// rest 形参也是本函数作用域绑定,遮蔽外层同名变量。
|
// rest 形参也是本函数作用域绑定,遮蔽外层同名变量。
|
||||||
if let Some(rest) = ¶ms.rest {
|
if let Some(rest) = ¶ms.rest {
|
||||||
if let oxide_parser::BindingPattern::BindingIdentifier(bi) = &rest.rest.argument {
|
self.collect_binding_pattern_names(&rest.rest.argument, &mut names);
|
||||||
names.insert(bi.name.to_string());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
names
|
names
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 递归收集 binding pattern 内全部绑定标识符名(解构 `[a, b]` / `{x: y}` 嵌套)。
|
/// 递归收集 binding pattern 内全部绑定标识符名(解构 `[a, b]` / `{x: y}` 嵌套)。
|
||||||
fn collect_binding_pattern_names(&self, pattern: &oxide_parser::BindingPattern, out: &mut HashSet<String>) {
|
pub(crate) fn collect_binding_pattern_names(
|
||||||
|
&self, pattern: &oxide_parser::BindingPattern, out: &mut HashSet<String>,
|
||||||
|
) {
|
||||||
match pattern {
|
match pattern {
|
||||||
oxide_parser::BindingPattern::BindingIdentifier(bi) => {
|
oxide_parser::BindingPattern::BindingIdentifier(bi) => {
|
||||||
out.insert(bi.name.to_string());
|
out.insert(bi.name.to_string());
|
||||||
|
|||||||
@@ -1100,6 +1100,11 @@ impl Emitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctx.own_bindings = self.collect_own_binding_names(¶m_names, body_stmts);
|
ctx.own_bindings = self.collect_own_binding_names(¶m_names, body_stmts);
|
||||||
|
for spec in param_specs {
|
||||||
|
if let ParamSpec::Pattern { pattern, .. } = spec {
|
||||||
|
self.collect_binding_pattern_names(pattern, &mut ctx.own_bindings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 自动声明 arguments 绑定(非箭头函数,且用户未显式声明同名标识符)。
|
// 自动声明 arguments 绑定(非箭头函数,且用户未显式声明同名标识符)。
|
||||||
// 先登记符号并纳入 own_bindings,使嵌套箭头引用 arguments 被识别为本函数
|
// 先登记符号并纳入 own_bindings,使嵌套箭头引用 arguments 被识别为本函数
|
||||||
|
|||||||
@@ -88,6 +88,17 @@ fn function_and_method_parameter_destructuring() {
|
|||||||
assert_num(result, 10.0);
|
assert_num(result, 10.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn destructured_callback_parameters_shadow_outer_bindings() {
|
||||||
|
let mut vm = Vm::new();
|
||||||
|
let result = eval(
|
||||||
|
&mut vm,
|
||||||
|
"let expected=100, result=0; [[1,2]].forEach(([value, expected]) => { result=value+expected; }); result",
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert_num(result, 3.0);
|
||||||
|
}
|
||||||
|
|
||||||
// 回归:赋值目标含嵌套 rest 模式(rest 元素本身是模式,如 `[...[x]]`)的 for-of
|
// 回归:赋值目标含嵌套 rest 模式(rest 元素本身是模式,如 `[...[x]]`)的 for-of
|
||||||
// 曾无限循环 / 报错,因为计数器相对 emitter 少计了 rest 目标的指令,破坏了循环跳转
|
// 曾无限循环 / 报错,因为计数器相对 emitter 少计了 rest 目标的指令,破坏了循环跳转
|
||||||
// 偏移。(对象 rest 嵌套目标按规范是语法错误,故不测。)
|
// 偏移。(对象 rest 嵌套目标按规范是语法错误,故不测。)
|
||||||
|
|||||||
Reference in New Issue
Block a user