fix(runtime): #1187 implement Date.prototype local-time setters#1189
Merged
Conversation
`d.setHours(d.getHours() + 1)` threw `TypeError: (number).setHours is not a function` because the HIR lowering only routed `setUTC*` to dedicated `DateSetUtc*` variants. Plain `setHours` / `setDate` / etc. fell through to the generic property-on-receiver path, and since Date is stored as a raw f64 timestamp with no method table the receiver became `(number)` and the call failed. Adds the local-time setters end-to-end: - Runtime: 8 new `js_date_set_*` functions in date.rs. The 7 component setters share a `rebuild_local_with` helper that round-trips through `timestamp_to_local_components`, swaps the requested component, and subtracts the tz offset at that instant to land back at UTC — same conversion as `js_date_new_local_components`. NaN passes through so Invalid Date stays Invalid Date; finite results re-register in DATE_REGISTRY so `instanceof Date` still holds after the mutation. `js_date_set_time` is one-shot — replace, register, return. - HIR: 8 new `DateSet*` Expr variants mirroring the existing UTC ones, walker visits, stable_hash tags 478–485. - HIR lowering: extended the existing setUTC* match arm to also catch `setFullYear` / `setMonth` / `setDate` / `setHours` / `setMinutes` / `setSeconds` / `setMilliseconds` / `setTime`. Same in-place mutation pattern — if the receiver is a `LocalGet`, wrap in `LocalSet` so `d.setHours(...)` writes the new timestamp back into `d`. - LLVM codegen + runtime_decls: 8 new lowering arms and decls. - JS / WASM backends: mirror arms so the new variants flow through every backend, not just LLVM. Regression repro lives in `test-files/test_issue_1187_date_setters.ts` and matches Node byte-for-byte.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
d.setHours(d.getHours() + 1)aborted withTypeError: (number).setHours is not a functionbecause the HIR lowering only routedsetUTC*— the local-time setters fell through to a generic property lookup, and since Date is stored as a raw f64 timestamp the receiver became(number).js_date_set_*runtime functions (setFullYear/setMonth/setDate/setHours/setMinutes/setSeconds/setMilliseconds/setTime), 8 matchingDateSet*HIR variants (walker / stable_hash / lowering), and lowering arms in the LLVM, JS, and WASM backends. Mirrors the existingDateSetUtc*plumbing.let d = new Date(); d.setHours(15)), the HIR wraps the setter result inLocalSetsodis updated in place and the expression still evaluates to the new ms timestamp.timestamp_to_local_components, swap the requested field, and subtract the tz offset at that instant to land back at UTC — same conversion asjs_date_new_local_components. NaN passes through (Invalid Date stays Invalid Date); finite results re-register inDATE_REGISTRYsoinstanceof Datestill holds after mutation.Test plan
test-files/test_issue_1187_date_setters.ts(new) compiles + matchesnode --experimental-strip-typesbyte-for-bytenew Date(); expiry.setHours(expiry.getHours()+1); return expiry; ... .toISOString()) compiles and prints a valid ISO string ~1 hour from nowtest-files/test_gap_date_methods.tsstill parity-matches Nodecargo test -p perry-runtime -p perry-hir -p perry-codegengreenVersion bump +
CHANGELOG.mdentry intentionally omitted — Ralph folds those in at merge time.