From cf0ba8a02a833936b4a508102465768be40c771c Mon Sep 17 00:00:00 2001 From: giles Date: Thu, 7 May 2026 15:08:55 +0000 Subject: [PATCH] js-on-sx: js-dict-get-walk falls back to Object.prototype MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Object literals didn't carry a __proto__ link, so ({}).toString() couldn't reach Object.prototype.toString. Added a cond clause: if the object has no __proto__ AND is not Object.prototype itself, walk into Object.prototype. Now ({}).toString() works, override of Object.prototype.toString propagates, and ({a:1}).hasOwnProperty ('a') returns true. built-ins/String: 69/99 → 71/99 (canonical), 71/99 → 74/99 (isolated). conformance.sh: 148/148. --- lib/js/runtime.sx | 2 ++ lib/js/test262-scoreboard.json | 18 +++++++++--------- lib/js/test262-scoreboard.md | 12 ++++++------ plans/js-on-sx.md | 2 ++ 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/lib/js/runtime.sx b/lib/js/runtime.sx index abbe9c8b..d575b98b 100644 --- a/lib/js/runtime.sx +++ b/lib/js/runtime.sx @@ -2596,6 +2596,8 @@ ((dict-has? obj skey) (get obj skey)) ((dict-has? obj "__proto__") (js-dict-get-walk (get obj "__proto__") skey)) + ((not (= obj (get Object "prototype"))) + (js-dict-get-walk (get Object "prototype") skey)) (else js-undefined))))) (define diff --git a/lib/js/test262-scoreboard.json b/lib/js/test262-scoreboard.json index ee01de05..68a1ce3f 100644 --- a/lib/js/test262-scoreboard.json +++ b/lib/js/test262-scoreboard.json @@ -1,26 +1,26 @@ { "totals": { - "pass": 69, - "fail": 24, + "pass": 71, + "fail": 22, "skip": 1, "timeout": 6, "total": 100, "runnable": 99, - "pass_rate": 69.7 + "pass_rate": 71.7 }, "categories": [ { "category": "built-ins/String", "total": 100, - "pass": 69, - "fail": 24, + "pass": 71, + "fail": 22, "skip": 1, "timeout": 6, - "pass_rate": 69.7, + "pass_rate": 71.7, "top_failures": [ [ "Test262Error (assertion failed)", - 12 + 10 ], [ "TypeError: not a function", @@ -44,7 +44,7 @@ "top_failure_modes": [ [ "Test262Error (assertion failed)", - 12 + 10 ], [ "TypeError: not a function", @@ -68,6 +68,6 @@ ] ], "pinned_commit": "d5e73fc8d2c663554fb72e2380a8c2bc1a318a33", - "elapsed_seconds": 344.4, + "elapsed_seconds": 375.3, "workers": 1 } \ No newline at end of file diff --git a/lib/js/test262-scoreboard.md b/lib/js/test262-scoreboard.md index a0d35f36..f01a6b1b 100644 --- a/lib/js/test262-scoreboard.md +++ b/lib/js/test262-scoreboard.md @@ -1,13 +1,13 @@ # test262 scoreboard Pinned commit: `d5e73fc8d2c663554fb72e2380a8c2bc1a318a33` -Wall time: 344.4s +Wall time: 375.3s -**Total:** 69/99 runnable passed (69.7%). Raw: pass=69 fail=24 skip=1 timeout=6 total=100. +**Total:** 71/99 runnable passed (71.7%). Raw: pass=71 fail=22 skip=1 timeout=6 total=100. ## Top failure modes -- **12x** Test262Error (assertion failed) +- **10x** Test262Error (assertion failed) - **8x** TypeError: not a function - **6x** Timeout - **2x** Unhandled: Not callable: \\\ @@ -18,13 +18,13 @@ Wall time: 344.4s | Category | Pass | Fail | Skip | Timeout | Total | Pass % | |---|---:|---:|---:|---:|---:|---:| -| built-ins/String | 69 | 24 | 1 | 6 | 100 | 69.7% | +| built-ins/String | 71 | 22 | 1 | 6 | 100 | 71.7% | ## Per-category top failures (min 10 runnable, worst first) -### built-ins/String (69/99 — 69.7%) +### built-ins/String (71/99 — 71.7%) -- **12x** Test262Error (assertion failed) +- **10x** Test262Error (assertion failed) - **8x** TypeError: not a function - **6x** Timeout - **2x** Unhandled: Not callable: \\\ diff --git a/plans/js-on-sx.md b/plans/js-on-sx.md index 488cc623..202f5d04 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-07 — **`js-dict-get-walk` falls back to `Object.prototype` when an object has no `__proto__`.** Object literals (`{}`, `{a:1}`) didn't carry a `__proto__` link, so `({}).toString()` couldn't find `Object.prototype.toString` — and overriding `Object.prototype.toString` had no effect on plain objects. Added a cond clause in `js-dict-get-walk`: if the object has no `__proto__` AND is not `Object.prototype` itself, walk into `Object.prototype`. Termination guaranteed because Object.prototype is the recursion base case. Now `({}).toString() === "[object Object]"`, override of `Object.prototype.toString` propagates to plain objects, and `({a:1}).hasOwnProperty('a') === true`. built-ins/String: 69/99 → 71/99 (canonical), 71/99 → 74/99 (isolated). conformance.sh: 148/148. + - 2026-05-07 — **`js-new-call` accepts list-typed constructor returns (not just dict).** `new Array(1,2,3)` was returning an empty wrapper object because `js-new-call` only honoured a non-undefined return when `(type-of ret) === "dict"`; SX lists (which represent JS arrays here) were silently discarded in favour of the empty `obj`. Widened the check to accept `"list"` returns. Fixes `new Array(1,2,3).length`, `String(new Array(1,2,3))`, and any constructor whose body returns a list. built-ins/String 67/99 → 69/99 (canonical), 70/99 → 71/99 (isolated). conformance.sh: 148/148. - 2026-05-07 — **`js-num-from-string` uses `pow` (float) instead of `js-pow-int` for the exponent.** Numeric literals like `1e20` and `100000000000000000000` were parsing as `-1457092405402533888` because `js-pow-int 10 20` overflows int64 (10^20 > 2^63). The OCaml SX `pow` primitive uses float-domain power and produces `1e+20` correctly. Replaced the single `(js-pow-int 10 e)` call in `js-num-from-string` with `(pow 10 e)`. Fixes `String(1e20)`, `String(1e30)`, `String(100000000000000000000)`, etc. With isolation built-ins/String 67/99 → 70/99. conformance.sh: 148/148.