sx: step 11 — migrate prolog hook + add worker plugin

Move `hs-prolog-hook` / `hs-set-prolog-hook!` / `prolog` out of
`lib/hyperscript/runtime.sx` into a self-contained plugin file at
`lib/hyperscript/plugins/prolog.sx`. The API surface is preserved —
`lib/prolog/hs-bridge.sx::pl-install-hs-hook!` still calls
`hs-set-prolog-hook!` exactly as before, just resolved to the plugin
file's binding rather than runtime.sx's.

Move the E39 worker stub registration out of `lib/hyperscript/parser.sx`
into `lib/hyperscript/plugins/worker.sx`. The plugin calls
`(hs-register-feature! "worker" ...)` at file load time. Behaviour is
identical — `worker MyWorker ...` raises the same helpful "plugin not
installed" error, just routed through the registry from a separate
file. The pre-existing `behavioral` test for the helpful error
("raises a helpful error when the worker plugin is not installed")
still passes via the new path.

Wire-up:
- OCaml `bin/run_tests.ml`: load `plugins/worker.sx` and
  `plugins/prolog.sx` after `runtime.sx`, before `integration.sx`.
- JS `tests/hs-kernel-eval.js`: extend HS module list with
  `hs-worker` / `hs-prolog`; add `HS_PLUGINS` resolver branch so the
  `hs-` prefix maps to `lib/hyperscript/plugins/`.
- WASM `hosts/ocaml/browser/bundle.sh`: copy plugin files into
  `dist/sx/hs-<name>.sx`.
- WASM `hosts/ocaml/browser/compile-modules.js`: add `hs-worker` /
  `hs-prolog` to `FILES`, `HS_DEPS`, and `HS_LAZY` so the lazy loader
  resolves them on first reference.
- Worker plugin carries a sentinel `(define hs-worker-loaded? true)`
  so `extractDefines` indexes it in the module manifest (the lazy
  loader skips files with no defines).

Mirrors `shared/static/wasm/sx/hs-{parser,runtime}.sx` are byte-identical
to source; new mirrors `hs-{prolog,worker}.sx` written via sx_write_file.

