js-on-sx: Object.keys throws on null/undefined, walks indices on string/array
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 20s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 20s
This commit is contained in:
@@ -3982,6 +3982,18 @@
|
||||
(fn
|
||||
(o)
|
||||
(cond
|
||||
((or (= o nil) (js-undefined? o))
|
||||
(raise (js-new-call TypeError (js-args "Object.keys called on null or undefined"))))
|
||||
((= (type-of o) "string")
|
||||
(let ((result (list)) (n (len o)))
|
||||
(begin
|
||||
(js-string-keys-loop result 0 n)
|
||||
result)))
|
||||
((list? o)
|
||||
(let ((result (list)) (n (len o)))
|
||||
(begin
|
||||
(js-string-keys-loop result 0 n)
|
||||
result)))
|
||||
((dict? o)
|
||||
(cond
|
||||
((contains? (keys o) "__js_order__")
|
||||
@@ -4002,6 +4014,17 @@
|
||||
result)))))
|
||||
(else (list)))))
|
||||
|
||||
(define
|
||||
js-string-keys-loop
|
||||
(fn
|
||||
(acc i n)
|
||||
(cond
|
||||
((>= i n) nil)
|
||||
(else
|
||||
(begin
|
||||
(append! acc (js-to-string i))
|
||||
(js-string-keys-loop acc (+ i 1) n))))))
|
||||
|
||||
(define
|
||||
js-object-values
|
||||
(fn
|
||||
|
||||
@@ -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-09 — **`Object.keys` throws TypeError on null/undefined and walks indices on strings/arrays.** Was returning `(list)` for non-dict input — `Object.keys(null)` silently returned `[]` instead of throwing per spec, and `Object.keys("abc")` returned `[]` instead of `["0","1","2"]`. Added explicit branches: null/undefined → TypeError, string/list → `["0","1",..."n-1"]` via `js-string-keys-loop`. Result: built-ins/Object/keys 19/30 → 22/30. Object 30/30, Map 18/30 unchanged. conformance.sh: 148/148.
|
||||
|
||||
- 2026-05-09 — **`Object.assign` ToObject's target, throws TypeError on null/undefined, copies own enumerable props from string sources.** Was returning the raw target unchanged when given a primitive (`Object.assign("a")` returned the string `"a"`), and silently no-op'd on null/undefined target instead of throwing per spec. Now coerces target via `js-coerce-this-arg` (boxes primitives), guards null/undefined with TypeError, and walks each source: dict → copy own keys (skipping internal `__js_order__` / `__proto__`), string → copy each character at numeric index, null/undefined → skip. Now `Object.assign("a")` returns a String wrapper whose `valueOf()` is `"a"`, and `Object.assign(null)` throws TypeError. Result: built-ins/Object/assign 5/25 → 13/25 (+8). Object 30/30 holds. conformance.sh: 148/148.
|
||||
|
||||
- 2026-05-09 — **`Number.prototype.toFixed`/`toString`/etc. unwrap Number wrappers and throw TypeError on non-Number receivers.** Was passing `(js-this)` straight through to `js-number-to-fixed`, so calling `Number.prototype.toFixed(1)` directly on `Number.prototype` (a Number wrapper dict) raised `"Expected number, got dict"`. Per spec, these methods must extract the Number primitive value (from primitive or wrapper) and throw TypeError otherwise. Added `js-number-this-val` helper that handles primitive number, rational, `__js_number_value__`-marked wrapper, and raises TypeError for everything else. Routed all six Number.prototype methods through it. Result: built-ins/Number/prototype/toFixed 5/13 → 7/13. Number 26/30 holds. conformance.sh: 148/148.
|
||||
|
||||
Reference in New Issue
Block a user