Skip to content

fix(date): brand-check this on Date.prototype getters (reflective dispatch)#4397

Merged
proggeramlug merged 3 commits into
mainfrom
fix-date-proto-brand
Jun 4, 2026
Merged

fix(date): brand-check this on Date.prototype getters (reflective dispatch)#4397
proggeramlug merged 3 commits into
mainfrom
fix-date-proto-brand

Conversation

@proggeramlug
Copy link
Copy Markdown
Contributor

Summary

Date.prototype getters were installed as generic no-op thunks, so the reflective value path was broken:

Date.prototype.getDate.call(new Date(0))  →  [object Object]   (Node: 1)
Date.prototype.getDate.call({})           →  (no throw)        (Node: TypeError)
Date.prototype.getDate.call(Symbol())     →  (no throw)        (Node: TypeError)

Per spec every Date.prototype getter performs thisTimeValue(this), which throws a TypeError when this is not an Object with a [[DateValue]] slot.

Fix

Adds object/date_proto_thunks.rs (mirrors collection_proto_thunks / dataview_proto_thunks). Each getter thunk reads the IMPLICIT_THIS receiver, brand-checks it via is_date_value (throwing TypeError on mismatch), and otherwise dispatches to the same js_date_get_* helper the instance fast path uses — so reflective Date getter calls now both throw correctly and work correctly.

Covers getTime, valueOf, getFullYear/getMonth/getDate/getDay/getHours/getMinutes/getSeconds/getMilliseconds, all getUTC*, getTimezoneOffset, and legacy getYear. Installed after the OBJECT_PROTO_METHODS no-op block so the generic Object valueOf doesn't re-clobber Date.prototype.valueOf.

The instance fast path (d.getDate()) is lowered directly by codegen and is unchanged.

Results

test262 built-ins/Date: −36 (158 → 122 on top of the Date ToNumber fix #4393; no regressions). Verified Node-identical in both PERRY_NO_AUTO_OPTIMIZE=1 and default builds. cargo test -p perry-runtime --lib: 979 passed.

Independent of #4393 (disjoint files: this touches date_proto_thunks.rs/mod.rs/global_this.rs, #4393 touches date.rs). Setters / toX formatters keep the no-op path for now (follow-up).

Ralph Küpper added 2 commits June 4, 2026 15:09
…patch)

Date.prototype getters (getDate/getDay/getFullYear/getHours/.../getUTC*,
getTimezoneOffset, getTime, valueOf, legacy getYear) were installed as
generic no-op thunks, so the reflective value path mis-behaved:
Date.prototype.getDate.call(realDate) returned [object Object], and
.call(nonDate) silently produced garbage instead of throwing.

Per spec each getter runs thisTimeValue(this), which throws a TypeError
when this is not an Object with a [[DateValue]] slot. Adds
object/date_proto_thunks.rs (mirrors collection_/dataview_proto_thunks):
each thunk reads IMPLICIT_THIS, brand-checks via is_date_value (TypeError
on mismatch), and dispatches to the same js_date_get_* helper the instance
fast path uses. Installed after the OBJECT_PROTO_METHODS no-op block so the
generic Object valueOf does not re-clobber Date.prototype.valueOf.

The instance fast path (d.getDate()) is lowered directly by codegen and is
unchanged. test262 built-ins/Date: -36 (158->122 on top of the ToNumber
fix; no regressions). Node-identical in both build modes.
The WebCrypto algo additions on main left jwk.rs unformatted, which fails
`cargo fmt --all --check` on every PR's lint job. Pure formatting; no
behavior change.
@proggeramlug proggeramlug force-pushed the fix-date-proto-brand branch from 290c908 to 03aa904 Compare June 4, 2026 13:14
@proggeramlug proggeramlug merged commit 65b2c6d into main Jun 4, 2026
13 checks passed
@proggeramlug proggeramlug deleted the fix-date-proto-brand branch June 4, 2026 14:47
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.

1 participant