diff --git a/crates/perry-hir/src/lower/expr_member.rs b/crates/perry-hir/src/lower/expr_member.rs index fd4d25fa7..488b7c2ac 100644 --- a/crates/perry-hir/src/lower/expr_member.rs +++ b/crates/perry-hir/src/lower/expr_member.rs @@ -1768,9 +1768,29 @@ fn lower_member_inner(ctx: &mut LoweringContext, member: &ast::MemberExpr) -> Re ast::MemberProp::Computed(_) => true, _ => false, }; + let outer_is_reified_object_static_value = property == "Object" + && matches!( + &member.prop, + ast::MemberProp::Ident(p) if matches!( + p.sym.as_ref(), + "assign" + | "create" + | "defineProperty" + | "entries" + | "freeze" + | "fromEntries" + | "getOwnPropertyDescriptor" + | "getOwnPropertyNames" + | "getPrototypeOf" + | "hasOwn" + | "keys" + | "values" + ) + ); if !outer_is_prototype_or_proto && !receiver_is_namespace_value && !outer_is_websocket_static + && !outer_is_reified_object_static_value { object_expr = Expr::GlobalGet(0); } diff --git a/crates/perry-runtime/src/object/global_this.rs b/crates/perry-runtime/src/object/global_this.rs index 0d9c62114..ca7fc5545 100644 --- a/crates/perry-runtime/src/object/global_this.rs +++ b/crates/perry-runtime/src/object/global_this.rs @@ -3103,7 +3103,14 @@ fn install_builtin_constructor_statics(name: &str, ctor: *mut crate::closure::Cl 1, false, ); - install_constructor_static(ctor, "assign", object_assign_thunk as *const u8, 1, true); + install_constructor_static_with_call_arity( + ctor, + "assign", + object_assign_thunk as *const u8, + 2, + 1, + true, + ); install_constructor_static(ctor, "hasOwn", object_hasown_thunk as *const u8, 2, false); } "Array" => { diff --git a/test-parity/node-suite/object/captured-object-assign.ts b/test-parity/node-suite/object/captured-object-assign.ts new file mode 100644 index 000000000..991f0cba7 --- /dev/null +++ b/test-parity/node-suite/object/captured-object-assign.ts @@ -0,0 +1,13 @@ +const assign = Object.assign; + +console.log("assign typeof:", typeof assign); +console.log("assign name:", assign.name); +console.log("assign length:", assign.length); + +const target: any = { base: 1 }; +const out: any = assign(target, { a: 2 }, { b: 3 }); + +console.log("same target:", out === target); +console.log("keys:", Object.keys(out).join(",")); +console.log("values:", [out.base, out.a, out.b].join(",")); +console.log("fresh copy:", JSON.stringify(assign({}, { x: 1 }, { y: 2 })));