feat: cut over to WASM backend

This commit is contained in:
udo
2026-06-13 08:42:31 +00:00
parent 577aae076e
commit afaa4dd7c0
16 changed files with 603 additions and 25 deletions
+43 -2
View File
@@ -103,6 +103,11 @@ extern "C" void uce_wasm_link_anchors()
(void*)(const char* (*)(const char*, int))&strchr,
(void*)(const char* (*)(const char*, int))&strrchr,
(void*)(const char* (*)(const char*, const char*))&strstr,
// ctype family (int(int)); units use these directly
(void*)&isalnum, (void*)&isalpha, (void*)&isblank, (void*)&iscntrl,
(void*)&isdigit, (void*)&isgraph, (void*)&islower, (void*)&isprint,
(void*)&ispunct, (void*)&isspace, (void*)&isupper, (void*)&isxdigit,
(void*)&tolower, (void*)&toupper,
};
(void)libc_anchors;
}
@@ -170,8 +175,13 @@ struct RequestPropsScope
}
};
// kind values shared with the host loader (see src/wasm/worker.h)
enum WasmResolveKind { WASM_RESOLVE_COMPONENT = 0, WASM_RESOLVE_RENDER = 1, WASM_RESOLVE_EXISTS = 2 };
// kind values shared with the host loader (src/wasm/worker.cpp)
enum WasmResolveKind {
WASM_RESOLVE_COMPONENT = 0,
WASM_RESOLVE_RENDER = 1,
WASM_RESOLVE_EXISTS = 2,
WASM_RESOLVE_ONCE = 3,
};
static s32 wasm_resolve_target(String target, s32 kind, String* resolved_out = 0)
{
@@ -205,6 +215,26 @@ bool component_exists(String name)
return(component_resolve(name) != "");
}
// Run a unit's ONCE() handler at most once per request (native
// compiler_run_unit_once_if_needed semantics): dedup on the resolved unit
// path via request.once_units. The handler emits head assets, etc.
static void wasm_run_once(const String& resolved, Request& request)
{
if(resolved == "")
return;
if(request.once_units.find(resolved) != request.once_units.end())
return;
request.once_units.insert(resolved);
s32 once_slot = wasm_resolve_target(resolved, WASM_RESOLVE_ONCE);
if(once_slot == 0)
return;
String previous_unit = request.resources.current_unit_file;
request.resources.current_unit_file = resolved;
request_ref_handler once_handler = (request_ref_handler)(uintptr_t)once_slot;
once_handler(request);
request.resources.current_unit_file = previous_unit;
}
void component_render(String name, DValue props, Request& request)
{
String resolved;
@@ -214,6 +244,7 @@ void component_render(String name, DValue props, Request& request)
print(component_error_banner("component not found: " + trim(name)));
return;
}
wasm_run_once(resolved, request);
RequestPropsScope props_scope(&request, props);
String previous_unit = request.resources.current_unit_file;
if(resolved != "")
@@ -249,6 +280,7 @@ void unit_render(String file_name, Request& request)
print(component_error_banner("unit not found: " + trim(file_name)));
return;
}
wasm_run_once(resolved, request);
String previous_unit = request.resources.current_unit_file;
if(resolved != "")
request.resources.current_unit_file = resolved;
@@ -261,6 +293,15 @@ void unit_render(String file_name) { unit_render(file_name, *context); }
extern "C" {
// Host calls this to render the request's entry unit. Routing through
// unit_render gives the entry the same ONCE() + dispatch semantics as
// components (the host pre-loaded it, so resolution is a cache hit).
void uce_wasm_render_entry(const char* path, size_t len)
{
// the host always runs uce_wasm_core_init + apply_context before this
unit_render(String(path, len), *context);
}
void* uce_alloc(size_t len)
{
return(malloc(len));