Skip to content

fix(dayjs): arguments in seq exprs + computed Date-method dispatch (#5133)#5147

Merged
proggeramlug merged 1 commit into
mainfrom
fix/dayjs-arguments-seq
Jun 14, 2026
Merged

fix(dayjs): arguments in seq exprs + computed Date-method dispatch (#5133)#5147
proggeramlug merged 1 commit into
mainfrom
fix/dayjs-arguments-seq

Conversation

@proggeramlug

@proggeramlug proggeramlug commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Fixes #5133.

compilePackages: dayjs threw ReferenceError: arguments is not defined, and once that was resolved .add()/.date(n) silently no-op'd. Two distinct, general root causes:

1. arguments hidden inside a sequence expression

Minified dayjs builds the wrapper as:

O=function(t,e){...return n.date=t,n.args=arguments,new _(n)}

The arguments reference lives inside a comma/sequence expression in the return. The synthetic-arguments pre-scan expr_uses_arguments (crates/perry-hir/src/lower_decl/helpers.rs) had no Expr::Seq arm, fell through its _ => false catch-all, so the enclosing function never synthesized its hidden raw-arguments param and Expr::Ident("arguments") resolved to nothing.

Fix: descend into Expr::Seq, plus the other operand-bearing forms the catch-all skipped — Await, Yield, OptChain, computed SuperProp, TaggedTpl.

2. Computed/dynamic Date-method calls dropped to generic dispatch

dayjs mutates dates via this.$d[l]($) (e.g. date["setDate"](44)). A DateCell is a NaN-boxed pointer but not an ObjectHeader; js_native_call_method special-cased only toString for date receivers, so every other computed/dynamic call fell through to generic object dispatch, returned [object Object] and dropped the mutation. Direct .setDate(44) worked (codegen fast path), but date[m](44) did not.

Fix: route any method on a date receiver through Date.prototype (where all getter/setter/toISOString/toJSON thunks are installed and read IMPLICIT_THIS), with this bound to the cell.

Validation

Issue repro now matches Node byte-for-byte:

2026-06-14 2026-07-14 164

-p perry-runtime date tests: 23 passed / 0 failed.

Known residual

A SIGSEGV in dayjs's month arithmetic (.endOf('month') / .set('month', …) — a number-as-pointer deref in js_object_get_field_by_name, unrelated to either fix here) is left for a follow-up.

Summary by CodeRabbit

  • Bug Fixes
    • Improved detection of arguments usage inside complex expression forms (sequence/comma, await/yield, optional chaining, computed super, tagged templates) to ensure it’s recognized reliably.
    • Fixed computed/dynamic Date method calls (e.g., date["setDate"](...)) so the correct receiver is used and mutations are no longer dropped; also improved toString dispatch.
  • Documentation
    • Updated changelog and version metadata to v0.5.1171.

@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: cf038735-e12f-4938-a0bd-b0acd886dd51

📥 Commits

Reviewing files that changed from the base of the PR and between 31dd2d1 and 37e22f0.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (5)
  • CHANGELOG.md
  • CLAUDE.md
  • Cargo.toml
  • crates/perry-hir/src/lower_decl/helpers.rs
  • crates/perry-runtime/src/object/native_call_method.rs

📝 Walkthrough

Walkthrough

Version bumped from 0.5.1170 to 0.5.1171. expr_uses_arguments is extended to descend into sequence, await, yield, optional-chain, computed super, and tagged-template AST nodes. Date-receiver dispatch in js_native_call_method is refactored with an is_date_value guard, and toString now calls js_date_to_string directly.

Changes

dayjs compatibility fixes and version bump

Layer / File(s) Summary
Extend expr_uses_arguments to additional AST forms
crates/perry-hir/src/lower_decl/helpers.rs
Adds match arms for sequence/comma expressions, await, yield, optional-chain (member and call bases/args), computed super properties, and tagged template tag/expressions so arguments references nested inside these forms are detected during lowering.
Refactor Date-receiver dispatch in js_native_call_method
crates/perry-runtime/src/object/native_call_method.rs
An outer is_date_value guard replaces the previous combined Date && method_name == "toString" check; the toString branch now returns js_date_to_string(object) directly rather than doing a Date.prototype property lookup and closure call.
Version bump and changelog
Cargo.toml, CLAUDE.md, CHANGELOG.md
Workspace version incremented to 0.5.1171; changelog documents the arguments-in-sequence-expressions fix and the Date computed method dispatch fix, plus a note on a separate residual SIGSEGV in month arithmetic.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related issues

Poem

🐇 Arguments hid in sequence expressions deep,
And Date mutations would silently creep.
I hopped through the AST, branch by every node,
And gave is_date_value the broader road.
Now dayjs runs true, its mutations remain,
One bunny fixed the lowering refrain! 🥕

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description violates the repository's explicit requirements by modifying CHANGELOG.md, CLAUDE.md, and Cargo.toml—all marked as maintainer-only in the template. Revert changes to CHANGELOG.md, CLAUDE.md, and Cargo.toml (version bumps); keep only the fixes in helper.rs and native_call_method.rs. The template explicitly states the maintainer handles these at merge time.
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the two main fixes: handling arguments in sequence expressions and computed Date-method dispatch, matching the core changes in the PR.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/dayjs-arguments-seq

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
crates/perry-runtime/src/object/native_call_method.rs (1)

2074-2099: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Date receiver path needs a terminal fallback to avoid unsafe fallthrough

At Line 2074, this branch documents that DateCell must not hit generic object dispatch, but when a method is not found (and not "toString"), execution currently falls through anyway. That reopens the same invalid DateCellObjectHeader reinterpretation risk this block is meant to prevent.

Suggested fix
 if crate::date::is_date_value(object) {
     let ctor = crate::object::js_get_global_this_builtin_value(b"Date".as_ptr(), 4);
     let ctor_ptr = crate::value::js_nanbox_get_pointer(ctor) as usize;
     if ctor_ptr != 0 {
         let proto = crate::closure::closure_get_dynamic_prop(ctor_ptr, "prototype");
         if let Some(proto_ptr) = object_ptr_from_value(proto) {
             let key = crate::string::js_string_from_bytes(
                 method_name_ptr as *const u8,
                 method_name_len as u32,
             );
             let value = crate::object::js_object_get_field_by_name(proto_ptr, key);
             if !value.is_undefined() {
                 let value_f64 = f64::from_bits(value.bits());
                 let prev_this = IMPLICIT_THIS.with(|c| c.replace(object.to_bits()));
                 let result =
                     crate::closure::js_native_call_value(value_f64, args_ptr, args_len);
                 IMPLICIT_THIS.with(|c| c.set(prev_this));
                 return result;
             }
         }
     }
     if method_name == "toString" {
         let string = crate::date::js_date_to_string(object);
         return f64::from_bits(JSValue::string_ptr(string).bits());
     }
+    crate::error::js_throw_type_error_not_a_function(
+        std::ptr::null(),
+        0,
+        method_name.as_ptr(),
+        method_name.len(),
+    );
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/perry-runtime/src/object/native_call_method.rs` around lines 2074 -
2099, The Date receiver branch starting with the `is_date_value(object)` check
needs a terminal fallback to prevent unsafe execution fallthrough. When a Date
method is not found in the prototype and is not "toString", the code currently
falls through to generic object dispatch, which would unsafely reinterpret a
DateCell as an ObjectHeader. Add an explicit fallback handler (such as returning
an undefined value or error) at the end of the Date branch, after the toString
check, to ensure that Date objects never reach the generic object dispatch path
when their requested method is not available.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@crates/perry-runtime/src/object/native_call_method.rs`:
- Around line 2074-2099: The Date receiver branch starting with the
`is_date_value(object)` check needs a terminal fallback to prevent unsafe
execution fallthrough. When a Date method is not found in the prototype and is
not "toString", the code currently falls through to generic object dispatch,
which would unsafely reinterpret a DateCell as an ObjectHeader. Add an explicit
fallback handler (such as returning an undefined value or error) at the end of
the Date branch, after the toString check, to ensure that Date objects never
reach the generic object dispatch path when their requested method is not
available.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 5d0448a3-dddd-4893-957d-1c5029b9fba9

📥 Commits

Reviewing files that changed from the base of the PR and between 35b2e58 and 31dd2d1.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (5)
  • CHANGELOG.md
  • CLAUDE.md
  • Cargo.toml
  • crates/perry-hir/src/lower_decl/helpers.rs
  • crates/perry-runtime/src/object/native_call_method.rs

…5133)

- expr_uses_arguments descends into Seq/Await/Yield/OptChain/computed
  SuperProp/TaggedTpl so synthetic-arguments pre-scan catches minified
  dayjs wrappers (return n.date=t, n.args=arguments, ...).
- Route any method on a date receiver through Date.prototype (not just
  toString) so computed/dynamic calls (date[m](...)) no longer drop
  setter mutations.

v0.5.1171
@proggeramlug proggeramlug force-pushed the fix/dayjs-arguments-seq branch from 31dd2d1 to 37e22f0 Compare June 14, 2026 19:33
@proggeramlug proggeramlug merged commit b86c791 into main Jun 14, 2026
14 of 15 checks passed
@proggeramlug proggeramlug deleted the fix/dayjs-arguments-seq branch June 14, 2026 19:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

compilePackages: dayjs throws ReferenceError: arguments is not defined at runtime

1 participant