edn: clean exception for an unknown reader tag

clojure.edn's __read-tagged seam called (empty-pmap) — applying the empty-pmap
VALUE as a procedure — so an unknown tag (e.g. #object[...] from a JVM-printed
object, or any unregistered #foo) crashed the Chez VM with "attempt to apply
non-procedure" and surfaced a malformed condition (class :object, nil message)
instead of a catchable error.

Throw a clean ex-info naming the tag, matching the JVM's "No reader function
for tag <tag>". A reader port over edn (transit-jolt's read-conformance skip
path, aero, etc.) now catches a real exception instead of aborting.

clojure.core/read-string stays lenient (returns the tagged form) so clojure.edn
can apply :readers / :default before falling through to this throw.
This commit is contained in:
Yogthos 2026-06-24 23:09:07 -04:00
parent 9c48440a43
commit fb2749ac4c
2 changed files with 10 additions and 2 deletions

View file

@ -645,8 +645,13 @@
(cond
((eq? tag (keyword #f "#uuid")) (jolt-uuid-from-string form))
((eq? tag (keyword #f "#inst")) (jolt-inst-from-string form))
(else (jolt-throw (jolt-ex-info (string-append "No reader function for tag " (jolt-pr-str tag))
(empty-pmap))))))
;; No registered reader: throw a clean, catchable ex-info naming the tag, like
;; the JVM's "No reader function for tag foobar" (empty-pmap is a VALUE — the
;; old (empty-pmap) applied it as a procedure and crashed the Chez VM).
(else (let* ((nm (keyword-t-name tag))
(bare (if (and (> (string-length nm) 0) (char=? (string-ref nm 0) #\#))
(substring nm 1 (string-length nm)) nm)))
(jolt-throw (jolt-ex-info (string-append "No reader function for tag " bare) empty-pmap))))))
(def-var! "clojure.core" "read-string" jolt-read-string)
(def-var! "clojure.core" "__parse-next" jolt-parse-next)