Dynamic IO proxy: derive proxied primitives from component io_refs

Replace hardcoded IO primitive lists on both client and server with
data-driven registration. Page registry entries carry :io-deps (list
of IO primitive names) instead of :has-io boolean. Client registers
proxied IO on demand per page via registerIoDeps(). Server builds
allowlist from component analysis.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-07 09:13:53 +00:00
parent c2a85ed026
commit cb0990feb3
7 changed files with 61 additions and 38 deletions

View File

@@ -385,6 +385,7 @@ class JSEmitter:
"try-client-route": "tryClientRoute",
"try-eval-content": "tryEvalContent",
"try-async-eval-content": "tryAsyncEvalContent",
"register-io-deps": "registerIoDeps",
"url-pathname": "urlPathname",
"bind-inline-handler": "bindInlineHandler",
"bind-preload": "bindPreload",
@@ -477,7 +478,6 @@ class JSEmitter:
"process-sx-scripts": "processSxScripts",
"process-component-script": "processComponentScript",
"init-style-dict": "initStyleDict",
"init-io-primitives": "initIoPrimitives",
"SX_VERSION": "SX_VERSION",
"boot-init": "bootInit",
"resolve-mount-target": "resolveMountTarget",
@@ -1733,16 +1733,20 @@ ASYNC_IO_JS = '''
});
}
// Register default proxied IO primitives
function initIoPrimitives() {
var defaults = [
"highlight", "current-user", "request-arg", "request-path",
"app-url", "asset-url", "config"
];
for (var i = 0; i < defaults.length; i++) {
registerProxiedIo(defaults[i]);
// Register IO deps as proxied primitives (idempotent, called per-page)
function registerIoDeps(names) {
if (!names || !names.length) return;
var registered = 0;
for (var i = 0; i < names.length; i++) {
var name = names[i];
if (!IO_PRIMITIVES[name]) {
registerProxiedIo(name);
registered++;
}
}
if (registered > 0) {
logInfo("sx:io registered " + registered + " proxied primitives: " + names.join(", "));
}
logInfo("sx:io registered " + defaults.length + " proxied primitives");
}
'''
@@ -3993,6 +3997,7 @@ def public_api_js(has_html, has_sx, has_dom, has_engine, has_orch, has_cssx, has
if has_dom:
api_lines.append(' registerIo: typeof registerIoPrimitive === "function" ? registerIoPrimitive : null,')
api_lines.append(' registerIoDeps: typeof registerIoDeps === "function" ? registerIoDeps : null,')
api_lines.append(' asyncRender: typeof asyncSxRenderWithEnv === "function" ? asyncSxRenderWithEnv : null,')
api_lines.append(' asyncRenderToDom: typeof asyncRenderToDom === "function" ? asyncRenderToDom : null,')
api_lines.append(f' _version: "{version}"')