js-on-sx: Map/Set prototype methods throw TypeError on non-Map/Set this
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 19s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 19s
This commit is contained in:
@@ -6394,66 +6394,86 @@
|
||||
(else nil)))
|
||||
entries))))
|
||||
|
||||
(define
|
||||
js-map-check!
|
||||
(fn
|
||||
(m method)
|
||||
(cond
|
||||
((or (not (dict? m)) (not (contains? (keys m) "__map_keys__")))
|
||||
(raise
|
||||
(js-new-call TypeError
|
||||
(js-args (str "Map.prototype." method " called on non-Map object")))))
|
||||
(else nil))))
|
||||
|
||||
(define
|
||||
js-map-do-set
|
||||
(fn
|
||||
(m k v)
|
||||
(let
|
||||
((ks (get m "__map_keys__")) (vs (get m "__map_vals__")))
|
||||
(begin
|
||||
(js-map-check! m "set")
|
||||
(let
|
||||
((idx (js-list-find-index ks k 0 (len ks))))
|
||||
(cond
|
||||
((>= idx 0) (begin (set-nth! vs idx v) m))
|
||||
(else
|
||||
(begin
|
||||
(append! ks k)
|
||||
(append! vs v)
|
||||
(dict-set! m "size" (len ks))
|
||||
m)))))))
|
||||
((ks (get m "__map_keys__")) (vs (get m "__map_vals__")))
|
||||
(let
|
||||
((idx (js-list-find-index ks k 0 (len ks))))
|
||||
(cond
|
||||
((>= idx 0) (begin (set-nth! vs idx v) m))
|
||||
(else
|
||||
(begin
|
||||
(append! ks k)
|
||||
(append! vs v)
|
||||
(dict-set! m "size" (len ks))
|
||||
m))))))))
|
||||
|
||||
(define
|
||||
js-map-do-get
|
||||
(fn
|
||||
(m k)
|
||||
(let
|
||||
((ks (get m "__map_keys__")) (vs (get m "__map_vals__")))
|
||||
(begin
|
||||
(js-map-check! m "get")
|
||||
(let
|
||||
((idx (js-list-find-index ks k 0 (len ks))))
|
||||
(cond ((>= idx 0) (nth vs idx)) (else js-undefined))))))
|
||||
((ks (get m "__map_keys__")) (vs (get m "__map_vals__")))
|
||||
(let
|
||||
((idx (js-list-find-index ks k 0 (len ks))))
|
||||
(cond ((>= idx 0) (nth vs idx)) (else js-undefined)))))))
|
||||
|
||||
(define
|
||||
js-map-do-has
|
||||
(fn
|
||||
(m k)
|
||||
(let
|
||||
((ks (get m "__map_keys__")))
|
||||
(>= (js-list-find-index ks k 0 (len ks)) 0))))
|
||||
(begin
|
||||
(js-map-check! m "has")
|
||||
(let
|
||||
((ks (get m "__map_keys__")))
|
||||
(>= (js-list-find-index ks k 0 (len ks)) 0)))))
|
||||
|
||||
(define
|
||||
js-map-do-delete
|
||||
(fn
|
||||
(m k)
|
||||
(let
|
||||
((ks (get m "__map_keys__")) (vs (get m "__map_vals__")))
|
||||
(begin
|
||||
(js-map-check! m "delete")
|
||||
(let
|
||||
((idx (js-list-find-index ks k 0 (len ks))))
|
||||
(cond
|
||||
((< idx 0) false)
|
||||
(else
|
||||
(let
|
||||
((new-ks (js-list-remove-at! ks idx))
|
||||
(new-vs (js-list-remove-at! vs idx)))
|
||||
(begin
|
||||
(dict-set! m "__map_keys__" new-ks)
|
||||
(dict-set! m "__map_vals__" new-vs)
|
||||
(dict-set! m "size" (len new-ks))
|
||||
true))))))))
|
||||
((ks (get m "__map_keys__")) (vs (get m "__map_vals__")))
|
||||
(let
|
||||
((idx (js-list-find-index ks k 0 (len ks))))
|
||||
(cond
|
||||
((< idx 0) false)
|
||||
(else
|
||||
(let
|
||||
((new-ks (js-list-remove-at! ks idx))
|
||||
(new-vs (js-list-remove-at! vs idx)))
|
||||
(begin
|
||||
(dict-set! m "__map_keys__" new-ks)
|
||||
(dict-set! m "__map_vals__" new-vs)
|
||||
(dict-set! m "size" (len new-ks))
|
||||
true)))))))))
|
||||
|
||||
(define
|
||||
js-map-do-clear
|
||||
(fn
|
||||
(m)
|
||||
(begin
|
||||
(js-map-check! m "clear")
|
||||
(dict-set! m "__map_keys__" (list))
|
||||
(dict-set! m "__map_vals__" (list))
|
||||
(dict-set! m "size" 0)
|
||||
@@ -6562,53 +6582,71 @@
|
||||
((items (js-iterable-to-list iter)))
|
||||
(for-each (fn (x) (js-set-do-add s x)) items))))
|
||||
|
||||
(define
|
||||
js-set-check!
|
||||
(fn
|
||||
(s method)
|
||||
(cond
|
||||
((or (not (dict? s)) (not (contains? (keys s) "__set_items__")))
|
||||
(raise
|
||||
(js-new-call TypeError
|
||||
(js-args (str "Set.prototype." method " called on non-Set object")))))
|
||||
(else nil))))
|
||||
|
||||
(define
|
||||
js-set-do-add
|
||||
(fn
|
||||
(s v)
|
||||
(let
|
||||
((items (get s "__set_items__")))
|
||||
(begin
|
||||
(js-set-check! s "add")
|
||||
(let
|
||||
((idx (js-list-find-index items v 0 (len items))))
|
||||
(cond
|
||||
((>= idx 0) s)
|
||||
(else
|
||||
(begin
|
||||
(append! items v)
|
||||
(dict-set! s "size" (len items))
|
||||
s)))))))
|
||||
((items (get s "__set_items__")))
|
||||
(let
|
||||
((idx (js-list-find-index items v 0 (len items))))
|
||||
(cond
|
||||
((>= idx 0) s)
|
||||
(else
|
||||
(begin
|
||||
(append! items v)
|
||||
(dict-set! s "size" (len items))
|
||||
s))))))))
|
||||
|
||||
(define
|
||||
js-set-do-has
|
||||
(fn
|
||||
(s v)
|
||||
(let
|
||||
((items (get s "__set_items__")))
|
||||
(>= (js-list-find-index items v 0 (len items)) 0))))
|
||||
(begin
|
||||
(js-set-check! s "has")
|
||||
(let
|
||||
((items (get s "__set_items__")))
|
||||
(>= (js-list-find-index items v 0 (len items)) 0)))))
|
||||
|
||||
(define
|
||||
js-set-do-delete
|
||||
(fn
|
||||
(s v)
|
||||
(let
|
||||
((items (get s "__set_items__")))
|
||||
(begin
|
||||
(js-set-check! s "delete")
|
||||
(let
|
||||
((idx (js-list-find-index items v 0 (len items))))
|
||||
(cond
|
||||
((< idx 0) false)
|
||||
(else
|
||||
(let
|
||||
((new-items (js-list-remove-at! items idx)))
|
||||
(begin
|
||||
(dict-set! s "__set_items__" new-items)
|
||||
(dict-set! s "size" (len new-items))
|
||||
true))))))))
|
||||
((items (get s "__set_items__")))
|
||||
(let
|
||||
((idx (js-list-find-index items v 0 (len items))))
|
||||
(cond
|
||||
((< idx 0) false)
|
||||
(else
|
||||
(let
|
||||
((new-items (js-list-remove-at! items idx)))
|
||||
(begin
|
||||
(dict-set! s "__set_items__" new-items)
|
||||
(dict-set! s "size" (len new-items))
|
||||
true)))))))))
|
||||
|
||||
(define
|
||||
js-set-do-clear
|
||||
(fn
|
||||
(s)
|
||||
(begin
|
||||
(js-set-check! s "clear")
|
||||
(dict-set! s "__set_items__" (list))
|
||||
(dict-set! s "size" 0)
|
||||
js-undefined)))
|
||||
|
||||
@@ -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 — **`Map.prototype.*` and `Set.prototype.*` raise TypeError when called on non-Map / non-Set `this`.** All five `js-map-do-*` and four `js-set-do-*` helpers were assuming `this` had `__map_keys__` / `__set_items__`, so `Map.prototype.clear.call({})` silently returned undefined (after creating dangling state) instead of throwing. Added `js-map-check!` / `js-set-check!` guards run as the first step of each method; raise spec-correct `TypeError` instances. Result: built-ins/Map 18/30 → 22/30 (+4). built-ins/Set 15/30 → 28/30 (+13). conformance.sh: 148/148.
|
||||
|
||||
- 2026-05-10 — **`Date.UTC` / `new Date(...)` propagate NaN/±Infinity arguments and return NaN.** `Date.UTC()` (no args) returned 0 instead of NaN; `Date.UTC(NaN, ...)` did the math and produced bogus ms; `new Date(year, NaN)` constructed a normal Date instead of an invalid one. Added `js-date-args-have-nan?` (also detects ±Infinity and propagates from rationals) used by both `Date.UTC` and the multi-arg constructor branch; UTC now returns NaN on no-arg / any-NaN-arg / out-of-range result, and `new Date(args)` stores NaN in `__date_value__` when any arg is NaN. Also fixed `js-date-from-one(undefined)` to return NaN. Result: built-ins/Date/UTC 6/16 → 10/16 (+4). Date 17/30 → 26/30 (timeouts dropped from 12 → 4 because invalid Dates now short-circuit). conformance.sh: 148/148.
|
||||
|
||||
- 2026-05-10 — **Real `Date` construction + getters via Howard-Hinnant civil-day arithmetic.** `js-date-from-parts` now computes a true ms-since-epoch from `(year, month, day, hour, min, sec, ms)` via `js-date-civil-to-days` (the inverse of last iteration's `days-to-ymd`), with the legacy 2-digit-year coercion (0..99 → 1900+y). `getFullYear/Month/Date/Day/Hours/Minutes/Seconds/Milliseconds` (UTC + non-UTC) all share a new `js-date-getter`: TypeErrors on non-Date this, returns NaN on invalid time, otherwise decomposes ms into y/m/d/h/m/s/ms/dow. Plus added `Date.prototype.constructor = Date` (was missing). Result: each of the 8 Date getter categories went 2/6 → 5/6 (+3 each, +24 total). Date toISOString 11/16 → 13/16. Some Date construction-loop tests now exceed the 15s per-test timeout — the new civil math is heavier than the old (year-1970)*ms-per-year approximation, but correctness wins. conformance.sh: 148/148.
|
||||
|
||||
Reference in New Issue
Block a user