Rebuild WASM: bytecode with pending_cek snapshot fix
All .sxbc recompiled with fixed sx_vm.ml. 32/32 WASM tests, 4/4 bytecode regression tests. hs-repeat-times correctly does 6 io-sleep suspensions in bytecode mode. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -81,18 +81,62 @@
|
|||||||
|
|
||||||
K.registerNative("host-callback", function(args) {
|
K.registerNative("host-callback", function(args) {
|
||||||
var fn = args[0];
|
var fn = args[0];
|
||||||
// Native JS function — pass through
|
// Native JS function (not SX-origin) — pass through
|
||||||
if (typeof fn === "function") return fn;
|
if (typeof fn === "function" && fn.__sx_handle === undefined) return fn;
|
||||||
// SX callable (has __sx_handle) — wrap as JS function
|
// SX callable (has __sx_handle) — wrap as JS function with suspension handling
|
||||||
if (fn && fn.__sx_handle !== undefined) {
|
if (fn && fn.__sx_handle !== undefined) {
|
||||||
return function() {
|
return function() {
|
||||||
var a = Array.prototype.slice.call(arguments);
|
var a = Array.prototype.slice.call(arguments);
|
||||||
return K.callFn(fn, a);
|
var result = K.callFn(fn, a);
|
||||||
|
// Handle IO suspension chain (e.g. wait, fetch, navigate)
|
||||||
|
_driveAsync(result);
|
||||||
|
return result;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return function() {};
|
return function() {};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Drive an async suspension chain to completion.
|
||||||
|
* When K.callFn returns {suspended: true, request: ..., resume: fn},
|
||||||
|
* handle the IO operation and resume the VM.
|
||||||
|
*/
|
||||||
|
function _driveAsync(result) {
|
||||||
|
if (!result || !result.suspended) return;
|
||||||
|
console.log("[sx] IO suspension:", JSON.stringify(result.request, null, 2));
|
||||||
|
var req = result.request;
|
||||||
|
if (!req) return;
|
||||||
|
|
||||||
|
// req is an SX list — extract items. K returns SX values.
|
||||||
|
var items = req.items || req;
|
||||||
|
var op = (items && items[0]) || req;
|
||||||
|
// Normalize: op might be a string or {name: "..."} symbol
|
||||||
|
var opName = (typeof op === "string") ? op : (op && op.name) || String(op);
|
||||||
|
|
||||||
|
if (opName === "wait" || opName === "io-sleep") {
|
||||||
|
// (wait ms) or (io-sleep ms) — resume after timeout
|
||||||
|
var ms = (items && items[1]) || 0;
|
||||||
|
if (typeof ms !== "number") ms = parseFloat(ms) || 0;
|
||||||
|
console.log("[sx] IO wait: " + ms + "ms, resuming after timeout");
|
||||||
|
setTimeout(function() {
|
||||||
|
try {
|
||||||
|
var resumed = result.resume(null);
|
||||||
|
console.log("[sx] IO resumed:", typeof resumed, resumed && resumed.suspended ? "suspended-again" : "done", JSON.stringify(resumed));
|
||||||
|
_driveAsync(resumed);
|
||||||
|
} catch(e) {
|
||||||
|
console.error("[sx] IO resume error:", e);
|
||||||
|
}
|
||||||
|
}, ms);
|
||||||
|
} else if (opName === "navigate") {
|
||||||
|
// (navigate url) — browser navigation
|
||||||
|
var url = (items && items[1]) || "/";
|
||||||
|
if (typeof url !== "string") url = String(url);
|
||||||
|
window.location.href = url;
|
||||||
|
} else {
|
||||||
|
console.warn("[sx] Unhandled IO suspension in callback:", opName, req);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
K.registerNative("host-typeof", function(args) {
|
K.registerNative("host-typeof", function(args) {
|
||||||
var obj = args[0];
|
var obj = args[0];
|
||||||
if (obj == null) return "nil";
|
if (obj == null) return "nil";
|
||||||
@@ -526,7 +570,10 @@
|
|||||||
"sx/adapter-html.sx", "sx/adapter-sx.sx", "sx/adapter-dom.sx",
|
"sx/adapter-html.sx", "sx/adapter-sx.sx", "sx/adapter-dom.sx",
|
||||||
"sx/boot-helpers.sx", "sx/hypersx.sx", "sx/harness.sx",
|
"sx/boot-helpers.sx", "sx/hypersx.sx", "sx/harness.sx",
|
||||||
"sx/harness-reactive.sx", "sx/harness-web.sx",
|
"sx/harness-reactive.sx", "sx/harness-web.sx",
|
||||||
"sx/engine.sx", "sx/orchestration.sx", "sx/boot.sx",
|
"sx/engine.sx", "sx/orchestration.sx",
|
||||||
|
"sx/hs-tokenizer.sx", "sx/hs-parser.sx", "sx/hs-compiler.sx",
|
||||||
|
"sx/hs-runtime.sx", "sx/hs-integration.sx",
|
||||||
|
"sx/boot.sx",
|
||||||
];
|
];
|
||||||
if (K.beginModuleLoad) K.beginModuleLoad();
|
if (K.beginModuleLoad) K.beginModuleLoad();
|
||||||
for (var i = 0; i < files.length; i++) {
|
for (var i = 0; i < files.length; i++) {
|
||||||
@@ -644,6 +691,13 @@
|
|||||||
"hydrated:", !!islands[j]._sxBoundislandhydrated || !!islands[j]["_sxBound" + "island-hydrated"],
|
"hydrated:", !!islands[j]._sxBoundislandhydrated || !!islands[j]["_sxBound" + "island-hydrated"],
|
||||||
"children:", islands[j].children.length);
|
"children:", islands[j].children.length);
|
||||||
}
|
}
|
||||||
|
// Activate _hyperscript compat on elements with _ attribute
|
||||||
|
if (document.querySelector('[_]')) {
|
||||||
|
if (K.beginModuleLoad) K.beginModuleLoad();
|
||||||
|
loadLibrary("hyperscript integration", {});
|
||||||
|
if (K.endModuleLoad) K.endModuleLoad();
|
||||||
|
K.eval("(hs-boot!)");
|
||||||
|
}
|
||||||
// Register popstate handler for back/forward navigation
|
// Register popstate handler for back/forward navigation
|
||||||
window.addEventListener("popstate", function(e) {
|
window.addEventListener("popstate", function(e) {
|
||||||
var state = e.state;
|
var state = e.state;
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -444,6 +444,7 @@
|
|||||||
(sx-hydrate-islands nil)
|
(sx-hydrate-islands nil)
|
||||||
(run-post-render-hooks)
|
(run-post-render-hooks)
|
||||||
(flush-collected-styles)
|
(flush-collected-styles)
|
||||||
|
(hs-boot!)
|
||||||
(set-timeout (fn () (process-elements nil)) 0)
|
(set-timeout (fn () (process-elements nil)) 0)
|
||||||
(dom-set-attr
|
(dom-set-attr
|
||||||
(host-get (dom-document) "documentElement")
|
(host-get (dom-document) "documentElement")
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -599,11 +599,12 @@
|
|||||||
(binding)
|
(binding)
|
||||||
(let
|
(let
|
||||||
((name (if (= (type-of (first binding)) "symbol") (symbol-name (first binding)) (first binding)))
|
((name (if (= (type-of (first binding)) "symbol") (symbol-name (first binding)) (first binding)))
|
||||||
(value (nth binding 1))
|
(value (nth binding 1)))
|
||||||
(slot (scope-define-local let-scope name)))
|
|
||||||
(compile-expr em value let-scope false)
|
(compile-expr em value let-scope false)
|
||||||
(emit-op em 17)
|
(let
|
||||||
(emit-byte em slot)))
|
((slot (scope-define-local let-scope name)))
|
||||||
|
(emit-op em 17)
|
||||||
|
(emit-byte em slot))))
|
||||||
bindings)
|
bindings)
|
||||||
(compile-begin em body let-scope tail?)))))
|
(compile-begin em body let-scope tail?)))))
|
||||||
(define
|
(define
|
||||||
@@ -640,29 +641,38 @@
|
|||||||
(fn-scope (make-scope scope))
|
(fn-scope (make-scope scope))
|
||||||
(fn-em (make-emitter)))
|
(fn-em (make-emitter)))
|
||||||
(dict-set! fn-scope "is-function" true)
|
(dict-set! fn-scope "is-function" true)
|
||||||
(for-each
|
|
||||||
(fn
|
|
||||||
(p)
|
|
||||||
(let
|
|
||||||
((name (cond (= (type-of p) "symbol") (symbol-name p) (and (list? p) (not (empty? p)) (= (type-of (first p)) "symbol")) (symbol-name (first p)) :else p)))
|
|
||||||
(when
|
|
||||||
(and (not (= name "&key")) (not (= name "&rest")))
|
|
||||||
(scope-define-local fn-scope name))))
|
|
||||||
params)
|
|
||||||
(compile-begin fn-em body fn-scope true)
|
|
||||||
(emit-op fn-em 50)
|
|
||||||
(let
|
(let
|
||||||
((upvals (get fn-scope "upvalues"))
|
((rest-pos -1) (rest-name nil))
|
||||||
(code {:upvalue-count (len upvals) :arity (len (get fn-scope "locals")) :constants (get (get fn-em "pool") "entries") :bytecode (get fn-em "bytecode")})
|
|
||||||
(code-idx (pool-add (get em "pool") code)))
|
|
||||||
(emit-op em 51)
|
|
||||||
(emit-u16 em code-idx)
|
|
||||||
(for-each
|
(for-each
|
||||||
(fn
|
(fn
|
||||||
(uv)
|
(p)
|
||||||
(emit-byte em (if (get uv "is-local") 1 0))
|
(let
|
||||||
(emit-byte em (get uv "index")))
|
((name (cond (= (type-of p) "symbol") (symbol-name p) (and (list? p) (not (empty? p)) (= (type-of (first p)) "symbol")) (symbol-name (first p)) :else p)))
|
||||||
upvals)))))
|
(cond
|
||||||
|
(= name "&rest")
|
||||||
|
(set! rest-pos (len (get fn-scope "locals")))
|
||||||
|
(= name "&key")
|
||||||
|
nil
|
||||||
|
:else (do
|
||||||
|
(when
|
||||||
|
(and (> rest-pos -1) (nil? rest-name))
|
||||||
|
(set! rest-name name))
|
||||||
|
(scope-define-local fn-scope name)))))
|
||||||
|
params)
|
||||||
|
(compile-begin fn-em body fn-scope true)
|
||||||
|
(emit-op fn-em 50)
|
||||||
|
(let
|
||||||
|
((upvals (get fn-scope "upvalues"))
|
||||||
|
(code (if (> rest-pos -1) {:upvalue-count (len upvals) :arity (len (get fn-scope "locals")) :constants (get (get fn-em "pool") "entries") :rest-arity rest-pos :bytecode (get fn-em "bytecode")} {:upvalue-count (len upvals) :arity (len (get fn-scope "locals")) :constants (get (get fn-em "pool") "entries") :bytecode (get fn-em "bytecode")}))
|
||||||
|
(code-idx (pool-add (get em "pool") code)))
|
||||||
|
(emit-op em 51)
|
||||||
|
(emit-u16 em code-idx)
|
||||||
|
(for-each
|
||||||
|
(fn
|
||||||
|
(uv)
|
||||||
|
(emit-byte em (if (get uv "is-local") 1 0))
|
||||||
|
(emit-byte em (get uv "index")))
|
||||||
|
upvals))))))
|
||||||
(define
|
(define
|
||||||
compile-define
|
compile-define
|
||||||
(fn
|
(fn
|
||||||
@@ -681,7 +691,7 @@
|
|||||||
(and
|
(and
|
||||||
(not (empty? rest-args))
|
(not (empty? rest-args))
|
||||||
(= (type-of (first rest-args)) "keyword"))
|
(= (type-of (first rest-args)) "keyword"))
|
||||||
(let
|
(letrec
|
||||||
((skip-annotations (fn (items) (if (empty? items) nil (if (= (type-of (first items)) "keyword") (skip-annotations (rest (rest items))) (first items))))))
|
((skip-annotations (fn (items) (if (empty? items) nil (if (= (type-of (first items)) "keyword") (skip-annotations (rest (rest items))) (first items))))))
|
||||||
(skip-annotations rest-args))
|
(skip-annotations rest-args))
|
||||||
(first rest-args)))))
|
(first rest-args)))))
|
||||||
@@ -724,38 +734,41 @@
|
|||||||
compile-cond
|
compile-cond
|
||||||
(fn
|
(fn
|
||||||
(em args scope tail?)
|
(em args scope tail?)
|
||||||
"Compile (cond test1 body1 test2 body2 ... :else fallback)."
|
"Compile (cond test1 body1 test2 body2 ... :else fallback).\n Also handles clause syntax: (cond (test1 body1) (test2 body2) ...)."
|
||||||
(if
|
(let
|
||||||
(< (len args) 2)
|
((flat-args (if (and (not (empty? args)) (list? (first args)) (> (len (first args)) 1) (list? (first (first args)))) (reduce (fn (acc clause) (if (list? clause) (append acc clause) (append acc (list clause)))) (list) args) args)))
|
||||||
(emit-op em 2)
|
(if
|
||||||
(let
|
(< (len flat-args) 2)
|
||||||
((test (first args))
|
(emit-op em 2)
|
||||||
(body (nth args 1))
|
(let
|
||||||
(rest-clauses (if (> (len args) 2) (slice args 2) (list))))
|
((test (nth flat-args 0))
|
||||||
(if
|
(body (nth flat-args 1))
|
||||||
(or
|
(rest-clauses
|
||||||
(and
|
(if (> (len flat-args) 2) (slice flat-args 2) (list))))
|
||||||
(= (type-of test) "keyword")
|
(if
|
||||||
(= (keyword-name test) "else"))
|
(or
|
||||||
(= test true))
|
(and
|
||||||
(compile-expr em body scope tail?)
|
(= (type-of test) "keyword")
|
||||||
(do
|
(= (keyword-name test) "else"))
|
||||||
(compile-expr em test scope false)
|
(= test true))
|
||||||
(emit-op em 33)
|
(compile-expr em body scope tail?)
|
||||||
(let
|
(do
|
||||||
((skip (current-offset em)))
|
(compile-expr em test scope false)
|
||||||
(emit-i16 em 0)
|
(emit-op em 33)
|
||||||
(compile-expr em body scope tail?)
|
|
||||||
(emit-op em 32)
|
|
||||||
(let
|
(let
|
||||||
((end-jump (current-offset em)))
|
((skip (current-offset em)))
|
||||||
(emit-i16 em 0)
|
(emit-i16 em 0)
|
||||||
(patch-i16 em skip (- (current-offset em) (+ skip 2)))
|
(compile-expr em body scope tail?)
|
||||||
(compile-cond em rest-clauses scope tail?)
|
(emit-op em 32)
|
||||||
(patch-i16
|
(let
|
||||||
em
|
((end-jump (current-offset em)))
|
||||||
end-jump
|
(emit-i16 em 0)
|
||||||
(- (current-offset em) (+ end-jump 2)))))))))))
|
(patch-i16 em skip (- (current-offset em) (+ skip 2)))
|
||||||
|
(compile-cond em rest-clauses scope tail?)
|
||||||
|
(patch-i16
|
||||||
|
em
|
||||||
|
end-jump
|
||||||
|
(- (current-offset em) (+ end-jump 2))))))))))))
|
||||||
(define
|
(define
|
||||||
compile-case
|
compile-case
|
||||||
(fn
|
(fn
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
3
shared/static/wasm/sx/hs-compiler.sxbc
Normal file
3
shared/static/wasm/sx/hs-compiler.sxbc
Normal file
File diff suppressed because one or more lines are too long
66
shared/static/wasm/sx/hs-integration.sx
Normal file
66
shared/static/wasm/sx/hs-integration.sx
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
;; _hyperscript integration — wire _="..." attributes to compiled SX
|
||||||
|
;;
|
||||||
|
;; Entry points:
|
||||||
|
;; (hs-handler src) — compile source to callable (fn (me) ...)
|
||||||
|
;; (hs-activate! el) — activate hyperscript on a single element
|
||||||
|
;; (hs-boot!) — scan DOM, activate all _="..." elements
|
||||||
|
;; (hs-boot-subtree! root) — activate within a subtree (for HTMX swaps)
|
||||||
|
|
||||||
|
;; ── Compile source to a handler function ────────────────────────
|
||||||
|
;; Returns a function (fn (me) ...) that can be called with a DOM element.
|
||||||
|
;; Uses eval-expr-cek to turn the SX data structure into a live closure.
|
||||||
|
|
||||||
|
(define
|
||||||
|
hs-handler
|
||||||
|
(fn
|
||||||
|
(src)
|
||||||
|
(let
|
||||||
|
((sx (hs-to-sx-from-source src)))
|
||||||
|
(eval-expr-cek
|
||||||
|
(list
|
||||||
|
(quote fn)
|
||||||
|
(list (quote me))
|
||||||
|
(list
|
||||||
|
(quote let)
|
||||||
|
(list (list (quote it) nil) (list (quote event) nil))
|
||||||
|
sx))))))
|
||||||
|
|
||||||
|
;; ── Activate a single element ───────────────────────────────────
|
||||||
|
;; Reads the _="..." attribute, compiles, and executes with me=element.
|
||||||
|
;; Marks the element to avoid double-activation.
|
||||||
|
|
||||||
|
(define
|
||||||
|
hs-activate!
|
||||||
|
(fn
|
||||||
|
(el)
|
||||||
|
(let
|
||||||
|
((src (dom-get-attr el "_")))
|
||||||
|
(when
|
||||||
|
(and src (not (dom-get-data el "hs-active")))
|
||||||
|
(dom-set-data el "hs-active" true)
|
||||||
|
(let ((handler (hs-handler src))) (handler el))))))
|
||||||
|
|
||||||
|
;; ── Boot: scan entire document ──────────────────────────────────
|
||||||
|
;; Called once at page load. Finds all elements with _ attribute,
|
||||||
|
;; compiles their hyperscript, and activates them.
|
||||||
|
|
||||||
|
(define
|
||||||
|
hs-boot!
|
||||||
|
(fn
|
||||||
|
()
|
||||||
|
(let
|
||||||
|
((elements (dom-query-all (dom-body) "[_]")))
|
||||||
|
(for-each (fn (el) (hs-activate! el)) elements))))
|
||||||
|
|
||||||
|
;; ── Boot subtree: for dynamic content ───────────────────────────
|
||||||
|
;; Called after HTMX swaps or dynamic DOM insertion.
|
||||||
|
;; Only activates elements within the given root.
|
||||||
|
|
||||||
|
(define
|
||||||
|
hs-boot-subtree!
|
||||||
|
(fn
|
||||||
|
(root)
|
||||||
|
(let
|
||||||
|
((elements (dom-query-all root "[_]")))
|
||||||
|
(for-each (fn (el) (hs-activate! el)) elements))
|
||||||
|
(when (dom-get-attr root "_") (hs-activate! root))))
|
||||||
3
shared/static/wasm/sx/hs-integration.sxbc
Normal file
3
shared/static/wasm/sx/hs-integration.sxbc
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
(sxbc 1 "af8c1b333d6af000"
|
||||||
|
(code
|
||||||
|
:constants ("hs-handler" {:upvalue-count 0 :arity 1 :constants ("hs-to-sx-from-source" "eval-expr-cek" "list" fn me let it event) :bytecode (20 0 0 16 0 48 1 17 1 20 1 0 1 3 0 1 4 0 52 2 0 1 1 5 0 1 6 0 2 52 2 0 2 1 7 0 2 52 2 0 2 52 2 0 2 16 1 52 2 0 3 52 2 0 3 49 1 50)} "hs-activate!" {:upvalue-count 0 :arity 1 :constants ("dom-get-attr" "_" "not" "dom-get-data" "hs-active" "dom-set-data" "hs-handler") :bytecode (20 0 0 16 0 1 1 0 48 2 17 1 16 1 6 33 15 0 5 20 3 0 16 0 1 4 0 48 2 52 2 0 1 33 30 0 20 5 0 16 0 1 4 0 3 48 3 5 20 6 0 16 1 48 1 17 2 16 2 16 0 49 1 32 1 0 2 50)} "hs-boot!" {:upvalue-count 0 :arity 0 :constants ("dom-query-all" "dom-body" "[_]" "for-each" {:upvalue-count 0 :arity 1 :constants ("hs-activate!") :bytecode (20 0 0 16 0 49 1 50)}) :bytecode (20 0 0 20 1 0 48 0 1 2 0 48 2 17 0 51 4 0 16 0 52 3 0 2 50)} "hs-boot-subtree!" {:upvalue-count 0 :arity 1 :constants ("dom-query-all" "[_]" "for-each" {:upvalue-count 0 :arity 1 :constants ("hs-activate!") :bytecode (20 0 0 16 0 49 1 50)} "dom-get-attr" "_" "hs-activate!") :bytecode (20 0 0 16 0 1 1 0 48 2 17 1 51 3 0 16 1 52 2 0 2 5 20 4 0 16 0 1 5 0 48 2 33 10 0 20 6 0 16 0 49 1 32 1 0 2 50)}) :bytecode (51 1 0 128 0 0 5 51 3 0 128 2 0 5 51 5 0 128 4 0 5 51 7 0 128 6 0 50)))
|
||||||
3
shared/static/wasm/sx/hs-parser.sxbc
Normal file
3
shared/static/wasm/sx/hs-parser.sxbc
Normal file
File diff suppressed because one or more lines are too long
3
shared/static/wasm/sx/hs-runtime.sxbc
Normal file
3
shared/static/wasm/sx/hs-runtime.sxbc
Normal file
File diff suppressed because one or more lines are too long
3
shared/static/wasm/sx/hs-tokenizer.sxbc
Normal file
3
shared/static/wasm/sx/hs-tokenizer.sxbc
Normal file
File diff suppressed because one or more lines are too long
@@ -797,7 +797,8 @@
|
|||||||
"sx dom",
|
"sx dom",
|
||||||
"sx browser",
|
"sx browser",
|
||||||
"web adapter-dom",
|
"web adapter-dom",
|
||||||
"web engine"
|
"web engine",
|
||||||
|
"hyperscript integration"
|
||||||
],
|
],
|
||||||
"exports": [
|
"exports": [
|
||||||
"_preload-cache",
|
"_preload-cache",
|
||||||
@@ -861,6 +862,89 @@
|
|||||||
"engine-init"
|
"engine-init"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"hyperscript tokenizer": {
|
||||||
|
"file": "hs-tokenizer.sxbc",
|
||||||
|
"deps": [],
|
||||||
|
"exports": [
|
||||||
|
"hs-tokenize",
|
||||||
|
"hs-make-token",
|
||||||
|
"hs-keywords",
|
||||||
|
"hs-keyword?",
|
||||||
|
"hs-digit?",
|
||||||
|
"hs-letter?",
|
||||||
|
"hs-ident-start?",
|
||||||
|
"hs-ident-char?",
|
||||||
|
"hs-ws?"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hyperscript parser": {
|
||||||
|
"file": "hs-parser.sxbc",
|
||||||
|
"deps": [
|
||||||
|
"hyperscript tokenizer"
|
||||||
|
],
|
||||||
|
"exports": [
|
||||||
|
"hs-parse",
|
||||||
|
"hs-compile"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hyperscript compiler": {
|
||||||
|
"file": "hs-compiler.sxbc",
|
||||||
|
"deps": [
|
||||||
|
"hyperscript parser"
|
||||||
|
],
|
||||||
|
"exports": [
|
||||||
|
"hs-to-sx",
|
||||||
|
"hs-to-sx-from-source"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hyperscript runtime": {
|
||||||
|
"file": "hs-runtime.sxbc",
|
||||||
|
"deps": [
|
||||||
|
"sx dom",
|
||||||
|
"sx browser"
|
||||||
|
],
|
||||||
|
"exports": [
|
||||||
|
"hs-on",
|
||||||
|
"hs-on-every",
|
||||||
|
"hs-init",
|
||||||
|
"hs-wait",
|
||||||
|
"hs-wait-for",
|
||||||
|
"hs-settle",
|
||||||
|
"hs-toggle-class!",
|
||||||
|
"hs-toggle-between!",
|
||||||
|
"hs-take!",
|
||||||
|
"hs-put!",
|
||||||
|
"hs-navigate!",
|
||||||
|
"hs-next",
|
||||||
|
"hs-previous",
|
||||||
|
"hs-query-first",
|
||||||
|
"hs-query-last",
|
||||||
|
"hs-first",
|
||||||
|
"hs-last",
|
||||||
|
"hs-repeat-times",
|
||||||
|
"hs-repeat-forever",
|
||||||
|
"hs-fetch",
|
||||||
|
"hs-coerce",
|
||||||
|
"hs-make",
|
||||||
|
"hs-install",
|
||||||
|
"hs-measure",
|
||||||
|
"hs-transition"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"hyperscript integration": {
|
||||||
|
"file": "hs-integration.sxbc",
|
||||||
|
"deps": [
|
||||||
|
"hyperscript compiler",
|
||||||
|
"hyperscript runtime",
|
||||||
|
"sx dom"
|
||||||
|
],
|
||||||
|
"exports": [
|
||||||
|
"hs-handler",
|
||||||
|
"hs-activate!",
|
||||||
|
"hs-boot!",
|
||||||
|
"hs-boot-subtree!"
|
||||||
|
]
|
||||||
|
},
|
||||||
"_entry": {
|
"_entry": {
|
||||||
"file": "boot.sxbc",
|
"file": "boot.sxbc",
|
||||||
"deps": [
|
"deps": [
|
||||||
|
|||||||
@@ -6,6 +6,9 @@
|
|||||||
(import (web adapter-dom))
|
(import (web adapter-dom))
|
||||||
(import (web engine))
|
(import (web engine))
|
||||||
|
|
||||||
|
(import (hyperscript integration)) ;; end define-library
|
||||||
|
|
||||||
|
;; Re-export to global namespace for backward compatibility
|
||||||
(define-library
|
(define-library
|
||||||
(web orchestration)
|
(web orchestration)
|
||||||
(export
|
(export
|
||||||
@@ -626,7 +629,8 @@
|
|||||||
(sx-hydrate-islands root)
|
(sx-hydrate-islands root)
|
||||||
(run-post-render-hooks)
|
(run-post-render-hooks)
|
||||||
(flush-collected-styles)
|
(flush-collected-styles)
|
||||||
(process-elements root)))
|
(process-elements root)
|
||||||
|
(hs-boot-subtree! root)))
|
||||||
(define
|
(define
|
||||||
process-settle-hooks
|
process-settle-hooks
|
||||||
:effects (mutation io)
|
:effects (mutation io)
|
||||||
@@ -1632,7 +1636,6 @@
|
|||||||
(do
|
(do
|
||||||
(sx-process-scripts nil)
|
(sx-process-scripts nil)
|
||||||
(sx-hydrate nil)
|
(sx-hydrate nil)
|
||||||
(process-elements nil)))))) ;; end define-library
|
(process-elements nil))))))
|
||||||
|
|
||||||
;; Re-export to global namespace for backward compatibility
|
|
||||||
(import (web orchestration))
|
(import (web orchestration))
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -137,18 +137,21 @@
|
|||||||
code-from-value
|
code-from-value
|
||||||
(fn
|
(fn
|
||||||
(v)
|
(v)
|
||||||
"Convert a compiler output dict to a vm-code object."
|
"Convert a compiler output dict to a vm-code dict. Idempotent — if v\n already has vm-code keys (vc-bytecode), returns as-is."
|
||||||
(if
|
(if
|
||||||
(not (dict? v))
|
(not (dict? v))
|
||||||
(make-vm-code 0 16 (list) (list))
|
(make-vm-code 0 16 (list) (list))
|
||||||
(let
|
(if
|
||||||
((bc-raw (get v "bytecode"))
|
(has-key? v "vc-bytecode")
|
||||||
(bc (if (nil? bc-raw) (list) bc-raw))
|
v
|
||||||
(consts-raw (get v "constants"))
|
(let
|
||||||
(consts (if (nil? consts-raw) (list) consts-raw))
|
((bc-raw (get v "bytecode"))
|
||||||
(arity-raw (get v "arity"))
|
(bc (if (nil? bc-raw) (list) bc-raw))
|
||||||
(arity (if (nil? arity-raw) 0 arity-raw)))
|
(consts-raw (get v "constants"))
|
||||||
(make-vm-code arity (+ arity 16) bc consts)))))
|
(consts (if (nil? consts-raw) (list) consts-raw))
|
||||||
|
(arity-raw (get v "arity"))
|
||||||
|
(arity (if (nil? arity-raw) 0 arity-raw)))
|
||||||
|
(make-vm-code arity (+ arity 16) bc consts))))))
|
||||||
(define vm-closure? (fn (v) (and (dict? v) (has-key? v "vm-code"))))
|
(define vm-closure? (fn (v) (and (dict? v) (has-key? v "vm-code"))))
|
||||||
(define *active-vm* nil)
|
(define *active-vm* nil)
|
||||||
(define *jit-compile-fn* nil)
|
(define *jit-compile-fn* nil)
|
||||||
@@ -297,27 +300,32 @@
|
|||||||
vm-global-get
|
vm-global-get
|
||||||
(fn
|
(fn
|
||||||
(vm frame name)
|
(vm frame name)
|
||||||
"Look up a global: globals table → closure env → primitives → HO wrappers"
|
"Look up a global: closure env → globals table → primitives → HO forms"
|
||||||
(let
|
(let
|
||||||
((globals (vm-globals-ref vm)))
|
((closure-env (get (frame-closure frame) "vm-closure-env")))
|
||||||
(if
|
(if
|
||||||
(has-key? globals name)
|
(nil? closure-env)
|
||||||
(get globals name)
|
|
||||||
(let
|
(let
|
||||||
((closure-env (-> frame frame-closure closure-env)))
|
((globals (vm-globals-ref vm)))
|
||||||
(if
|
(if
|
||||||
(nil? closure-env)
|
(has-key? globals name)
|
||||||
|
(get globals name)
|
||||||
(cek-try
|
(cek-try
|
||||||
(fn () (get-primitive name))
|
(fn () (get-primitive name))
|
||||||
(fn (e) (vm-resolve-ho-form vm name)))
|
(fn (e) (vm-resolve-ho-form vm name)))))
|
||||||
|
(let
|
||||||
|
((found (env-walk closure-env name)))
|
||||||
|
(if
|
||||||
|
(nil? found)
|
||||||
(let
|
(let
|
||||||
((found (env-walk closure-env name)))
|
((globals (vm-globals-ref vm)))
|
||||||
(if
|
(if
|
||||||
(nil? found)
|
(has-key? globals name)
|
||||||
|
(get globals name)
|
||||||
(cek-try
|
(cek-try
|
||||||
(fn () (get-primitive name))
|
(fn () (get-primitive name))
|
||||||
(fn (e) (vm-resolve-ho-form vm name)))
|
(fn (e) (vm-resolve-ho-form vm name)))))
|
||||||
found))))))))
|
found))))))
|
||||||
(define
|
(define
|
||||||
vm-resolve-ho-form
|
vm-resolve-ho-form
|
||||||
(fn
|
(fn
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1792,7 +1792,7 @@
|
|||||||
blake2_js_for_wasm_create: blake2_js_for_wasm_create};
|
blake2_js_for_wasm_create: blake2_js_for_wasm_create};
|
||||||
}
|
}
|
||||||
(globalThis))
|
(globalThis))
|
||||||
({"link":[["runtime-0db9b496",0],["prelude-d7e4b000",0],["stdlib-23ce0836",[]],["re-9a0de245",[2]],["sx-f96dc336",[2,3]],["jsoo_runtime-f96b44a8",[2]],["js_of_ocaml-651f6707",[2,5]],["dune__exe__Sx_browser-b7a948a6",[2,4,6]],["std_exit-10fb8830",[2]],["start-f808dbe1",0]],"generated":(b=>{var
|
({"link":[["runtime-0db9b496",0],["prelude-d7e4b000",0],["stdlib-23ce0836",[]],["re-9a0de245",[2]],["sx-9799aa33",[2,3]],["jsoo_runtime-f96b44a8",[2]],["js_of_ocaml-651f6707",[2,5]],["dune__exe__Sx_browser-b7a948a6",[2,4,6]],["std_exit-10fb8830",[2]],["start-f808dbe1",0]],"generated":(b=>{var
|
||||||
c=b,a=b?.module?.export||b;return{"env":{"caml_ba_kind_of_typed_array":()=>{throw new
|
c=b,a=b?.module?.export||b;return{"env":{"caml_ba_kind_of_typed_array":()=>{throw new
|
||||||
Error("caml_ba_kind_of_typed_array not implemented")},"caml_exn_with_js_backtrace":()=>{throw new
|
Error("caml_ba_kind_of_typed_array not implemented")},"caml_exn_with_js_backtrace":()=>{throw new
|
||||||
Error("caml_exn_with_js_backtrace not implemented")},"caml_int64_create_lo_mi_hi":()=>{throw new
|
Error("caml_exn_with_js_backtrace not implemented")},"caml_int64_create_lo_mi_hi":()=>{throw new
|
||||||
|
|||||||
Reference in New Issue
Block a user