From e97bdc46027bbc683d85341e6cba338eb100a7bc Mon Sep 17 00:00:00 2001 From: giles Date: Fri, 8 May 2026 11:27:18 +0000 Subject: [PATCH] js-on-sx: native prototypes carry wrapped primitive marker MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per ES, Boolean.prototype is a Boolean wrapper around false, Number.prototype wraps 0, String.prototype wraps "". So Boolean.prototype == false (loose-eq unwraps), and Object.prototype.toString.call(Number.prototype) === "[object Number]". Set __js_*_value__ on each in post-init. built-ins/Boolean: 23/27 → 24/27, String: 80/99 → 84/99. conformance.sh: 148/148. --- lib/js/runtime.sx | 5 ++- lib/js/test262-scoreboard.json | 62 +++++++++++++++++++++------------- lib/js/test262-scoreboard.md | 20 ++++++----- plans/js-on-sx.md | 2 ++ 4 files changed, 57 insertions(+), 32 deletions(-) diff --git a/lib/js/runtime.sx b/lib/js/runtime.sx index 74deaa86..adaa56e1 100644 --- a/lib/js/runtime.sx +++ b/lib/js/runtime.sx @@ -4651,6 +4651,9 @@ (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 js-function-global "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}) diff --git a/lib/js/test262-scoreboard.json b/lib/js/test262-scoreboard.json index c8fa7863..6d2404ff 100644 --- a/lib/js/test262-scoreboard.json +++ b/lib/js/test262-scoreboard.json @@ -1,45 +1,61 @@ { "totals": { - "pass": 46, - "fail": 2, - "skip": 0, - "timeout": 2, - "total": 50, - "runnable": 50, - "pass_rate": 92.0 + "pass": 84, + "fail": 12, + "skip": 1, + "timeout": 3, + "total": 100, + "runnable": 99, + "pass_rate": 84.8 }, "categories": [ { - "category": "built-ins/Number", - "total": 50, - "pass": 46, - "fail": 2, - "skip": 0, - "timeout": 2, - "pass_rate": 92.0, + "category": "built-ins/String", + "total": 100, + "pass": 84, + "fail": 12, + "skip": 1, + "timeout": 3, + "pass_rate": 84.8, "top_failures": [ [ - "Timeout", - 2 + "Test262Error (assertion failed)", + 10 ], [ - "Test262Error (assertion failed)", - 2 + "Timeout", + 3 + ], + [ + "ReferenceError (undefined symbol)", + 1 + ], + [ + "SyntaxError (parse/unsupported syntax)", + 1 ] ] } ], "top_failure_modes": [ [ - "Timeout", - 2 + "Test262Error (assertion failed)", + 10 ], [ - "Test262Error (assertion failed)", - 2 + "Timeout", + 3 + ], + [ + "ReferenceError (undefined symbol)", + 1 + ], + [ + "SyntaxError (parse/unsupported syntax)", + 1 ] ], "pinned_commit": "d5e73fc8d2c663554fb72e2380a8c2bc1a318a33", - "elapsed_seconds": 90.4, + "elapsed_seconds": 192.4, "workers": 1 } \ No newline at end of file diff --git a/lib/js/test262-scoreboard.md b/lib/js/test262-scoreboard.md index 6685d1cf..b832b42e 100644 --- a/lib/js/test262-scoreboard.md +++ b/lib/js/test262-scoreboard.md @@ -1,24 +1,28 @@ # test262 scoreboard Pinned commit: `d5e73fc8d2c663554fb72e2380a8c2bc1a318a33` -Wall time: 90.4s +Wall time: 192.4s -**Total:** 46/50 runnable passed (92.0%). Raw: pass=46 fail=2 skip=0 timeout=2 total=50. +**Total:** 84/99 runnable passed (84.8%). Raw: pass=84 fail=12 skip=1 timeout=3 total=100. ## Top failure modes -- **2x** Timeout -- **2x** Test262Error (assertion failed) +- **10x** Test262Error (assertion failed) +- **3x** Timeout +- **1x** ReferenceError (undefined symbol) +- **1x** SyntaxError (parse/unsupported syntax) ## Categories (worst pass-rate first, min 10 runnable) | Category | Pass | Fail | Skip | Timeout | Total | Pass % | |---|---:|---:|---:|---:|---:|---:| -| built-ins/Number | 46 | 2 | 0 | 2 | 50 | 92.0% | +| built-ins/String | 84 | 12 | 1 | 3 | 100 | 84.8% | ## Per-category top failures (min 10 runnable, worst first) -### built-ins/Number (46/50 — 92.0%) +### built-ins/String (84/99 — 84.8%) -- **2x** Timeout -- **2x** Test262Error (assertion failed) +- **10x** Test262Error (assertion failed) +- **3x** Timeout +- **1x** ReferenceError (undefined symbol) +- **1x** SyntaxError (parse/unsupported syntax) diff --git a/plans/js-on-sx.md b/plans/js-on-sx.md index 53f26bcc..245859eb 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-08 — **Native prototypes carry the wrapped primitive marker.** Per ES, `Boolean.prototype` is a Boolean wrapper around `false`, `Number.prototype` wraps `0`, `String.prototype` wraps `""`. So `Boolean.prototype == false` (loose-eq unwraps), `Object.prototype.toString.call(Number.prototype) === "[object Number]"`, etc. Set `__js_boolean_value__: false` / `__js_number_value__: 0` / `__js_string_value__: ""` on the respective prototypes in the post-init block. built-ins/Boolean: 23/27 → 24/27, String: 80/99 → 84/99. conformance.sh: 148/148. + - 2026-05-08 — **`js-to-number` throws TypeError when valueOf+toString both return non-primitive.** Mirrors the earlier `js-to-string` fix. Per spec, `Number(obj)` must throw if `ToPrimitive` cannot extract a primitive. Was returning `NaN` silently. Replaced the inner `(js-nan-value)` fallback with `(raise (js-new-call TypeError ...))`. built-ins/Number: 45/50 → 46/50. conformance.sh: 148/148. - 2026-05-08 — **`Array.prototype` / `Number.prototype` / etc. inherit from `Object.prototype`.** Per ES, every native prototype's `[[Prototype]]` is `Object.prototype` (and `Function.prototype.[[Prototype]]` is also `Object.prototype`). Was missing those `__proto__` links, so `Object.prototype.isPrototypeOf(Boolean.prototype)` returned false (the explicit isPrototypeOf walks `__proto__`, not the recent fallback). Added 5 `dict-set!` lines to the post-init block at the end of `runtime.sx`. built-ins/Boolean: 22/27 → 23/27, built-ins/Number: 44/50 → 45/50. conformance.sh: 148/148.