js-on-sx: Date constructor + prototype stubs
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 36s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 36s
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user