js-on-sx: object literal __proto__ + try/catch error wrapping
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 36s

This commit is contained in:
2026-05-08 22:13:17 +00:00
parent 0d9c45176b
commit a1030dce5d
3 changed files with 58 additions and 2 deletions

View File

@@ -991,6 +991,34 @@
(define SuppressedError :js-undefined)
(define
js-str-startswith?
(fn
(s prefix)
(cond
((< (len s) (len prefix)) false)
(else (= (js-string-slice s 0 (len prefix)) prefix)))))
(define
js-wrap-exn
(fn
(e)
(cond
((not (= (type-of e) "string")) e)
((js-str-startswith? e "Undefined symbol:")
(js-new-call ReferenceError (js-args e)))
((js-str-startswith? e "TypeError:")
(js-new-call TypeError (js-args (js-string-slice e 11 (len e)))))
((js-str-startswith? e "RangeError:")
(js-new-call RangeError (js-args (js-string-slice e 12 (len e)))))
((js-str-startswith? e "SyntaxError:")
(js-new-call SyntaxError (js-args (js-string-slice e 13 (len e)))))
((js-str-startswith? e "ReferenceError:")
(js-new-call ReferenceError (js-args (js-string-slice e 16 (len e)))))
((js-str-startswith? e "URIError:")
(js-new-call URIError (js-args (js-string-slice e 10 (len e)))))
(else e))))
(define
js-date-from-one
(fn
@@ -3194,7 +3222,12 @@
(define
js-make-obj
(fn () (let ((d (dict))) (begin (dict-set! d "__js_order__" (list)) d))))
(fn ()
(let ((d (dict)))
(begin
(dict-set! d "__js_order__" (list))
(dict-set! d "__proto__" (get Object "prototype"))
d))))
(define
js-obj-order-add!

View File

@@ -1407,7 +1407,28 @@
(let
((body-tr (js-transpile body)))
(let
((with-catch (cond ((= catch-part nil) body-tr) (else (let ((pname (nth catch-part 0)) (cbody (nth catch-part 1))) (list (js-sym "guard") (list (if (= pname nil) (js-sym "__exc__") (js-sym pname)) (list (js-sym "else") (js-transpile cbody))) body-tr))))))
((with-catch
(cond
((= catch-part nil) body-tr)
(else
(let
((pname (nth catch-part 0))
(cbody (nth catch-part 1))
(raw-sym (js-sym "__raw_exc__")))
(list
(js-sym "guard")
(list
raw-sym
(list
(js-sym "else")
(cond
((= pname nil) (js-transpile cbody))
(else
(list
(js-sym "let")
(list (list (js-sym pname) (list (js-sym "js-wrap-exn") raw-sym)))
(js-transpile cbody))))))
body-tr))))))
(cond
((= finally-part nil) with-catch)
(else

View File

@@ -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 — **Object literals get `__proto__: Object.prototype`; try/catch wraps SX error strings into JS Error instances.** Two fixes that work together: (1) `js-make-obj` now sets `__proto__` to `(get Object "prototype")` on every plain object literal `{}` — was missing, so `({}) instanceof Object` was `false`. (2) `js-transpile-try` now wraps the catch param via `js-wrap-exn` — when SX throws an `Eval_error("TypeError: ...")` / `("RangeError: ...")` / `("SyntaxError: ...")` etc. into the catch body, the user previously got a plain string. Now each prefix dispatches to the matching `js-new-call` so `e instanceof TypeError` etc. is truthy. Note: `Eval_error("Undefined symbol: y")` is NOT caught by SX `guard` at all, so the `1 + y → ReferenceError` shape remains unfixable from JS land — out of scope (would need OCaml-side change to make symbol lookup raisable). Result: language/expressions/instanceof 13/30 → 18/30 (+5). Object/Map/Array unchanged. conformance.sh: 148/148.
- 2026-05-08 — **`Date` constructor + prototype stubs.** `Date` was undefined globally — every test in `built-ins/Date` died at `new Date(...)` with ReferenceError. Implemented as a dict-with-`__callable__` (same pattern as `Map`/`Set`/`Object`). Constructor accepts 0 args (epoch 0), 1 number arg (ms), 1 string arg (parses leading `YYYY` to compute approx ms via `(year-1970)*31557600000`), or 2+ args (year, month, day → simple ms calc). `__date_value__` is the internal slot. Statics: `Date.now()`, `Date.parse(s)`, `Date.UTC(...)`. Prototype: `getTime` / `valueOf` / `setTime`, all `getX` / `getUTCX` (most return 0/1 — only `getFullYear` actually computes), `toISOString` / `toJSON` / `toString` / `toUTCString` produce `YYYY-01-01T00:00:00.000Z` from the stored year, plus the locale variants. Wired `Date` into `js-global` and the post-init `__proto__` chain. The maths is approximate (ignores leap years, varying month lengths, timezone offsets) — but the structural tests `typeof new Date(...) === "object"` and the basic flow now work. Result: built-ins/Date 0/30 → 3/30 (rest timeouts/assertions on month-rollover/leap-year math we don't model). conformance.sh: 148/148.
- 2026-05-08 — **`Error.isError` static + `[[ErrorData]]` slot + `verifyEqualTo` harness helper.** Added `Error.isError(v)` per the Stage-3 proposal: returns `true` only for objects with the internal `[[ErrorData]]` slot. Implemented as `__js_error_data__: true` set on `this` by every Error subclass constructor (Error/TypeError/RangeError/SyntaxError/ReferenceError/URIError/EvalError); `js-error-is-error` walks `__proto__` looking for the marker. Wired through the lambda-static-prop path next to the existing `Promise.resolve` / `Promise.reject` lookup. Defined `AggregateError` and `SuppressedError` as `:js-undefined` so `typeof AggregateError !== 'undefined'` resolves cleanly (without these, the bare ident lookup throws ReferenceError). Added `verifyEqualTo` to the harness — `propertyHelper.js` includes it, used by `Error/message_property.js` etc. Result: built-ins/Error 6/30 → 11/30 (+5), Error/isError sub-suite 0/9 → 5/9. Map/Object unchanged. conformance.sh: 148/148.