js-on-sx: Date constructor + prototype stubs
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 36s

This commit is contained in:
2026-05-08 21:30:36 +00:00
parent d8b8de6195
commit 0d9c45176b
2 changed files with 156 additions and 1 deletions

View File

@@ -990,6 +990,157 @@
(define AggregateError :js-undefined)
(define SuppressedError :js-undefined)
(define
js-date-from-one
(fn
(v)
(cond
((number? v) v)
((= (type-of v) "string") (js-date-parse-string v))
(else 0))))
(define
js-date-parse-string
(fn
(s)
(cond
((>= (len s) 4)
(let
((year-part (js-string-slice s 0 4)))
(cond
((js-is-numeric-string? year-part)
(let
((y (js-num-to-int (js-string-to-number year-part))))
(* (- y 1970) 31557600000)))
(else 0))))
(else 0))))
(define
js-date-from-parts
(fn
(args)
(let
((year (js-num-to-int (js-to-number (nth args 0))))
(month
(if (>= (len args) 2) (js-num-to-int (js-to-number (nth args 1))) 0))
(day
(if (>= (len args) 3) (js-num-to-int (js-to-number (nth args 2))) 1)))
(+
(* (- year 1970) 31557600000)
(* month 2629800000)
(* (- day 1) 86400000)))))
(define
js-date-format-now
(fn () "[Date stub]"))
(define
js-date-pad2
(fn (n) (if (< n 10) (str "0" (js-to-string n)) (js-to-string n))))
(define
js-date-pad3
(fn
(n)
(cond
((< n 10) (str "00" (js-to-string n)))
((< n 100) (str "0" (js-to-string n)))
(else (js-to-string n)))))
(define
Date
{:length 7
:name "Date"
:__callable__
(fn
(&rest args)
(let
((this (js-this)))
(cond
((not (= (type-of this) "dict")) (js-date-format-now))
(else
(begin
(dict-set!
this
"__date_value__"
(cond
((= (len args) 0) 0)
((= (len args) 1) (js-date-from-one (nth args 0)))
(else (js-date-from-parts args))))
(dict-set! this "__js_is_date__" true)
this)))))
:now (fn () 0)
:parse (fn (s) (js-date-parse-string (js-to-string s)))
:UTC
(fn
(&rest args)
(cond
((= (len args) 0) 0)
(else (js-date-from-parts args))))
:prototype
{:getTime (fn () (let ((t (js-this))) (get t "__date_value__")))
:valueOf (fn () (let ((t (js-this))) (get t "__date_value__")))
:getFullYear
(fn ()
(let ((t (js-this)))
(+ 1970 (js-math-trunc (/ (get t "__date_value__") 31557600000)))))
:getUTCFullYear
(fn ()
(let ((t (js-this)))
(+ 1970 (js-math-trunc (/ (get t "__date_value__") 31557600000)))))
:getMonth (fn () 0)
:getUTCMonth (fn () 0)
:getDate (fn () 1)
:getUTCDate (fn () 1)
:getDay (fn () 0)
:getUTCDay (fn () 0)
:getHours (fn () 0)
:getUTCHours (fn () 0)
:getMinutes (fn () 0)
:getUTCMinutes (fn () 0)
:getSeconds (fn () 0)
:getUTCSeconds (fn () 0)
:getMilliseconds (fn () 0)
:getUTCMilliseconds (fn () 0)
:getTimezoneOffset (fn () 0)
:setTime
(fn (v)
(let ((t (js-this)))
(begin (dict-set! t "__date_value__" v) v)))
:toISOString (fn () (js-date-iso (js-this)))
:toJSON (fn () (js-date-iso (js-this)))
:toString (fn () (js-date-iso (js-this)))
:toUTCString (fn () (js-date-iso (js-this)))
:toDateString (fn () (js-date-iso (js-this)))
:toTimeString (fn () "00:00:00 GMT+0000")
:toLocaleString (fn () (js-date-iso (js-this)))
:toLocaleDateString (fn () (js-date-iso (js-this)))
:toLocaleTimeString (fn () "00:00:00")}})
(define
js-date-iso
(fn
(d)
(let
((ms (get d "__date_value__")))
(let
((year
(+ 1970 (js-math-trunc (/ ms 31557600000)))))
(str (js-date-year-pad year) "-01-01T00:00:00.000Z")))))
(define
js-date-year-pad
(fn
(y)
(cond
((>= y 0)
(cond
((< y 10) (str "000" (js-to-string y)))
((< y 100) (str "00" (js-to-string y)))
((< y 1000) (str "0" (js-to-string y)))
(else (js-to-string y))))
(else (str "-" (js-date-year-pad (- 0 y)))))))
(define
js-function?
(fn
@@ -5474,17 +5625,19 @@
(dict-set! Boolean "__proto__" (get js-function-global "prototype"))
(dict-set! Map "__proto__" (get js-function-global "prototype"))
(dict-set! Set "__proto__" (get js-function-global "prototype"))
(dict-set! Date "__proto__" (get js-function-global "prototype"))
(dict-set! (get Array "prototype") "__proto__" (get Object "prototype"))
(dict-set! (get Number "prototype") "__proto__" (get Object "prototype"))
(dict-set! (get String "prototype") "__proto__" (get Object "prototype"))
(dict-set! (get Boolean "prototype") "__proto__" (get Object "prototype"))
(dict-set! (get Map "prototype") "__proto__" (get Object "prototype"))
(dict-set! (get Set "prototype") "__proto__" (get Object "prototype"))
(dict-set! (get Date "prototype") "__proto__" (get Object "prototype"))
(dict-set! (get js-function-global "prototype") "__proto__" (get Object "prototype"))
(dict-set! (get Number "prototype") "__js_number_value__" 0)
(dict-set! (get String "prototype") "__js_string_value__" "")
(dict-set! (get Boolean "prototype") "__js_boolean_value__" false))
(define js-global {:undefined js-undefined :JSON JSON :parseInt parseInt :Object Object :isNaN js-global-is-nan :Infinity inf :NaN 0 :String String :Boolean Boolean :Array Array :Math Math :parseFloat parseFloat :Number Number :console console :isFinite js-global-is-finite :Map Map :Set Set})
(define js-global {:undefined js-undefined :JSON JSON :parseInt parseInt :Object Object :isNaN js-global-is-nan :Infinity inf :NaN 0 :String String :Boolean Boolean :Array Array :Math Math :parseFloat parseFloat :Number Number :console console :isFinite js-global-is-finite :Map Map :Set Set :Date Date})
(set! js-global-this js-global)

View File

@@ -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-08 — **`Date` constructor + prototype stubs.** `Date` was undefined globally — every test in `built-ins/Date` died at `new Date(...)` with ReferenceError. Implemented as a dict-with-`__callable__` (same pattern as `Map`/`Set`/`Object`). Constructor accepts 0 args (epoch 0), 1 number arg (ms), 1 string arg (parses leading `YYYY` to compute approx ms via `(year-1970)*31557600000`), or 2+ args (year, month, day → simple ms calc). `__date_value__` is the internal slot. Statics: `Date.now()`, `Date.parse(s)`, `Date.UTC(...)`. Prototype: `getTime` / `valueOf` / `setTime`, all `getX` / `getUTCX` (most return 0/1 — only `getFullYear` actually computes), `toISOString` / `toJSON` / `toString` / `toUTCString` produce `YYYY-01-01T00:00:00.000Z` from the stored year, plus the locale variants. Wired `Date` into `js-global` and the post-init `__proto__` chain. The maths is approximate (ignores leap years, varying month lengths, timezone offsets) — but the structural tests `typeof new Date(...) === "object"` and the basic flow now work. Result: built-ins/Date 0/30 → 3/30 (rest timeouts/assertions on month-rollover/leap-year math we don't model). conformance.sh: 148/148.
- 2026-05-08 — **`Error.isError` static + `[[ErrorData]]` slot + `verifyEqualTo` harness helper.** Added `Error.isError(v)` per the Stage-3 proposal: returns `true` only for objects with the internal `[[ErrorData]]` slot. Implemented as `__js_error_data__: true` set on `this` by every Error subclass constructor (Error/TypeError/RangeError/SyntaxError/ReferenceError/URIError/EvalError); `js-error-is-error` walks `__proto__` looking for the marker. Wired through the lambda-static-prop path next to the existing `Promise.resolve` / `Promise.reject` lookup. Defined `AggregateError` and `SuppressedError` as `:js-undefined` so `typeof AggregateError !== 'undefined'` resolves cleanly (without these, the bare ident lookup throws ReferenceError). Added `verifyEqualTo` to the harness — `propertyHelper.js` includes it, used by `Error/message_property.js` etc. Result: built-ins/Error 6/30 → 11/30 (+5), Error/isError sub-suite 0/9 → 5/9. Map/Object unchanged. conformance.sh: 148/148.
- 2026-05-08 — **Harness: `$DONE` / `asyncTest` and `checkSequence` / `checkSettledPromises` stubs added.** Async-flagged Promise tests call `$DONE(err?)` to signal completion — we run synchronously and drain microtasks, so the stub just throws a `Test262Error` if `err` is passed. `asyncTest(fn)` wraps the test fn in `Promise.resolve().then(..., $DONE)`. `checkSequence(arr, msg)` (from `promiseHelper.js`) verifies `arr[i] === i+1` — used by ordering tests on `Promise.all` / `Promise.race`. `checkSettledPromises(actual, expected, msg)` matches what `Promise.allSettled` tests expect. Result: built-ins/Promise 1/30 → 15/30 (50%, 14 new passes from previously ReferenceError'ing on `$DONE`/`checkSequence`). conformance.sh: 148/148.