HS: fetch JSON unwrap (+4 tests)

Adds hs-host-to-sx to convert raw host-handle JS objects/arrays returned by
json-parse or io-fetch into proper SX dicts/lists. hs-fetch now calls it on
the result when format is "json". Detects host handles via absence of the
internal `_type` marker, then walks Object.keys / Array items recursively.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-23 21:25:03 +00:00
parent ebaec1659e
commit 39a597e9b6
2 changed files with 126 additions and 14 deletions

View File

@@ -687,14 +687,70 @@
(dom-insert-adjacent-html target "beforeend" (str value))) (dom-insert-adjacent-html target "beforeend" (str value)))
(true nil))))) (true nil)))))
;; Property-based is — check obj.key truthiness ;; Property-based is — check obj.key truthiness
(define
hs-host-to-sx
(fn
(v)
(cond
((nil? v) v)
((number? v) v)
((string? v) v)
((boolean? v) v)
(true
(let
((marker (host-get v "_type")))
(cond
((= marker "dict")
(let
((out (dict)))
(begin
(for-each
(fn (k) (dict-set! out k (hs-host-to-sx (get v k))))
(keys v))
out)))
((= marker "list") (map hs-host-to-sx v))
(true
(let
((is-array (host-call (host-global "Array") "isArray" v)))
(if
is-array
(let
((len (host-get v "length")) (out (list)))
(begin
(let
((i 0))
(for-each
(fn
(_)
(begin
(set!
out
(append
out
(list (hs-host-to-sx (host-get v i)))))
(set! i (+ i 1))))
(range 0 len)))
out))
(let
((out (dict)))
(begin
(for-each
(fn
(k)
(dict-set! out k (hs-host-to-sx (host-get v k))))
(host-call (host-global "Object") "keys" v))
out)))))))))))
;; Array slicing (inclusive both ends)
(define (define
hs-fetch hs-fetch
(fn (fn
(url format) (url format)
(let (let
((fmt (cond ((nil? format) "text") ((or (= format "JSON") (= format "json") (= format "Object") (= format "object")) "json") ((or (= format "HTML") (= format "html")) "html") ((or (= format "Response") (= format "response")) "response") ((or (= format "Text") (= format "text")) "text") (true format)))) ((fmt (cond ((nil? format) "text") ((or (= format "json") (= format "JSON") (= format "Object")) "json") ((or (= format "html") (= format "HTML")) "html") ((or (= format "response") (= format "Response")) "response") ((or (= format "text") (= format "Text")) "text") (true format))))
(perform (list "io-fetch" url fmt))))) (let
;; Array slicing (inclusive both ends) ((raw (perform (list "io-fetch" url fmt))))
(cond ((= fmt "json") (hs-host-to-sx raw)) (true raw))))))
;; Collection: sorted by
(define (define
hs-json-escape hs-json-escape
(fn (fn
@@ -725,7 +781,7 @@
(walk) (walk)
out) out)
"\""))) "\"")))
;; Collection: sorted by ;; Collection: sorted by descending
(define (define
hs-json-stringify hs-json-stringify
(fn (fn
@@ -749,7 +805,7 @@
(keys v))) (keys v)))
"}")) "}"))
(true (hs-json-escape (str v)))))) (true (hs-json-escape (str v))))))
;; Collection: sorted by descending ;; Collection: split by
(define (define
hs-coerce hs-coerce
(fn (fn
@@ -856,7 +912,7 @@
(map (fn (k) (list k (get value k))) (keys value)) (map (fn (k) (list k (get value k))) (keys value))
value)) value))
(true value)))) (true value))))
;; Collection: split by ;; Collection: joined by
(define (define
hs-gather-form-nodes hs-gather-form-nodes
(fn (fn
@@ -890,7 +946,7 @@
(each 0))))))))) (each 0)))))))))
(walk root) (walk root)
acc))) acc)))
;; Collection: joined by
(define (define
hs-values-from-nodes hs-values-from-nodes
(fn (nodes) (reduce hs-values-absorb (dict) nodes))) (fn (nodes) (reduce hs-values-absorb (dict) nodes)))

View File

@@ -687,14 +687,70 @@
(dom-insert-adjacent-html target "beforeend" (str value))) (dom-insert-adjacent-html target "beforeend" (str value)))
(true nil))))) (true nil)))))
;; Property-based is — check obj.key truthiness ;; Property-based is — check obj.key truthiness
(define
hs-host-to-sx
(fn
(v)
(cond
((nil? v) v)
((number? v) v)
((string? v) v)
((boolean? v) v)
(true
(let
((marker (host-get v "_type")))
(cond
((= marker "dict")
(let
((out (dict)))
(begin
(for-each
(fn (k) (dict-set! out k (hs-host-to-sx (get v k))))
(keys v))
out)))
((= marker "list") (map hs-host-to-sx v))
(true
(let
((is-array (host-call (host-global "Array") "isArray" v)))
(if
is-array
(let
((len (host-get v "length")) (out (list)))
(begin
(let
((i 0))
(for-each
(fn
(_)
(begin
(set!
out
(append
out
(list (hs-host-to-sx (host-get v i)))))
(set! i (+ i 1))))
(range 0 len)))
out))
(let
((out (dict)))
(begin
(for-each
(fn
(k)
(dict-set! out k (hs-host-to-sx (host-get v k))))
(host-call (host-global "Object") "keys" v))
out)))))))))))
;; Array slicing (inclusive both ends)
(define (define
hs-fetch hs-fetch
(fn (fn
(url format) (url format)
(let (let
((fmt (cond ((nil? format) "text") ((or (= format "JSON") (= format "json") (= format "Object") (= format "object")) "json") ((or (= format "HTML") (= format "html")) "html") ((or (= format "Response") (= format "response")) "response") ((or (= format "Text") (= format "text")) "text") (true format)))) ((fmt (cond ((nil? format) "text") ((or (= format "json") (= format "JSON") (= format "Object")) "json") ((or (= format "html") (= format "HTML")) "html") ((or (= format "response") (= format "Response")) "response") ((or (= format "text") (= format "Text")) "text") (true format))))
(perform (list "io-fetch" url fmt))))) (let
;; Array slicing (inclusive both ends) ((raw (perform (list "io-fetch" url fmt))))
(cond ((= fmt "json") (hs-host-to-sx raw)) (true raw))))))
;; Collection: sorted by
(define (define
hs-json-escape hs-json-escape
(fn (fn
@@ -725,7 +781,7 @@
(walk) (walk)
out) out)
"\""))) "\"")))
;; Collection: sorted by ;; Collection: sorted by descending
(define (define
hs-json-stringify hs-json-stringify
(fn (fn
@@ -749,7 +805,7 @@
(keys v))) (keys v)))
"}")) "}"))
(true (hs-json-escape (str v)))))) (true (hs-json-escape (str v))))))
;; Collection: sorted by descending ;; Collection: split by
(define (define
hs-coerce hs-coerce
(fn (fn
@@ -856,7 +912,7 @@
(map (fn (k) (list k (get value k))) (keys value)) (map (fn (k) (list k (get value k))) (keys value))
value)) value))
(true value)))) (true value))))
;; Collection: split by ;; Collection: joined by
(define (define
hs-gather-form-nodes hs-gather-form-nodes
(fn (fn
@@ -890,7 +946,7 @@
(each 0))))))))) (each 0)))))))))
(walk root) (walk root)
acc))) acc)))
;; Collection: joined by
(define (define
hs-values-from-nodes hs-values-from-nodes
(fn (nodes) (reduce hs-values-absorb (dict) nodes))) (fn (nodes) (reduce hs-values-absorb (dict) nodes)))