Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions crates/perry-hir/src/lower/expr_member.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1851,11 +1851,27 @@ fn lower_member_inner(ctx: &mut LoweringContext, member: &ast::MemberExpr) -> Re
// with detached `Math.log`.
let receiver_is_detached_console_read =
property == "console" && !member_is_call_callee;
// #4596: `Date.now` / `Date.parse` / `Date.UTC` read as a
// VALUE needs the reified Date constructor receiver so it
// resolves to the real native function object (typeof
// "function", correct `.name`/`.length`, callable). Undoing
// the reroute collapses it to `GlobalGet(0).now`, for which
// codegen has no intrinsic handler (unlike `Object.keys` /
// `Math.max`) — so the read mis-folds to a number. Direct
// CALLS (`Date.now()`) are intercepted earlier as
// `Expr::DateNow` / `DateParse` / `DateUtc`, so gate on a
// non-callee read.
let outer_is_reified_date_static_value = !member_is_call_callee
&& property == "Date"
&& outer_static_member
.map(|member| matches!(member, "now" | "parse" | "UTC"))
.unwrap_or(false);
if !outer_is_prototype_or_proto
&& !receiver_is_namespace_value
&& !outer_is_websocket_static
&& !outer_is_reified_object_static_value
&& !outer_is_reified_builtin_static_value
&& !outer_is_reified_date_static_value
&& !receiver_is_detached_console_read
{
object_expr = Expr::GlobalGet(0);
Expand Down
8 changes: 7 additions & 1 deletion crates/perry-runtime/src/object/date_proto_thunks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,11 +220,17 @@ pub(crate) fn install_date_constructor_statics(ctor: *mut crate::closure::Closur
1,
false,
);
super::global_this::install_constructor_static(
// `date_utc_static` collects *all* arguments into its `rest` param, so the
// call-arity (fixed params before the rest) must be 0 — otherwise the rest
// registration reserves 7 fixed slots and `Date.UTC(2020, 0)` (fewer than 7
// args) puts nothing in the rest array → js_date_utc([]) → NaN. The spec
// `.length` stays 7. (#4596)
super::global_this::install_constructor_static_with_call_arity(
ctor,
"UTC",
date_utc_static as *const u8,
7,
0,
true,
);
}
Expand Down
2 changes: 1 addition & 1 deletion crates/perry-runtime/src/object/global_this.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3430,7 +3430,7 @@ pub(super) fn install_constructor_static(
install_constructor_static_with_call_arity(ctor, name, func_ptr, arity, arity, has_rest);
}

fn install_constructor_static_with_call_arity(
pub(super) fn install_constructor_static_with_call_arity(
ctor: *mut crate::closure::ClosureHeader,
name: &str,
func_ptr: *const u8,
Expand Down