This commit is contained in:
udo
2026-06-13 02:07:38 +00:00
parent eb8f303f94
commit 577aae076e
27 changed files with 2937 additions and 21 deletions
+1 -1
View File
@@ -494,7 +494,7 @@ String compiler_rewrite_named_render_syntax(String content)
String compiler_preprocess_shared_unit_char_wise(Request* context, SharedUnit* su, String content)
{
String parsed_content =
("#include \"")+context->server->config["COMPILER_SYS_PATH"] +"/src/lib/uce_lib.h\" \n"+
"#include \"uce_lib.h\" \n"+
file_get_contents(
context->server->config["COMPILER_SYS_PATH"] + "/" + context->server->config["SETUP_TEMPLATE"]
)+
+32 -1
View File
@@ -132,6 +132,23 @@ String compiler_unit_metadata_text(Request* context, SharedUnit* su)
);
}
bool compiler_wasm_unit_compile_enabled(Request* context)
{
if(!context || !context->server)
return(false);
return(config_bool("COMPILE_WASM_UNITS", false));
}
String compiler_wasm_compile_script(Request* context)
{
String script = "scripts/compile_wasm_unit";
if(context && context->server)
script = first(context->server->config["WASM_COMPILE_SCRIPT"], script);
if(script != "" && script[0] != '/' && context && context->server)
script = path_join(context->server->config["COMPILER_SYS_PATH"], script);
return(script);
}
SharedUnitCompileCheck shared_unit_compile_check(const SharedUnitFilesystemState& state)
{
SharedUnitCompileCheck result;
@@ -647,9 +664,12 @@ void setup_unit_paths(Request* context, SharedUnit* su, String file_name)
su->src_file_name = basename(file_name);
su->bin_file_name = su->src_file_name + ".so";
su->wasm_file_name = su->src_file_name + ".wasm";
su->pre_file_name = su->src_file_name + ".cpp";
su->so_name = su->bin_path + "/" + su->bin_file_name;
su->wasm_name = su->bin_path + "/" + su->wasm_file_name;
su->wasm_check_file_name = su->bin_path + "/" + su->src_file_name + ".wasm-check.txt";
su->api_file_name = su->bin_path + "/" + su->src_file_name + ".exports.txt";
su->meta_file_name = su->bin_path + "/" + su->src_file_name + ".meta.txt";
su->compile_output_file_name = su->bin_path + "/" + su->src_file_name + ".compile.txt";
@@ -740,7 +760,7 @@ void load_shared_unit(Request* context, SharedUnit* su)
String result =
String("#ifndef UCE_LIB_INCLUDED\n") +
"#define UCE_LIB_INCLUDED\n" +
("#include \"")+context->server->config["COMPILER_SYS_PATH"] +"/src/lib/uce_lib.h\" \n"+
"#include \"uce_lib.h\" \n"+
file_get_contents(
context->server->config["COMPILER_SYS_PATH"] + "/" + context->server->config["SETUP_TEMPLATE"]) +
"#endif \n";
@@ -839,6 +859,15 @@ void compile_shared_unit(Request* context, SharedUnit* su)
shell_escape(su->bin_file_name)
));
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))+" "+
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(su->compiler_messages.length() > 0)
{
String raw_messages = su->compiler_messages;
@@ -1171,6 +1200,8 @@ DValue unit_info(String path)
info["bin_file_name"] = su->bin_file_name;
info["pre_file_name"] = su->pre_file_name;
info["so_name"] = su->so_name;
info["wasm_name"] = su->wasm_name;
info["wasm_exists"].set_bool(file_exists(su->wasm_name));
info["api_file_name"] = su->api_file_name;
info["meta_file_name"] = su->meta_file_name;
info["compile_output_file_name"] = su->compile_output_file_name;
+54
View File
@@ -1,7 +1,9 @@
#include "functionlib.h"
#ifndef __UCE_WASM_CORE__
#define PCRE2_CODE_UNIT_WIDTH 8
#include <pcre2.h>
#endif
#include <cctype>
#include <stdexcept>
#include <algorithm>
@@ -296,6 +298,7 @@ String replace(String s, String search, String replace_with)
return(result);
}
#ifndef __UCE_WASM_CORE__
namespace {
String regex_flags_label(String flags)
@@ -637,6 +640,47 @@ StringList regex_split(String pattern, String subject, String flags)
return(result);
}
#else
bool regex_match(String pattern, String subject, String flags)
{
(void)pattern; (void)subject; (void)flags;
return(false);
}
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 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);
}
String regex_replace(String pattern, String replacement, String subject, String flags)
{
(void)pattern; (void)replacement; (void)flags;
return(subject);
}
StringList regex_split(String pattern, String subject, String flags)
{
(void)pattern; (void)flags;
return(StringList{ subject });
}
#endif
String trim(String raw)
{
s64 len = raw.length();
@@ -1323,7 +1367,12 @@ String xml_decode_text(String s)
void xml_throw(String message)
{
#ifdef __UCE_WASM_CORE__
(void)message;
__builtin_trap();
#else
throw std::runtime_error("xml_decode(): " + message);
#endif
}
struct XmlParser
@@ -1856,7 +1905,12 @@ String yaml_decode_quoted(String raw)
void yaml_throw(String message)
{
#ifdef __UCE_WASM_CORE__
(void)message;
__builtin_trap();
#else
throw std::runtime_error("yaml_decode(): " + message);
#endif
}
struct YamlParser
+7 -4
View File
@@ -55,8 +55,11 @@ String to_string(SharedUnit* u) {
return(result);
}
// NB: header-defined function templates must be inline — wasm side modules
// compile with -fvisibility-inlines-hidden so instantiations bind locally
// instead of becoming unresolvable self-imports (WASM-PROPOSAL §6)
template <typename ITYPE>
String to_hex(ITYPE w, size_t hex_len = sizeof(ITYPE)<<1)
inline String to_hex(ITYPE w, size_t hex_len = sizeof(ITYPE)<<1)
{
static const char* digits = "0123456789ABCDEF";
String rc(hex_len,'0');
@@ -66,7 +69,7 @@ String to_hex(ITYPE w, size_t hex_len = sizeof(ITYPE)<<1)
}
template<typename T, typename F>
std::vector<T> filter(std::vector<T> items, F f)
inline std::vector<T> filter(std::vector<T> items, F f)
{
std::vector<T> new_items;
for(auto item : items)
@@ -78,7 +81,7 @@ std::vector<T> filter(std::vector<T> items, F f)
}
template<typename T, typename F>
auto map(std::vector<T> items, F f)
inline auto map(std::vector<T> items, F f)
{
using ResultType = decltype(f(items[0]));
std::vector<ResultType> new_items;
@@ -101,7 +104,7 @@ DValue dv_filter(DValue tree, std::function<bool (const DValue&, String)> f);
DValue dv_group_by(DValue tree, std::function<String (const DValue&, String)> f);
template <class ...Args>
String first(Args... args)
inline String first(Args... args)
{
std::vector<String> vec = {args...};
for(auto s : vec)
+5
View File
@@ -19,6 +19,11 @@ A million repetitions of "a"
/* #define LITTLE_ENDIAN * This should be #define'd already, if true. */
/* #define SHA1HANDSOFF * Copies data before messing with it. */
#ifdef __UCE_WASM_CORE__
#include <stdint.h>
typedef uint32_t u_int32_t;
#endif
typedef struct {
u_int32_t state[5];
u_int32_t count[2];
+119
View File
@@ -1,3 +1,119 @@
#ifdef __UCE_WASM_CORE__
#include "types.h"
#include "functionlib.h"
#include "sys.h"
extern "C" {
uint64_t uce_host_time(void);
double uce_host_time_precise(void);
size_t uce_host_env(const char* key, size_t key_len, char* buf, size_t cap);
size_t uce_host_random(char* buf, size_t len);
void uce_host_log(int level, const char* buf, size_t len);
// read-only file membrane, policy-gated host-side to the site tree;
// relative paths resolve against the current unit's directory (the native
// 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);
}
static String wasm_current_unit_file()
{
return(context ? context->resources.current_unit_file : String(""));
}
String shell_exec(String cmd) { (void)cmd; return(""); }
String shell_escape(String raw) { return(raw); }
String basename(String fn) { while(fn.find("/") != String::npos) fn = fn.substr(fn.find("/") + 1); return(fn); }
String dirname(String fn) { auto pos = fn.find_last_of('/'); return(pos == String::npos ? "" : fn.substr(0, pos)); }
String path_join(String base, String child) { if(base == "") return(child); if(child == "") return(base); if(child[0] == '/') return(child); return(base + (base.back() == '/' ? "" : "/") + child); }
String path_real(String path) { return(path); }
bool path_is_within(String path, String root) { return(str_starts_with(path, root)); }
bool mkdir(String path) { (void)path; return(false); }
bool file_exists(String path)
{
String current = wasm_current_unit_file();
return(uce_host_file_exists(path.data(), path.size(), current.data(), current.size()) != 0);
}
int file_open_locked(String file_name, int open_flags, int lock_type, int create_mode, f64 wait_timeout_seconds, String purpose) { (void)file_name; (void)open_flags; (void)lock_type; (void)create_mode; (void)wait_timeout_seconds; (void)purpose; return(-1); }
void file_close_locked(int fd) { (void)fd; }
void file_release_process_locks(String reason) { (void)reason; }
String file_get_contents_locked_fd(int fd) { (void)fd; return(""); }
bool file_put_contents_locked_fd(int fd, String content) { (void)fd; (void)content; return(false); }
String file_get_contents(String file_name)
{
String current = wasm_current_unit_file();
size_t required = uce_host_file_read(file_name.data(), file_name.size(), current.data(), current.size(), 0, 0);
if(required == 0)
return("");
String content(required, 0);
size_t got = uce_host_file_read(file_name.data(), file_name.size(), current.data(), current.size(), &content[0], required);
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); }
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; }
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); }
f64 config_map_f64(StringMap& cfg, String key, f64 fallback) { String raw = first(cfg[key], std::to_string(fallback)); char* end = 0; double v = strtod(raw.c_str(), &end); return(end && *end == 0 ? (f64)v : fallback); }
bool config_bool_value(String raw, bool fallback) { if(raw == "") return(fallback); return(raw != "0" && raw != "false" && raw != "no" && raw != "off"); }
bool config_map_bool(StringMap& cfg, String key, bool fallback) { return(config_bool_value(cfg[key], fallback)); }
u64 config_u64(String key, u64 fallback) { return(context ? config_map_u64(context->server->config, key, fallback) : fallback); }
f64 config_f64(String key, f64 fallback) { return(context ? config_map_f64(context->server->config, key, fallback) : fallback); }
bool config_bool(String key, bool fallback) { return(context ? config_map_bool(context->server->config, key, fallback) : fallback); }
f64 time_precise() { return(uce_host_time_precise()); }
u64 time() { return(uce_host_time()); }
String time_format_local(String format, u64 timestamp) { (void)format; return(std::to_string(timestamp ? timestamp : time())); }
String time_format_utc(String format, u64 timestamp) { (void)format; return(std::to_string(timestamp ? timestamp : time())); }
String time_format_relative(u64 timestamp, String format_very_recent, u64 medium_recency_seconds, String format_medium_recent, u64 not_recent_seconds, String format_not_recent) { (void)format_very_recent; (void)medium_recency_seconds; (void)format_medium_recent; (void)not_recent_seconds; (void)format_not_recent; return(std::to_string(timestamp)); }
u64 time_parse(String time_String) { char* end = 0; unsigned long long v = strtoull(time_String.c_str(), &end, 10); return(end && *end == 0 ? (u64)v : 0); }
u64 socket_connect(String host, short port) { (void)host; (void)port; return(0); }
void socket_close(u64 sockfd) { (void)sockfd; }
bool socket_write(u64 sockfd, String data) { (void)sockfd; (void)data; return(false); }
String socket_read(u64 sockfd, u32 max_length, u32 timeout) { (void)sockfd; (void)max_length; (void)timeout; return(""); }
String ws_message() { return(context ? context->in : ""); }
String ws_connection_id() { return(context ? context->resources.websocket_connection_id : ""); }
String ws_scope() { return(context ? context->resources.websocket_scope : ""); }
u8 ws_opcode() { return(context ? context->resources.websocket_opcode : 0); }
bool ws_is_binary() { return(context && context->resources.websocket_is_binary); }
StringList ws_connections(String scope) { (void)scope; return(StringList()); }
u64 ws_connection_count(String scope) { (void)scope; return(0); }
bool ws_send(String message, bool binary, String scope) { (void)message; (void)binary; (void)scope; return(false); }
bool ws_send_to(String connection_id, String message, bool binary) { (void)connection_id; (void)message; (void)binary; return(false); }
bool ws_close(String connection_id) { (void)connection_id; return(false); }
String backtrace_frames_string(void* const* frames, size_t size, u32 skip_frames) { (void)frames; (void)size; (void)skip_frames; return(""); }
String capture_backtrace_string(u32 max_frames, u32 skip_frames) { (void)max_frames; (void)skip_frames; return(""); }
String signal_name(int sig) { (void)sig; return(""); }
String memcache_escape_key(String key) { return(key); }
StringList memcache_escape_keys(StringList keys) { return(keys); }
u64 memcache_connect(String host, short port) { (void)host; (void)port; return(0); }
String memcache_command(u64 connection, String command) { (void)connection; (void)command; return(""); }
bool memcache_set(u64 connection, String key, String value, u64 expires_in) { (void)connection; (void)key; (void)value; (void)expires_in; return(false); }
bool memcache_delete(u64 connection, String key) { (void)connection; (void)key; return(false); }
String memcache_get(u64 connection, String key, String default_value) { (void)connection; (void)key; return(default_value); }
StringMap memcache_get_multiple(u64 connection, StringList keys) { (void)connection; (void)keys; return(StringMap()); }
void on_segfault(int sig) { (void)sig; }
int task_kill(pid_t pid, int sig) { (void)pid; (void)sig; return(-1); }
String runtime_safe_key(String key, String label) { (void)label; return(key); }
pid_t task(String key, std::function<void()> exec_after_spawn, u64 timeout) { (void)key; (void)exec_after_spawn; (void)timeout; return(0); }
pid_t task_repeat(String key, f64 interval, std::function<void()> exec_after_spawn, u64 timeout) { (void)key; (void)interval; (void)exec_after_spawn; (void)timeout; return(0); }
pid_t task_pid(String key) { (void)key; return(0); }
pid_t server_start_http(String key, String socket_fn_or_port, String call_uce_filename, String call_function) { (void)key; (void)socket_fn_or_port; (void)call_uce_filename; (void)call_function; return(0); }
bool server_stop(String key) { (void)key; return(false); }
StringMap default_config()
{
StringMap cfg;
cfg["SESSION_TIME"] = std::to_string(60*60*24*30);
cfg["MAX_MEMORY"] = std::to_string(1024*1024*16);
return(cfg);
}
#else
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
@@ -942,6 +1058,8 @@ StringMap make_server_settings()
cfg["BIN_DIRECTORY"] = "/tmp/uce/work";
cfg["COMPILE_SCRIPT"] = "scripts/compile";
cfg["WASM_COMPILE_SCRIPT"] = "scripts/compile_wasm_unit";
cfg["COMPILE_WASM_UNITS"] = "0";
cfg["SETUP_TEMPLATE"] = "scripts/setup.h.template";
cfg["LIT_ESC"] = "3d5b5_1";
cfg["CONTENT_TYPE"] = "text/html; charset=utf-8";
@@ -999,3 +1117,4 @@ StringMap make_server_settings()
return(cfg);
}
#endif
+22 -1
View File
@@ -1,7 +1,28 @@
#pragma once
#if defined(__UCE_WASM_CORE__) || defined(__UCE_WASM_UNIT__)
#ifndef LOCK_SH
#define LOCK_SH 1
#define LOCK_EX 2
#define LOCK_UN 8
#endif
#ifndef SIGABRT
#define SIGABRT 6
#endif
#ifndef SIGSEGV
#define SIGSEGV 11
#endif
typedef int pid_t;
extern "C" {
int raise(int);
unsigned int sleep(unsigned int seconds);
int usleep(unsigned int usec);
}
#else
#include <sys/file.h>
#include <signal.h>
#endif
#include <ctime>
#include <sstream>
String shell_exec(String cmd);
@@ -22,7 +43,7 @@ String file_get_contents(String file_name);
bool file_put_contents(String file_name, String content);
bool file_append_contents(String file_name, String content);
template <typename... Ts>
bool file_append(String file_name, Ts... args)
inline bool file_append(String file_name, Ts... args)
{
std::ostringstream out;
((out << args), ...);
+9 -4
View File
@@ -1,16 +1,17 @@
#ifndef __UCE_WASM_CORE__
#include <sys/file.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <dlfcn.h>
#endif
#include <stdlib.h>
#include <iostream>
#include <filesystem>
#include <ctype.h>
#include <fstream>
#include <sys/stat.h>
#include <ctime>
#include <dlfcn.h>
#include <limits.h>
#include <algorithm>
#include <sys/stat.h>
#include <iostream>
#include "types.h"
@@ -52,10 +53,12 @@ String http_status_reason(s32 code)
SharedUnit::~SharedUnit()
{
#ifndef __UCE_WASM_CORE__
if(so_handle)
{
dlclose(so_handle);
}
#endif
}
String nibble(String div, String& haystack)
@@ -98,6 +101,8 @@ Request::~Request()
delete stream;
ob_stack.clear();
ob = 0;
#ifndef __UCE_WASM_CORE__
for(auto& sockfd : resources.sockets)
close(sockfd);
#endif
}
+10 -3
View File
@@ -65,6 +65,8 @@ struct SharedUnit {
String file_name;
String so_name;
String wasm_name;
String wasm_check_file_name;
String api_file_name;
String meta_file_name;
String compile_output_file_name;
@@ -77,6 +79,7 @@ struct SharedUnit {
String pre_path;
String src_file_name;
String bin_file_name;
String wasm_file_name;
String pre_file_name;
void* so_handle = 0;
@@ -243,26 +246,29 @@ Request* context;
#include <iostream>
// NB: header templates must be inline — wasm units rely on
// -fvisibility-inlines-hidden binding instantiations locally (§6)
template <typename... Ts>
void print(Ts... args)
inline void print(Ts... args)
{
((*context->ob << args), ...);
}
template <typename... Ts>
void out(Ts... args)
inline void out(Ts... args)
{
((*context->ob << args), ...);
}
template <typename... Ts>
String concat(Ts... args)
inline String concat(Ts... args)
{
ByteStream out;
((out << args), ...);
return(out.str());
}
#ifndef __UCE_WASM_UNIT__
void * operator new(decltype(sizeof(0)) n) noexcept(false)
{
void* ptr = malloc(n);
@@ -280,3 +286,4 @@ void operator delete(void * p) throw()
//TO DO: track deallocations
free(p);
}
#endif
+3
View File
@@ -11,9 +11,12 @@
#include "sys.cpp"
#include "uri.cpp"
#include "cli.cpp"
#ifndef __UCE_WASM_CORE__
#include "compiler-parser.cpp"
#include "compiler.cpp"
#include "markdown.cpp"
#include "zip.cpp"
#include "mysql-connector.cpp"
#include "sqlite-connector.cpp"
#endif
+18
View File
@@ -4,6 +4,10 @@
#include <fcntl.h>
#include <unistd.h>
#ifdef __UCE_WASM_CORE__
extern "C" size_t uce_host_random(char* buf, size_t len);
#endif
String base64_encode(String raw)
{
static const char* chars =
@@ -714,6 +718,19 @@ StringMap parse_cookies(String cookie_String)
String session_id_create()
{
#ifdef __UCE_WASM_CORE__
unsigned char bytes[32];
if(uce_host_random((char*)bytes, sizeof(bytes)) != sizeof(bytes))
__builtin_trap();
String result;
static const char* hex = "0123456789abcdef";
for(unsigned char b : bytes)
{
result.push_back(hex[b >> 4]);
result.push_back(hex[b & 0x0f]);
}
return(result);
#else
unsigned char bytes[32];
int fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC);
if(fd == -1)
@@ -738,6 +755,7 @@ String session_id_create()
result.push_back(hex[b & 0x0f]);
}
return(result);
#endif
}
bool is_valid_session_id(String session_id)