js-on-sx: real Date prototype setters (setFullYear/Month/Date/Hours/Minutes/Seconds/Milliseconds)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 25s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 25s
This commit is contained in:
@@ -1067,6 +1067,115 @@
|
||||
(js-new-call URIError (js-args (js-string-slice e 10 (len e)))))
|
||||
(else e))))
|
||||
|
||||
(define
|
||||
js-date-setter-arg
|
||||
(fn
|
||||
(args fallback i)
|
||||
(cond
|
||||
((>= (len args) (+ i 1)) (js-to-number (nth args i)))
|
||||
(else fallback))))
|
||||
|
||||
(define
|
||||
js-date-setter
|
||||
(fn
|
||||
(d field args)
|
||||
(cond
|
||||
((or (not (dict? d)) (not (contains? (keys d) "__js_is_date__")))
|
||||
(raise (js-new-call TypeError (js-args "this is not a Date object"))))
|
||||
(else
|
||||
(let
|
||||
((ms-raw (get d "__date_value__")))
|
||||
(let
|
||||
((ms-orig
|
||||
(cond
|
||||
((or (= ms-raw nil) (js-undefined? ms-raw)) (js-nan-value))
|
||||
((= (type-of ms-raw) "rational") (exact->inexact ms-raw))
|
||||
(else ms-raw))))
|
||||
(let
|
||||
((parts (js-date-decompose ms-orig)))
|
||||
(let
|
||||
((y
|
||||
(cond
|
||||
((= field "fullYear") (js-date-setter-arg args (js-nan-value) 0))
|
||||
(else (nth parts 0))))
|
||||
(mo
|
||||
(cond
|
||||
((= field "fullYear") (js-date-setter-arg args (nth parts 1) 1))
|
||||
((= field "month") (js-date-setter-arg args (js-nan-value) 0))
|
||||
(else (nth parts 1))))
|
||||
(da
|
||||
(cond
|
||||
((= field "fullYear") (js-date-setter-arg args (nth parts 2) 2))
|
||||
((= field "month") (js-date-setter-arg args (nth parts 2) 1))
|
||||
((= field "date") (js-date-setter-arg args (js-nan-value) 0))
|
||||
(else (nth parts 2))))
|
||||
(hh
|
||||
(cond
|
||||
((= field "hours") (js-date-setter-arg args (js-nan-value) 0))
|
||||
(else (nth parts 3))))
|
||||
(mm
|
||||
(cond
|
||||
((= field "hours") (js-date-setter-arg args (nth parts 4) 1))
|
||||
((= field "minutes") (js-date-setter-arg args (js-nan-value) 0))
|
||||
(else (nth parts 4))))
|
||||
(ss
|
||||
(cond
|
||||
((= field "hours") (js-date-setter-arg args (nth parts 5) 2))
|
||||
((= field "minutes") (js-date-setter-arg args (nth parts 5) 1))
|
||||
((= field "seconds") (js-date-setter-arg args (js-nan-value) 0))
|
||||
(else (nth parts 5))))
|
||||
(msv
|
||||
(cond
|
||||
((= field "hours") (js-date-setter-arg args (nth parts 6) 3))
|
||||
((= field "minutes") (js-date-setter-arg args (nth parts 6) 2))
|
||||
((= field "seconds") (js-date-setter-arg args (nth parts 6) 1))
|
||||
((= field "ms") (js-date-setter-arg args (js-nan-value) 0))
|
||||
(else (nth parts 6)))))
|
||||
(cond
|
||||
((or (js-number-is-nan y) (js-number-is-nan mo) (js-number-is-nan da)
|
||||
(js-number-is-nan hh) (js-number-is-nan mm) (js-number-is-nan ss) (js-number-is-nan msv))
|
||||
(begin (dict-set! d "__date_value__" (js-nan-value)) (js-nan-value)))
|
||||
(else
|
||||
(let
|
||||
((days (js-date-civil-to-days (js-num-to-int y) (+ (js-num-to-int mo) 1) (js-num-to-int da)))
|
||||
(tod
|
||||
(+
|
||||
(* (js-num-to-int hh) 3600000)
|
||||
(* (js-num-to-int mm) 60000)
|
||||
(* (js-num-to-int ss) 1000)
|
||||
(js-num-to-int msv))))
|
||||
(let
|
||||
((new-ms (+ (* days 86400000) tod)))
|
||||
(cond
|
||||
((or (> new-ms 8640000000000000) (< new-ms -8640000000000000))
|
||||
(begin (dict-set! d "__date_value__" (js-nan-value)) (js-nan-value)))
|
||||
(else
|
||||
(begin (dict-set! d "__date_value__" new-ms) new-ms)))))))))))))))
|
||||
|
||||
(define
|
||||
js-date-decompose
|
||||
(fn
|
||||
(ms)
|
||||
(cond
|
||||
((or (= ms nil) (js-undefined? ms) (not (number? ms)) (js-number-is-nan ms))
|
||||
(list 1970 0 1 0 0 0 0))
|
||||
(else
|
||||
(let
|
||||
((days (floor (/ ms 86400000)))
|
||||
(tod
|
||||
(let ((m (modulo (js-num-to-int ms) 86400000)))
|
||||
(if (< m 0) (+ m 86400000) m))))
|
||||
(let
|
||||
((ymd (js-date-days-to-ymd days)))
|
||||
(list
|
||||
(nth ymd 0)
|
||||
(- (nth ymd 1) 1)
|
||||
(nth ymd 2)
|
||||
(js-math-trunc (/ tod 3600000))
|
||||
(js-math-trunc (/ (modulo tod 3600000) 60000))
|
||||
(js-math-trunc (/ (modulo tod 60000) 1000))
|
||||
(modulo tod 1000))))))))
|
||||
|
||||
(define
|
||||
js-date-time-value
|
||||
(fn
|
||||
@@ -1288,7 +1397,26 @@
|
||||
:setTime
|
||||
(fn (v)
|
||||
(let ((t (js-this)))
|
||||
(begin (dict-set! t "__date_value__" v) v)))
|
||||
(let
|
||||
((n (js-to-number v)))
|
||||
(cond
|
||||
((or (js-number-is-nan n) (> n 8640000000000000) (< n -8640000000000000))
|
||||
(begin (dict-set! t "__date_value__" (js-nan-value)) (js-nan-value)))
|
||||
(else (begin (dict-set! t "__date_value__" n) n))))))
|
||||
:setFullYear (fn (&rest args) (js-date-setter (js-this) "fullYear" args))
|
||||
:setUTCFullYear (fn (&rest args) (js-date-setter (js-this) "fullYear" args))
|
||||
:setMonth (fn (&rest args) (js-date-setter (js-this) "month" args))
|
||||
:setUTCMonth (fn (&rest args) (js-date-setter (js-this) "month" args))
|
||||
:setDate (fn (&rest args) (js-date-setter (js-this) "date" args))
|
||||
:setUTCDate (fn (&rest args) (js-date-setter (js-this) "date" args))
|
||||
:setHours (fn (&rest args) (js-date-setter (js-this) "hours" args))
|
||||
:setUTCHours (fn (&rest args) (js-date-setter (js-this) "hours" args))
|
||||
:setMinutes (fn (&rest args) (js-date-setter (js-this) "minutes" args))
|
||||
:setUTCMinutes (fn (&rest args) (js-date-setter (js-this) "minutes" args))
|
||||
:setSeconds (fn (&rest args) (js-date-setter (js-this) "seconds" args))
|
||||
:setUTCSeconds (fn (&rest args) (js-date-setter (js-this) "seconds" args))
|
||||
:setMilliseconds (fn (&rest args) (js-date-setter (js-this) "ms" args))
|
||||
:setUTCMilliseconds (fn (&rest args) (js-date-setter (js-this) "ms" args))
|
||||
:toISOString (fn () (js-date-iso (js-this)))
|
||||
:toJSON (fn () (js-date-iso (js-this)))
|
||||
:toString (fn () (js-date-iso (js-this)))
|
||||
|
||||
@@ -158,6 +158,8 @@ Each item: implement → tests → update progress. Mark `[x]` when tests green.
|
||||
|
||||
Append-only record of completed iterations. Loop writes one line per iteration: date, what was done, test count delta.
|
||||
|
||||
- 2026-05-10 — **Real `Date.prototype.setFullYear/setMonth/setDate/setHours/setMinutes/setSeconds/setMilliseconds` (+ UTC variants) and a corrected `setTime`.** All Date setters were missing — only `setTime` existed and didn't validate. Added a unified `js-date-setter(d, field, args)` that decomposes the current ms into `(y mo da hh mm ss msv)` via `js-date-decompose`, splices in the `args` per the field's optional-arg contract (e.g. `setHours(h, m?, s?, ms?)`), recomposes via `js-date-civil-to-days`, and TimeClips at ±8.64e15. NaN args anywhere → ms set to NaN. Wired all 14 setters to the helper. Hit a parser gotcha: SX `cond` clause body is single-form only — multi-expression bodies like `(else (dict-set! ...) new-ms)` silently treat the second form as `(<first-result> new-ms)` ("Not callable: false"). Wrapped these in `(begin ...)`. Result: setFullYear 5/18 → 13/18 (+8). setHours 5/21 → 15/21 (+10). setMonth 3/15 → 9/15 (+6). setMinutes 4/16 → 10/16 (+6). setSeconds 3/15 → 9/15 (+6). setDate 2/12 → 6/12 (+4). setMilliseconds 2/12 → 6/12 (+4). setTime 4/9 → 6/9 (+2). conformance.sh: 148/148.
|
||||
|
||||
- 2026-05-10 — **`Object.assign` keys now visible to `Object.keys` / `JSON.stringify`.** `Object.assign({}, {a:1})` was mutating the target via `dict-set!` which bypasses our `__js_order__` insertion-order side table; `Object.keys(t)` (which iterates `__js_order__` when present) returned `[]`, and `JSON.stringify` saw nothing. Switched `js-object-assign` to use `js-set-prop` (which calls `js-obj-order-add!` on new keys) for both dict and string sources. Result: built-ins/Object/assign 13/25 → 14/25. conformance.sh: 148/148.
|
||||
|
||||
- 2026-05-10 — **User functions' `prototype` chain through Object.prototype + auto-set `constructor`.** Per ES spec, every function's `prototype` slot defaults to `{ constructor: F, __proto__: Object.prototype }`. Our `js-get-ctor-proto` lazily created a fresh empty `(dict)` for user functions on first access — so `(new F) instanceof Object` was `false`, `F.prototype.constructor` was undefined, and `x.constructor === F` failed. Now the lazy-init seeds the proto with `__proto__ → Object.prototype` and `constructor → F` before caching in `__js_proto_table__`. Result: language/expressions/instanceof 25/30 → 26/30. conformance.sh: 148/148.
|
||||
|
||||
Reference in New Issue
Block a user