From ada7a147e556aa61a272e5417ee08fc0cc470494 Mon Sep 17 00:00:00 2001 From: giles Date: Sat, 9 May 2026 20:41:10 +0000 Subject: [PATCH] js-on-sx: Array.prototype methods carry spec lengths + names --- lib/js/runtime.sx | 51 +++++++++++++++++++++++++++++++++++++++++------ plans/js-on-sx.md | 2 ++ 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/lib/js/runtime.sx b/lib/js/runtime.sx index 5d6b0f71..10b39120 100644 --- a/lib/js/runtime.sx +++ b/lib/js/runtime.sx @@ -4369,17 +4369,56 @@ (define js-array-of (fn (&rest args) args)) +(define + js-array-proto-fn-length + (fn + (name) + (cond + ((= name "concat") 1) + ((= name "copyWithin") 2) + ((= name "every") 1) + ((= name "fill") 1) + ((= name "filter") 1) + ((= name "find") 1) + ((= name "findIndex") 1) + ((= name "findLast") 1) + ((= name "findLastIndex") 1) + ((= name "flat") 0) + ((= name "flatMap") 1) + ((= name "forEach") 1) + ((= name "includes") 1) + ((= name "indexOf") 1) + ((= name "join") 1) + ((= name "lastIndexOf") 1) + ((= name "map") 1) + ((= name "push") 1) + ((= name "reduce") 1) + ((= name "reduceRight") 1) + ((= name "slice") 2) + ((= name "some") 1) + ((= name "sort") 1) + ((= name "splice") 2) + ((= name "unshift") 1) + ((= name "at") 1) + ((= name "toSorted") 1) + ((= name "toReversed") 0) + ((= name "with") 2) + (else 0)))) + (define js-array-proto-fn (fn (name) - (fn - (&rest args) - (let - ((this-val (js-this))) + {:__callable__ + (fn + (&rest args) (let - ((recv (cond ((list? this-val) this-val) ((and (dict? this-val) (contains? (keys this-val) "length")) (js-arraylike-to-list this-val)) (else this-val)))) - (js-invoke-method recv name args)))))) + ((this-val (js-this))) + (let + ((recv (cond ((list? this-val) this-val) ((and (dict? this-val) (contains? (keys this-val) "length")) (js-arraylike-to-list this-val)) (else this-val)))) + (js-invoke-method recv name args)))) + :length (js-array-proto-fn-length name) + :name name})) (define js-array-from diff --git a/plans/js-on-sx.md b/plans/js-on-sx.md index 5d835cc8..5df613c3 100644 --- a/plans/js-on-sx.md +++ b/plans/js-on-sx.md @@ -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 — **`Array.prototype` methods carry spec lengths and names.** Continuation of the same fix. `js-array-proto-fn` was returning bare lambdas → `Array.prototype.push.length === 0` instead of `1`. Added `js-array-proto-fn-length` (lookup table for the ~30 method names — `push:1`, `slice:2`, `splice:2`, `concat:1`, `forEach:1`, `every:1`, `flat:0`, etc.) and changed the helper to return the dict-with-`__callable__` form. Now `Array.prototype.push.length === 1`, `Array.prototype.slice.length === 2`. Array 27/50, Array.prototype 8/30, Object 30/30 unchanged. conformance.sh: 148/148. + - 2026-05-09 — **`Number.prototype` and `String.prototype` methods carry spec lengths and names.** Same shape as the earlier Function.prototype fix. Number.prototype.{toFixed/toExponential/toPrecision/toString/valueOf/toLocaleString} were bare `(fn ...)` lambdas → length 0 → tests assert e.g. `Number.prototype.toExponential.length === 1`. Wrapped each in a dict-with-`__callable__` with `:length` and `:name`. For String.prototype, `js-string-proto-fn` was a single helper applied to ~30 method names; added `js-string-proto-fn-length` (lookup table for spec-defined lengths: `concat:1`, `indexOf:1`, `slice:2`, `substring:2`, `replace:2`, etc.) and changed the helper to return the dict form, so all string methods now report correctly. Result: built-ins/Number/prototype 18/30 → 20/30, String/prototype 18/30 → 21/30. Number 26/30 holds, String 29/30. conformance.sh: 148/148. - 2026-05-09 — **`Boolean.prototype.toString`/`valueOf` throw TypeError on non-Boolean receivers.** Per spec, both methods are not generic — calling them with a `this` that isn't a Boolean primitive or wrapper must throw TypeError. Was silently returning `"true"`/`"false"` based on whether the receiver was truthy (`s1.toString = Boolean.prototype.toString; s1.toString()` returned `"true"` for any non-empty string instead of throwing). Added an `else (raise (js-new-call TypeError ...))` branch to both prototype methods. Result: built-ins/Boolean 28/30 → 29/30. Object 30/30 holds. conformance.sh: 148/148.