diff --git a/lib/js/runtime.sx b/lib/js/runtime.sx index d7f93a87..545d2dc8 100644 --- a/lib/js/runtime.sx +++ b/lib/js/runtime.sx @@ -4042,10 +4042,36 @@ js-object-get-own-property-descriptor (fn (o key) - (if - (and (dict? o) (contains? (keys o) (js-to-string key))) - {:configurable true :enumerable true :value (get o (js-to-string key)) :writable true} - :js-undefined))) + (let + ((sk (js-to-string key))) + (cond + ((and (dict? o) (contains? (keys o) sk)) + {:configurable true :enumerable true :value (get o sk) :writable true}) + ((list? o) + (cond + ((= sk "length") + {:configurable false :enumerable false :value (len o) :writable true}) + ((js-int-key? sk) + (let + ((i (js-num-to-int (js-string-to-number sk)))) + (cond + ((and (>= i 0) (< i (len o))) + {:configurable true :enumerable true :value (nth o i) :writable true}) + (else :js-undefined)))) + (else :js-undefined))) + ((and (= (type-of o) "string")) + (cond + ((= sk "length") + {:configurable false :enumerable false :value (len o) :writable false}) + ((js-int-key? sk) + (let + ((i (js-num-to-int (js-string-to-number sk)))) + (cond + ((and (>= i 0) (< i (len o))) + {:configurable false :enumerable true :value (char-at o i) :writable false}) + (else :js-undefined)))) + (else :js-undefined))) + (else :js-undefined))))) (define js-object-get-own-property-descriptors diff --git a/plans/js-on-sx.md b/plans/js-on-sx.md index 060f4e52..f40fac8f 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 — **`Object.getOwnPropertyDescriptor` now returns descriptors for arrays and strings, not just dicts.** Was: `(if (and (dict? o) ...) {...} :js-undefined)` — every list and string returned `undefined`. Extended: lists give `{value: arr[i], writable: true, enumerable: true, configurable: true}` for valid integer indices, plus `{value: arr.length, writable: true, enumerable: false, configurable: false}` for `"length"`. Strings give read-only descriptors for `"length"` and individual code units. The integer-index test reuses `js-int-key?` (added earlier for `__js_order__` integer-key sorting). Result: built-ins/Object/getOwnPropertyDescriptor 50/60 → 54/60, language/arguments-object 12/30 → 13/30. Array unchanged. conformance.sh: 148/148. + - 2026-05-09 — **Fixed `RegExp.prototype.test/exec` calling `nil` as a function when no regex platform impl is registered.** `js-regex-invoke-method` was checking `(js-undefined? impl)` to decide whether to fall back to the stub — but `(get __js_regex_platform__ "test")` returns `nil` (not `:js-undefined`) when the key is absent, so the check was false and the next branch `(impl rx arg)` tried to call `nil`. The OCaml CEK reports this as `Not callable: ` (showing the regex receiver in the error, which made the failure look like the regex itself wasn't callable). Changed both `test` and `exec` clauses to `(or (js-undefined? impl) (= impl nil))`. Now `RegExp("0").exec("1")` returns `null` (correctly, no match) instead of crashing. Result: language/literals 24/30 → 25/30. RegExp unchanged (still needs a real engine for the rest). conformance.sh: 148/148. - 2026-05-09 — **`RegExp` constructor exposed as a global.** Was undefined — every test in `built-ins/RegExp` died at `new RegExp(...)` with ReferenceError. The internals (`js-regex-new`, `js-regex?`, `js-regex-stub-test`, `js-regex-stub-exec`) already existed for regex literals; this iteration just wraps them as a JS-visible constructor with the dict-with-`__callable__` pattern. Constructor handles `new RegExp(/x/, "g")` (re-flags an existing regex), `new RegExp(pattern)` and `new RegExp(pattern, flags)`. Prototype methods: `test`, `exec`, `toString`, `compile` (matching the stub semantics — substring search with `i` flag honoured, no real regex engine). Added `RegExp` to `js-global` and the post-init `__proto__` chain. Result: built-ins/RegExp 0/30 → 1/30; the rest still need a real regex engine (or fail on character-class escapes / lookaheads / etc.). conformance.sh: 148/148.