From c8ab505c32eaa68b96d3068f5fae9bec78abf045 Mon Sep 17 00:00:00 2001 From: giles Date: Sat, 9 May 2026 01:01:39 +0000 Subject: [PATCH] js-on-sx: fix RegExp test/exec calling nil when platform impl missing --- lib/js/runtime.sx | 16 ++++++++-------- plans/js-on-sx.md | 2 ++ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/lib/js/runtime.sx b/lib/js/runtime.sx index 922a5bfc..d7f93a87 100644 --- a/lib/js/runtime.sx +++ b/lib/js/runtime.sx @@ -5391,10 +5391,10 @@ (= (len args) 0) "" (js-to-string (nth args 0))))) - (if - (js-undefined? impl) - (js-regex-stub-test rx arg) - (impl rx arg)))) + (cond + ((or (js-undefined? impl) (= impl nil)) + (js-regex-stub-test rx arg)) + (else (impl rx arg))))) ((= name "exec") (let ((impl (get __js_regex_platform__ "exec")) @@ -5403,10 +5403,10 @@ (= (len args) 0) "" (js-to-string (nth args 0))))) - (if - (js-undefined? impl) - (js-regex-stub-exec rx arg) - (impl rx arg)))) + (cond + ((or (js-undefined? impl) (= impl nil)) + (js-regex-stub-exec rx arg)) + (else (impl rx arg))))) ((= name "toString") (str "/" (get rx "source") "/" (get rx "flags"))) (else js-undefined)))) diff --git a/plans/js-on-sx.md b/plans/js-on-sx.md index 66dc217c..060f4e52 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 — **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. - 2026-05-08 — **`js-is-space?` recognises the full ES whitespace set** (was only ` \t\n\r`). `parseFloat(" 1.1")`, `parseFloat(" 1.1")`, etc. now strip leading whitespace correctly per spec. Added: form feed (12), vertical tab (11), NBSP (160), Ogham space mark (5760), the en/em-width run 8192–8202, line/paragraph separator (8232/8233), narrow no-break space (8239), medium math space (8287), ideographic space (12288), ZWNBSP/BOM (65279). Single helper used by every trim/whitespace path (`parseFloat`, `parseInt`, `String.prototype.trim*`, `js-string-to-number`, JSON parse-ws). Result: built-ins/parseFloat 15/30 → 17/30. String/Number/parseInt unchanged. conformance.sh: 148/148.