host: ring-core enablement part 2 — class tokens, vendored spork/http, reader-draining slurp

Class names evaluate to their canonical class-name STRINGS (the same values
class returns), so a (defmulti m (comp class :body)) matches (defmethod m
String ...) — ring.util.request dispatches exactly this way. Constructor
sugar and the new special form resolve the actual ctor from the registry
when given a token; dispatch-only names (InputStream, File, ISeq, ...) are
interned for defmethod position. nil is a legal multimethod dispatch value
now (sentinel-keyed: janet tables drop nil keys) — ring keys body-string's
no-body case on it.

spork/http is VENDORED (vendor/spork/http.janet, MIT) and baked into the
image, reaching the jolt layer as janet.spork.http/* through the janet.*
bridge — whose lookup is now a chain (runtime fiber env, module env, the
vendored registry), which also fixes janet/* resolution inside net/server
connection fibers (they carry a foreign env). jolt.http is rewritten over
the spork client (its old net/request never existed; also fixes its own
get shadowing clojure.core/get).

Also: slurp accepts opts and DRAINS reader shims (ring middleware slurps
request bodies), clojure.string/replace takes fn replacements with Clojure's
match-or-groups argument, .indexOf int needles are char codes, .getBytes on
the String surface, and ^bytes-style return hints on param vectors parse
(the fn macro unwraps the with-meta form).

Suite steady at 4715/5348; conformance x3 green; deps-conformance medley +
cuerdas green (the stuartsierra/dependency failure predates this change).
This commit is contained in:
Yogthos 2026-06-11 19:50:52 -04:00
parent 7c26a182e8
commit 8212bc76f7
7 changed files with 679 additions and 31 deletions

View file

@ -163,3 +163,26 @@
"(do (defprotocol Ps (ps [x])) (extend-protocol Ps Map (ps [m] :map) Object (ps [o] :obj)) (ps (sorted-map 1 2)))"]
["reduce over reified IReduceInit" "42"
"(reduce + 0 (reify clojure.lang.IReduceInit (reduce [_ f init] (f (f init 40) 2))))"])
# ring-core enablement, part 2: class-name symbols evaluate to canonical
# class-name strings (so class-dispatch defmultis match), ctor sugar still
# constructs, type-hinted param vectors parse, slurp drains reader shims,
# str/replace takes fn replacements, and int needles are char codes.
(defspec "host-interop / class tokens & readers"
["class name evaluates to canonical string" "\"java.lang.String\"" "String"]
["dispatch-only class name" "\"java.io.InputStream\"" "InputStream"]
["(class x) matches the token" "true" "(= String (class \"abc\"))"]
["defmulti on class dispatches" ":str"
"(do (defmulti cm (fn [x] (class x))) (defmethod cm String [x] :str) (cm \"a\"))"]
["defmethod on nil dispatch value" ":nil"
"(do (defmulti cn (fn [x] (class x))) (defmethod cn nil [x] :nil) (defmethod cn String [x] :str) (cn nil))"]
["ctor sugar still constructs" "\"x\"" "(.toString (StringBuilder. \"x\"))"]
["return-hinted defn parses" "7" "(do (defn- hb ^bytes [b] b) (hb 7))"]
["hinted multi-arity parses" ":two" "((fn ([x] :one) (^String [x y] :two)) 1 2)"]
["slurp drains a StringReader" "\"a=1\"" "(slurp (StringReader. \"a=1\"))"]
["slurp accepts :encoding opts" "\"b\"" "(slurp (StringReader. \"b\") :encoding \"UTF-8\")"]
["replace with fn replacement is literal" "\"$0\""
"(do (require (quote [clojure.string :as s9])) (s9/replace \"x\" #\".\" (fn [m] \"$0\")))"]
["replace fn gets group vector" "\"v=k\""
"(do (require (quote [clojure.string :as s9])) (s9/replace \"k=v\" #\"(\\w+)=(\\w+)\" (fn [[_ k v]] (str v \"=\" k))))"]
["indexOf int needle is a char code" "1" "(.indexOf \"a=b\" 61)"])