// WASM-PROPOSAL Phase 3 — dynamic-loader core scaffold. // // This core owns the UCE heap, Request, DValue/UCEB1, and output buffer. The // Phase 3 loader dynamically links a PIC side module generated in the same // shape as UCE preprocessor output, sets its Request* context, and invokes its // __uce_render entry. #include #include #include #include "../../src/lib/types.h" #include "../../src/lib/dvalue.cpp" extern "C" { size_t uce_host_ctx_read(char* buf, size_t cap); void uce_host_log(int level, const char* buf, size_t len); } extern "C" void phase3_core_print(const char* data, size_t len) { if(context && context->ob) context->ob->write(data, len); } extern "C" void phase3_core_invoke_callback(void (*cb)(int), int value) { cb(value); } extern "C" void phase3_core_invoke_function(std::function* f, int value) { String out = "

fn=" + std::to_string((*f)(value)) + "

\n"; phase3_core_print(out.data(), out.size()); } extern "C" intptr_t core_table_index_of_phase3_core_print() { return(reinterpret_cast(phase3_core_print)); } static Request g_request; static ByteStream g_ob; static String g_output; SharedUnit::~SharedUnit() {} String html_escape(String s) { String result; for(char c : s) { switch(c) { case '&': result += "&"; break; case '<': result += "<"; break; case '>': result += ">"; break; case '"': result += """; break; case '\'': result += "'"; break; default: result.push_back(c); break; } } return(result); } String nibble(String div, String& haystack) { auto pos = haystack.find(div); if(pos == String::npos) { auto result = haystack; haystack.clear(); return(result); } auto result = haystack.substr(0, pos); haystack.erase(0, pos + div.length()); return(result); } void Request::ob_start() { ob_stack.push_back(new ByteStream()); ob = ob_stack.back(); } void Request::set_status(s32 code, String reason) { if(reason == "") reason = code == 200 ? "OK" : "Status"; response_code = "HTTP/1.1 " + std::to_string(code) + " " + reason; } Request::~Request() { for(auto* stream : ob_stack) delete stream; ob_stack.clear(); } static void phase3_clear_ob_stack() { for(auto* stream : g_request.ob_stack) delete stream; g_request.ob_stack.clear(); } static void phase3_apply_context(DValue& root) { g_request.call = root; g_request.params.clear(); DValue* params = root.key("params"); if(params) { params->each([&](const DValue& item, String key) { g_request.params[key] = item.to_string(); }); } } extern "C" { void* uce_alloc(size_t len) { return(malloc(len)); } void uce_free(void* ptr) { free(ptr); } int uce_phase3_prepare() { context = &g_request; phase3_clear_ob_stack(); g_ob.str(""); g_ob.clear(); g_request.ob = &g_ob; g_request.out = ""; g_output = ""; size_t ctx_required = uce_host_ctx_read(0, 0); if(ctx_required == 0) return(10); char* ctx_buf = (char*)malloc(ctx_required); if(ctx_buf == 0) return(11); size_t ctx_len = uce_host_ctx_read(ctx_buf, ctx_required); if(ctx_len != ctx_required) { free(ctx_buf); return(12); } DValue decoded; String error; bool ok = ucb_decode(String(ctx_buf, ctx_len), decoded, &error); free(ctx_buf); if(!ok) { uce_host_log(3, error.data(), error.size()); return(20); } phase3_apply_context(decoded); return(0); } Request* uce_phase3_request() { return(&g_request); } void uce_phase3_finish() { g_output = g_ob.str(); } const char* uce_phase3_output_data() { return(g_output.data()); } size_t uce_phase3_output_size() { return(g_output.size()); } }