OCaml: 4545 passed, 1339 failed — matches baseline.
JS: 2591 passed, 2465 failed — matches baseline.
Smoke tests: `(prolog ...)` raises "prolog hook not installed" cleanly,
`(hs-set-prolog-hook! ...)` then `(prolog ...)` returns the hook result,
`(hs-compile "worker MyWorker def noop() end end")` raises the worker
stub error via the registry path.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-07 01:20:32 +00:00
parent c08e217e2a
commit 6328b810bd
21 changed files with 492 additions and 106 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -3373,9 +3373,6 @@
(hs-register-feature!
"when"
(fn (ctx) (begin ((dict-get ctx :adv!)) ((dict-get ctx :parse-when-feat)))))
(hs-register-feature!
"worker"
(fn (ctx) (error "worker plugin is not installed — see https://hyperscript.org/features/worker")))
(hs-register-feature!
"bind"
(fn (ctx) (begin ((dict-get ctx :adv!)) ((dict-get ctx :parse-bind-feat)))))

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,24 @@
;; lib/hyperscript/plugins/prolog.sx — Prolog plugin
;;
;; Provides the `prolog` HS-level function. Replaces the ad-hoc
;; hs-prolog-hook / hs-set-prolog-hook! slots that previously lived in
;; lib/hyperscript/runtime.sx (nodes 140142 of the plugin design doc).
;;
;; Two-step wiring preserves the original API:
;; 1. lib/prolog/runtime.sx loaded → defines pl-query-one
;; 2. lib/prolog/hs-bridge.sx (or this file's auto-wire) calls
;; (hs-set-prolog-hook! (fn (db goal) (not (= nil (pl-query-one db goal)))))
;; If neither is loaded, calling (prolog db goal) raises a clear error.
(define hs-prolog-hook nil)
(define hs-set-prolog-hook! (fn (f) (set! hs-prolog-hook f)))
(define
prolog
(fn
(db goal)
(if
(nil? hs-prolog-hook)
(raise "prolog hook not installed")
(hs-prolog-hook db goal))))

View File

@@ -0,0 +1,3 @@
(sxbc 1 "b07521593ca7ed98"
(code
:constants ("hs-prolog-hook" "hs-set-prolog-hook!" {:upvalue-count nil :arity nil :constants ("hs-prolog-hook") :bytecode (nil nil nil nil nil nil)} "prolog" {:upvalue-count nil :arity nil :constants ("nil?" "hs-prolog-hook" "prolog hook not installed") :bytecode (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)}) :bytecode (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)))

View File

@@ -12,29 +12,6 @@
;; Register an event listener. Returns unlisten function.
;; (hs-on target event-name handler) → unlisten-fn
(begin
(define _hs-config-log-all false)
(define _hs-log-captured (list))
(define
hs-set-log-all!
(fn (flag) (set! _hs-config-log-all (if flag true false))))
(define hs-get-log-captured (fn () _hs-log-captured))
(define
hs-clear-log-captured!
(fn () (begin (set! _hs-log-captured (list)) nil)))
(define
hs-log-event!
(fn
(msg)
(when
_hs-config-log-all
(begin
(set! _hs-log-captured (append _hs-log-captured (list msg)))
(host-call (host-global "console") "log" msg)
nil)))))
;; Register for every occurrence (no queuing — each fires independently).
;; Stock hyperscript queues by default; "every" disables queuing.
(define
hs-each
(fn
@@ -45,6 +22,12 @@
;; (hs-init thunk) — called at element boot time
(define meta (host-new "Object"))
;; Run an initializer function immediately.
;; (hs-init thunk) — called at element boot time
(define
hs-on-every
(fn (target event-name handler) (dom-listen target event-name handler)))
;; ── Async / timing ──────────────────────────────────────────────
;; Wait for a duration in milliseconds.
@@ -68,13 +51,20 @@
hs-on
(fn
(target event-name handler)
(let
((wrapped (fn (event) (do (host-set! meta "caller" _hs-on-caller) (host-set! meta "owner" target) (let ((__hs-no-stop false)) (guard (e ((and (not (= event-name "exception")) (not (= event-name "error"))) (do (when (and (list? e) (= (first e) "hs-halt-default")) (set! __hs-no-stop true)) (when (not __hs-no-stop) (dom-dispatch target "exception" {:error e})))) (true (raise e))) (handler event)) (when (not __hs-no-stop) (host-call event "stopPropagation")))))))
(when
(not (nil? target))
(let
((unlisten (dom-listen target event-name wrapped))
(prev (or (dom-get-data target "hs-unlisteners") (list))))
(dom-set-data target "hs-unlisteners" (append prev (list unlisten)))
unlisten))))
((me-el (host-get (host-global "window") "__hs_current_me")))
(let
((wrapped (fn (event) (when (not (and me-el (not (hs-ref-eq me-el target)) (nil? (host-get me-el "parentElement")))) (do (host-set! meta "caller" _hs-on-caller) (host-set! meta "owner" target) (let ((__hs-no-stop false)) (guard (e ((and (not (= event-name "exception")) (not (= event-name "error"))) (do (when (and (list? e) (= (first e) "hs-halt-default")) (set! __hs-no-stop true)) (when (not __hs-no-stop) (dom-dispatch target "exception" {:error e})))) (true (raise e))) (handler event)) (when (not __hs-no-stop) (host-call event "stopPropagation"))))))))
(let
((unlisten (dom-listen target event-name wrapped))
(prev (or (dom-get-data target "hs-unlisteners") (list))))
(dom-set-data
target
"hs-unlisteners"
(append prev (list unlisten)))
unlisten))))))
;; Wait for CSS transitions/animations to settle on an element.
(define
@@ -279,7 +269,8 @@
(when with-cls (dom-remove-class target with-cls))))
(let
((attr-val (if (> (len extra) 0) (first extra) nil))
(with-val (if (> (len extra) 1) (nth extra 1) nil)))
(with-val
(if (> (len extra) 1) (nth extra 1) nil)))
(do
(for-each
(fn
@@ -503,7 +494,10 @@
((i (if (< idx 0) (+ n idx) idx)))
(cond
((or (< i 0) (>= i n)) target)
(true (concat (slice target 0 i) (slice target (+ i 1) n))))))
(true
(concat
(slice target 0 i)
(slice target (+ i 1) n))))))
(do
(when
target
@@ -603,6 +597,11 @@
((w (host-global "window")))
(if w (if (host-call w "confirm" msg) yes-val no-val) no-val))))
;; ── Transition ──────────────────────────────────────────────────
;; Transition a CSS property to a value, optionally with duration.
;; (hs-transition target prop value duration)
(define
hs-answer-alert
(fn
@@ -993,7 +992,7 @@
(host-get value "outerHTML")
(str value))))
(true nil)))))
;; Collection: joined by
(define
hs-sender
(fn
@@ -1210,7 +1209,14 @@
((= type-name "Array") (if (list? value) value (list value)))
((= type-name "HTML")
(cond
((list? value) (join "" (map (fn (x) (str x)) value)))
((list? value)
(join
""
(map
(fn
(x)
(if (hs-element? x) (host-get x "outerHTML") (str x)))
value)))
((hs-element? value) (host-get value "outerHTML"))
(true (str value))))
((= type-name "JSON")
@@ -1261,7 +1267,25 @@
((factor (pow 10 digits)))
(str (/ (floor (+ (* num factor) 0.5)) factor))))))
((= type-name "Selector") (str value))
((= type-name "Fragment") value)
((= type-name "Fragment")
(let
((frag (host-call (dom-document) "createDocumentFragment")))
(do
(for-each
(fn
(item)
(if
(hs-element? item)
(dom-append frag item)
(let
((tmp (dom-create-element "div")))
(do
(dom-set-inner-html tmp (str item))
(for-each
(fn (k) (dom-append frag k))
(host-get tmp "children"))))))
(if (list? value) value (list value)))
frag)))
((= type-name "Values") (hs-as-values value))
((= type-name "Keys")
(if
@@ -1599,10 +1623,14 @@
((ch (substring sel i (+ i 1))))
(cond
((= ch ".")
(do (flush!) (set! mode "class") (walk (+ i 1))))
(do
(flush!)
(set! mode "class")
(walk (+ i 1))))
((= ch "#")
(do (flush!) (set! mode "id") (walk (+ i 1))))
(true (do (set! cur (str cur ch)) (walk (+ i 1)))))))))
(true
(do (set! cur (str cur ch)) (walk (+ i 1)))))))))
(walk 0)
(flush!)
{:tag tag :classes classes :id id}))))
@@ -1700,6 +1728,7 @@
hs-strict-eq
(fn (a b) (and (= (type-of a) (type-of b)) (= a b))))
(define
hs-id=
(fn
@@ -1776,7 +1805,10 @@
((and (dict? a) (dict? b))
(let
((pos (host-call a "compareDocumentPosition" b)))
(if (number? pos) (not (= 0 (mod (/ pos 4) 2))) false)))
(if
(number? pos)
(not (= 0 (mod (/ pos 4) 2)))
false)))
(true (< (str a) (str b))))))
(define
@@ -1897,7 +1929,10 @@
((and (dict? a) (dict? b))
(let
((pos (host-call a "compareDocumentPosition" b)))
(if (number? pos) (not (= 0 (mod (/ pos 4) 2))) false)))
(if
(number? pos)
(not (= 0 (mod (/ pos 4) 2)))
false)))
(true (< (str a) (str b))))))
(define
@@ -1950,7 +1985,9 @@
(define
hs-morph-char
(fn (s p) (if (or (< p 0) (>= p (string-length s))) nil (nth s p))))
(fn
(s p)
(if (or (< p 0) (>= p (string-length s))) nil (nth s p))))
(define
hs-morph-index-from
@@ -1978,7 +2015,10 @@
(q)
(let
((c (hs-morph-char s q)))
(if (and c (< (index-of stop c) 0)) (loop (+ q 1)) q))))
(if
(and c (< (index-of stop c) 0))
(loop (+ q 1))
q))))
(let ((e (loop p))) (list (substring s p e) e))))
(define
@@ -2020,7 +2060,9 @@
(append
acc
(list
(list name (substring s (+ p4 1) close)))))))
(list
name
(substring s (+ p4 1) close)))))))
((= c2 "'")
(let
((close (hs-morph-index-from s "'" (+ p4 1))))
@@ -2030,7 +2072,9 @@
(append
acc
(list
(list name (substring s (+ p4 1) close)))))))
(list
name
(substring s (+ p4 1) close)))))))
(true
(let
((r2 (hs-morph-read-until s p4 " \t\n/>")))
@@ -2114,7 +2158,9 @@
(for-each
(fn
(c)
(when (> (string-length c) 0) (dom-add-class el c)))
(when
(> (string-length c) 0)
(dom-add-class el c)))
(split v " ")))
((and keep-id (= n "id")) nil)
(true (dom-set-attr el n v)))))
@@ -2215,7 +2261,8 @@
((parts (split resolved ":")))
(let
((prop (first parts))
(val (if (> (len parts) 1) (nth parts 1) nil)))
(val
(if (> (len parts) 1) (nth parts 1) nil)))
(cond
((and (not (= prop "display")) (not (= prop "opacity")) (not (= prop "visibility")) (not (= prop "hidden")) (not (= prop "class-hidden")) (not (= prop "class-invisible")) (not (= prop "class-opacity")) (not (= prop "details")) (not (= prop "dialog")) (dict-has? _hs-hide-strategies prop))
(let
@@ -2255,7 +2302,8 @@
((parts (split resolved ":")))
(let
((prop (first parts))
(val (if (> (len parts) 1) (nth parts 1) nil)))
(val
(if (> (len parts) 1) (nth parts 1) nil)))
(cond
((and (not (= prop "display")) (not (= prop "opacity")) (not (= prop "visibility")) (not (= prop "hidden")) (not (= prop "class-hidden")) (not (= prop "class-invisible")) (not (= prop "class-opacity")) (not (= prop "details")) (not (= prop "dialog")) (dict-has? _hs-hide-strategies prop))
(let
@@ -2360,10 +2408,14 @@
(if
(= depth 1)
j
(find-close (+ j 1) (- depth 1)))
(find-close
(+ j 1)
(- depth 1)))
(if
(= (nth raw j) "{")
(find-close (+ j 1) (+ depth 1))
(find-close
(+ j 1)
(+ depth 1))
(find-close (+ j 1) depth))))))
(let
((close (find-close start 1)))
@@ -2474,7 +2526,10 @@
(if
(= (len lst) 0)
-1
(if (= (first lst) item) i (idx-loop (rest lst) (+ i 1))))))
(if
(= (first lst) item)
i
(idx-loop (rest lst) (+ i 1))))))
(idx-loop obj 0)))
(true
(let
@@ -2566,7 +2621,8 @@
(cond
((= end "hs-pick-end") n)
((= end "hs-pick-start") 0)
((and (number? end) (< end 0)) (max 0 (+ n end)))
((and (number? end) (< end 0))
(max 0 (+ n end)))
(true end))))
(cond
((string? col) (slice col s e))
@@ -2877,7 +2933,9 @@
((results (hs-query-all selector)))
(if
(and
(or (nil? results) (and (list? results) (= (len results) 0)))
(or
(nil? results)
(and (list? results) (= (len results) 0)))
(string? selector)
(> (len selector) 0)
(= (substring selector 0 1) "#"))
@@ -2902,21 +2960,27 @@
(if
fn
(let
((result (host-call-fn fn args)))
((result (host-call-fn-raising fn args)))
(if
(= (host-typeof result) "promise")
(let
((state (host-promise-state result)))
(= result "__hs_js_throw__")
(raise (host-take-js-throw))
(if
(= result "__hs_async_error__")
(raise "__hs_async_error__")
(if
(and state (= (host-get state "ok") false))
(do
(host-set!
(host-global "window")
"__hs_async_error"
(host-get state "value"))
(raise "__hs_async_error__"))
(if state (host-get state "value") result)))
result))
(= (host-typeof result) "promise")
(let
((state (host-promise-state result)))
(if
(and state (= (host-get state "ok") false))
(do
(host-set!
(host-global "window")
"__hs_async_error"
(host-get state "value"))
(raise "__hs_async_error__"))
(if state (host-get state "value") result)))
result))))
(let
((msg (str "'" fn-name "' is null")))
(host-set! (host-global "window") "_hs_null_error" msg)
@@ -3138,3 +3202,98 @@
(define hs-token-value (fn (tok) (dict-get tok :value)))
(define hs-token-op? (fn (tok) (dict-get tok :op)))
(define
hs-try-json-parse
(fn (data) (if (string? data) (guard (_e nil) (json-parse data)) nil)))
(define
hs-socket-normalise-url
(fn
(url)
(if
(or (starts-with? url "ws://") (starts-with? url "wss://"))
url
(let
((proto (host-get (host-global "location") "protocol"))
(host-str (host-get (host-global "location") "host")))
(let
((scheme (if (= proto "https:") "wss://" "ws://")))
(str scheme host-str url))))))
(define
hs-socket-bind-name!
(fn
(name-path wrapper)
(let
((win (host-global "window")))
(if
(= (len name-path) 1)
(host-set! win (first name-path) wrapper)
(do
(when
(nil? (host-get win (first name-path)))
(host-set! win (first name-path) (host-new "Object")))
(host-set!
(host-get win (first name-path))
(nth name-path 1)
wrapper))))))
(define
hs-socket-resolve-rpc!
(fn
(wrapper data)
(let
((iid (host-get data "iid")))
(when
(not (nil? iid))
(let
((pending (host-get wrapper "_pending")))
(when
(not (nil? pending))
(let
((entry (host-get pending iid)))
(when
(not (nil? entry))
(host-set! pending iid nil)
(if
(not (nil? (host-get data "throw")))
(host-call-fn
(host-get entry "reject")
(list (host-get data "throw")))
(host-call-fn
(host-get entry "resolve")
(list (host-get data "return"))))))))))))
(define
hs-socket-register!
(fn
(name-path url timeout on-message-handler json?)
(let
((norm-url (hs-socket-normalise-url url)))
(let
((wrapper (host-new "Object")))
(do
(host-set! wrapper "_url" norm-url)
(host-set! wrapper "_timeout" (if (nil? timeout) 0 timeout))
(host-set! wrapper "_pending" (host-new "Object"))
(host-set! wrapper "_closed" false)
(let
((ws (host-new "WebSocket" norm-url)))
(do
(host-set! wrapper "_ws" ws)
(let
((msg-handler (host-callback (fn (evt) (do (let ((parsed (hs-try-json-parse (host-get evt "data")))) (when (and (not (nil? parsed)) (not (nil? (host-get parsed "iid")))) (hs-socket-resolve-rpc! wrapper parsed))) (when (not (nil? on-message-handler)) (if json? (let ((data (hs-try-json-parse (host-get evt "data")))) (when (not (nil? data)) (on-message-handler data))) (on-message-handler evt))))))))
(do
(host-set! ws "onmessage" msg-handler)
(host-set! wrapper "_onmessage_handler" msg-handler)
(host-set!
ws
"onclose"
(host-callback
(fn (e) (host-set! wrapper "_closed" true))))
(host-call-fn
(host-global "_hsSetupSocket")
(list wrapper))
(hs-socket-bind-name! name-path wrapper)
wrapper)))))))))

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,19 @@
;; lib/hyperscript/plugins/worker.sx — Worker plugin (stub)
;;
;; Phase 1 of the worker plugin: the registration formerly inlined in
;; lib/hyperscript/parser.sx (E39 stub) moves here. Behaviour is
;; identical — `worker MyWorker ...` raises a helpful error directing
;; users to the full plugin (not yet implemented).
;;
;; Phase 2 (future) replaces this stub with parse-worker-feat, a
;; compiler entry, hs-worker-define!, and the postMessage-based
;; method dispatch documented in plans/designs/hs-plugin-system.md §4a.
(define hs-worker-loaded? true)
(hs-register-feature!
"worker"
(fn
(ctx)
(error
"worker plugin is not installed — see https://hyperscript.org/features/worker")))

View File

@@ -0,0 +1,3 @@
(sxbc 1 "857de8641ad2e912"
(code
:constants ("hs-worker-loaded?" "hs-register-feature!" "worker" {:upvalue-count nil :arity nil :constants ("error" "worker plugin is not installed — see https://hyperscript.org/features/worker") :bytecode (nil nil nil nil nil nil nil nil)}) :bytecode (nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil)))

View File

@@ -946,9 +946,12 @@
"hs-ident-start?",
"hs-ident-char?",
"hs-ws?",
"hs-hex-digit?",
"hs-hex-val",
"hs-keywords",
"hs-keyword?",
"hs-tokenize"
"hs-tokenize",
"hs-tokenize-template"
]
},
"hs-parser": {
@@ -958,7 +961,9 @@
],
"exports": [
"hs-parse",
"hs-compile"
"hs-span-mode",
"hs-compile",
"hs-parse-ast"
]
},
"hs-compiler": {
@@ -969,6 +974,7 @@
],
"exports": [
"hs-to-sx",
"hs-receiver-selector",
"hs-to-sx-from-source"
]
},
@@ -981,30 +987,50 @@
],
"exports": [
"hs-each",
"meta",
"hs-on-every",
"_hs-on-caller",
"hs-on",
"hs-on-every",
"hs-on-intersection-attach!",
"hs-on-mutation-attach!",
"hs-init",
"hs-wait",
"hs-wait-for",
"hs-settle",
"hs-toggle-class!",
"hs-toggle-var-cycle!",
"hs-toggle-between!",
"hs-toggle-style!",
"hs-toggle-style-between!",
"hs-toggle-style-cycle!",
"hs-take!",
"hs-put!",
"hs-add-to!",
"hs-remove-from!",
"hs-splice-at!",
"hs-index",
"hs-put-at!",
"hs-dict-without",
"hs-set-on!",
"hs-navigate!",
"hs-ask",
"hs-answer",
"hs-answer-alert",
"hs-scroll!",
"hs-halt!",
"hs-select!",
"hs-get-selection",
"hs-reset!",
"hs-next",
"hs-previous",
"_hs-last-query-sel",
"hs-null-raise!",
"hs-empty-raise!",
"hs-query-all-checked",
"hs-dispatch!",
"hs-query-all",
"hs-query-all-in",
"hs-list-set",
"hs-to-number",
"hs-query-first",
"hs-query-last",
"hs-first",
@@ -1014,44 +1040,150 @@
"hs-repeat-while",
"hs-repeat-until",
"hs-for-each",
"hs-sender",
"hs-host-to-sx",
"hs-fetch-impl",
"hs-fetch",
"hs-fetch-no-throw",
"hs-json-escape",
"hs-json-stringify",
"hs-coerce",
"hs-gather-form-nodes",
"hs-values-from-nodes",
"hs-value-of-node",
"hs-select-multi-values",
"hs-values-absorb",
"hs-as-values",
"hs-default?",
"hs-array-set!",
"hs-add",
"hs-make",
"hs-install",
"hs-measure",
"hs-transition",
"hs-transition-from",
"hs-type-check",
"hs-type-check-strict",
"hs-strict-eq",
"hs-id=",
"hs-eq-ignore-case",
"hs-starts-with?",
"hs-ends-with?",
"hs-scoped-set!",
"hs-scoped-get",
"hs-precedes?",
"hs-follows?",
"hs-starts-with-ic?",
"hs-ends-with-ic?",
"hs-matches-ignore-case?",
"hs-contains-ignore-case?",
"hs-falsy?",
"hs-matches?",
"hs-contains?",
"hs-in?",
"hs-in-bool?",
"hs-is",
"precedes?",
"hs-empty?",
"hs-empty-like",
"hs-empty-target!",
"hs-morph-char",
"hs-morph-index-from",
"hs-morph-sws",
"hs-morph-read-until",
"hs-morph-parse-attrs",
"hs-morph-parse-element",
"hs-morph-parse-children",
"hs-morph-apply-attrs",
"hs-morph-build-children",
"hs-morph-build-child",
"hs-morph!",
"hs-open!",
"hs-close!",
"hs-hide!",
"hs-show!",
"hs-show-when!",
"hs-hide-when!",
"hs-first",
"hs-last",
"hs-template",
"hs-make-object",
"hs-strip-order-deep",
"hs-method-call",
"hs-beep",
"hs-prop-is",
"hs-slice",
"hs-pick-first",
"hs-pick-last",
"hs-pick-random",
"hs-pick-items",
"hs-pick-match",
"hs-pick-matches",
"hs-sorted-by",
"hs-sorted-by-desc",
"hs-split-by",
"hs-joined-by",
"hs-sorted-by",
"hs-sorted-by-desc"
"hs-sorted-by",
"hs-sorted-by-desc",
"hs-dom-has-var?",
"hs-dom-get-var-raw",
"hs-dom-set-var-raw!",
"hs-dom-resolve-start",
"hs-dom-walk",
"hs-dom-find-owner",
"hs-dom-get",
"hs-dom-set!",
"_hs-dom-watchers",
"hs-dom-watch!",
"hs-dom-fire-watchers!",
"hs-null-error!",
"hs-named-target",
"hs-named-target-list",
"hs-query-named-all",
"hs-dom-is-ancestor?",
"hs-win-call",
"hs-source-for",
"hs-line-for",
"hs-node-get",
"hs-src",
"hs-src-at",
"hs-line-at",
"hs-js-exec",
"hs-raw->api-token",
"hs-eof-sentinel",
"hs-tokens-of",
"hs-stream-token",
"hs-stream-consume",
"hs-stream-has-more",
"hs-token-type",
"hs-token-value",
"hs-token-op?",
"hs-try-json-parse",
"hs-socket-normalise-url",
"hs-socket-bind-name!",
"hs-socket-resolve-rpc!",
"hs-socket-register!"
]
},
"hs-worker": {
"file": "hs-worker.sxbc",
"deps": [
"hs-tokenizer",
"hs-parser"
],
"exports": [
"hs-worker-loaded?"
]
},
"hs-prolog": {
"file": "hs-prolog.sxbc",
"deps": [
"hs-tokenizer",
"hs-parser",
"hs-compiler",
"hs-runtime"
],
"exports": [
"hs-prolog-hook",
"hs-set-prolog-hook!",
"prolog"
]
},
"hs-integration": {
@@ -1060,10 +1192,15 @@
"hs-tokenizer",
"hs-parser",
"hs-compiler",
"hs-runtime"
"hs-runtime",
"hs-worker",
"hs-prolog"
],
"exports": [
"hs-register-scripts!",
"hs-scripting-disabled?",
"hs-activate!",
"hs-deactivate!",
"hs-boot!",
"hs-boot-subtree!"
]
@@ -1075,6 +1212,8 @@
"hs-parser",
"hs-compiler",
"hs-runtime",
"hs-worker",
"hs-prolog",
"hs-integration"
],
"exports": [
@@ -1158,6 +1297,8 @@
"hs-parser",
"hs-compiler",
"hs-runtime",
"hs-worker",
"hs-prolog",
"hs-integration",
"hs-htmx"
]