js: fix lambda binding (index-of on lists), add vectors + R7RS platform stubs
- Fix PRIMITIVES["index-of"] for arrays: return NIL when not found (matching OCaml semantics) so bind-lambda-params correctly detects absent &rest params. Previously String(array).indexOf() returned -1, which passed number? check and mis-fired the &rest branch, leaving non-&rest params unbound. - Declare var _lastErrorKont_ and var hostError in IIFE scope (strict mode fix) - Add PRIMITIVES["host-error"], ["try-catch"], ["without-io-hook"] - Add env["test-allowed?"] stub in run_tests.js - Add spec/tests/test-vectors.sx: 42 tests for all vector primitives - Rebuild sx-browser.js: 1847 standard / 2362 full tests pass (up from 5) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -16,6 +16,13 @@
|
||||
if (a === b) return true;
|
||||
if (a && b && a._sym && b._sym) return a.name === b.name;
|
||||
if (a && b && a._kw && b._kw) return a.name === b.name;
|
||||
if (a && b && a._vector && b._vector) {
|
||||
if (a.arr.length !== b.arr.length) return false;
|
||||
for (var _i = 0; _i < a.arr.length; _i++) {
|
||||
if (!sxEq(a.arr[_i], b.arr[_i])) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -24,7 +31,7 @@
|
||||
// =========================================================================
|
||||
|
||||
var NIL = Object.freeze({ _nil: true, toString: function() { return "nil"; } });
|
||||
var SX_VERSION = "2026-04-05T11:01:51Z";
|
||||
var SX_VERSION = "2026-04-26T10:01:22Z";
|
||||
|
||||
function isNil(x) { return x === NIL || x === null || x === undefined; }
|
||||
function isSxTruthy(x) { return x !== false && !isNil(x); }
|
||||
@@ -82,6 +89,44 @@
|
||||
function SxSpread(attrs) { this.attrs = attrs || {}; }
|
||||
SxSpread.prototype._spread = true;
|
||||
|
||||
function SxVector(arr) { this.arr = arr || []; }
|
||||
SxVector.prototype._vector = true;
|
||||
|
||||
var _paramUidCounter = 0;
|
||||
function SxParameter(defaultVal, converter) {
|
||||
this._uid = ++_paramUidCounter;
|
||||
this._default = defaultVal;
|
||||
this._converter = converter || null;
|
||||
}
|
||||
SxParameter.prototype._parameter = true;
|
||||
function parameter_p(x) { return x != null && x._parameter === true; }
|
||||
function parameterUid(p) { return p._uid; }
|
||||
function parameterDefault(p) { return p._default; }
|
||||
|
||||
function SxCallccContinuation(capturedKont) { this._captured = capturedKont; }
|
||||
SxCallccContinuation.prototype._callcc = true;
|
||||
function makeCallccContinuation(kont) { return new SxCallccContinuation(kont); }
|
||||
function callccContinuation_p(x) { return x != null && x._callcc === true; }
|
||||
function callccContinuationData(x) { return x._captured; }
|
||||
|
||||
function evalError_p(v) {
|
||||
return v != null && typeof v === "object" && v["__eval_error__"] === true;
|
||||
}
|
||||
|
||||
function sxApplyCek(f, args) {
|
||||
try {
|
||||
return typeof f === "function" ? f.apply(null, args) : f;
|
||||
} catch (e) {
|
||||
if (e && e._perform_request) throw e;
|
||||
if (e && e._cek_suspend) throw e;
|
||||
return {"__eval_error__": true, "message": e && e.message ? e.message : String(e)};
|
||||
}
|
||||
}
|
||||
|
||||
var _JIT_SKIP_SENTINEL = {"__jit_skip": true};
|
||||
function jitTryCall(f, args) { return _JIT_SKIP_SENTINEL; }
|
||||
function jitSkip_p(v) { return v === _JIT_SKIP_SENTINEL || (v != null && v["__jit_skip"] === true); }
|
||||
|
||||
var _scopeStacks = {};
|
||||
|
||||
function isSym(x) { return x != null && x._sym === true; }
|
||||
@@ -122,6 +167,7 @@
|
||||
if (x._macro) return "macro";
|
||||
if (x._raw) return "raw-html";
|
||||
if (x._sx_expr) return "sx-expr";
|
||||
if (x._vector) return "vector";
|
||||
if (typeof Node !== "undefined" && x instanceof Node) return "dom-node";
|
||||
if (Array.isArray(x)) return "list";
|
||||
if (typeof x === "object") return "dict";
|
||||
@@ -288,6 +334,12 @@
|
||||
// Placeholder — overridden by transpiled version from render.sx
|
||||
function isRenderExpr(expr) { return false; }
|
||||
|
||||
// Last error continuation — saved when a raise goes unhandled, for post-mortem inspection.
|
||||
var _lastErrorKont_ = null;
|
||||
|
||||
// hostError — throw a host-level error that propagates out of cekRun.
|
||||
function hostError(msg) { throw new Error(typeof msg === "string" ? msg : inspect(msg)); }
|
||||
|
||||
// Render dispatch — call the active adapter's render function.
|
||||
// Set by each adapter when loaded; defaults to identity (no rendering).
|
||||
var _renderExprFn = null;
|
||||
@@ -390,7 +442,20 @@
|
||||
PRIMITIVES["split"] = function(s, sep) { return String(s).split(sep || " "); };
|
||||
PRIMITIVES["join"] = function(sep, coll) { return coll.join(sep); };
|
||||
PRIMITIVES["replace"] = function(s, old, nw) { return s.split(old).join(nw); };
|
||||
PRIMITIVES["index-of"] = function(s, needle, from) { return String(s).indexOf(needle, from || 0); };
|
||||
PRIMITIVES["index-of"] = function(s, needle, from) {
|
||||
if (Array.isArray(s)) {
|
||||
var _start = from || 0;
|
||||
for (var _i = _start; _i < s.length; _i++) {
|
||||
var _a = s[_i];
|
||||
if (_a === needle) return _i;
|
||||
if (_a != null && needle != null && typeof _a === "object" && typeof needle === "object") {
|
||||
if ((_a._sym && needle._sym || _a._kw && needle._kw) && _a.name === needle.name) return _i;
|
||||
}
|
||||
}
|
||||
return NIL;
|
||||
}
|
||||
return String(s).indexOf(needle, from || 0);
|
||||
};
|
||||
PRIMITIVES["starts-with?"] = function(s, p) { return String(s).indexOf(p) === 0; };
|
||||
PRIMITIVES["ends-with?"] = function(s, p) { var str = String(s); return str.indexOf(p, str.length - p.length) !== -1; };
|
||||
PRIMITIVES["slice"] = function(c, a, b) { if (!c || typeof c.slice !== "function") { console.error("[sx-debug] slice called on non-sliceable:", typeof c, c, "a=", a, "b=", b, new Error().stack); return []; } return b !== undefined ? c.slice(a, b) : c.slice(a); };
|
||||
@@ -470,6 +535,38 @@
|
||||
};
|
||||
|
||||
|
||||
// core.vectors — R7RS mutable fixed-size arrays
|
||||
PRIMITIVES["make-vector"] = function(n, fill) {
|
||||
var arr = new Array(n);
|
||||
var f = (fill !== undefined) ? fill : NIL;
|
||||
for (var i = 0; i < n; i++) arr[i] = f;
|
||||
return new SxVector(arr);
|
||||
};
|
||||
PRIMITIVES["vector"] = function() {
|
||||
return new SxVector(Array.prototype.slice.call(arguments));
|
||||
};
|
||||
PRIMITIVES["vector?"] = function(x) { return x != null && x._vector === true; };
|
||||
PRIMITIVES["vector-length"] = function(v) { return v.arr.length; };
|
||||
PRIMITIVES["vector-ref"] = function(v, i) {
|
||||
if (i < 0 || i >= v.arr.length) throw new Error("vector-ref: index " + i + " out of bounds (length " + v.arr.length + ")");
|
||||
return v.arr[i];
|
||||
};
|
||||
PRIMITIVES["vector-set!"] = function(v, i, val) {
|
||||
if (i < 0 || i >= v.arr.length) throw new Error("vector-set!: index " + i + " out of bounds (length " + v.arr.length + ")");
|
||||
v.arr[i] = val; return NIL;
|
||||
};
|
||||
PRIMITIVES["vector->list"] = function(v) { return v.arr.slice(); };
|
||||
PRIMITIVES["list->vector"] = function(l) { return new SxVector(l.slice()); };
|
||||
PRIMITIVES["vector-fill!"] = function(v, val) {
|
||||
for (var i = 0; i < v.arr.length; i++) v.arr[i] = val; return NIL;
|
||||
};
|
||||
PRIMITIVES["vector-copy"] = function(v, start, end) {
|
||||
var s = (start !== undefined) ? start : 0;
|
||||
var e = (end !== undefined) ? Math.min(end, v.arr.length) : v.arr.length;
|
||||
return new SxVector(v.arr.slice(s, e));
|
||||
};
|
||||
|
||||
|
||||
// stdlib.format
|
||||
PRIMITIVES["format-decimal"] = function(v, p) { return Number(v).toFixed(p || 2); };
|
||||
PRIMITIVES["parse-int"] = function(v, d) { var n = parseInt(v, 10); return isNaN(n) ? (d || 0) : n; };
|
||||
@@ -1029,6 +1126,10 @@ PRIMITIVES["make-let-frame"] = makeLetFrame;
|
||||
var makeDefineFrame = function(name, env, hasEffects, effectList) { return {"env": env, "effect-list": effectList, "has-effects": hasEffects, "type": "define", "name": name}; };
|
||||
PRIMITIVES["make-define-frame"] = makeDefineFrame;
|
||||
|
||||
// make-define-foreign-frame
|
||||
var makeDefineForeignFrame = function(name, spec, env) { return {"spec": spec, "env": env, "type": "define-foreign", "name": name}; };
|
||||
PRIMITIVES["make-define-foreign-frame"] = makeDefineForeignFrame;
|
||||
|
||||
// make-set-frame
|
||||
var makeSetFrame = function(name, env) { return {"env": env, "type": "set", "name": name}; };
|
||||
PRIMITIVES["make-set-frame"] = makeSetFrame;
|
||||
@@ -1321,6 +1422,18 @@ PRIMITIVES["*render-fn*"] = _renderFn;
|
||||
var _bindTracking_ = NIL;
|
||||
PRIMITIVES["*bind-tracking*"] = _bindTracking_;
|
||||
|
||||
// *provide-batch-depth*
|
||||
var _provideBatchDepth_ = 0;
|
||||
PRIMITIVES["*provide-batch-depth*"] = _provideBatchDepth_;
|
||||
|
||||
// *provide-batch-queue*
|
||||
var _provideBatchQueue_ = [];
|
||||
PRIMITIVES["*provide-batch-queue*"] = _provideBatchQueue_;
|
||||
|
||||
// *provide-subscribers*
|
||||
var _provideSubscribers_ = {};
|
||||
PRIMITIVES["*provide-subscribers*"] = _provideSubscribers_;
|
||||
|
||||
// *library-registry*
|
||||
var _libraryRegistry_ = {};
|
||||
PRIMITIVES["*library-registry*"] = _libraryRegistry_;
|
||||
@@ -1361,6 +1474,132 @@ PRIMITIVES["io-lookup"] = ioLookup;
|
||||
var ioNames = function() { return keys(_ioRegistry_); };
|
||||
PRIMITIVES["io-names"] = ioNames;
|
||||
|
||||
// *foreign-registry*
|
||||
var _foreignRegistry_ = {};
|
||||
PRIMITIVES["*foreign-registry*"] = _foreignRegistry_;
|
||||
|
||||
// foreign-register!
|
||||
var foreignRegister_b = function(name, spec) { return dictSet(_foreignRegistry_, name, spec); };
|
||||
PRIMITIVES["foreign-register!"] = foreignRegister_b;
|
||||
|
||||
// foreign-registered?
|
||||
var foreignRegistered_p = function(name) { return dictHas(_foreignRegistry_, name); };
|
||||
PRIMITIVES["foreign-registered?"] = foreignRegistered_p;
|
||||
|
||||
// foreign-lookup
|
||||
var foreignLookup = function(name) { return get(_foreignRegistry_, name); };
|
||||
PRIMITIVES["foreign-lookup"] = foreignLookup;
|
||||
|
||||
// foreign-names
|
||||
var foreignNames = function() { return keys(_foreignRegistry_); };
|
||||
PRIMITIVES["foreign-names"] = foreignNames;
|
||||
|
||||
// foreign-parse-params
|
||||
var foreignParseParams = function(paramList) { return (function() {
|
||||
var result = [];
|
||||
var i = 0;
|
||||
var items = (isSxTruthy(isList(paramList)) ? paramList : []);
|
||||
return foreignParseParamsLoop(items, result);
|
||||
})(); };
|
||||
PRIMITIVES["foreign-parse-params"] = foreignParseParams;
|
||||
|
||||
// foreign-parse-kwargs!
|
||||
var foreignParseKwargs_b = function(spec, remaining) { return (isSxTruthy((isSxTruthy(!isSxTruthy(isEmpty(remaining))) && isSxTruthy((len(remaining) >= 2)) && keyword_p(first(remaining)))) ? (dictSet(spec, keywordName(first(remaining)), (function() {
|
||||
var v = nth(remaining, 1);
|
||||
return (isSxTruthy(keyword_p(v)) ? keywordName(v) : v);
|
||||
})()), foreignParseKwargs_b(spec, rest(rest(remaining)))) : NIL); };
|
||||
PRIMITIVES["foreign-parse-kwargs!"] = foreignParseKwargs_b;
|
||||
|
||||
// foreign-resolve-binding
|
||||
var foreignResolveBinding = function(bindingStr) { return (function() {
|
||||
var parts = split(bindingStr, ".");
|
||||
return (isSxTruthy((len(parts) <= 1)) ? {"method": bindingStr, "object": NIL} : (function() {
|
||||
var method = last(parts);
|
||||
var obj = join(".", reverse(rest(reverse(parts))));
|
||||
return {"method": method, "object": obj};
|
||||
})());
|
||||
})(); };
|
||||
PRIMITIVES["foreign-resolve-binding"] = foreignResolveBinding;
|
||||
|
||||
// foreign-check-args
|
||||
var foreignCheckArgs = function(name, params, args) { if (isSxTruthy((isSxTruthy(!isSxTruthy(isEmpty(params))) && (len(args) < len(params))))) {
|
||||
error((String("foreign ") + String(name) + String(": expected ") + String(len(params)) + String(" args, got ") + String(len(args))));
|
||||
}
|
||||
return forEach(function(i) { return (function() {
|
||||
var spec = nth(params, i);
|
||||
var val = nth(args, i);
|
||||
var expected = get(spec, "type");
|
||||
return (isSxTruthy((isSxTruthy(!isSxTruthy(sxEq(expected, "any"))) && !isSxTruthy(valueMatchesType_p(val, expected)))) ? error((String("foreign ") + String(name) + String(": arg '") + String(get(spec, "name")) + String("' expected ") + String(expected) + String(", got ") + String(typeOf(val)))) : NIL);
|
||||
})(); }, range(0, min(len(params), len(args)))); };
|
||||
PRIMITIVES["foreign-check-args"] = foreignCheckArgs;
|
||||
|
||||
// foreign-build-lambda
|
||||
var foreignBuildLambda = function(spec) { return (function() {
|
||||
var name = get(spec, "name");
|
||||
var mode = (isSxTruthy(dictHas(spec, "returns")) ? (function() {
|
||||
var r = get(spec, "returns");
|
||||
return (isSxTruthy(sxEq(r, "promise")) ? "async" : "sync");
|
||||
})() : "sync");
|
||||
return (isSxTruthy(sxEq(mode, "async")) ? [new Symbol("fn"), [new Symbol("&rest"), new Symbol("__ffi-args__")], [new Symbol("perform"), [new Symbol("foreign-dispatch"), [new Symbol("quote"), name], new Symbol("__ffi-args__")]]] : [new Symbol("fn"), [new Symbol("&rest"), new Symbol("__ffi-args__")], [new Symbol("foreign-dispatch"), [new Symbol("quote"), name], new Symbol("__ffi-args__")]]);
|
||||
})(); };
|
||||
PRIMITIVES["foreign-build-lambda"] = foreignBuildLambda;
|
||||
|
||||
// sf-define-foreign
|
||||
var sfDefineForeign = function(args, env) { return (function() {
|
||||
var name = (isSxTruthy(symbol_p(first(args))) ? symbolName(first(args)) : first(args));
|
||||
var paramList = nth(args, 1);
|
||||
var spec = {};
|
||||
spec["name"] = name;
|
||||
spec["params"] = foreignParseParams(paramList);
|
||||
foreignParseKwargs_b(spec, rest(rest(args)));
|
||||
foreignRegister_b(name, spec);
|
||||
return spec;
|
||||
})(); };
|
||||
PRIMITIVES["sf-define-foreign"] = sfDefineForeign;
|
||||
|
||||
// step-sf-define-foreign
|
||||
var stepSfDefineForeign = function(args, env, kont) { return (function() {
|
||||
var spec = sfDefineForeign(args, env);
|
||||
var name = (isSxTruthy(symbol_p(first(args))) ? symbolName(first(args)) : first(args));
|
||||
var lambdaExpr = foreignBuildLambda(spec);
|
||||
return makeCekState(lambdaExpr, env, kontPush(makeDefineForeignFrame(name, spec, env), kont));
|
||||
})(); };
|
||||
PRIMITIVES["step-sf-define-foreign"] = stepSfDefineForeign;
|
||||
|
||||
// foreign-dispatch
|
||||
var foreignDispatch = function(name, args) { return (function() {
|
||||
var spec = foreignLookup(name);
|
||||
if (isSxTruthy(isNil(spec))) {
|
||||
error((String("foreign-dispatch: unknown foreign function '") + String(name) + String("'")));
|
||||
}
|
||||
return (function() {
|
||||
var params = get(spec, "params");
|
||||
var binding = get(spec, "js");
|
||||
foreignCheckArgs(name, (isSxTruthy(isNil(params)) ? [] : params), args);
|
||||
return (isSxTruthy(isNil(binding)) ? error((String("foreign ") + String(name) + String(": no binding for current platform"))) : (function() {
|
||||
var resolved = foreignResolveBinding(binding);
|
||||
var objName = get(resolved, "object");
|
||||
var method = get(resolved, "method");
|
||||
return (isSxTruthy(isPrimitive("host-call")) ? (isSxTruthy(isNil(objName)) ? apply(getPrimitive("host-call"), concat([NIL, method], args)) : (function() {
|
||||
var obj = (getPrimitive("host-global"))(objName);
|
||||
return apply(getPrimitive("host-call"), concat([obj, method], args));
|
||||
})()) : error((String("foreign ") + String(name) + String(": host-call not available on this platform"))));
|
||||
})());
|
||||
})();
|
||||
})(); };
|
||||
PRIMITIVES["foreign-dispatch"] = foreignDispatch;
|
||||
|
||||
// foreign-parse-params-loop
|
||||
var foreignParseParamsLoop = function(items, acc) { return (isSxTruthy(isEmpty(items)) ? acc : (function() {
|
||||
var item = first(items);
|
||||
var restItems = rest(items);
|
||||
return (isSxTruthy((isSxTruthy(!isSxTruthy(isEmpty(restItems))) && isSxTruthy(keyword_p(first(restItems))) && isSxTruthy(sxEq(keywordName(first(restItems)), "as")) && (len(restItems) >= 2))) ? foreignParseParamsLoop(rest(rest(restItems)), append(acc, [{"type": (function() {
|
||||
var t = nth(restItems, 1);
|
||||
return (isSxTruthy(keyword_p(t)) ? keywordName(t) : (String(t)));
|
||||
})(), "name": (isSxTruthy(symbol_p(item)) ? symbolName(item) : (String(item)))}])) : foreignParseParamsLoop(restItems, append(acc, [{"type": "any", "name": (isSxTruthy(symbol_p(item)) ? symbolName(item) : (String(item)))}])));
|
||||
})()); };
|
||||
PRIMITIVES["foreign-parse-params-loop"] = foreignParseParamsLoop;
|
||||
|
||||
// step-sf-io
|
||||
var stepSfIo = function(args, env, kont) { return (function() {
|
||||
var name = first(args);
|
||||
@@ -1839,7 +2078,7 @@ PRIMITIVES["step-sf-let-match"] = stepSfLetMatch;
|
||||
var args = rest(expr);
|
||||
return (isSxTruthy(!isSxTruthy(sxOr(sxEq(typeOf(head), "symbol"), sxEq(typeOf(head), "lambda"), sxEq(typeOf(head), "list")))) ? (isSxTruthy(isEmpty(expr)) ? makeCekValue([], env, kont) : makeCekState(first(expr), env, kontPush(makeMapFrame(NIL, rest(expr), [], env), kont))) : (isSxTruthy(sxEq(typeOf(head), "symbol")) ? (function() {
|
||||
var name = symbolName(head);
|
||||
return (function() { var _m = name; if (_m == "if") return stepSfIf(args, env, kont); if (_m == "when") return stepSfWhen(args, env, kont); if (_m == "cond") return stepSfCond(args, env, kont); if (_m == "case") return stepSfCase(args, env, kont); if (_m == "and") return stepSfAnd(args, env, kont); if (_m == "or") return stepSfOr(args, env, kont); if (_m == "let") return stepSfLet(args, env, kont); if (_m == "let*") return stepSfLet(args, env, kont); if (_m == "lambda") return stepSfLambda(args, env, kont); if (_m == "fn") return stepSfLambda(args, env, kont); if (_m == "define") return stepSfDefine(args, env, kont); if (_m == "defcomp") return makeCekValue(sfDefcomp(args, env), env, kont); if (_m == "defisland") return makeCekValue(sfDefisland(args, env), env, kont); if (_m == "defmacro") return makeCekValue(sfDefmacro(args, env), env, kont); if (_m == "defio") return makeCekValue(sfDefio(args, env), env, kont); if (_m == "io") return stepSfIo(args, env, kont); if (_m == "begin") return stepSfBegin(args, env, kont); if (_m == "do") return (isSxTruthy((isSxTruthy(!isSxTruthy(isEmpty(args))) && isSxTruthy(isList(first(args))) && isSxTruthy(!isSxTruthy(isEmpty(first(args)))) && isList(first(first(args))))) ? (function() {
|
||||
return (function() { var _m = name; if (_m == "if") return stepSfIf(args, env, kont); if (_m == "when") return stepSfWhen(args, env, kont); if (_m == "cond") return stepSfCond(args, env, kont); if (_m == "case") return stepSfCase(args, env, kont); if (_m == "and") return stepSfAnd(args, env, kont); if (_m == "or") return stepSfOr(args, env, kont); if (_m == "let") return stepSfLet(args, env, kont); if (_m == "let*") return stepSfLet(args, env, kont); if (_m == "lambda") return stepSfLambda(args, env, kont); if (_m == "fn") return stepSfLambda(args, env, kont); if (_m == "define") return stepSfDefine(args, env, kont); if (_m == "defcomp") return makeCekValue(sfDefcomp(args, env), env, kont); if (_m == "defisland") return makeCekValue(sfDefisland(args, env), env, kont); if (_m == "defmacro") return makeCekValue(sfDefmacro(args, env), env, kont); if (_m == "defio") return makeCekValue(sfDefio(args, env), env, kont); if (_m == "define-foreign") return stepSfDefineForeign(args, env, kont); if (_m == "io") return stepSfIo(args, env, kont); if (_m == "begin") return stepSfBegin(args, env, kont); if (_m == "do") return (isSxTruthy((isSxTruthy(!isSxTruthy(isEmpty(args))) && isSxTruthy(isList(first(args))) && isSxTruthy(!isSxTruthy(isEmpty(first(args)))) && isList(first(first(args))))) ? (function() {
|
||||
var bindings = first(args);
|
||||
var testClause = nth(args, 1);
|
||||
var body = rest(rest(args));
|
||||
@@ -1849,10 +2088,10 @@ PRIMITIVES["step-sf-let-match"] = stepSfLetMatch;
|
||||
var test = first(testClause);
|
||||
var result = rest(testClause);
|
||||
return stepEvalList(cons(new Symbol("let"), cons(new Symbol("__do-loop"), cons(map(function(b) { return [first(b), nth(b, 1)]; }, bindings), [cons(new Symbol("if"), cons(test, cons((isSxTruthy(isEmpty(result)) ? NIL : cons(new Symbol("begin"), result)), [cons(new Symbol("begin"), append(body, [cons(new Symbol("__do-loop"), steps)]))])))]))), env, kont);
|
||||
})() : stepSfBegin(args, env, kont)); if (_m == "guard") return stepSfGuard(args, env, kont); if (_m == "quote") return makeCekValue((isSxTruthy(isEmpty(args)) ? NIL : first(args)), env, kont); if (_m == "quasiquote") return makeCekValue(qqExpand(first(args), env), env, kont); if (_m == "->") return stepSfThreadFirst(args, env, kont); if (_m == "->>") return stepSfThreadLast(args, env, kont); if (_m == "|>") return stepSfThreadLast(args, env, kont); if (_m == "as->") return stepSfThreadAs(args, env, kont); if (_m == "set!") return stepSfSet(args, env, kont); if (_m == "letrec") return stepSfLetrec(args, env, kont); if (_m == "reset") return stepSfReset(args, env, kont); if (_m == "shift") return stepSfShift(args, env, kont); if (_m == "deref") return stepSfDeref(args, env, kont); if (_m == "scope") return stepSfScope(args, env, kont); if (_m == "provide") return stepSfProvide(args, env, kont); if (_m == "peek") return stepSfPeek(args, env, kont); if (_m == "provide!") return stepSfProvide_b(args, env, kont); if (_m == "context") return stepSfContext(args, env, kont); if (_m == "bind") return stepSfBind(args, env, kont); if (_m == "emit!") return stepSfEmit(args, env, kont); if (_m == "emitted") return stepSfEmitted(args, env, kont); if (_m == "handler-bind") return stepSfHandlerBind(args, env, kont); if (_m == "restart-case") return stepSfRestartCase(args, env, kont); if (_m == "signal-condition") return stepSfSignal(args, env, kont); if (_m == "invoke-restart") return stepSfInvokeRestart(args, env, kont); if (_m == "match") return stepSfMatch(args, env, kont); if (_m == "let-match") return stepSfLetMatch(args, env, kont); if (_m == "dynamic-wind") return makeCekValue(sfDynamicWind(args, env), env, kont); if (_m == "map") return stepHoMap(args, env, kont); if (_m == "map-indexed") return stepHoMapIndexed(args, env, kont); if (_m == "filter") return stepHoFilter(args, env, kont); if (_m == "reduce") return stepHoReduce(args, env, kont); if (_m == "some") return stepHoSome(args, env, kont); if (_m == "every?") return stepHoEvery(args, env, kont); if (_m == "for-each") return stepHoForEach(args, env, kont); if (_m == "raise") return stepSfRaise(args, env, kont); if (_m == "raise-continuable") return makeCekState(first(args), env, kontPush(makeRaiseEvalFrame(env, true), kont)); if (_m == "call/cc") return stepSfCallcc(args, env, kont); if (_m == "call-with-current-continuation") return stepSfCallcc(args, env, kont); if (_m == "perform") return stepSfPerform(args, env, kont); if (_m == "define-library") return stepSfDefineLibrary(args, env, kont); if (_m == "import") return stepSfImport(args, env, kont); if (_m == "define-record-type") return makeCekValue(sfDefineRecordType(args, env), env, kont); if (_m == "define-protocol") return makeCekValue(sfDefineProtocol(args, env), env, kont); if (_m == "implement") return makeCekValue(sfImplement(args, env), env, kont); if (_m == "parameterize") return stepSfParameterize(args, env, kont); if (_m == "syntax-rules") return makeCekValue(sfSyntaxRules(args, env), env, kont); if (_m == "define-syntax") return stepSfDefine(args, env, kont); return (isSxTruthy(dictHas(_customSpecialForms, name)) ? makeCekValue((get(_customSpecialForms, name))(args, env), env, kont) : (isSxTruthy((isSxTruthy(envHas(env, name)) && isMacro(envGet(env, name)))) ? (function() {
|
||||
})() : stepSfBegin(args, env, kont)); if (_m == "guard") return stepSfGuard(args, env, kont); if (_m == "quote") return makeCekValue((isSxTruthy(isEmpty(args)) ? NIL : first(args)), env, kont); if (_m == "quasiquote") return makeCekValue(qqExpand(first(args), env), env, kont); if (_m == "->") return stepSfThreadFirst(args, env, kont); if (_m == "->>") return stepSfThreadLast(args, env, kont); if (_m == "|>") return stepSfThreadLast(args, env, kont); if (_m == "as->") return stepSfThreadAs(args, env, kont); if (_m == "set!") return stepSfSet(args, env, kont); if (_m == "letrec") return stepSfLetrec(args, env, kont); if (_m == "reset") return stepSfReset(args, env, kont); if (_m == "shift") return stepSfShift(args, env, kont); if (_m == "deref") return stepSfDeref(args, env, kont); if (_m == "scope") return stepSfScope(args, env, kont); if (_m == "provide") return stepSfProvide(args, env, kont); if (_m == "peek") return stepSfPeek(args, env, kont); if (_m == "provide!") return stepSfProvide_b(args, env, kont); if (_m == "context") return stepSfContext(args, env, kont); if (_m == "bind") return stepSfBind(args, env, kont); if (_m == "emit!") return stepSfEmit(args, env, kont); if (_m == "emitted") return stepSfEmitted(args, env, kont); if (_m == "handler-bind") return stepSfHandlerBind(args, env, kont); if (_m == "restart-case") return stepSfRestartCase(args, env, kont); if (_m == "signal-condition") return stepSfSignal(args, env, kont); if (_m == "invoke-restart") return stepSfInvokeRestart(args, env, kont); if (_m == "match") return stepSfMatch(args, env, kont); if (_m == "let-match") return stepSfLetMatch(args, env, kont); if (_m == "dynamic-wind") return makeCekValue(sfDynamicWind(args, env), env, kont); if (_m == "map") return stepHoMap(args, env, kont); if (_m == "map-indexed") return stepHoMapIndexed(args, env, kont); if (_m == "filter") return stepHoFilter(args, env, kont); if (_m == "reduce") return stepHoReduce(args, env, kont); if (_m == "some") return stepHoSome(args, env, kont); if (_m == "every?") return stepHoEvery(args, env, kont); if (_m == "for-each") return stepHoForEach(args, env, kont); if (_m == "raise") return stepSfRaise(args, env, kont); if (_m == "raise-continuable") return makeCekState(first(args), env, kontPush(makeRaiseEvalFrame(env, true), kont)); if (_m == "call/cc") return stepSfCallcc(args, env, kont); if (_m == "call-with-current-continuation") return stepSfCallcc(args, env, kont); if (_m == "perform") return stepSfPerform(args, env, kont); if (_m == "define-library") return stepSfDefineLibrary(args, env, kont); if (_m == "import") return stepSfImport(args, env, kont); if (_m == "define-record-type") return makeCekValue(sfDefineRecordType(args, env), env, kont); if (_m == "define-protocol") return makeCekValue(sfDefineProtocol(args, env), env, kont); if (_m == "implement") return makeCekValue(sfImplement(args, env), env, kont); if (_m == "parameterize") return stepSfParameterize(args, env, kont); if (_m == "syntax-rules") return makeCekValue(sfSyntaxRules(args, env), env, kont); if (_m == "define-syntax") return stepSfDefine(args, env, kont); return (isSxTruthy((isSxTruthy(dictHas(_customSpecialForms, name)) && !isSxTruthy(envHas(env, name)))) ? makeCekValue((get(_customSpecialForms, name))(args, env), env, kont) : (isSxTruthy((isSxTruthy(envHas(env, name)) && isMacro(envGet(env, name)))) ? (function() {
|
||||
var mac = envGet(env, name);
|
||||
return makeCekState(expandMacro(mac, args, env), env, kont);
|
||||
})() : (isSxTruthy((isSxTruthy(_renderCheck) && _renderCheck(expr, env))) ? makeCekValue(_renderFn(expr, env), env, kont) : stepEvalCall(head, args, env, kont)))); })();
|
||||
})() : (isSxTruthy((isSxTruthy(_renderCheck) && isSxTruthy(!isSxTruthy(envHas(env, name))) && _renderCheck(expr, env))) ? makeCekValue(_renderFn(expr, env), env, kont) : stepEvalCall(head, args, env, kont)))); })();
|
||||
})() : stepEvalCall(head, args, env, kont)));
|
||||
})(); };
|
||||
PRIMITIVES["step-eval-list"] = stepEvalList;
|
||||
@@ -1868,10 +2107,30 @@ PRIMITIVES["kont-extract-provides"] = kontExtractProvides;
|
||||
// fire-provide-subscribers
|
||||
var fireProvideSubscribers = function(frame, kont) { return (function() {
|
||||
var subs = get(frame, "subscribers");
|
||||
return (isSxTruthy(!isSxTruthy(isEmpty(subs))) ? forEach(function(sub) { return cekCall(sub, [kont]); }, subs) : NIL);
|
||||
return (isSxTruthy(!isSxTruthy(isEmpty(subs))) ? (isSxTruthy((_provideBatchDepth_ > 0)) ? forEach(function(sub) { return (isSxTruthy(!isSxTruthy(contains(_provideBatchQueue_, sub))) ? append_b(_provideBatchQueue_, sub) : NIL); }, subs) : forEach(function(sub) { return cekCall(sub, [kont]); }, subs)) : NIL);
|
||||
})(); };
|
||||
PRIMITIVES["fire-provide-subscribers"] = fireProvideSubscribers;
|
||||
|
||||
// fire-provide-subscribers
|
||||
var fireProvideSubscribers = function(name) { return (function() {
|
||||
var subs = get(_provideSubscribers_, name);
|
||||
return (isSxTruthy((isSxTruthy(subs) && !isSxTruthy(isEmpty(subs)))) ? (isSxTruthy((_provideBatchDepth_ > 0)) ? forEach(function(sub) { return (isSxTruthy(!isSxTruthy(contains(_provideBatchQueue_, sub))) ? append_b(_provideBatchQueue_, sub) : NIL); }, subs) : forEach(function(sub) { return cekCall(sub, [NIL]); }, subs)) : NIL);
|
||||
})(); };
|
||||
PRIMITIVES["fire-provide-subscribers"] = fireProvideSubscribers;
|
||||
|
||||
// batch-begin!
|
||||
var batchBegin_b = function() { return (_provideBatchDepth_ = (_provideBatchDepth_ + 1)); };
|
||||
PRIMITIVES["batch-begin!"] = batchBegin_b;
|
||||
|
||||
// batch-end!
|
||||
var batchEnd_b = function() { _provideBatchDepth_ = (_provideBatchDepth_ - 1);
|
||||
return (isSxTruthy(sxEq(_provideBatchDepth_, 0)) ? (function() {
|
||||
var queue = _provideBatchQueue_;
|
||||
_provideBatchQueue_ = [];
|
||||
return forEach(function(sub) { return cekCall(sub, [NIL]); }, queue);
|
||||
})() : NIL); };
|
||||
PRIMITIVES["batch-end!"] = batchEnd_b;
|
||||
|
||||
// step-sf-bind
|
||||
var stepSfBind = function(args, env, kont) { return (function() {
|
||||
var body = first(args);
|
||||
@@ -2011,7 +2270,7 @@ PRIMITIVES["sf-syntax-rules"] = sfSyntaxRules;
|
||||
{ var _c = decls; for (var _i = 0; _i < _c.length; _i++) { var decl = _c[_i]; if (isSxTruthy((isSxTruthy(isList(decl)) && isSxTruthy(!isSxTruthy(isEmpty(decl))) && symbol_p(first(decl))))) {
|
||||
(function() {
|
||||
var kind = symbolName(first(decl));
|
||||
return (isSxTruthy(sxEq(kind, "export")) ? (exports = append(exports, map(function(s) { return (isSxTruthy(symbol_p(s)) ? symbolName(s) : (String(s))); }, rest(decl)))) : (isSxTruthy(sxEq(kind, "begin")) ? (bodyForms = append(bodyForms, rest(decl))) : NIL));
|
||||
return (isSxTruthy(sxEq(kind, "export")) ? (exports = append(exports, map(function(s) { return (isSxTruthy(symbol_p(s)) ? symbolName(s) : (String(s))); }, rest(decl)))) : (isSxTruthy(sxEq(kind, "import")) ? forEach(function(importSet) { return bindImportSet(importSet, libEnv); }, rest(decl)) : (isSxTruthy(sxEq(kind, "begin")) ? (bodyForms = append(bodyForms, rest(decl))) : NIL)));
|
||||
})();
|
||||
} } }
|
||||
{ var _c = bodyForms; for (var _i = 0; _i < _c.length; _i++) { var form = _c[_i]; evalExpr(form, libEnv); } }
|
||||
@@ -2407,10 +2666,10 @@ PRIMITIVES["step-sf-provide"] = stepSfProvide;
|
||||
_bindTracking_.push(name);
|
||||
}
|
||||
}
|
||||
return makeCekValue((isSxTruthy(frame) ? get(frame, "value") : (function() {
|
||||
return makeCekValue((function() {
|
||||
var sv = scopePeek(name);
|
||||
return (isSxTruthy(isNil(sv)) ? defaultVal : sv);
|
||||
})()), env, kont);
|
||||
return (isSxTruthy(isNil(sv)) ? (isSxTruthy(frame) ? get(frame, "value") : defaultVal) : sv);
|
||||
})(), env, kont);
|
||||
})(); };
|
||||
PRIMITIVES["step-sf-context"] = stepSfContext;
|
||||
|
||||
@@ -2649,6 +2908,14 @@ PRIMITIVES["step-ho-for-each"] = stepHoForEach;
|
||||
})();
|
||||
}
|
||||
return makeCekValue(value, fenv, restK);
|
||||
})(); if (_m == "define-foreign") return (function() {
|
||||
var name = get(frame, "name");
|
||||
var fenv = get(frame, "env");
|
||||
if (isSxTruthy((isSxTruthy(isLambda(value)) && isNil(lambdaName(value))))) {
|
||||
value.name = name;
|
||||
}
|
||||
envBind(fenv, name, value);
|
||||
return makeCekValue(value, fenv, restK);
|
||||
})(); if (_m == "set") return (function() {
|
||||
var name = get(frame, "name");
|
||||
var fenv = get(frame, "env");
|
||||
@@ -2780,8 +3047,8 @@ PRIMITIVES["step-ho-for-each"] = stepHoForEach;
|
||||
(function() {
|
||||
var subscriber = function(fireKont) { return cekRun(makeCekState(body, fenv, [])); };
|
||||
return forEach(function(name) { return (function() {
|
||||
var pf = kontFindProvide(restK, name);
|
||||
return (isSxTruthy(pf) ? dictSet(pf, "subscribers", append(get(pf, "subscribers"), [subscriber])) : NIL);
|
||||
var existing = get(_provideSubscribers_, name);
|
||||
return dictSet(_provideSubscribers_, name, append((isSxTruthy(existing) ? existing : []), [subscriber]));
|
||||
})(); }, tracked);
|
||||
})();
|
||||
return makeCekValue(value, fenv, restK);
|
||||
@@ -2789,16 +3056,18 @@ PRIMITIVES["step-ho-for-each"] = stepHoForEach;
|
||||
var name = get(frame, "name");
|
||||
var fenv = get(frame, "env");
|
||||
var target = kontFindProvide(restK, name);
|
||||
return (isSxTruthy(target) ? (function() {
|
||||
var oldVal = get(target, "value");
|
||||
return (function() {
|
||||
var oldVal = (isSxTruthy(target) ? get(target, "value") : scopePeek(name));
|
||||
if (isSxTruthy(target)) {
|
||||
target["value"] = value;
|
||||
}
|
||||
scopePop(name);
|
||||
scopePush(name, value);
|
||||
if (isSxTruthy(!isSxTruthy(sxEq(oldVal, value)))) {
|
||||
fireProvideSubscribers(target, restK);
|
||||
fireProvideSubscribers(name);
|
||||
}
|
||||
return makeCekValue(value, fenv, restK);
|
||||
})() : (isSxTruthy(envHas(fenv, "provide-set!")) ? (apply(envGet(fenv, "provide-set!"), [name, value]), makeCekValue(value, fenv, restK)) : makeCekValue(NIL, fenv, restK)));
|
||||
})();
|
||||
})(); if (_m == "scope-acc") return (function() {
|
||||
var remaining = get(frame, "remaining");
|
||||
var fenv = get(frame, "env");
|
||||
@@ -2936,7 +3205,10 @@ PRIMITIVES["step-continue"] = stepContinue;
|
||||
return makeCekValue(result, env, kont);
|
||||
})();
|
||||
})();
|
||||
})() : (isSxTruthy((isSxTruthy(isCallable(f)) && isSxTruthy(!isSxTruthy(isLambda(f))) && isSxTruthy(!isSxTruthy(isComponent(f))) && !isSxTruthy(isIsland(f)))) ? makeCekValue(apply(f, args), env, kont) : (isSxTruthy(isLambda(f)) ? (function() {
|
||||
})() : (isSxTruthy((isSxTruthy(isCallable(f)) && isSxTruthy(!isSxTruthy(isLambda(f))) && isSxTruthy(!isSxTruthy(isComponent(f))) && !isSxTruthy(isIsland(f)))) ? (function() {
|
||||
var result = sxApplyCek(f, args);
|
||||
return (isSxTruthy(evalError_p(result)) ? makeCekValue(get(result, "message"), env, kontPush(makeRaiseEvalFrame(env, false), kont)) : (isSxTruthy((isSxTruthy(isDict(result)) && get(result, "__vm_suspended"))) ? makeCekSuspended(get(result, "request"), env, kontPush(makeVmResumeFrame(get(result, "resume"), env), kont)) : makeCekValue(result, env, kont)));
|
||||
})() : (isSxTruthy(isLambda(f)) ? (function() {
|
||||
var params = lambdaParams(f);
|
||||
var local = envMerge(lambdaClosure(f), env);
|
||||
if (isSxTruthy(!isSxTruthy(bindLambdaParams(params, args, local)))) {
|
||||
@@ -2948,7 +3220,7 @@ PRIMITIVES["step-continue"] = stepContinue;
|
||||
}
|
||||
return (function() {
|
||||
var jitResult = jitTryCall(f, args);
|
||||
return (isSxTruthy(isNil(jitResult)) ? makeCekState(lambdaBody(f), local, kont) : (isSxTruthy((isSxTruthy(isDict(jitResult)) && get(jitResult, "__vm_suspended"))) ? makeCekSuspended(get(jitResult, "request"), env, kontPush(makeVmResumeFrame(get(jitResult, "resume"), env), kont)) : makeCekValue(jitResult, local, kont)));
|
||||
return (isSxTruthy(jitSkip_p(jitResult)) ? makeCekState(lambdaBody(f), local, kont) : (isSxTruthy((isSxTruthy(isDict(jitResult)) && get(jitResult, "__vm_suspended"))) ? makeCekSuspended(get(jitResult, "request"), env, kontPush(makeVmResumeFrame(get(jitResult, "resume"), env), kont)) : makeCekValue(jitResult, local, kont)));
|
||||
})();
|
||||
})() : (isSxTruthy(sxOr(isComponent(f), isIsland(f))) ? (function() {
|
||||
var parsed = parseKeywordArgs(rawArgs, env);
|
||||
@@ -3350,10 +3622,16 @@ PRIMITIVES["serialize"] = serialize;
|
||||
|
||||
// === Transpiled from lib/dom (DOM library) ===
|
||||
|
||||
// dom-visible?
|
||||
var domVisible_p = function(el) { return (isSxTruthy(el) ? !isSxTruthy(sxEq(hostGet(hostGet(el, "style"), "display"), "none")) : false); };
|
||||
PRIMITIVES["dom-visible?"] = domVisible_p;
|
||||
|
||||
|
||||
// === Transpiled from lib/browser (browser API library) ===
|
||||
|
||||
// json-stringify
|
||||
var jsonStringify = function(v) { return hostCall(hostGlobal("JSON"), "stringify", v); };
|
||||
PRIMITIVES["json-stringify"] = jsonStringify;
|
||||
|
||||
|
||||
// === Transpiled from adapter-dom ===
|
||||
@@ -3524,6 +3802,7 @@ PRIMITIVES["process-page-scripts"] = processPageScripts;
|
||||
// sx-hydrate-islands
|
||||
var sxHydrateIslands = function(root) { return (function() {
|
||||
var els = domQueryAll(sxOr(root, domBody()), "[data-sx-island]");
|
||||
preloadIslandDefs();
|
||||
logInfo((String("sx-hydrate-islands: ") + String(len(els)) + String(" island(s) in ") + String((isSxTruthy(root) ? "subtree" : "document"))));
|
||||
return forEach(function(el) { return (isSxTruthy(isProcessed(el, "island-hydrated")) ? logInfo((String(" skip (already hydrated): ") + String(domGetAttr(el, "data-sx-island")))) : (logInfo((String(" hydrating: ") + String(domGetAttr(el, "data-sx-island")))), markProcessed(el, "island-hydrated"), hydrateIsland(el))); }, els);
|
||||
})(); };
|
||||
@@ -3537,26 +3816,34 @@ PRIMITIVES["sx-hydrate-islands"] = sxHydrateIslands;
|
||||
var compName = (String("~") + String(name));
|
||||
var env = getRenderEnv(NIL);
|
||||
return (function() {
|
||||
var comp = envGet(env, compName);
|
||||
var comp = envGet(globalEnv(), compName);
|
||||
return (isSxTruthy(!isSxTruthy(sxOr(isComponent(comp), isIsland(comp)))) ? logWarn((String("hydrate-island: unknown island ") + String(compName))) : (function() {
|
||||
var kwargs = sxOr(first(sxParse(stateSx)), {});
|
||||
var disposers = [];
|
||||
var local = envMerge(componentClosure(comp), env);
|
||||
{ var _c = componentParams(comp); for (var _i = 0; _i < _c.length; _i++) { var p = _c[_i]; envBind(local, p, (isSxTruthy(dictHas(kwargs, p)) ? dictGet(kwargs, p) : NIL)); } }
|
||||
return (function() {
|
||||
var bodyDom = cekTry(function() { return withIslandScope(function(disposable) { return append_b(disposers, disposable); }, function() { return renderToDom(componentBody(comp), local, NIL); }); }, function(err) { logWarn((String("hydrate-island FAILED: ") + String(compName) + String(" — ") + String(err)));
|
||||
var cursor = {["parent"]: el, ["index"]: 0};
|
||||
hostCall(el, "replaceChildren");
|
||||
scopePush("sx-hydrating", NIL);
|
||||
cekTry(function() { return withIslandScope(function(disposable) { return append_b(disposers, disposable); }, function() { return (function() {
|
||||
var bodyDom = renderToDom(componentBody(comp), local, NIL);
|
||||
return (isSxTruthy(bodyDom) ? domAppend(el, bodyDom) : NIL);
|
||||
})(); }); }, function(err) { scopePop("sx-hydrating");
|
||||
logWarn((String("hydrate fallback: ") + String(compName) + String(" — ") + String(err)));
|
||||
return (function() {
|
||||
var errorEl = domCreateElement("div", NIL);
|
||||
domSetAttr(errorEl, "class", "sx-island-error");
|
||||
domSetAttr(errorEl, "style", "padding:8px;margin:4px 0;border:1px solid #ef4444;border-radius:4px;background:#fef2f2;color:#b91c1c;font-family:monospace;font-size:12px;white-space:pre-wrap");
|
||||
domSetTextContent(errorEl, (String("Island error: ") + String(compName) + String("\n") + String(err)));
|
||||
return errorEl;
|
||||
var fallback = cekTry(function() { return withIslandScope(function(d) { return append_b(disposers, d); }, function() { return renderToDom(componentBody(comp), local, NIL); }); }, function(err2) { return (function() {
|
||||
var e = domCreateElement("div", NIL);
|
||||
domSetTextContent(e, (String("Island error: ") + String(compName) + String("\n") + String(err2)));
|
||||
return e;
|
||||
})(); });
|
||||
domSetTextContent(el, "");
|
||||
domAppend(el, bodyDom);
|
||||
hostCall(el, "replaceChildren", fallback);
|
||||
return NIL;
|
||||
})(); });
|
||||
scopePop("sx-hydrating");
|
||||
domSetData(el, "sx-disposers", disposers);
|
||||
setTimeout_(function() { return processElements(el); }, 0);
|
||||
return logInfo((String("hydrated island: ") + String(compName) + String(" (") + String(len(disposers)) + String(" disposers)")));
|
||||
return logInfo((String("hydrated island: ~") + String(compName) + String(" (") + String(len(disposers)) + String(" disposers)")));
|
||||
})();
|
||||
})());
|
||||
})();
|
||||
@@ -3656,6 +3943,18 @@ PRIMITIVES["boot-init"] = bootInit;
|
||||
// Core primitives that require native JS (cannot be expressed via FFI)
|
||||
// -----------------------------------------------------------------------
|
||||
PRIMITIVES["error"] = function(msg) { throw new Error(msg); };
|
||||
PRIMITIVES["host-error"] = function(msg) { throw new Error(typeof msg === "string" ? msg : inspect(msg)); };
|
||||
PRIMITIVES["try-catch"] = function(tryFn, catchFn) {
|
||||
try {
|
||||
return cekRun(continueWithCall(tryFn, [], makeEnv(), [], []));
|
||||
} catch(e) {
|
||||
var msg = e && e.message ? e.message : String(e);
|
||||
return cekRun(continueWithCall(catchFn, [msg], makeEnv(), [msg], []));
|
||||
}
|
||||
};
|
||||
PRIMITIVES["without-io-hook"] = function(thunk) {
|
||||
return cekRun(continueWithCall(thunk, [], makeEnv(), [], []));
|
||||
};
|
||||
PRIMITIVES["sort"] = function(lst) {
|
||||
if (!Array.isArray(lst)) return lst;
|
||||
return lst.slice().sort(function(a, b) {
|
||||
@@ -3723,7 +4022,7 @@ PRIMITIVES["boot-init"] = bootInit;
|
||||
PRIMITIVES["dom-tag-name"] = domTagName;
|
||||
PRIMITIVES["dom-get-prop"] = domGetProp;
|
||||
PRIMITIVES["dom-set-prop"] = domSetProp;
|
||||
PRIMITIVES["reactive-text"] = reactiveText;
|
||||
if (typeof reactiveText === "function") PRIMITIVES["reactive-text"] = reactiveText;
|
||||
PRIMITIVES["set-interval"] = setInterval_;
|
||||
PRIMITIVES["clear-interval"] = clearInterval_;
|
||||
PRIMITIVES["promise-then"] = promiseThen;
|
||||
@@ -3807,6 +4106,13 @@ PRIMITIVES["boot-init"] = bootInit;
|
||||
PRIMITIVES["lambda-name"] = lambdaName;
|
||||
PRIMITIVES["component?"] = isComponent;
|
||||
PRIMITIVES["island?"] = isIsland;
|
||||
PRIMITIVES["parameter?"] = parameter_p;
|
||||
PRIMITIVES["parameter-uid"] = parameterUid;
|
||||
PRIMITIVES["parameter-default"] = parameterDefault;
|
||||
PRIMITIVES["make-parameter"] = function(defaultVal, converter) {
|
||||
var p = new SxParameter(defaultVal, converter || null);
|
||||
return p;
|
||||
};
|
||||
PRIMITIVES["make-symbol"] = function(n) { return new Symbol(n); };
|
||||
PRIMITIVES["is-html-tag?"] = function(n) { return HTML_TAGS.indexOf(n) >= 0; };
|
||||
function makeEnv() { return merge(componentEnv, PRIMITIVES); }
|
||||
@@ -3997,7 +4303,7 @@ PRIMITIVES["boot-init"] = bootInit;
|
||||
}
|
||||
|
||||
function domDispatch(el, name, detail) {
|
||||
if (!_hasDom || !el) return false;
|
||||
if (!_hasDom || !el || typeof el.dispatchEvent !== "function") return false;
|
||||
var evt = new CustomEvent(name, { bubbles: true, cancelable: true, detail: detail || {} });
|
||||
return el.dispatchEvent(evt);
|
||||
}
|
||||
@@ -4119,6 +4425,14 @@ PRIMITIVES["boot-init"] = bootInit;
|
||||
// Platform interface — Orchestration (browser-only)
|
||||
// =========================================================================
|
||||
|
||||
// --- Stubs for define-library functions not transpiled by extract_defines ---
|
||||
// These are defined in orchestration.sx's define-library and called from
|
||||
// boot.sx top-level defines. The JS bootstrapper only transpiles top-level
|
||||
// defines, so we provide stubs here for functions that need a JS identity.
|
||||
|
||||
function flushCollectedStyles() { return NIL; }
|
||||
function processElements(root) { return NIL; }
|
||||
|
||||
// --- Browser/Network ---
|
||||
|
||||
function browserNavigate(url) {
|
||||
@@ -4604,6 +4918,10 @@ PRIMITIVES["boot-init"] = bootInit;
|
||||
return el && el.closest ? el.closest(sel) : null;
|
||||
}
|
||||
|
||||
function domDocument() {
|
||||
return _hasDom ? document : null;
|
||||
}
|
||||
|
||||
function domBody() {
|
||||
return _hasDom ? document.body : null;
|
||||
}
|
||||
@@ -5045,6 +5363,8 @@ PRIMITIVES["boot-init"] = bootInit;
|
||||
// Platform interface — Boot (mount, hydrate, scripts, cookies)
|
||||
// =========================================================================
|
||||
|
||||
function preloadIslandDefs() { return NIL; }
|
||||
|
||||
function resolveMountTarget(target) {
|
||||
if (typeof target === "string") return _hasDom ? document.querySelector(target) : null;
|
||||
return target;
|
||||
@@ -5920,52 +6240,52 @@ PRIMITIVES["boot-init"] = bootInit;
|
||||
hydrateIslands: typeof sxHydrateIslands === "function" ? sxHydrateIslands : null,
|
||||
disposeIsland: typeof disposeIsland === "function" ? disposeIsland : null,
|
||||
init: typeof bootInit === "function" ? bootInit : null,
|
||||
scanRefs: scanRefs,
|
||||
scanComponentsFromSource: scanComponentsFromSource,
|
||||
transitiveDeps: transitiveDeps,
|
||||
computeAllDeps: computeAllDeps,
|
||||
componentsNeeded: componentsNeeded,
|
||||
pageComponentBundle: pageComponentBundle,
|
||||
pageCssClasses: pageCssClasses,
|
||||
scanIoRefs: scanIoRefs,
|
||||
transitiveIoRefs: transitiveIoRefs,
|
||||
computeAllIoRefs: computeAllIoRefs,
|
||||
componentPure_p: componentPure_p,
|
||||
categorizeSpecialForms: categorizeSpecialForms,
|
||||
buildReferenceData: buildReferenceData,
|
||||
buildAttrDetail: buildAttrDetail,
|
||||
buildHeaderDetail: buildHeaderDetail,
|
||||
buildEventDetail: buildEventDetail,
|
||||
buildComponentSource: buildComponentSource,
|
||||
buildBundleAnalysis: buildBundleAnalysis,
|
||||
buildRoutingAnalysis: buildRoutingAnalysis,
|
||||
buildAffinityAnalysis: buildAffinityAnalysis,
|
||||
splitPathSegments: splitPathSegments,
|
||||
parseRoutePattern: parseRoutePattern,
|
||||
matchRoute: matchRoute,
|
||||
findMatchingRoute: findMatchingRoute,
|
||||
urlToExpr: urlToExpr,
|
||||
autoQuoteUnknowns: autoQuoteUnknowns,
|
||||
prepareUrlExpr: prepareUrlExpr,
|
||||
scanRefs: typeof scanRefs === "function" ? scanRefs : null,
|
||||
scanComponentsFromSource: typeof scanComponentsFromSource === "function" ? scanComponentsFromSource : null,
|
||||
transitiveDeps: typeof transitiveDeps === "function" ? transitiveDeps : null,
|
||||
computeAllDeps: typeof computeAllDeps === "function" ? computeAllDeps : null,
|
||||
componentsNeeded: typeof componentsNeeded === "function" ? componentsNeeded : null,
|
||||
pageComponentBundle: typeof pageComponentBundle === "function" ? pageComponentBundle : null,
|
||||
pageCssClasses: typeof pageCssClasses === "function" ? pageCssClasses : null,
|
||||
scanIoRefs: typeof scanIoRefs === "function" ? scanIoRefs : null,
|
||||
transitiveIoRefs: typeof transitiveIoRefs === "function" ? transitiveIoRefs : null,
|
||||
computeAllIoRefs: typeof computeAllIoRefs === "function" ? computeAllIoRefs : null,
|
||||
componentPure_p: typeof componentPure_p === "function" ? componentPure_p : null,
|
||||
categorizeSpecialForms: typeof categorizeSpecialForms === "function" ? categorizeSpecialForms : null,
|
||||
buildReferenceData: typeof buildReferenceData === "function" ? buildReferenceData : null,
|
||||
buildAttrDetail: typeof buildAttrDetail === "function" ? buildAttrDetail : null,
|
||||
buildHeaderDetail: typeof buildHeaderDetail === "function" ? buildHeaderDetail : null,
|
||||
buildEventDetail: typeof buildEventDetail === "function" ? buildEventDetail : null,
|
||||
buildComponentSource: typeof buildComponentSource === "function" ? buildComponentSource : null,
|
||||
buildBundleAnalysis: typeof buildBundleAnalysis === "function" ? buildBundleAnalysis : null,
|
||||
buildRoutingAnalysis: typeof buildRoutingAnalysis === "function" ? buildRoutingAnalysis : null,
|
||||
buildAffinityAnalysis: typeof buildAffinityAnalysis === "function" ? buildAffinityAnalysis : null,
|
||||
splitPathSegments: typeof splitPathSegments === "function" ? splitPathSegments : null,
|
||||
parseRoutePattern: typeof parseRoutePattern === "function" ? parseRoutePattern : null,
|
||||
matchRoute: typeof matchRoute === "function" ? matchRoute : null,
|
||||
findMatchingRoute: typeof findMatchingRoute === "function" ? findMatchingRoute : null,
|
||||
urlToExpr: typeof urlToExpr === "function" ? urlToExpr : null,
|
||||
autoQuoteUnknowns: typeof autoQuoteUnknowns === "function" ? autoQuoteUnknowns : null,
|
||||
prepareUrlExpr: typeof prepareUrlExpr === "function" ? prepareUrlExpr : null,
|
||||
registerIo: typeof registerIoPrimitive === "function" ? registerIoPrimitive : null,
|
||||
registerIoDeps: typeof registerIoDeps === "function" ? registerIoDeps : null,
|
||||
asyncRender: typeof asyncSxRenderWithEnv === "function" ? asyncSxRenderWithEnv : null,
|
||||
asyncRenderToDom: typeof asyncRenderToDom === "function" ? asyncRenderToDom : null,
|
||||
signal: signal,
|
||||
deref: deref,
|
||||
reset: reset_b,
|
||||
swap: swap_b,
|
||||
computed: computed,
|
||||
effect: effect,
|
||||
batch: batch,
|
||||
isSignal: isSignal,
|
||||
makeSignal: makeSignal,
|
||||
defStore: defStore,
|
||||
useStore: useStore,
|
||||
clearStores: clearStores,
|
||||
emitEvent: emitEvent,
|
||||
onEvent: onEvent,
|
||||
bridgeEvent: bridgeEvent,
|
||||
signal: typeof signal === "function" ? signal : null,
|
||||
deref: typeof deref === "function" ? deref : null,
|
||||
reset: typeof reset_b === "function" ? reset_b : null,
|
||||
swap: typeof swap_b === "function" ? swap_b : null,
|
||||
computed: typeof computed === "function" ? computed : null,
|
||||
effect: typeof effect === "function" ? effect : null,
|
||||
batch: typeof batch === "function" ? batch : null,
|
||||
isSignal: typeof isSignal === "function" ? isSignal : null,
|
||||
makeSignal: typeof makeSignal === "function" ? makeSignal : null,
|
||||
defStore: typeof defStore === "function" ? defStore : null,
|
||||
useStore: typeof useStore === "function" ? useStore : null,
|
||||
clearStores: typeof clearStores === "function" ? clearStores : null,
|
||||
emitEvent: typeof emitEvent === "function" ? emitEvent : null,
|
||||
onEvent: typeof onEvent === "function" ? onEvent : null,
|
||||
bridgeEvent: typeof bridgeEvent === "function" ? bridgeEvent : null,
|
||||
makeSpread: makeSpread,
|
||||
isSpread: isSpread,
|
||||
spreadAttrs: spreadAttrs,
|
||||
|
||||
Reference in New Issue
Block a user