js-on-sx: js-display filter to format JS values without leaking internals

The OCaml epoch-protocol printer serializes raw SX dicts. JS object literals
now carry __proto__ / __js_order__ bookkeeping that points into Object.prototype,
a complex dict containing lambdas that close over Object — the printer
recurses indefinitely and hangs.

js-display walks the value once, dropping any dict key that matches the
__name__ dunder convention. js-eval calls it on its return value so the
output is the user-facing shape only. Restores 587/593 passing (up from
191/593 post-merge and 492/585 pre-merge) — the surviving 6 failures are
legitimate pre-existing test mismatches (illegal return/break/continue,
parseFloat float vs rational, escaped backtick).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-13 08:38:47 +00:00
parent 480462646d
commit a7665a7b25

View File

@@ -1593,6 +1593,36 @@
param-syms
(list (js-sym "js-async-wrap") (list (js-sym "fn") (list) body-tr))))))
(define
js-internal-key?
(fn
(k)
(and
(string? k)
(>= (len k) 4)
(= (substring k 0 2) "__")
(= (substring k (- (len k) 2) (len k)) "__"))))
(define
js-display
(fn
(val)
(cond
((dict? val)
(let
((cleaned (dict)))
(begin
(for-each
(fn
(k)
(when
(not (js-internal-key? k))
(dict-set! cleaned k (js-display (get val k)))))
(keys val))
cleaned)))
((list? val) (map js-display val))
(else val))))
(define
js-eval
(fn
@@ -1600,6 +1630,6 @@
(let
((result (eval-expr (list (quote let) (list (list (js-sym "this") (list (js-sym "js-this")))) (js-transpile (js-parse (js-tokenize src)))))))
(js-drain-microtasks!)
result)))
(js-display result))))
(define js-compile-expr (fn (src) (js-transpile (js-parse-expr src))))