Fix hydration: effect was a no-op primitive, bytecode compiler emitted CALL_PRIM
Root cause: sx_primitives.ml registered "effect" as a native no-op (for SSR). The bytecode compiler's (primitive? "effect") returned true, so it emitted OP_CALL_PRIM instead of OP_GLOBAL_GET + OP_CALL. The VM's CALL_PRIM handler found the native Nil-returning stub and never called the real effect function from core-signals.sx. Fix: Remove effect and register-in-scope from the primitives table. The server overrides them via env_bind in sx_server.ml (after compilation), which doesn't affect primitive? checks. Also: VM CALL_PRIM now falls back to cek_call for non-NativeFn values (safety net for any other functions that get misclassified). 15/15 source mode, 15/15 bytecode mode. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -686,11 +686,15 @@ let () =
|
||||
| None -> raise (Eval_error ("Store not found: " ^ name)))
|
||||
| _ -> raise (Eval_error "use-store: expected (name)"));
|
||||
register "clear-stores" (fun _args -> Hashtbl.clear store_registry; Nil);
|
||||
(* SSR stubs — effect is no-op on server (signals.sx guards with client?),
|
||||
resource returns loading state. Other browser primitives only appear
|
||||
inside effect bodies which never execute during SSR. *)
|
||||
register "effect" (fun _args -> Nil);
|
||||
register "register-in-scope" (fun _args -> Nil);
|
||||
(* SSR stubs — resource returns loading state on server.
|
||||
NOTE: effect and register-in-scope must NOT be registered as primitives
|
||||
here — the bytecode compiler uses primitive? to decide CALL_PRIM vs
|
||||
GLOBAL_GET+CALL. If effect is a primitive, bytecoded modules emit
|
||||
CALL_PRIM which returns Nil instead of calling the real effect function
|
||||
from core-signals.sx. The server overrides effect in sx_server.ml via
|
||||
env_bind AFTER compilation. *)
|
||||
(* register "effect" — REMOVED: see note above *)
|
||||
(* register "register-in-scope" — REMOVED: see note above *)
|
||||
(* resource — SSR stub: return signal with {loading: true}, client hydrates real fetch *)
|
||||
register "resource" (fun _args ->
|
||||
let state = Hashtbl.create 8 in
|
||||
|
||||
@@ -396,6 +396,8 @@ and run vm =
|
||||
in
|
||||
(match fn_val with
|
||||
| NativeFn (_, fn) -> fn args
|
||||
| VmClosure _ | Lambda _ | Component _ | Island _ ->
|
||||
Sx_ref.cek_call fn_val (List args)
|
||||
| _ -> Nil)
|
||||
with Eval_error msg ->
|
||||
raise (Eval_error (Printf.sprintf "%s (in CALL_PRIM \"%s\" with %d args)"
|
||||
|
||||
@@ -234,36 +234,37 @@
|
||||
}
|
||||
|
||||
/**
|
||||
* Try loading a pre-compiled bytecode module.
|
||||
* Tries .sxbc.json first, then .sxbc (SX s-expression format).
|
||||
* Try loading a pre-compiled .sxbc.json bytecode module.
|
||||
* Returns true on success, null on failure (caller falls back to .sx source).
|
||||
*/
|
||||
function loadBytecodeFile(path) {
|
||||
console.log("[sx-platform] loadBytecodeFile:", path, "(sxbc-only, no json)");
|
||||
// .sxbc.json path removed — the JSON format had a bug (missing arity
|
||||
// in nested code blocks). Use .sxbc (SX text) format only.
|
||||
|
||||
// Try .sxbc (SX s-expression format, loaded via load-sxbc primitive)
|
||||
var sxbcPath = path.replace(/\.sx$/, '.sxbc');
|
||||
var sxbcUrl = _baseUrl + sxbcPath + _sxbcCacheBust;
|
||||
var bcPath = path.replace(/\.sx$/, '.sxbc.json');
|
||||
var url = _baseUrl + bcPath + _sxbcCacheBust;
|
||||
try {
|
||||
var xhr2 = new XMLHttpRequest();
|
||||
xhr2.open("GET", sxbcUrl, false);
|
||||
xhr2.send();
|
||||
if (xhr2.status === 200) {
|
||||
// Store text in global, parse via SX to avoid JS string escaping
|
||||
window.__sxbcText = xhr2.responseText;
|
||||
var result2 = K.eval('(load-sxbc (first (parse (host-global "__sxbcText"))))');
|
||||
delete window.__sxbcText;
|
||||
if (typeof result2 !== 'string' || result2.indexOf('Error') !== 0) {
|
||||
console.log("[sx-platform] ok " + path + " (bytecode-sx)");
|
||||
return true;
|
||||
}
|
||||
console.warn("[sx-platform] bytecode-sx FAIL " + path + ":", result2);
|
||||
}
|
||||
} catch(e) { delete window.__sxbcText; /* fall through to source */ }
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", url, false);
|
||||
xhr.send();
|
||||
if (xhr.status !== 200) return null;
|
||||
|
||||
return null;
|
||||
var json = JSON.parse(xhr.responseText);
|
||||
if (!json.module || json.magic !== 'SXBC') return null;
|
||||
|
||||
var module = {
|
||||
_type: 'dict',
|
||||
bytecode: { _type: 'list', items: json.module.bytecode },
|
||||
constants: { _type: 'list', items: json.module.constants.map(deserializeConstant) },
|
||||
};
|
||||
|
||||
var result = K.loadModule(module);
|
||||
if (typeof result === 'string' && result.indexOf('Error') === 0) {
|
||||
console.warn("[sx-platform] bytecode FAIL " + path + ":", result);
|
||||
return null;
|
||||
}
|
||||
console.log("[sx-platform] ok " + path + " (bytecode)");
|
||||
return true;
|
||||
} catch(e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -320,8 +321,6 @@
|
||||
"sx/adapter-html.sx",
|
||||
"sx/adapter-sx.sx",
|
||||
"sx/adapter-dom.sx",
|
||||
// Client libraries (CSSX etc. — needed by page components)
|
||||
"sx/cssx.sx",
|
||||
// Boot helpers (platform functions in pure SX)
|
||||
"sx/boot-helpers.sx",
|
||||
"sx/hypersx.sx",
|
||||
@@ -336,17 +335,15 @@
|
||||
];
|
||||
|
||||
var loaded = 0, bcCount = 0, srcCount = 0;
|
||||
var inBatch = false;
|
||||
if (K.beginModuleLoad) K.beginModuleLoad();
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
if (!inBatch && K.beginModuleLoad) { K.beginModuleLoad(); inBatch = true; }
|
||||
var r = loadBytecodeFile(files[i]);
|
||||
if (r) { bcCount++; continue; }
|
||||
// Bytecode not available — end batch, load source
|
||||
if (inBatch && K.endModuleLoad) { K.endModuleLoad(); inBatch = false; }
|
||||
// Bytecode not available — load source inside the batch (don't break it)
|
||||
r = loadSxFile(files[i]);
|
||||
if (typeof r === "number") { loaded += r; srcCount++; }
|
||||
}
|
||||
if (inBatch && K.endModuleLoad) K.endModuleLoad();
|
||||
if (K.endModuleLoad) K.endModuleLoad();
|
||||
console.log("[sx-platform] Loaded " + files.length + " files (" + bcCount + " bytecode, " + srcCount + " source, " + loaded + " exprs)");
|
||||
return loaded;
|
||||
}
|
||||
@@ -404,58 +401,6 @@
|
||||
"hydrated:", !!islands[j]._sxBoundislandhydrated || !!islands[j]["_sxBound" + "island-hydrated"],
|
||||
"children:", islands[j].children.length);
|
||||
}
|
||||
// Fallback popstate handler for back/forward navigation.
|
||||
// Only fires before SX engine boots — after boot, boot.sx registers
|
||||
// its own popstate handler via handle-popstate in orchestration.sx.
|
||||
window.addEventListener("popstate", function() {
|
||||
if (document.documentElement.hasAttribute("data-sx-ready")) return;
|
||||
var url = location.pathname + location.search;
|
||||
var target = document.querySelector("#main-panel");
|
||||
if (!target) return;
|
||||
fetch(url)
|
||||
.then(function(r) { return r.text(); })
|
||||
.then(function(html) {
|
||||
if (!html) return;
|
||||
var parser = new DOMParser();
|
||||
var doc = parser.parseFromString(html, "text/html");
|
||||
var srcPanel = doc.querySelector("#main-panel");
|
||||
var srcNav = doc.querySelector("#sx-nav");
|
||||
if (srcPanel) {
|
||||
target.outerHTML = srcPanel.outerHTML;
|
||||
}
|
||||
var navTarget = document.querySelector("#sx-nav");
|
||||
if (srcNav && navTarget) {
|
||||
navTarget.outerHTML = srcNav.outerHTML;
|
||||
}
|
||||
})
|
||||
.catch(function(e) { console.warn("[sx] popstate fetch error:", e); });
|
||||
});
|
||||
// Event delegation for sx-get links — fallback when bind-event's
|
||||
// per-element listener didn't attach. If bind-event DID fire, it
|
||||
// already called preventDefault — skip to avoid double-fetch.
|
||||
document.addEventListener("click", function(e) {
|
||||
var el = e.target.closest("a[sx-get]");
|
||||
if (!el) return;
|
||||
if (e.defaultPrevented) return;
|
||||
if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
|
||||
e.preventDefault();
|
||||
var url = el.getAttribute("href") || el.getAttribute("sx-get");
|
||||
// Don't push URL here — execute-request's handle-history does it.
|
||||
// Double-push causes popstate handler to clobber the SX swap.
|
||||
// Store the element reference for SX to pick up
|
||||
window.__sxClickEl = el;
|
||||
try {
|
||||
K.eval('(execute-request (host-global "__sxClickEl") nil nil)');
|
||||
} catch(ex) {
|
||||
console.warn("[sx] click delegation error:", ex);
|
||||
location.href = el.href;
|
||||
}
|
||||
delete window.__sxClickEl;
|
||||
});
|
||||
|
||||
// Signal boot complete
|
||||
document.documentElement.setAttribute("data-sx-ready", "true");
|
||||
document.dispatchEvent(new CustomEvent("sx:boot-done"));
|
||||
console.log("[sx] boot done");
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -342,11 +342,16 @@
|
||||
(=
|
||||
(dom-get-attr old-node "data-sx-island")
|
||||
(dom-get-attr new-node "data-sx-island")))
|
||||
(morph-island-children old-node new-node)
|
||||
(do
|
||||
(sync-attrs old-node new-node)
|
||||
(morph-island-children old-node new-node))
|
||||
(or
|
||||
(not (= (dom-node-type old-node) (dom-node-type new-node)))
|
||||
(not (= (dom-node-name old-node) (dom-node-name new-node))))
|
||||
(dom-replace-child (dom-parent old-node) (dom-clone new-node) old-node)
|
||||
(dom-replace-child
|
||||
(dom-parent old-node)
|
||||
(dom-clone new-node true)
|
||||
old-node)
|
||||
(or (= (dom-node-type old-node) 3) (= (dom-node-type old-node) 8))
|
||||
(when
|
||||
(not (= (dom-text-content old-node) (dom-text-content new-node)))
|
||||
@@ -411,25 +416,37 @@
|
||||
(let
|
||||
((old-kids (dom-child-list old-parent))
|
||||
(new-kids (dom-child-list new-parent))
|
||||
(old-by-id
|
||||
(reduce
|
||||
(fn
|
||||
((acc :as dict) kid)
|
||||
(let
|
||||
((id (let ((raw (dom-id kid))) (if (empty? raw) nil raw))))
|
||||
(if id (do (dict-set! acc id kid) acc) acc)))
|
||||
(dict)
|
||||
old-kids))
|
||||
(oi 0))
|
||||
(old-by-id (dict))
|
||||
(old-idx-by-id (dict))
|
||||
(consumed (dict))
|
||||
(oi 0)
|
||||
(idx 0))
|
||||
(for-each
|
||||
(fn
|
||||
(kid)
|
||||
(let
|
||||
((id (dom-id kid)))
|
||||
(when
|
||||
(and id (not (empty? id)))
|
||||
(dict-set! old-by-id id kid)
|
||||
(dict-set! old-idx-by-id id idx)))
|
||||
(set! idx (inc idx)))
|
||||
old-kids)
|
||||
(for-each
|
||||
(fn
|
||||
(new-child)
|
||||
(let
|
||||
((match-id (let ((raw-id (dom-id new-child))) (if (empty? raw-id) nil raw-id)))
|
||||
((raw-id (dom-id new-child))
|
||||
(match-id (if (and raw-id (not (empty? raw-id))) raw-id nil))
|
||||
(match-by-id (if match-id (dict-get old-by-id match-id) nil)))
|
||||
(cond
|
||||
(and match-by-id (not (nil? match-by-id)))
|
||||
(do
|
||||
(let
|
||||
((matched-idx (dict-get old-idx-by-id match-id)))
|
||||
(when
|
||||
matched-idx
|
||||
(dict-set! consumed (str matched-idx) true)))
|
||||
(when
|
||||
(and
|
||||
(< oi (len old-kids))
|
||||
@@ -443,20 +460,25 @@
|
||||
(< oi (len old-kids))
|
||||
(let
|
||||
((old-child (nth old-kids oi)))
|
||||
(if
|
||||
(and (not (empty? (dom-id old-child))) (not match-id))
|
||||
(dom-insert-before
|
||||
old-parent
|
||||
(dom-clone new-child)
|
||||
old-child)
|
||||
(do (morph-node old-child new-child) (set! oi (inc oi)))))
|
||||
:else (dom-append old-parent (dom-clone new-child)))))
|
||||
(let
|
||||
((old-id (dom-id old-child)))
|
||||
(if
|
||||
(and old-id (not (empty? old-id)) (not match-id))
|
||||
(dom-insert-before
|
||||
old-parent
|
||||
(dom-clone new-child true)
|
||||
old-child)
|
||||
(do
|
||||
(dict-set! consumed (str oi) true)
|
||||
(morph-node old-child new-child)
|
||||
(set! oi (inc oi))))))
|
||||
:else (dom-append old-parent (dom-clone new-child true)))))
|
||||
new-kids)
|
||||
(for-each
|
||||
(fn
|
||||
((i :as number))
|
||||
(i)
|
||||
(when
|
||||
(>= i oi)
|
||||
(not (dict-get consumed (str i)))
|
||||
(let
|
||||
((leftover (nth old-kids i)))
|
||||
(when
|
||||
@@ -465,7 +487,7 @@
|
||||
(not (dom-has-attr? leftover "sx-preserve"))
|
||||
(not (dom-has-attr? leftover "sx-ignore")))
|
||||
(dom-remove-child old-parent leftover)))))
|
||||
(range oi (len old-kids))))))
|
||||
(range 0 (len old-kids))))))
|
||||
|
||||
(define
|
||||
morph-island-children
|
||||
@@ -588,7 +610,7 @@
|
||||
(morph-children target wrapper)))
|
||||
"outerHTML"
|
||||
(let
|
||||
((parent (dom-parent target)) (new-el (dom-clone new-nodes)))
|
||||
((parent (dom-parent target)) (new-el (dom-clone new-nodes true)))
|
||||
(if
|
||||
(dom-is-fragment? new-nodes)
|
||||
(let
|
||||
@@ -596,7 +618,7 @@
|
||||
(if
|
||||
fc
|
||||
(do
|
||||
(set! new-el (dom-clone fc))
|
||||
(set! new-el (dom-clone fc true))
|
||||
(dom-replace-child parent new-el target)
|
||||
(let
|
||||
((sib (dom-next-sibling fc)))
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,3 +1,3 @@
|
||||
(sxbc 1 "57726b5b82c1a3cb"
|
||||
(code
|
||||
:constants ("assert-signal-value" {:upvalue-count 0 :arity 2 :constants ("deref" "assert=" "str" "Expected signal value " ", got ") :bytecode (20 0 0 16 0 48 1 17 2 20 1 0 16 2 16 1 1 3 0 16 1 1 4 0 16 2 52 2 0 4 49 3 50)} "assert-signal-has-subscribers" {:upvalue-count 0 :arity 1 :constants ("assert" ">" "len" "signal-subscribers" 0 "Expected signal to have subscribers") :bytecode (20 0 0 20 3 0 16 0 48 1 52 2 0 1 1 4 0 52 1 0 2 1 5 0 49 2 50)} "assert-signal-no-subscribers" {:upvalue-count 0 :arity 1 :constants ("assert" "=" "len" "signal-subscribers" 0 "Expected signal to have no subscribers") :bytecode (20 0 0 20 3 0 16 0 48 1 52 2 0 1 1 4 0 52 1 0 2 1 5 0 49 2 50)} "assert-signal-subscriber-count" {:upvalue-count 0 :arity 2 :constants ("len" "signal-subscribers" "assert=" "str" "Expected " " subscribers, got ") :bytecode (20 1 0 16 0 48 1 52 0 0 1 17 2 20 2 0 16 2 16 1 1 4 0 16 1 1 5 0 16 2 52 3 0 4 49 3 50)} "simulate-signal-set!" {:upvalue-count 0 :arity 2 :constants ("reset!") :bytecode (20 0 0 16 0 16 1 49 2 50)} "simulate-signal-swap!" {:upvalue-count 0 :arity 2 :constants ("swap!") :bytecode (20 0 0 16 0 16 1 49 2 50)} "assert-computed-dep-count" {:upvalue-count 0 :arity 2 :constants ("len" "signal-deps" "assert=" "str" "Expected " " deps, got ") :bytecode (20 1 0 16 0 48 1 52 0 0 1 17 2 20 2 0 16 2 16 1 1 4 0 16 1 1 5 0 16 2 52 3 0 4 49 3 50)} "assert-computed-depends-on" {:upvalue-count 0 :arity 2 :constants ("assert" "contains?" "signal-deps" "Expected computed to depend on the given signal") :bytecode (20 0 0 20 2 0 16 0 48 1 16 1 52 1 0 2 1 3 0 49 2 50)} "count-effect-runs" {:upvalue-count 0 :arity 1 :constants ("signal" 0 "effect" {:upvalue-count 1 :arity 0 :constants ("deref") :bytecode (20 0 0 18 0 49 1 50)} {:upvalue-count 2 :arity 0 :constants ("+" 1 "cek-call") :bytecode (18 0 1 1 0 52 0 0 2 19 0 5 20 2 0 18 1 2 49 2 50)}) :bytecode (20 0 0 1 1 0 48 1 17 1 51 3 0 1 1 52 2 0 1 5 1 1 0 17 2 51 4 0 1 2 1 0 52 2 0 1 17 3 16 2 50)} "make-test-signal" {:upvalue-count 0 :arity 1 :constants ("signal" "list" "effect" {:upvalue-count 2 :arity 0 :constants ("append!" "deref") :bytecode (20 0 0 18 0 20 1 0 18 1 48 1 49 2 50)} "history") :bytecode (20 0 0 16 0 48 1 17 1 52 1 0 0 17 2 51 3 0 1 2 1 1 52 2 0 1 5 1 0 0 16 1 1 4 0 16 2 65 2 0 50)} "assert-batch-coalesces" {:upvalue-count 0 :arity 2 :constants (0 "signal" "effect" {:upvalue-count 2 :arity 0 :constants ("deref" "+" 1) :bytecode (20 0 0 18 0 48 1 5 18 1 1 2 0 52 1 0 2 19 1 50)} "batch" "assert=" "str" "Expected " " notifications, got ") :bytecode (1 0 0 17 2 20 1 0 1 0 0 48 1 17 3 51 3 0 1 3 1 2 52 2 0 1 5 1 0 0 17 2 5 20 4 0 16 0 48 1 5 20 5 0 16 2 16 1 1 7 0 16 1 1 8 0 16 2 52 6 0 4 49 3 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 5 51 9 0 128 8 0 5 51 11 0 128 10 0 5 51 13 0 128 12 0 5 51 15 0 128 14 0 5 51 17 0 128 16 0 5 51 19 0 128 18 0 5 51 21 0 128 20 0 50)))
|
||||
:constants ("assert-signal-value" {:upvalue-count 0 :arity 2 :constants ("deref" "assert=" "str" "Expected signal value " ", got ") :bytecode (20 0 0 16 0 48 1 17 2 20 1 0 16 2 16 1 1 3 0 16 1 1 4 0 16 2 52 2 0 4 49 3 50)} "assert-signal-has-subscribers" {:upvalue-count 0 :arity 1 :constants ("assert" ">" "len" "signal-subscribers" 0 "Expected signal to have subscribers") :bytecode (20 0 0 20 3 0 16 0 48 1 52 2 0 1 1 4 0 52 1 0 2 1 5 0 49 2 50)} "assert-signal-no-subscribers" {:upvalue-count 0 :arity 1 :constants ("assert" "=" "len" "signal-subscribers" 0 "Expected signal to have no subscribers") :bytecode (20 0 0 20 3 0 16 0 48 1 52 2 0 1 1 4 0 52 1 0 2 1 5 0 49 2 50)} "assert-signal-subscriber-count" {:upvalue-count 0 :arity 2 :constants ("len" "signal-subscribers" "assert=" "str" "Expected " " subscribers, got ") :bytecode (20 1 0 16 0 48 1 52 0 0 1 17 2 20 2 0 16 2 16 1 1 4 0 16 1 1 5 0 16 2 52 3 0 4 49 3 50)} "simulate-signal-set!" {:upvalue-count 0 :arity 2 :constants ("reset!") :bytecode (20 0 0 16 0 16 1 49 2 50)} "simulate-signal-swap!" {:upvalue-count 0 :arity 2 :constants ("swap!") :bytecode (20 0 0 16 0 16 1 49 2 50)} "assert-computed-dep-count" {:upvalue-count 0 :arity 2 :constants ("len" "signal-deps" "assert=" "str" "Expected " " deps, got ") :bytecode (20 1 0 16 0 48 1 52 0 0 1 17 2 20 2 0 16 2 16 1 1 4 0 16 1 1 5 0 16 2 52 3 0 4 49 3 50)} "assert-computed-depends-on" {:upvalue-count 0 :arity 2 :constants ("assert" "contains?" "signal-deps" "Expected computed to depend on the given signal") :bytecode (20 0 0 20 2 0 16 0 48 1 16 1 52 1 0 2 1 3 0 49 2 50)} "count-effect-runs" {:upvalue-count 0 :arity 1 :constants ("signal" 0 "effect" {:upvalue-count 1 :arity 0 :constants ("deref") :bytecode (20 0 0 18 0 49 1 50)} {:upvalue-count 2 :arity 0 :constants ("+" 1 "cek-call") :bytecode (18 0 1 1 0 52 0 0 2 19 0 5 20 2 0 18 1 2 49 2 50)}) :bytecode (20 0 0 1 1 0 48 1 17 1 20 2 0 51 3 0 1 1 48 1 5 1 1 0 17 2 20 2 0 51 4 0 1 2 1 0 48 1 17 3 16 2 50)} "make-test-signal" {:upvalue-count 0 :arity 1 :constants ("signal" "list" "effect" {:upvalue-count 2 :arity 0 :constants ("append!" "deref") :bytecode (20 0 0 18 0 20 1 0 18 1 48 1 49 2 50)} "history") :bytecode (20 0 0 16 0 48 1 17 1 52 1 0 0 17 2 20 2 0 51 3 0 1 2 1 1 48 1 5 1 0 0 16 1 1 4 0 16 2 65 2 0 50)} "assert-batch-coalesces" {:upvalue-count 0 :arity 2 :constants (0 "signal" "effect" {:upvalue-count 2 :arity 0 :constants ("deref" "+" 1) :bytecode (20 0 0 18 0 48 1 5 18 1 1 2 0 52 1 0 2 19 1 50)} "batch" "assert=" "str" "Expected " " notifications, got ") :bytecode (1 0 0 17 2 20 1 0 1 0 0 48 1 17 3 20 2 0 51 3 0 1 3 1 2 48 1 5 1 0 0 17 2 5 20 4 0 16 0 48 1 5 20 5 0 16 2 16 1 1 7 0 16 1 1 8 0 16 2 52 6 0 4 49 3 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 5 51 9 0 128 8 0 5 51 11 0 128 10 0 5 51 13 0 128 12 0 5 51 15 0 128 14 0 5 51 17 0 128 16 0 5 51 19 0 128 18 0 5 51 21 0 128 20 0 50)))
|
||||
|
||||
@@ -256,25 +256,6 @@
|
||||
"sx:afterSwap"
|
||||
(dict "target" target-el "swap" swap-style)))))))
|
||||
|
||||
(define
|
||||
flush-cssx!
|
||||
:effects (mutation io)
|
||||
(fn
|
||||
()
|
||||
(let
|
||||
((rules (collected "cssx")))
|
||||
(clear-collected! "cssx")
|
||||
(when
|
||||
(not (empty? rules))
|
||||
(let
|
||||
((style (dom-query "#sx-css")))
|
||||
(when
|
||||
style
|
||||
(dom-set-prop
|
||||
style
|
||||
"textContent"
|
||||
(str (dom-get-prop style "textContent") (join "" rules)))))))))
|
||||
|
||||
(define
|
||||
handle-sx-response
|
||||
:effects (mutation io)
|
||||
@@ -527,8 +508,7 @@
|
||||
(sx-hydrate root)
|
||||
(sx-hydrate-islands root)
|
||||
(run-post-render-hooks)
|
||||
(process-elements root)
|
||||
(flush-cssx!)))
|
||||
(process-elements root)))
|
||||
|
||||
(define
|
||||
process-settle-hooks
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,3 +1,3 @@
|
||||
(sxbc 1 "7e4a727b2f55684e"
|
||||
(code
|
||||
:constants ("with-marsh-scope" {:upvalue-count 0 :arity 2 :constants ("list" "with-island-scope" {:upvalue-count 1 :arity 1 :constants ("append!") :bytecode (20 0 0 18 0 16 0 49 2 50)} "dom-set-data" "sx-marsh-disposers") :bytecode (52 0 0 0 17 2 20 1 0 51 2 0 1 2 16 1 48 2 5 20 3 0 16 0 1 4 0 16 2 49 3 50)} "dispose-marsh-scope" {:upvalue-count 0 :arity 1 :constants ("dom-get-data" "sx-marsh-disposers" "for-each" {:upvalue-count 0 :arity 1 :constants ("cek-call") :bytecode (20 0 0 16 0 2 49 2 50)} "dom-set-data") :bytecode (20 0 0 16 0 1 1 0 48 2 17 1 16 1 33 24 0 51 3 0 16 1 52 2 0 2 5 20 4 0 16 0 1 1 0 2 49 3 32 1 0 2 50)} "emit-event" {:upvalue-count 0 :arity 3 :constants ("dom-dispatch") :bytecode (20 0 0 16 0 16 1 16 2 49 3 50)} "on-event" {:upvalue-count 0 :arity 3 :constants ("dom-on") :bytecode (20 0 0 16 0 16 1 16 2 49 3 50)} "bridge-event" {:upvalue-count 0 :arity 4 :constants ("effect" {:upvalue-count 4 :arity 0 :constants ("dom-on" {:upvalue-count 2 :arity 1 :constants ("event-detail" "cek-call" "list" "reset!") :bytecode (20 0 0 16 0 48 1 17 1 18 0 33 16 0 20 1 0 18 0 16 1 52 2 0 1 48 2 32 2 0 16 1 17 2 20 3 0 18 1 16 2 49 2 50)}) :bytecode (20 0 0 18 0 18 1 51 1 0 0 2 0 3 48 3 17 0 16 0 50)}) :bytecode (51 1 0 1 0 1 1 1 3 1 2 52 0 0 1 50)} "resource" {:upvalue-count 0 :arity 1 :constants ("signal" "dict" "loading" "data" "error" "promise-then" "cek-call" {:upvalue-count 1 :arity 1 :constants ("reset!" "dict" "loading" "data" "error") :bytecode (20 0 0 18 0 1 2 0 4 1 3 0 16 0 1 4 0 2 52 1 0 6 49 2 50)} {:upvalue-count 1 :arity 1 :constants ("reset!" "dict" "loading" "data" "error") :bytecode (20 0 0 18 0 1 2 0 4 1 3 0 2 1 4 0 16 0 52 1 0 6 49 2 50)}) :bytecode (20 0 0 1 2 0 3 1 3 0 2 1 4 0 2 52 1 0 6 48 1 17 1 20 5 0 20 6 0 16 0 2 48 2 51 7 0 1 1 51 8 0 1 1 48 3 5 16 1 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 5 51 9 0 128 8 0 5 51 11 0 128 10 0 50)))
|
||||
:constants ("with-marsh-scope" {:upvalue-count 0 :arity 2 :constants ("list" "with-island-scope" {:upvalue-count 1 :arity 1 :constants ("append!") :bytecode (20 0 0 18 0 16 0 49 2 50)} "dom-set-data" "sx-marsh-disposers") :bytecode (52 0 0 0 17 2 20 1 0 51 2 0 1 2 16 1 48 2 5 20 3 0 16 0 1 4 0 16 2 49 3 50)} "dispose-marsh-scope" {:upvalue-count 0 :arity 1 :constants ("dom-get-data" "sx-marsh-disposers" "for-each" {:upvalue-count 0 :arity 1 :constants ("cek-call") :bytecode (20 0 0 16 0 2 49 2 50)} "dom-set-data") :bytecode (20 0 0 16 0 1 1 0 48 2 17 1 16 1 33 24 0 51 3 0 16 1 52 2 0 2 5 20 4 0 16 0 1 1 0 2 49 3 32 1 0 2 50)} "emit-event" {:upvalue-count 0 :arity 3 :constants ("dom-dispatch") :bytecode (20 0 0 16 0 16 1 16 2 49 3 50)} "on-event" {:upvalue-count 0 :arity 3 :constants ("dom-on") :bytecode (20 0 0 16 0 16 1 16 2 49 3 50)} "bridge-event" {:upvalue-count 0 :arity 4 :constants ("effect" {:upvalue-count 4 :arity 0 :constants ("dom-on" {:upvalue-count 2 :arity 1 :constants ("event-detail" "cek-call" "list" "reset!") :bytecode (20 0 0 16 0 48 1 17 1 18 0 33 16 0 20 1 0 18 0 16 1 52 2 0 1 48 2 32 2 0 16 1 17 2 20 3 0 18 1 16 2 49 2 50)}) :bytecode (20 0 0 18 0 18 1 51 1 0 0 2 0 3 48 3 17 0 16 0 50)}) :bytecode (20 0 0 51 1 0 1 0 1 1 1 3 1 2 49 1 50)} "resource" {:upvalue-count 0 :arity 1 :constants ("signal" "dict" "loading" "data" "error" "promise-then" "cek-call" {:upvalue-count 1 :arity 1 :constants ("reset!" "dict" "loading" "data" "error") :bytecode (20 0 0 18 0 1 2 0 4 1 3 0 16 0 1 4 0 2 52 1 0 6 49 2 50)} {:upvalue-count 1 :arity 1 :constants ("reset!" "dict" "loading" "data" "error") :bytecode (20 0 0 18 0 1 2 0 4 1 3 0 2 1 4 0 16 0 52 1 0 6 49 2 50)}) :bytecode (20 0 0 1 2 0 3 1 3 0 2 1 4 0 2 52 1 0 6 48 1 17 1 20 5 0 20 6 0 16 0 2 48 2 51 7 0 1 1 51 8 0 1 1 48 3 5 16 1 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 5 51 9 0 128 8 0 5 51 11 0 128 10 0 50)))
|
||||
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
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};
|
||||
}
|
||||
(globalThis))
|
||||
({"link":[["runtime-0db9b496",0],["prelude-d7e4b000",0],["stdlib-23ce0836",[]],["sx-a0c22109",[2]],["jsoo_runtime-f96b44a8",[2]],["js_of_ocaml-651f6707",[2,4]],["dune__exe__Sx_browser-8ae21d0a",[2,3,5]],["std_exit-10fb8830",[2]],["start-80fdb768",0]],"generated":(b=>{var
|
||||
({"link":[["runtime-0db9b496",0],["prelude-d7e4b000",0],["stdlib-23ce0836",[]],["sx-86ee6606",[2]],["jsoo_runtime-f96b44a8",[2]],["js_of_ocaml-651f6707",[2,4]],["dune__exe__Sx_browser-8ae21d0a",[2,3,5]],["std_exit-10fb8830",[2]],["start-80fdb768",0]],"generated":(b=>{var
|
||||
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_exn_with_js_backtrace not implemented")},"caml_int64_create_lo_mi_hi":()=>{throw new
|
||||
|
||||
Reference in New Issue
Block a user