From a8596bd090f308b5157b3768dd3fba31c86ac361 Mon Sep 17 00:00:00 2001 From: giles Date: Sun, 10 May 2026 15:37:15 +0000 Subject: [PATCH] js-on-sx: Object.assign uses js-set-prop so keys appear in __js_order__ --- lib/js/runtime.sx | 4 ++-- plans/js-on-sx.md | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/js/runtime.sx b/lib/js/runtime.sx index e4ed4adf..fa3e74ea 100644 --- a/lib/js/runtime.sx +++ b/lib/js/runtime.sx @@ -4518,7 +4518,7 @@ (for-each (fn (k) - (if (js-key-internal? k) nil (dict-set! target k (get src k)))) + (if (js-key-internal? k) nil (js-set-prop target k (get src k)))) (js-object-keys src))) ((= (type-of src) "string") (let @@ -4535,7 +4535,7 @@ ((>= i n) nil) (else (begin - (dict-set! target (js-to-string i) (char-at s i)) + (js-set-prop target (js-to-string i) (char-at s i)) (js-object-assign-string-loop target s (+ i 1) n)))))) (define js-object-freeze (fn (o) o)) diff --git a/plans/js-on-sx.md b/plans/js-on-sx.md index 0ab04ec4..e6fe0726 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-10 — **`Object.assign` keys now visible to `Object.keys` / `JSON.stringify`.** `Object.assign({}, {a:1})` was mutating the target via `dict-set!` which bypasses our `__js_order__` insertion-order side table; `Object.keys(t)` (which iterates `__js_order__` when present) returned `[]`, and `JSON.stringify` saw nothing. Switched `js-object-assign` to use `js-set-prop` (which calls `js-obj-order-add!` on new keys) for both dict and string sources. Result: built-ins/Object/assign 13/25 → 14/25. conformance.sh: 148/148. + - 2026-05-10 — **User functions' `prototype` chain through Object.prototype + auto-set `constructor`.** Per ES spec, every function's `prototype` slot defaults to `{ constructor: F, __proto__: Object.prototype }`. Our `js-get-ctor-proto` lazily created a fresh empty `(dict)` for user functions on first access — so `(new F) instanceof Object` was `false`, `F.prototype.constructor` was undefined, and `x.constructor === F` failed. Now the lazy-init seeds the proto with `__proto__ → Object.prototype` and `constructor → F` before caching in `__js_proto_table__`. Result: language/expressions/instanceof 25/30 → 26/30. conformance.sh: 148/148. - 2026-05-10 — **Postfix `++`/`--` reject a preceding LineTerminator (ASI).** Per ES spec, `x\n++;` is a syntax error: no LineTerminator allowed between LHS and postfix `++`/`--`. Our `jp-parse-postfix` was matching `++`/`--` regardless of whether the preceding token had `:nl true`. Added `(not (jp-token-nl? st))` guard so newline-before-`++` makes the postfix arm fall through, the `++` then becomes a prefix-expr starting a new statement, which fails to parse and the runner classifies as SyntaxError. Result: language/expressions/postfix-increment 16/30 → 18/30 (+2). postfix-decrement 16/30 → 18/30 (+2). conformance.sh: 148/148.