This commit is contained in:
udo
2026-06-13 15:10:42 +00:00
parent afaa4dd7c0
commit 5a56d4f39e
14 changed files with 531 additions and 83 deletions
+13 -1
View File
@@ -860,13 +860,25 @@ void compile_shared_unit(Request* context, SharedUnit* su)
));
if(su->compiler_messages.length() == 0 && !su->opt_so_optional && compiler_wasm_unit_compile_enabled(context))
su->compiler_messages = trim(shell_exec(shell_escape(compiler_wasm_compile_script(context))+" "+
{
// The wasm side-module build is best-effort: a unit that cannot compile
// to wasm (e.g. try/catch) still works via the native .so and falls back
// to native at request time. Record the failure, never fail the unit on
// it. On failure, remove any stale .wasm so the backend won't serve it.
String wasm_messages = trim(shell_exec(shell_escape(compiler_wasm_compile_script(context))+" "+
shell_escape(su->src_path)+" "+
shell_escape(su->bin_path)+" "+
shell_escape(su->file_name)+" "+
shell_escape(su->pre_file_name)+" "+
shell_escape(su->wasm_file_name)
));
if(wasm_messages.length() > 0)
{
file_put_contents(su->wasm_check_file_name, wasm_messages + "\n");
file_unlink(su->wasm_name);
printf("(i) wasm side-module unavailable for %s (native .so serves it)\n", su->file_name.c_str());
}
}
if(su->compiler_messages.length() > 0)
{
+45 -17
View File
@@ -642,41 +642,69 @@ StringList regex_split(String pattern, String subject, String flags)
#else
// PCRE2 is not compiled into the wasm core; regex runs host-side (the host
// already links libpcre2). One UCEB1-marshalled hostcall carries the request
// {op,pattern,subject,flags,replacement} in and the result tree out — the host
// runs the real regex_* and packs the answer. See uce_host_regex in
// src/wasm/worker.cpp.
extern "C" size_t uce_host_regex(const char* in, size_t in_len, char* out, size_t cap);
static DValue wasm_regex_call(String op, String pattern, String subject, String flags, String replacement = "")
{
DValue request;
request["op"] = op;
request["pattern"] = pattern;
request["subject"] = subject;
request["flags"] = flags;
request["replacement"] = replacement;
String encoded = ucb_encode(request);
size_t need = uce_host_regex(encoded.data(), encoded.size(), 0, 0);
if(need == 0)
return(DValue());
String buffer(need, 0);
size_t got = uce_host_regex(encoded.data(), encoded.size(), &buffer[0], need);
if(got == 0 || got > need)
return(DValue());
DValue response;
String error;
ucb_decode(String(buffer.data(), got), response, &error);
return(response);
}
bool regex_match(String pattern, String subject, String flags)
{
(void)pattern; (void)subject; (void)flags;
return(false);
return(wasm_regex_call("match", pattern, subject, flags)["bool"].to_bool());
}
DValue regex_search(String pattern, String subject, String flags)
{
DValue result;
result["matched"].set_bool(false);
result["pattern"] = pattern;
result["flags"] = flags == "" ? "default" : flags;
return(result);
DValue response = wasm_regex_call("search", pattern, subject, flags);
DValue* tree = response.key("tree");
return(tree ? *tree : DValue());
}
DValue regex_search_all(String pattern, String subject, String flags)
{
DValue result;
result["matched"].set_bool(false);
result["pattern"] = pattern;
result["flags"] = flags == "" ? "default" : flags;
result["count"] = (f64)0;
return(result);
DValue response = wasm_regex_call("search_all", pattern, subject, flags);
DValue* tree = response.key("tree");
return(tree ? *tree : DValue());
}
String regex_replace(String pattern, String replacement, String subject, String flags)
{
(void)pattern; (void)replacement; (void)flags;
return(subject);
return(wasm_regex_call("replace", pattern, subject, flags, replacement)["text"].to_string());
}
StringList regex_split(String pattern, String subject, String flags)
{
(void)pattern; (void)flags;
return(StringList{ subject });
DValue response = wasm_regex_call("split", pattern, subject, flags);
StringList result;
DValue* list = response.key("list");
if(list)
list->each([&](const DValue& part, String) {
result.push_back(part.to_string());
});
return(result);
}
#endif
+17 -3
View File
@@ -14,6 +14,8 @@ void uce_host_log(int level, const char* buf, size_t len);
// cwd convention); file_read uses the length-query convention
int uce_host_file_exists(const char* path, size_t path_len, const char* current, size_t current_len);
size_t uce_host_file_read(const char* path, size_t path_len, const char* current, size_t current_len, char* buf, size_t cap);
int uce_host_file_write(const char* path, size_t path_len, const char* current, size_t current_len, const char* content, size_t content_len, int append);
void uce_host_file_unlink(const char* path, size_t path_len, const char* current, size_t current_len);
}
static String wasm_current_unit_file()
@@ -50,13 +52,25 @@ String file_get_contents(String file_name)
content.resize(got <= required ? got : 0);
return(content);
}
bool file_put_contents(String file_name, String content) { (void)file_name; (void)content; return(false); }
bool file_append_contents(String file_name, String content) { (void)file_name; (void)content; return(false); }
bool file_put_contents(String file_name, String content)
{
String current = wasm_current_unit_file();
return(uce_host_file_write(file_name.data(), file_name.size(), current.data(), current.size(), content.data(), content.size(), 0) != 0);
}
bool file_append_contents(String file_name, String content)
{
String current = wasm_current_unit_file();
return(uce_host_file_write(file_name.data(), file_name.size(), current.data(), current.size(), content.data(), content.size(), 1) != 0);
}
String cwd_get() { return("/"); }
void cwd_set(String path) { (void)path; }
String process_start_directory() { return("/"); }
time_t file_mtime(String file_name) { (void)file_name; return(0); }
void file_unlink(String file_name) { (void)file_name; }
void file_unlink(String file_name)
{
String current = wasm_current_unit_file();
uce_host_file_unlink(file_name.data(), file_name.size(), current.data(), current.size());
}
String expand_path(String path, String relative_to_path) { return(path_join(relative_to_path, path)); }
StringList ls(String dir) { (void)dir; return(StringList()); }
u64 config_map_u64(StringMap& cfg, String key, u64 fallback) { String raw = first(cfg[key], std::to_string(fallback)); char* end = 0; unsigned long long v = strtoull(raw.c_str(), &end, 10); return(end && *end == 0 ? (u64)v : fallback); }
+10
View File
@@ -12,6 +12,16 @@
#include "uri.cpp"
#include "cli.cpp"
#ifdef __UCE_WASM_CORE__
// markdown is pure compute (no PCRE/syscalls/regex) — it belongs in the wasm
// core so markdown_to_html/markdown_to_ast render in-workspace. compiler.cpp
// (which declares component() ahead of markdown in the native build) is carved
// out here, and the wasm core defines component() later in src/wasm/core.cpp,
// so markdown just needs the forward declaration.
String component(String name, DValue props, Request& context);
#include "markdown.cpp"
#endif
#ifndef __UCE_WASM_CORE__
#include "compiler-parser.cpp"
#include "compiler.cpp"
+6 -2
View File
@@ -15,7 +15,11 @@
#include <string>
#include <vector>
#if defined(__GNUG__)
// The demangler is a host-side nicety for trap traces. wasi-libc++ does not
// provide __cxa_demangle, and a wasm unit that merely includes uce_lib.h must
// not pull it in as an unresolvable import — so it is host-only.
#if defined(__GNUG__) && !defined(__wasm__)
#define UCE_WASM_TRACE_HAVE_DEMANGLE 1
#include <cxxabi.h>
#endif
@@ -30,7 +34,7 @@ struct WasmTraceSummary
inline std::string wasm_trace_demangle(const std::string& name)
{
#if defined(__GNUG__)
#if defined(UCE_WASM_TRACE_HAVE_DEMANGLE)
// frame names look like "module!symbol"; demangle the symbol part
auto bang = name.find('!');
std::string prefix = bang == std::string::npos ? "" : name.substr(0, bang + 1);