Transpile dom.sx + browser.sx into bundle; add FFI variable aliases

dom-lib and browser-lib were listed in ADAPTER_FILES but never actually
transpiled — their functions only existed as native PLATFORM_*_JS code.
Add them to the build loop so the FFI library wrappers are compiled.
Add hostCall/hostGet/etc. variable aliases for transpiled code, and
console-log to browser.sx for runtime-eval'd SX code.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-24 11:43:42 +00:00
parent bc7da977a0
commit 8e6e7dce43
4 changed files with 434 additions and 2 deletions

View File

@@ -14,7 +14,7 @@
// =========================================================================
var NIL = Object.freeze({ _nil: true, toString: function() { return "nil"; } });
var SX_VERSION = "2026-03-24T11:14:33Z";
var SX_VERSION = "2026-03-24T11:42:17Z";
function isNil(x) { return x === NIL || x === null || x === undefined; }
function isSxTruthy(x) { return x !== false && !isNil(x); }
@@ -730,6 +730,15 @@
promise.then(cb);
}
};
// Aliases for transpiled dom.sx / browser.sx code (transpiler mangles host-* names)
var hostGlobal = PRIMITIVES["host-global"];
var hostGet = PRIMITIVES["host-get"];
var hostSet = PRIMITIVES["host-set!"];
var hostCall = PRIMITIVES["host-call"];
var hostNew = PRIMITIVES["host-new"];
var hostCallback = PRIMITIVES["host-callback"];
var hostTypeof = PRIMITIVES["host-typeof"];
var hostAwait = PRIMITIVES["host-await"];
// processBindings and evalCond — now specced in render.sx, bootstrapped above
@@ -2960,6 +2969,415 @@ PRIMITIVES["aser-special"] = aserSpecial;
PRIMITIVES["eval-case-aser"] = evalCaseAser;
// === Transpiled from lib/dom (DOM library) ===
// dom-document
var domDocument = function() { return hostGlobal("document"); };
PRIMITIVES["dom-document"] = domDocument;
// dom-window
var domWindow = function() { return hostGlobal("window"); };
PRIMITIVES["dom-window"] = domWindow;
// dom-body
var domBody = function() { return hostGet(domDocument(), "body"); };
PRIMITIVES["dom-body"] = domBody;
// dom-head
var domHead = function() { return hostGet(domDocument(), "head"); };
PRIMITIVES["dom-head"] = domHead;
// dom-create-element
var domCreateElement = function(tag) { return hostCall(domDocument(), "createElement", tag); };
PRIMITIVES["dom-create-element"] = domCreateElement;
// create-text-node
var createTextNode = function(s) { return hostCall(domDocument(), "createTextNode", s); };
PRIMITIVES["create-text-node"] = createTextNode;
// create-fragment
var createFragment = function() { return hostCall(domDocument(), "createDocumentFragment"); };
PRIMITIVES["create-fragment"] = createFragment;
// dom-append
var domAppend = function(parent, child) { return (isSxTruthy((isSxTruthy(parent) && child)) ? hostCall(parent, "appendChild", child) : NIL); };
PRIMITIVES["dom-append"] = domAppend;
// dom-prepend
var domPrepend = function(parent, child) { return (isSxTruthy((isSxTruthy(parent) && child)) ? hostCall(parent, "prepend", child) : NIL); };
PRIMITIVES["dom-prepend"] = domPrepend;
// dom-insert-before
var domInsertBefore = function(parent, child, ref) { return (isSxTruthy((isSxTruthy(parent) && child)) ? hostCall(parent, "insertBefore", child, ref) : NIL); };
PRIMITIVES["dom-insert-before"] = domInsertBefore;
// dom-remove-child
var domRemoveChild = function(parent, child) { return (isSxTruthy((isSxTruthy(parent) && child)) ? hostCall(parent, "removeChild", child) : NIL); };
PRIMITIVES["dom-remove-child"] = domRemoveChild;
// dom-replace-child
var domReplaceChild = function(parent, newChild, oldChild) { return (isSxTruthy((isSxTruthy(parent) && isSxTruthy(newChild) && oldChild)) ? hostCall(parent, "replaceChild", newChild, oldChild) : NIL); };
PRIMITIVES["dom-replace-child"] = domReplaceChild;
// dom-clone
var domClone = function(node, deep) { return hostCall(node, "cloneNode", (isSxTruthy(isNil(deep)) ? true : deep)); };
PRIMITIVES["dom-clone"] = domClone;
// dom-query
var domQuery = function(sel) { return hostCall(domDocument(), "querySelector", sel); };
PRIMITIVES["dom-query"] = domQuery;
// dom-query-all
var domQueryAll = function(root, sel) { return (isSxTruthy(isNil(sel)) ? hostCall(domDocument(), "querySelectorAll", root) : hostCall(root, "querySelectorAll", sel)); };
PRIMITIVES["dom-query-all"] = domQueryAll;
// dom-query-by-id
var domQueryById = function(id) { return hostCall(domDocument(), "getElementById", id); };
PRIMITIVES["dom-query-by-id"] = domQueryById;
// dom-closest
var domClosest = function(el, sel) { return (isSxTruthy(el) ? hostCall(el, "closest", sel) : NIL); };
PRIMITIVES["dom-closest"] = domClosest;
// dom-matches?
var domMatches = function(el, sel) { return (isSxTruthy((isSxTruthy(el) && hostGet(el, "matches"))) ? hostCall(el, "matches", sel) : false); };
PRIMITIVES["dom-matches?"] = domMatches;
// dom-get-attr
var domGetAttr = function(el, name) { return (isSxTruthy((isSxTruthy(el) && hostGet(el, "getAttribute"))) ? (function() {
var v = hostCall(el, "getAttribute", name);
return (isSxTruthy(isNil(v)) ? NIL : v);
})() : NIL); };
PRIMITIVES["dom-get-attr"] = domGetAttr;
// dom-set-attr
var domSetAttr = function(el, name, val) { return (isSxTruthy((isSxTruthy(el) && hostGet(el, "setAttribute"))) ? hostCall(el, "setAttribute", name, val) : NIL); };
PRIMITIVES["dom-set-attr"] = domSetAttr;
// dom-remove-attr
var domRemoveAttr = function(el, name) { return (isSxTruthy((isSxTruthy(el) && hostGet(el, "removeAttribute"))) ? hostCall(el, "removeAttribute", name) : NIL); };
PRIMITIVES["dom-remove-attr"] = domRemoveAttr;
// dom-has-attr?
var domHasAttr = function(el, name) { return (isSxTruthy((isSxTruthy(el) && hostGet(el, "hasAttribute"))) ? hostCall(el, "hasAttribute", name) : false); };
PRIMITIVES["dom-has-attr?"] = domHasAttr;
// dom-add-class
var domAddClass = function(el, cls) { return (isSxTruthy(el) ? hostCall(hostGet(el, "classList"), "add", cls) : NIL); };
PRIMITIVES["dom-add-class"] = domAddClass;
// dom-remove-class
var domRemoveClass = function(el, cls) { return (isSxTruthy(el) ? hostCall(hostGet(el, "classList"), "remove", cls) : NIL); };
PRIMITIVES["dom-remove-class"] = domRemoveClass;
// dom-has-class?
var domHasClass = function(el, cls) { return (isSxTruthy(el) ? hostCall(hostGet(el, "classList"), "contains", cls) : false); };
PRIMITIVES["dom-has-class?"] = domHasClass;
// dom-text-content
var domTextContent = function(el) { return hostGet(el, "textContent"); };
PRIMITIVES["dom-text-content"] = domTextContent;
// dom-set-text-content
var domSetTextContent = function(el, val) { return hostSet(el, "textContent", val); };
PRIMITIVES["dom-set-text-content"] = domSetTextContent;
// dom-inner-html
var domInnerHtml = function(el) { return hostGet(el, "innerHTML"); };
PRIMITIVES["dom-inner-html"] = domInnerHtml;
// dom-set-inner-html
var domSetInnerHtml = function(el, val) { return hostSet(el, "innerHTML", val); };
PRIMITIVES["dom-set-inner-html"] = domSetInnerHtml;
// dom-outer-html
var domOuterHtml = function(el) { return hostGet(el, "outerHTML"); };
PRIMITIVES["dom-outer-html"] = domOuterHtml;
// dom-insert-adjacent-html
var domInsertAdjacentHtml = function(el, position, html) { return hostCall(el, "insertAdjacentHTML", position, html); };
PRIMITIVES["dom-insert-adjacent-html"] = domInsertAdjacentHtml;
// dom-get-style
var domGetStyle = function(el, prop) { return hostGet(hostGet(el, "style"), prop); };
PRIMITIVES["dom-get-style"] = domGetStyle;
// dom-set-style
var domSetStyle = function(el, prop, val) { return hostCall(hostGet(el, "style"), "setProperty", prop, val); };
PRIMITIVES["dom-set-style"] = domSetStyle;
// dom-get-prop
var domGetProp = function(el, name) { return hostGet(el, name); };
PRIMITIVES["dom-get-prop"] = domGetProp;
// dom-set-prop
var domSetProp = function(el, name, val) { return hostSet(el, name, val); };
PRIMITIVES["dom-set-prop"] = domSetProp;
// dom-tag-name
var domTagName = function(el) { return (isSxTruthy(el) ? lower(sxOr(hostGet(el, "tagName"), "")) : ""); };
PRIMITIVES["dom-tag-name"] = domTagName;
// dom-node-type
var domNodeType = function(el) { return hostGet(el, "nodeType"); };
PRIMITIVES["dom-node-type"] = domNodeType;
// dom-node-name
var domNodeName = function(el) { return hostGet(el, "nodeName"); };
PRIMITIVES["dom-node-name"] = domNodeName;
// dom-id
var domId = function(el) { return hostGet(el, "id"); };
PRIMITIVES["dom-id"] = domId;
// dom-parent
var domParent = function(el) { return hostGet(el, "parentNode"); };
PRIMITIVES["dom-parent"] = domParent;
// dom-first-child
var domFirstChild = function(el) { return hostGet(el, "firstChild"); };
PRIMITIVES["dom-first-child"] = domFirstChild;
// dom-next-sibling
var domNextSibling = function(el) { return hostGet(el, "nextSibling"); };
PRIMITIVES["dom-next-sibling"] = domNextSibling;
// dom-child-list
var domChildList = function(el) { return (isSxTruthy(el) ? hostCall(hostGlobal("Array"), "from", hostGet(el, "childNodes")) : []); };
PRIMITIVES["dom-child-list"] = domChildList;
// dom-is-fragment?
var domIsFragment = function(el) { return (hostGet(el, "nodeType") == 11); };
PRIMITIVES["dom-is-fragment?"] = domIsFragment;
// dom-focus
var domFocus = function(el) { return (isSxTruthy(el) ? hostCall(el, "focus") : NIL); };
PRIMITIVES["dom-focus"] = domFocus;
// dom-parse-html
var domParseHtml = function(html) { return (function() {
var parser = hostNew("DOMParser");
var doc = hostCall(parser, "parseFromString", html, "text/html");
return hostGet(hostGet(doc, "body"), "childNodes");
})(); };
PRIMITIVES["dom-parse-html"] = domParseHtml;
// dom-listen
var domListen = function(el, eventName, handler) { return (function() {
var cb = hostCallback(handler);
hostCall(el, "addEventListener", eventName, cb);
return function() { return hostCall(el, "removeEventListener", eventName, cb); };
})(); };
PRIMITIVES["dom-listen"] = domListen;
// dom-dispatch
var domDispatch = function(el, eventName, detail) { return (function() {
var evt = hostNew("CustomEvent", eventName, {["detail"]: detail, ["bubbles"]: true});
return hostCall(el, "dispatchEvent", evt);
})(); };
PRIMITIVES["dom-dispatch"] = domDispatch;
// event-detail
var eventDetail = function(evt) { return hostGet(evt, "detail"); };
PRIMITIVES["event-detail"] = eventDetail;
// prevent-default
var preventDefault_ = function(e) { return (isSxTruthy(e) ? hostCall(e, "preventDefault") : NIL); };
PRIMITIVES["prevent-default"] = preventDefault_;
// stop-propagation
var stopPropagation_ = function(e) { return (isSxTruthy(e) ? hostCall(e, "stopPropagation") : NIL); };
PRIMITIVES["stop-propagation"] = stopPropagation_;
// event-modifier-key?
var eventModifierKey_p = function(e) { return (isSxTruthy(e) && sxOr(hostGet(e, "ctrlKey"), hostGet(e, "metaKey"), hostGet(e, "shiftKey"), hostGet(e, "altKey"))); };
PRIMITIVES["event-modifier-key?"] = eventModifierKey_p;
// element-value
var elementValue = function(el) { return (isSxTruthy((isSxTruthy(el) && !isSxTruthy(isNil(hostGet(el, "value"))))) ? hostGet(el, "value") : NIL); };
PRIMITIVES["element-value"] = elementValue;
// error-message
var errorMessage = function(e) { return (isSxTruthy((isSxTruthy(e) && hostGet(e, "message"))) ? hostGet(e, "message") : (String(e))); };
PRIMITIVES["error-message"] = errorMessage;
// dom-get-data
var domGetData = function(el, key) { return (function() {
var store = hostGet(el, "__sx_data");
return (isSxTruthy(store) ? hostGet(store, key) : NIL);
})(); };
PRIMITIVES["dom-get-data"] = domGetData;
// dom-set-data
var domSetData = function(el, key, val) { if (isSxTruthy(!isSxTruthy(hostGet(el, "__sx_data")))) {
hostSet(el, "__sx_data", {});
}
return hostSet(hostGet(el, "__sx_data"), key, val); };
PRIMITIVES["dom-set-data"] = domSetData;
// dom-append-to-head
var domAppendToHead = function(el) { return (isSxTruthy(domHead()) ? hostCall(domHead(), "appendChild", el) : NIL); };
PRIMITIVES["dom-append-to-head"] = domAppendToHead;
// set-document-title
var setDocumentTitle = function(title) { return hostSet(domDocument(), "title", title); };
PRIMITIVES["set-document-title"] = setDocumentTitle;
// === Transpiled from lib/browser (browser API library) ===
// browser-location-href
var browserLocationHref = function() { return hostGet(hostGet(domWindow(), "location"), "href"); };
PRIMITIVES["browser-location-href"] = browserLocationHref;
// browser-location-pathname
var browserLocationPathname = function() { return hostGet(hostGet(domWindow(), "location"), "pathname"); };
PRIMITIVES["browser-location-pathname"] = browserLocationPathname;
// browser-location-origin
var browserLocationOrigin = function() { return hostGet(hostGet(domWindow(), "location"), "origin"); };
PRIMITIVES["browser-location-origin"] = browserLocationOrigin;
// browser-same-origin?
var browserSameOrigin = function(url) { return startsWith(url, browserLocationOrigin()); };
PRIMITIVES["browser-same-origin?"] = browserSameOrigin;
// browser-push-state
var browserPushState = function(state, title, url) { return hostCall(hostGet(domWindow(), "history"), "pushState", state, title, url); };
PRIMITIVES["browser-push-state"] = browserPushState;
// browser-replace-state
var browserReplaceState = function(state, title, url) { return hostCall(hostGet(domWindow(), "history"), "replaceState", state, title, url); };
PRIMITIVES["browser-replace-state"] = browserReplaceState;
// browser-reload
var browserReload = function() { return hostCall(hostGet(domWindow(), "location"), "reload"); };
PRIMITIVES["browser-reload"] = browserReload;
// browser-navigate
var browserNavigate = function(url) { return hostSet(hostGet(domWindow(), "location"), "href", url); };
PRIMITIVES["browser-navigate"] = browserNavigate;
// local-storage-get
var localStorageGet = function(key) { return hostCall(hostGet(domWindow(), "localStorage"), "getItem", key); };
PRIMITIVES["local-storage-get"] = localStorageGet;
// local-storage-set
var localStorageSet = function(key, val) { return hostCall(hostGet(domWindow(), "localStorage"), "setItem", key, val); };
PRIMITIVES["local-storage-set"] = localStorageSet;
// local-storage-remove
var localStorageRemove = function(key) { return hostCall(hostGet(domWindow(), "localStorage"), "removeItem", key); };
PRIMITIVES["local-storage-remove"] = localStorageRemove;
// set-timeout
var setTimeout_ = function(fnVal, ms) { return hostCall(domWindow(), "setTimeout", hostCallback(fnVal), ms); };
PRIMITIVES["set-timeout"] = setTimeout_;
// set-interval
var setInterval_ = function(fnVal, ms) { return hostCall(domWindow(), "setInterval", hostCallback(fnVal), ms); };
PRIMITIVES["set-interval"] = setInterval_;
// clear-timeout
var clearTimeout_ = function(id) { return hostCall(domWindow(), "clearTimeout", id); };
PRIMITIVES["clear-timeout"] = clearTimeout_;
// clear-interval
var clearInterval_ = function(id) { return hostCall(domWindow(), "clearInterval", id); };
PRIMITIVES["clear-interval"] = clearInterval_;
// request-animation-frame
var requestAnimationFrame_ = function(fnVal) { return hostCall(domWindow(), "requestAnimationFrame", hostCallback(fnVal)); };
PRIMITIVES["request-animation-frame"] = requestAnimationFrame_;
// fetch-request
var fetchRequest = function(url, opts) { return hostCall(domWindow(), "fetch", url, opts); };
PRIMITIVES["fetch-request"] = fetchRequest;
// new-abort-controller
var newAbortController = function() { return hostNew("AbortController"); };
PRIMITIVES["new-abort-controller"] = newAbortController;
// controller-signal
var controllerSignal = function(controller) { return hostGet(controller, "signal"); };
PRIMITIVES["controller-signal"] = controllerSignal;
// controller-abort
var controllerAbort = function(controller) { return hostCall(controller, "abort"); };
PRIMITIVES["controller-abort"] = controllerAbort;
// promise-then
var promiseThen = function(p, onResolve, onReject) { return (function() {
var cbResolve = hostCallback(onResolve);
var cbReject = (isSxTruthy(onReject) ? hostCallback(onReject) : NIL);
return (isSxTruthy(cbReject) ? hostCall(hostCall(p, "then", cbResolve), "catch", cbReject) : hostCall(p, "then", cbResolve));
})(); };
PRIMITIVES["promise-then"] = promiseThen;
// promise-resolve
var promiseResolve = function(val) { return hostCall(hostGlobal("Promise"), "resolve", val); };
PRIMITIVES["promise-resolve"] = promiseResolve;
// promise-delayed
var promiseDelayed = function(ms, val) { return hostNew("Promise", hostCallback(function(resolve) { return setTimeout_(function() { return hostCall(resolve, "call", NIL, val); }, ms); })); };
PRIMITIVES["promise-delayed"] = promiseDelayed;
// browser-confirm
var browserConfirm = function(msg) { return hostCall(domWindow(), "confirm", msg); };
PRIMITIVES["browser-confirm"] = browserConfirm;
// browser-prompt
var browserPrompt = function(msg, default_) { return hostCall(domWindow(), "prompt", msg, default_); };
PRIMITIVES["browser-prompt"] = browserPrompt;
// browser-media-matches?
var browserMediaMatches = function(query) { return hostGet(hostCall(domWindow(), "matchMedia", query), "matches"); };
PRIMITIVES["browser-media-matches?"] = browserMediaMatches;
// json-parse
var jsonParse = function(s) { return hostCall(hostGlobal("JSON"), "parse", s); };
PRIMITIVES["json-parse"] = jsonParse;
// log-info
var logInfo = function(msg) { return hostCall(hostGlobal("console"), "log", (String("[sx] ") + String(msg))); };
PRIMITIVES["log-info"] = logInfo;
// log-warn
var logWarn = function(msg) { return hostCall(hostGlobal("console"), "warn", (String("[sx] ") + String(msg))); };
PRIMITIVES["log-warn"] = logWarn;
// console-log
var consoleLog = function() { var args = Array.prototype.slice.call(arguments, 0); return hostCall(hostGlobal("console"), "log", join(" ", cons("[sx]", map(str, args)))); };
PRIMITIVES["console-log"] = consoleLog;
// now-ms
var nowMs = function() { return hostCall(hostGlobal("Date"), "now"); };
PRIMITIVES["now-ms"] = nowMs;
// schedule-idle
var scheduleIdle = function(f) { return (function() {
var cb = hostCallback(f);
return (isSxTruthy(hostGet(domWindow(), "requestIdleCallback")) ? hostCall(domWindow(), "requestIdleCallback", cb) : setTimeout_(cb, 0));
})(); };
PRIMITIVES["schedule-idle"] = scheduleIdle;
// set-cookie
var setCookie = function(name, value, days) { return (function() {
var d = sxOr(days, 365);
var expires = hostCall(hostNew("Date", (hostCall(hostGlobal("Date"), "now") + (d * 86400000.0))), "toUTCString");
return hostSet(domDocument(), "cookie", (String(name) + String("=") + String(hostCall(NIL, "encodeURIComponent", value)) + String(";expires=") + String(expires) + String(";path=/;SameSite=Lax")));
})(); };
PRIMITIVES["set-cookie"] = setCookie;
// get-cookie
var getCookie = function(name) { return (function() {
var cookies = hostGet(domDocument(), "cookie");
var match = hostCall(cookies, "match", hostNew("RegExp", (String("(?:^|;\\s*)") + String(name) + String("=([^;]*)"))));
return (isSxTruthy(match) ? hostCall(NIL, "decodeURIComponent", hostGet(match, 1)) : NIL);
})(); };
PRIMITIVES["get-cookie"] = getCookie;
// === Transpiled from adapter-dom ===
// SVG_NS