Private
Public Access
Reduce compiler runtime code and unify theme paths.
This commit is contained in:
1 parent
54619748f4
commit
51558716af
20 files changed
+175
-509
No files matched your search
@@ -22,4 +22,4 @@ int main()
|
||||
EOF
|
||||
"${CXX:-c++}" -std=c++20 -fpermissive -I. "$source" -lpcre2-8 -o "$binary"
|
||||
"$binary"
|
||||
echo "exact decimal SQLite/MySQL request-handle protocol passed"
|
||||
echo "exact BRRB u64 decimal round-trip passed"
|
||||
@@ -2,10 +2,7 @@
|
||||
|
||||
COMPONENT(Request& context)
|
||||
{
|
||||
DValue asset_props;
|
||||
asset_props["css"]["0"] = "themes/common/css/gauges.css";
|
||||
asset_props["js"]["0"] = "components/gauges/common.js";
|
||||
print(component("../theme/assets", asset_props, context));
|
||||
gauge_assets(context);
|
||||
|
||||
String gauge_id = first(context.props["id"].to_string(), "arcgauge-" + std::to_string((u64)time()));
|
||||
String title = context.props["title"].to_string();
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
#load "../../lib/app.uce"
|
||||
#include <math.h>
|
||||
|
||||
void gauge_assets(Request& context)
|
||||
{
|
||||
DValue props;
|
||||
props["css"]["0"] = "themes/common/css/gauges.css";
|
||||
props["js"]["0"] = "components/gauges/common.js";
|
||||
print(component("../theme/assets", props, context));
|
||||
}
|
||||
|
||||
f64 gauge_clamp_value(f64 value, f64 min_value, f64 max_value)
|
||||
{
|
||||
return(std::max(min_value, std::min(max_value, value)));
|
||||
|
||||
@@ -2,10 +2,7 @@
|
||||
|
||||
COMPONENT(Request& context)
|
||||
{
|
||||
DValue asset_props;
|
||||
asset_props["css"]["0"] = "themes/common/css/gauges.css";
|
||||
asset_props["js"]["0"] = "components/gauges/common.js";
|
||||
print(component("../theme/assets", asset_props, context));
|
||||
gauge_assets(context);
|
||||
|
||||
String gauge_id = first(context.props["id"].to_string(), "needlegauge-" + std::to_string((u64)time()));
|
||||
String style = context.props["style"].to_string();
|
||||
|
||||
@@ -2,10 +2,7 @@
|
||||
|
||||
COMPONENT(Request& context)
|
||||
{
|
||||
DValue asset_props;
|
||||
asset_props["css"]["0"] = "themes/common/css/gauges.css";
|
||||
asset_props["js"]["0"] = "components/gauges/common.js";
|
||||
print(component("../theme/assets", asset_props, context));
|
||||
gauge_assets(context);
|
||||
|
||||
String gauge_id = first(context.props["id"].to_string(), "progressbar-" + std::to_string((u64)time()));
|
||||
String style = context.props["style"].to_string();
|
||||
|
||||
@@ -1,3 +1,16 @@
|
||||
void config_theme(DValue& options, String key, String label, String path, String mode, String description, String footer_text, String meta_description, String theme_color)
|
||||
{
|
||||
DValue& theme = options[key];
|
||||
theme["label"] = label;
|
||||
theme["path"] = path;
|
||||
theme["mode"] = mode;
|
||||
theme["mode-class"] = mode == "dark" ? "dark-theme" : "";
|
||||
theme["description"] = description;
|
||||
theme["footer_text"] = footer_text;
|
||||
theme["meta_description"] = meta_description;
|
||||
theme["theme_color"] = theme_color;
|
||||
}
|
||||
|
||||
DValue get_config()
|
||||
{
|
||||
DValue config;
|
||||
@@ -10,59 +23,13 @@ DValue get_config()
|
||||
config["filebase"]["path"] = "/tmp/bearer-starter-data";
|
||||
|
||||
config["theme"]["key"] = "portal-dark";
|
||||
config["theme"]["options"]["light"]["label"] = "Starter Light";
|
||||
config["theme"]["options"]["light"]["path"] = "themes/light/";
|
||||
config["theme"]["options"]["light"]["mode"] = "light";
|
||||
config["theme"]["options"]["light"]["mode-class"] = "";
|
||||
config["theme"]["options"]["light"]["description"] = "Original starter light theme kept for backward compatibility.";
|
||||
config["theme"]["options"]["light"]["footer_text"] = "BEARER Starter running with the Starter Light theme.";
|
||||
config["theme"]["options"]["light"]["meta_description"] = "Starter Light theme for the BEARER starter";
|
||||
config["theme"]["options"]["light"]["theme_color"] = "#3b82f6";
|
||||
|
||||
config["theme"]["options"]["dark"]["label"] = "Starter Dark";
|
||||
config["theme"]["options"]["dark"]["path"] = "themes/dark/";
|
||||
config["theme"]["options"]["dark"]["mode"] = "dark";
|
||||
config["theme"]["options"]["dark"]["mode-class"] = "dark-theme";
|
||||
config["theme"]["options"]["dark"]["description"] = "Original starter dark theme kept for backward compatibility.";
|
||||
config["theme"]["options"]["dark"]["footer_text"] = "BEARER Starter running with the Starter Dark theme.";
|
||||
config["theme"]["options"]["dark"]["meta_description"] = "Starter Dark theme for the BEARER starter";
|
||||
config["theme"]["options"]["dark"]["theme_color"] = "#0f172a";
|
||||
|
||||
config["theme"]["options"]["portal-light"]["label"] = "AI Portal Light";
|
||||
config["theme"]["options"]["portal-light"]["path"] = "themes/portal-light/";
|
||||
config["theme"]["options"]["portal-light"]["mode"] = "light";
|
||||
config["theme"]["options"]["portal-light"]["mode-class"] = "";
|
||||
config["theme"]["options"]["portal-light"]["description"] = "Dense, corporate portal layout in a light palette.";
|
||||
config["theme"]["options"]["portal-light"]["footer_text"] = "BEARER Starter running with the AI Portal Light starter theme.";
|
||||
config["theme"]["options"]["portal-light"]["meta_description"] = "AI Portal Light theme for the BEARER starter";
|
||||
config["theme"]["options"]["portal-light"]["theme_color"] = "#0f68ad";
|
||||
|
||||
config["theme"]["options"]["portal-dark"]["label"] = "AI Portal Dark";
|
||||
config["theme"]["options"]["portal-dark"]["path"] = "themes/portal-dark/";
|
||||
config["theme"]["options"]["portal-dark"]["mode"] = "dark";
|
||||
config["theme"]["options"]["portal-dark"]["mode-class"] = "dark-theme";
|
||||
config["theme"]["options"]["portal-dark"]["description"] = "Glassy dark portal shell and the current default starter theme.";
|
||||
config["theme"]["options"]["portal-dark"]["footer_text"] = "BEARER Starter running with the AI Portal Dark starter theme.";
|
||||
config["theme"]["options"]["portal-dark"]["meta_description"] = "AI Portal Dark theme for the BEARER starter";
|
||||
config["theme"]["options"]["portal-dark"]["theme_color"] = "#0f172a";
|
||||
|
||||
config["theme"]["options"]["localfirst"]["label"] = "Local First";
|
||||
config["theme"]["options"]["localfirst"]["path"] = "themes/localfirst/";
|
||||
config["theme"]["options"]["localfirst"]["mode"] = "dark";
|
||||
config["theme"]["options"]["localfirst"]["mode-class"] = "dark-theme";
|
||||
config["theme"]["options"]["localfirst"]["description"] = "llm2-derived admin shell with sidebar chrome.";
|
||||
config["theme"]["options"]["localfirst"]["footer_text"] = "BEARER Starter running with the Local First starter theme.";
|
||||
config["theme"]["options"]["localfirst"]["meta_description"] = "Local First admin-shell theme for the BEARER starter";
|
||||
config["theme"]["options"]["localfirst"]["theme_color"] = "#020913";
|
||||
|
||||
config["theme"]["options"]["retro-gaming"]["label"] = "Retro Gaming";
|
||||
config["theme"]["options"]["retro-gaming"]["path"] = "themes/retro-gaming/";
|
||||
config["theme"]["options"]["retro-gaming"]["mode"] = "dark";
|
||||
config["theme"]["options"]["retro-gaming"]["mode-class"] = "dark-theme";
|
||||
config["theme"]["options"]["retro-gaming"]["description"] = "CRT scanlines, pixel font, neon glow.";
|
||||
config["theme"]["options"]["retro-gaming"]["footer_text"] = "INSERT COIN // BEARER Starter running the Retro Gaming theme.";
|
||||
config["theme"]["options"]["retro-gaming"]["meta_description"] = "Retro Gaming pixel theme for the BEARER starter";
|
||||
config["theme"]["options"]["retro-gaming"]["theme_color"] = "#0a0a1a";
|
||||
DValue& themes = config["theme"]["options"];
|
||||
config_theme(themes, "light", "Starter Light", "themes/light/", "light", "Original starter light theme kept for backward compatibility.", "BEARER Starter running with the Starter Light theme.", "Starter Light theme for the BEARER starter", "#3b82f6");
|
||||
config_theme(themes, "dark", "Starter Dark", "themes/dark/", "dark", "Original starter dark theme kept for backward compatibility.", "BEARER Starter running with the Starter Dark theme.", "Starter Dark theme for the BEARER starter", "#0f172a");
|
||||
config_theme(themes, "portal-light", "AI Portal Light", "themes/portal-light/", "light", "Dense, corporate portal layout in a light palette.", "BEARER Starter running with the AI Portal Light starter theme.", "AI Portal Light theme for the BEARER starter", "#0f68ad");
|
||||
config_theme(themes, "portal-dark", "AI Portal Dark", "themes/portal-dark/", "dark", "Glassy dark portal shell and the current default starter theme.", "BEARER Starter running with the AI Portal Dark starter theme.", "AI Portal Dark theme for the BEARER starter", "#0f172a");
|
||||
config_theme(themes, "localfirst", "Local First", "themes/localfirst/", "dark", "llm2-derived admin shell with sidebar chrome.", "BEARER Starter running with the Local First starter theme.", "Local First admin-shell theme for the BEARER starter", "#020913");
|
||||
config_theme(themes, "retro-gaming", "Retro Gaming", "themes/retro-gaming/", "dark", "CRT scanlines, pixel font, neon glow.", "INSERT COIN // BEARER Starter running the Retro Gaming theme.", "Retro Gaming pixel theme for the BEARER starter", "#0a0a1a");
|
||||
|
||||
config["menu"][""]["title"] = "Home";
|
||||
config["menu"][""]["hidden"].set_bool(true);
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
#load "../../lib/app.uce"
|
||||
|
||||
inline void render_common_theme_page(Request& context)
|
||||
{
|
||||
String main_html = context.call["fragments"]["main"].to_string();
|
||||
String key = context.cfg.get_by_path("theme/key").to_string();
|
||||
String body_class;
|
||||
if(key == "portal-dark") body_class = "portal-theme portal-dark-theme dark-theme";
|
||||
else if(key == "portal-light") body_class = "portal-theme portal-light-theme";
|
||||
|
||||
<>
|
||||
<!doctype html>
|
||||
<html class="no-js <?= context.cfg.get_by_path("theme/mode-class").to_string() ?>" lang="en" data-theme-key="<?= key ?>">
|
||||
<head>
|
||||
<?: component("../../components/theme/head", context) ?>
|
||||
</head>
|
||||
<? if(body_class == "") { ?><body><? } else { ?><body class="<?= body_class ?>"><? } ?>
|
||||
<? if(key == "retro-gaming") { ?><div class="retro-stars"></div><? } ?>
|
||||
<?: component("../../components/theme/global_controls", context) ?>
|
||||
<?: component("../../components/theme/standard_nav", context) ?>
|
||||
<div id="content">
|
||||
<?: main_html ?>
|
||||
</div>
|
||||
<?: component("../../components/theme/footer", context) ?>
|
||||
</body>
|
||||
</html>
|
||||
</>
|
||||
}
|
||||
@@ -1,28 +1,3 @@
|
||||
#load "../../lib/app.uce"
|
||||
#load "../common/page.uce"
|
||||
|
||||
COMPONENT(Request& context)
|
||||
{
|
||||
String main_html = context.call["fragments"]["main"].to_string();
|
||||
|
||||
DValue nav_props;
|
||||
nav_props["account_wrapper_class"] = "nav-account nav-menu";
|
||||
|
||||
DValue footer_props;
|
||||
|
||||
<>
|
||||
<!doctype html>
|
||||
<html class="no-js <?= context.cfg.get_by_path("theme/mode-class").to_string() ?>" lang="en" data-theme-key="<?= context.cfg.get_by_path("theme/key").to_string() ?>">
|
||||
<head>
|
||||
<?: component("../../components/theme/head", context) ?>
|
||||
</head>
|
||||
<body>
|
||||
<?: component("../../components/theme/global_controls", context) ?>
|
||||
<?: component("../../components/theme/standard_nav", nav_props, context) ?>
|
||||
<div id="content">
|
||||
<?: main_html ?>
|
||||
</div>
|
||||
<?: component("../../components/theme/footer", footer_props, context) ?>
|
||||
</body>
|
||||
</html>
|
||||
</>
|
||||
}
|
||||
COMPONENT(Request& context) { render_common_theme_page(context); }
|
||||
@@ -1,25 +1,3 @@
|
||||
#load "../../lib/app.uce"
|
||||
#load "../common/page.uce"
|
||||
|
||||
COMPONENT(Request& context)
|
||||
{
|
||||
String main_html = context.call["fragments"]["main"].to_string();
|
||||
|
||||
DValue footer_props;
|
||||
|
||||
<>
|
||||
<!doctype html>
|
||||
<html class="no-js <?= context.cfg.get_by_path("theme/mode-class").to_string() ?>" lang="en" data-theme-key="<?= context.cfg.get_by_path("theme/key").to_string() ?>">
|
||||
<head>
|
||||
<?: component("../../components/theme/head", context) ?>
|
||||
</head>
|
||||
<body>
|
||||
<?: component("../../components/theme/global_controls", context) ?>
|
||||
<?: component("../../components/theme/standard_nav", context) ?>
|
||||
<div id="content">
|
||||
<?: main_html ?>
|
||||
</div>
|
||||
<?: component("../../components/theme/footer", footer_props, context) ?>
|
||||
</body>
|
||||
</html>
|
||||
</>
|
||||
}
|
||||
COMPONENT(Request& context) { render_common_theme_page(context); }
|
||||
@@ -1,28 +1,3 @@
|
||||
#load "../../lib/app.uce"
|
||||
#load "../common/page.uce"
|
||||
|
||||
COMPONENT(Request& context)
|
||||
{
|
||||
String main_html = context.call["fragments"]["main"].to_string();
|
||||
|
||||
DValue nav_props;
|
||||
nav_props["account_wrapper_class"] = "nav-account nav-menu";
|
||||
|
||||
DValue footer_props;
|
||||
|
||||
<>
|
||||
<!doctype html>
|
||||
<html class="no-js <?= context.cfg.get_by_path("theme/mode-class").to_string() ?>" lang="en" data-theme-key="<?= context.cfg.get_by_path("theme/key").to_string() ?>">
|
||||
<head>
|
||||
<?: component("../../components/theme/head", context) ?>
|
||||
</head>
|
||||
<body class="portal-theme portal-dark-theme dark-theme">
|
||||
<?: component("../../components/theme/global_controls", context) ?>
|
||||
<?: component("../../components/theme/standard_nav", nav_props, context) ?>
|
||||
<div id="content">
|
||||
<?: main_html ?>
|
||||
</div>
|
||||
<?: component("../../components/theme/footer", footer_props, context) ?>
|
||||
</body>
|
||||
</html>
|
||||
</>
|
||||
}
|
||||
COMPONENT(Request& context) { render_common_theme_page(context); }
|
||||
@@ -1,26 +1,3 @@
|
||||
#load "../../lib/app.uce"
|
||||
#load "../common/page.uce"
|
||||
|
||||
COMPONENT(Request& context)
|
||||
{
|
||||
String main_html = context.call["fragments"]["main"].to_string();
|
||||
|
||||
DValue footer_props;
|
||||
footer_props["inner_class"] = "footer-inner";
|
||||
|
||||
<>
|
||||
<!doctype html>
|
||||
<html class="no-js <?= context.cfg.get_by_path("theme/mode-class").to_string() ?>" lang="en" data-theme-key="<?= context.cfg.get_by_path("theme/key").to_string() ?>">
|
||||
<head>
|
||||
<?: component("../../components/theme/head", context) ?>
|
||||
</head>
|
||||
<body class="portal-theme portal-light-theme">
|
||||
<?: component("../../components/theme/global_controls", context) ?>
|
||||
<?: component("../../components/theme/standard_nav", context) ?>
|
||||
<div id="content">
|
||||
<?: main_html ?>
|
||||
</div>
|
||||
<?: component("../../components/theme/footer", footer_props, context) ?>
|
||||
</body>
|
||||
</html>
|
||||
</>
|
||||
}
|
||||
COMPONENT(Request& context) { render_common_theme_page(context); }
|
||||
@@ -1,29 +1,3 @@
|
||||
#load "../../lib/app.uce"
|
||||
#load "../common/page.uce"
|
||||
|
||||
COMPONENT(Request& context)
|
||||
{
|
||||
String main_html = context.call["fragments"]["main"].to_string();
|
||||
|
||||
DValue nav_props;
|
||||
nav_props["account_wrapper_class"] = "nav-account nav-menu";
|
||||
|
||||
DValue footer_props;
|
||||
|
||||
<>
|
||||
<!doctype html>
|
||||
<html class="no-js <?= context.cfg.get_by_path("theme/mode-class").to_string() ?>" lang="en" data-theme-key="<?= context.cfg.get_by_path("theme/key").to_string() ?>">
|
||||
<head>
|
||||
<?: component("../../components/theme/head", context) ?>
|
||||
</head>
|
||||
<body>
|
||||
<div class="retro-stars"></div>
|
||||
<?: component("../../components/theme/global_controls", context) ?>
|
||||
<?: component("../../components/theme/standard_nav", nav_props, context) ?>
|
||||
<div id="content">
|
||||
<?: main_html ?>
|
||||
</div>
|
||||
<?: component("../../components/theme/footer", footer_props, context) ?>
|
||||
</body>
|
||||
</html>
|
||||
</>
|
||||
}
|
||||
COMPONENT(Request& context) { render_common_theme_page(context); }
|
||||
@@ -1,77 +0,0 @@
|
||||
var enable_debug = true;
|
||||
|
||||
var starterReady = (typeof $ !== 'undefined' && $.ready)
|
||||
? $.ready.bind($)
|
||||
: function(callback) {
|
||||
if (document.readyState !== 'loading') {
|
||||
callback();
|
||||
} else {
|
||||
document.addEventListener('DOMContentLoaded', callback);
|
||||
}
|
||||
};
|
||||
|
||||
var UI = {
|
||||
|
||||
smoothScrollToNamedAnchors: function() {
|
||||
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
|
||||
anchor.addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
const target = document.querySelector(this.getAttribute('href'));
|
||||
if (target) {
|
||||
target.scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
block: 'start'
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
enablePageTransitions: function() {
|
||||
var style = document.createElement('style');
|
||||
style.textContent = `
|
||||
::view-transition-old(root),
|
||||
::view-transition-new(root) {
|
||||
animation-duration: 0.25s;
|
||||
}
|
||||
|
||||
::view-transition-old(root) {
|
||||
animation-name: fade-out;
|
||||
}
|
||||
|
||||
::view-transition-new(root) {
|
||||
animation-name: fade-in;
|
||||
}
|
||||
|
||||
@keyframes fade-out {
|
||||
from { opacity: 1; }
|
||||
to { opacity: 0; }
|
||||
}
|
||||
|
||||
@keyframes fade-in {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
}`;
|
||||
document.body.appendChild(style);
|
||||
|
||||
document.addEventListener('click', e => {
|
||||
const link = e.target.closest('a[href]');
|
||||
if (!link) return;
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
document.startViewTransition(() => {
|
||||
window.location.href = link.href;
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
init: function() {
|
||||
//UI.enablePageTransitions();
|
||||
UI.smoothScrollToNamedAnchors();
|
||||
document.body.classList.add('loaded');
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
starterReady(UI.init);
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../examples/bearer-starter/js/site.js
|
||||
+39
-100
@@ -317,6 +317,15 @@ void store_field(Bytes& code, const std::string& type, unsigned offset)
|
||||
wasm::append_uleb(code, offset);
|
||||
}
|
||||
|
||||
void store_i32_constant(Bytes& code, unsigned object, std::int32_t value, unsigned offset)
|
||||
{
|
||||
code.push_back(0x20);
|
||||
wasm::append_uleb(code, object);
|
||||
code.push_back(0x41);
|
||||
wasm::append_sleb32(code, value);
|
||||
store_field(code, "s32", offset);
|
||||
}
|
||||
|
||||
void managed_payload_pointer(Bytes& code, unsigned local, const std::string& type)
|
||||
{
|
||||
code.push_back(0x20);
|
||||
@@ -2641,14 +2650,7 @@ std::pair<Bytes, unsigned> FunctionLowerer::allocate_blob(const std::string& typ
|
||||
append(code, module_.marker(location));
|
||||
code.insert(code.end(), {0x00, 0x0b});
|
||||
for (const auto [header, offset] : {std::pair<std::int32_t, unsigned>{1, 0}, {1, 4}, {static_cast<std::int32_t>(type_id), 8}})
|
||||
{
|
||||
code.push_back(0x20);
|
||||
wasm::append_uleb(code, pointer);
|
||||
code.push_back(0x41);
|
||||
wasm::append_sleb32(code, header);
|
||||
code.insert(code.end(), {0x36, 0x02});
|
||||
wasm::append_uleb(code, offset);
|
||||
}
|
||||
store_i32_constant(code, pointer, header, offset);
|
||||
code.push_back(0x20);
|
||||
wasm::append_uleb(code, pointer);
|
||||
code.push_back(0x20);
|
||||
@@ -3542,14 +3544,7 @@ std::pair<Bytes, std::string> FunctionLowerer::expression(Expr* value, bool valu
|
||||
{static_cast<std::int32_t>(type_id), 8},
|
||||
{static_cast<std::int32_t>(size), 12},
|
||||
{static_cast<std::int32_t>(slot), 16}})
|
||||
{
|
||||
code.push_back(0x20);
|
||||
wasm::append_uleb(code, pointer);
|
||||
code.push_back(0x41);
|
||||
wasm::append_sleb32(code, header);
|
||||
code.insert(code.end(), {0x36, 0x02});
|
||||
wasm::append_uleb(code, offset);
|
||||
}
|
||||
store_i32_constant(code, pointer, header, offset);
|
||||
code.insert(code.end(), {0x23, 0x01, 0x41, 0x01, 0x6a, 0x24, 0x01});
|
||||
for (std::size_t i = 0; i < captures.size(); ++i)
|
||||
{
|
||||
@@ -3605,14 +3600,7 @@ std::pair<Bytes, std::string> FunctionLowerer::expression(Expr* value, bool valu
|
||||
{1, 4},
|
||||
{static_cast<std::int32_t>(module_.tuple_type(type)), 8},
|
||||
{static_cast<std::int32_t>(layout.size), 12}})
|
||||
{
|
||||
code.push_back(0x20);
|
||||
wasm::append_uleb(code, pointer);
|
||||
code.push_back(0x41);
|
||||
wasm::append_sleb32(code, header);
|
||||
code.insert(code.end(), {0x36, 0x02});
|
||||
wasm::append_uleb(code, offset);
|
||||
}
|
||||
store_i32_constant(code, pointer, header, offset);
|
||||
code.insert(code.end(), {0x23, 0x01, 0x41, 0x01, 0x6a, 0x24, 0x01});
|
||||
for (std::size_t i = 0; i < tuple->items.size(); ++i)
|
||||
{
|
||||
@@ -4089,14 +4077,7 @@ std::pair<Bytes, std::string> FunctionLowerer::expression(Expr* value, bool valu
|
||||
code.push_back(0x00);
|
||||
code.push_back(0x0b);
|
||||
for (const auto [header, offset] : {std::pair<std::int32_t, unsigned>{1, 0}, {1, 4}, {1, 8}})
|
||||
{
|
||||
code.insert(code.end(), {0x20});
|
||||
wasm::append_uleb(code, pointer);
|
||||
code.push_back(0x41);
|
||||
wasm::append_sleb32(code, header);
|
||||
code.insert(code.end(), {0x36, 0x02});
|
||||
wasm::append_uleb(code, offset);
|
||||
}
|
||||
store_i32_constant(code, pointer, header, offset);
|
||||
code.insert(code.end(), {0x20});
|
||||
wasm::append_uleb(code, pointer);
|
||||
code.insert(code.end(), {0x20});
|
||||
@@ -4997,14 +4978,7 @@ std::pair<Bytes, std::string> FunctionLowerer::expression(Expr* value, bool valu
|
||||
{1, 4},
|
||||
{static_cast<std::int32_t>(aggregate.type_id), 8},
|
||||
{static_cast<std::int32_t>(layout.size), 12}})
|
||||
{
|
||||
code.push_back(0x20);
|
||||
wasm::append_uleb(code, pointer);
|
||||
code.push_back(0x41);
|
||||
wasm::append_sleb32(code, header);
|
||||
code.insert(code.end(), {0x36, 0x02});
|
||||
wasm::append_uleb(code, offset);
|
||||
}
|
||||
store_i32_constant(code, pointer, header, offset);
|
||||
code.insert(code.end(), {0x23, 0x01, 0x41, 0x01, 0x6a, 0x24, 0x01});
|
||||
for (std::size_t i = 0; i < arguments->size(); ++i)
|
||||
{
|
||||
@@ -6091,76 +6065,41 @@ std::vector<Bytes> Module::runtime_bodies() const
|
||||
0x20, 0x00, 0x28, 0x02, 0x18, 0x22, 0x01, 0x45, 0x04, 0x40, 0x05, 0x20, 0x01, 0x10});
|
||||
wasm::append_uleb(code, import_index("bearer_free"));
|
||||
code.insert(code.end(), {0x0b, 0x0b});
|
||||
for (const auto& [type_id, captures] : closure_types_)
|
||||
auto release_aggregate_fields = [&](unsigned type_id, const std::vector<std::string>& fields, unsigned first_offset)
|
||||
{
|
||||
const AggregateLayout layout = aggregate_layout(captures, 24);
|
||||
std::vector<unsigned> managed;
|
||||
for (unsigned i = 0; i < captures.size(); ++i)
|
||||
if (managed_type(captures[i]))
|
||||
managed.push_back(i);
|
||||
if (managed.empty())
|
||||
continue;
|
||||
code.insert(code.end(), {0x20, 0x00, 0x28, 0x02, 0x08, 0x41});
|
||||
wasm::append_sleb32(code, static_cast<std::int32_t>(type_id));
|
||||
code.insert(code.end(), {0x46, 0x04, 0x40});
|
||||
for (unsigned i : managed)
|
||||
{
|
||||
code.push_back(0x20);
|
||||
wasm::append_uleb(code, 0);
|
||||
load_field(code, captures[i], layout.offsets[i]);
|
||||
code.push_back(0x10);
|
||||
wasm::append_uleb(code, release_index());
|
||||
}
|
||||
code.push_back(0x0b);
|
||||
}
|
||||
for (const auto& [name, aggregate] : structs_)
|
||||
{
|
||||
std::vector<std::string> field_types;
|
||||
for (const auto& [field_name, field_type] : aggregate.fields)
|
||||
field_types.push_back(field_type);
|
||||
const AggregateLayout layout = aggregate_layout(field_types, 16);
|
||||
std::vector<unsigned> managed;
|
||||
for (unsigned i = 0; i < aggregate.fields.size(); ++i)
|
||||
if (managed_type(aggregate.fields[i].second))
|
||||
managed.push_back(i);
|
||||
if (managed.empty())
|
||||
continue;
|
||||
code.insert(code.end(), {0x20, 0x00, 0x28, 0x02, 0x08, 0x41});
|
||||
wasm::append_sleb32(code, static_cast<std::int32_t>(aggregate.type_id));
|
||||
code.insert(code.end(), {0x46, 0x04, 0x40});
|
||||
for (unsigned i : managed)
|
||||
{
|
||||
code.push_back(0x20);
|
||||
wasm::append_uleb(code, 0);
|
||||
load_field(code, aggregate.fields[i].second, layout.offsets[i]);
|
||||
code.push_back(0x10);
|
||||
wasm::append_uleb(code, release_index());
|
||||
}
|
||||
code.push_back(0x0b);
|
||||
}
|
||||
for (const auto& [type, id] : tuples_)
|
||||
{
|
||||
const auto fields = aggregate_elements(type);
|
||||
const AggregateLayout layout = aggregate_layout(fields, 16);
|
||||
std::vector<unsigned> managed;
|
||||
const AggregateLayout layout = aggregate_layout(fields, first_offset);
|
||||
bool guarded = false;
|
||||
for (unsigned i = 0; i < fields.size(); ++i)
|
||||
if (managed_type(fields[i]))
|
||||
managed.push_back(i);
|
||||
if (managed.empty())
|
||||
continue;
|
||||
code.insert(code.end(), {0x20, 0x00, 0x28, 0x02, 0x08, 0x41});
|
||||
wasm::append_sleb32(code, static_cast<std::int32_t>(id));
|
||||
code.insert(code.end(), {0x46, 0x04, 0x40});
|
||||
for (unsigned i : managed)
|
||||
{
|
||||
if (!managed_type(fields[i]))
|
||||
continue;
|
||||
if (!guarded)
|
||||
{
|
||||
code.insert(code.end(), {0x20, 0x00, 0x28, 0x02, 0x08, 0x41});
|
||||
wasm::append_sleb32(code, static_cast<std::int32_t>(type_id));
|
||||
code.insert(code.end(), {0x46, 0x04, 0x40});
|
||||
guarded = true;
|
||||
}
|
||||
code.push_back(0x20);
|
||||
wasm::append_uleb(code, 0);
|
||||
load_field(code, fields[i], layout.offsets[i]);
|
||||
code.push_back(0x10);
|
||||
wasm::append_uleb(code, release_index());
|
||||
}
|
||||
code.push_back(0x0b);
|
||||
if (guarded)
|
||||
code.push_back(0x0b);
|
||||
};
|
||||
for (const auto& [type_id, captures] : closure_types_)
|
||||
release_aggregate_fields(type_id, captures, 24);
|
||||
for (const auto& [name, aggregate] : structs_)
|
||||
{
|
||||
std::vector<std::string> fields;
|
||||
for (const auto& [field_name, field_type] : aggregate.fields)
|
||||
fields.push_back(field_type);
|
||||
release_aggregate_fields(aggregate.type_id, fields, 16);
|
||||
}
|
||||
for (const auto& [type, id] : tuples_)
|
||||
release_aggregate_fields(id, aggregate_elements(type), 16);
|
||||
code.insert(code.end(), {0x23, 0x01, 0x41, 0x01, 0x6b, 0x24, 0x01, 0x20, 0x00, 0x10});
|
||||
wasm::append_uleb(code, import_index("bearer_free"));
|
||||
code.push_back(0x0b);
|
||||
|
||||
@@ -34,7 +34,9 @@
|
||||
|
||||
#include "fcgicc.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <errno.h> // E*
|
||||
@@ -51,6 +53,17 @@
|
||||
|
||||
namespace {
|
||||
|
||||
std::atomic<u64> websocket_connection_sequence{0};
|
||||
|
||||
static u64 next_websocket_connection_sequence()
|
||||
{
|
||||
u64 current = websocket_connection_sequence.load(std::memory_order_relaxed);
|
||||
while(current != std::numeric_limits<u64>::max())
|
||||
if(websocket_connection_sequence.compare_exchange_weak(current, current + 1, std::memory_order_relaxed))
|
||||
return(current + 1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
struct TransportLimits {
|
||||
u64 max_client_connections = 256;
|
||||
u64 max_http_header_bytes = 16 * 1024;
|
||||
@@ -838,8 +851,14 @@ FastCGIServer::validate_websocket_upgrade(FastCGIRequest& request, Connection& c
|
||||
void
|
||||
FastCGIServer::begin_websocket_upgrade(FastCGIRequest& request, Connection& connection, String& data)
|
||||
{
|
||||
u64 sequence = next_websocket_connection_sequence();
|
||||
if(sequence == 0)
|
||||
{
|
||||
reject_http_connection(connection, "HTTP/1.1 503 Service Unavailable", "WebSocket connection ID space is exhausted");
|
||||
return;
|
||||
}
|
||||
connection.is_websocket = true;
|
||||
connection.websocket_connection_id = std::to_string(getpid()) + ":" + std::to_string(connection.client_socket);
|
||||
connection.websocket_connection_id = std::to_string(getpid()) + ":" + std::to_string(sequence);
|
||||
connection.websocket_scope = first(
|
||||
request.params["SCRIPT_FILENAME"],
|
||||
request.params["DOCUMENT_URI"],
|
||||
|
||||
@@ -270,8 +270,6 @@ DValue MySQL::get_pending_result()
|
||||
return(result_data);
|
||||
}
|
||||
|
||||
static bool mysql_has_unquoted_positional_placeholder(String query, bool no_backslash_escapes);
|
||||
|
||||
DValue MySQL::query(String q)
|
||||
{
|
||||
affected_rows = 0;
|
||||
@@ -300,30 +298,6 @@ DValue MySQL::query(String q)
|
||||
return(result);
|
||||
}
|
||||
|
||||
static bool mysql_has_unquoted_positional_placeholder(String query, bool no_backslash_escapes)
|
||||
{
|
||||
char quote = 0;
|
||||
bool line_comment = false, block_comment = false;
|
||||
for(size_t i = 0; i < query.size(); i++)
|
||||
{
|
||||
char c = query[i], next = i + 1 < query.size() ? query[i + 1] : 0;
|
||||
if(line_comment) { if(c == '\n' || c == '\r') line_comment = false; continue; }
|
||||
if(block_comment) { if(c == '*' && next == '/') { block_comment = false; i++; } continue; }
|
||||
if(quote)
|
||||
{
|
||||
if(!no_backslash_escapes && c == '\\') { if(next) i++; continue; }
|
||||
if(c == quote) { if(next == quote) i++; else quote = 0; }
|
||||
continue;
|
||||
}
|
||||
if(c == '\'' || c == '"' || c == '`') { quote = c; continue; }
|
||||
if(c == '#') { line_comment = true; continue; }
|
||||
if(c == '-' && next == '-' && (i + 2 >= query.size() || isspace((unsigned char)query[i + 2]))) { line_comment = true; i++; continue; }
|
||||
if(c == '/' && next == '*') { block_comment = true; i++; continue; }
|
||||
if(c == '?') return(true);
|
||||
}
|
||||
return(false);
|
||||
}
|
||||
|
||||
DValue MySQL::query(String q, StringMap params)
|
||||
{
|
||||
// Positional ? placeholders survive named substitution (ordinary values
|
||||
|
||||
@@ -1,5 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
inline bool mysql_has_unquoted_positional_placeholder(const String& query, bool no_backslash_escapes)
|
||||
{
|
||||
char quote = 0;
|
||||
bool line_comment = false, block_comment = false;
|
||||
for(size_t i = 0; i < query.size(); i++)
|
||||
{
|
||||
char c = query[i], next = i + 1 < query.size() ? query[i + 1] : 0;
|
||||
if(line_comment) { if(c == '\n' || c == '\r') line_comment = false; continue; }
|
||||
if(block_comment) { if(c == '*' && next == '/') { block_comment = false; i++; } continue; }
|
||||
if(quote)
|
||||
{
|
||||
if(!no_backslash_escapes && c == '\\') { if(next) i++; continue; }
|
||||
if(c == quote) { if(next == quote) i++; else quote = 0; }
|
||||
continue;
|
||||
}
|
||||
if(c == '\'' || c == '"' || c == '`') { quote = c; continue; }
|
||||
if(c == '#') { line_comment = true; continue; }
|
||||
if(c == '-' && next == '-' && (i + 2 >= query.size() || std::isspace((unsigned char)query[i + 2]))) { line_comment = true; i++; continue; }
|
||||
if(c == '/' && next == '*') { block_comment = true; i++; continue; }
|
||||
if(c == '?') return(true);
|
||||
}
|
||||
return(false);
|
||||
}
|
||||
|
||||
struct MySQLFieldInfo {
|
||||
String name;
|
||||
String table;
|
||||
|
||||
+6
-12
@@ -191,24 +191,18 @@ static DValue wasm_decode_dvalue_result(String encoded)
|
||||
brb_decode(encoded, out, &error);
|
||||
return(out);
|
||||
}
|
||||
DValue file_stat(String path)
|
||||
template<typename Hostcall>
|
||||
static DValue wasm_file_dvalue(String path, Hostcall hostcall)
|
||||
{
|
||||
String current = wasm_current_unit_file();
|
||||
size_t required = bearer_host_file_stat(path.data(), path.size(), current.data(), current.size(), 0, 0);
|
||||
size_t required = hostcall(path.data(), path.size(), current.data(), current.size(), 0, 0);
|
||||
String encoded(required, 0);
|
||||
size_t got = required ? bearer_host_file_stat(path.data(), path.size(), current.data(), current.size(), &encoded[0], required) : 0;
|
||||
encoded.resize(got <= required ? got : 0);
|
||||
return(wasm_decode_dvalue_result(encoded));
|
||||
}
|
||||
DValue dir_list(String path)
|
||||
{
|
||||
String current = wasm_current_unit_file();
|
||||
size_t required = bearer_host_dir_list(path.data(), path.size(), current.data(), current.size(), 0, 0);
|
||||
String encoded(required, 0);
|
||||
size_t got = required ? bearer_host_dir_list(path.data(), path.size(), current.data(), current.size(), &encoded[0], required) : 0;
|
||||
size_t got = required ? hostcall(path.data(), path.size(), current.data(), current.size(), &encoded[0], required) : 0;
|
||||
encoded.resize(got <= required ? got : 0);
|
||||
return(wasm_decode_dvalue_result(encoded));
|
||||
}
|
||||
DValue file_stat(String path) { return(wasm_file_dvalue(path, bearer_host_file_stat)); }
|
||||
DValue dir_list(String path) { return(wasm_file_dvalue(path, bearer_host_dir_list)); }
|
||||
bool file_rename(String from, String to)
|
||||
{
|
||||
String current = wasm_current_unit_file();
|
||||
|
||||
+5
-16
@@ -242,25 +242,14 @@ void on_request_fault_signal(int sig)
|
||||
on_segfault(sig);
|
||||
}
|
||||
|
||||
void install_request_fault_handlers()
|
||||
void set_request_fault_handlers(void (*handler)(int))
|
||||
{
|
||||
signal(SIGSEGV, on_request_fault_signal);
|
||||
signal(SIGABRT, on_request_fault_signal);
|
||||
signal(SIGBUS, on_request_fault_signal);
|
||||
signal(SIGILL, on_request_fault_signal);
|
||||
signal(SIGFPE, on_request_fault_signal);
|
||||
signal(SIGALRM, on_request_fault_signal);
|
||||
for(int sig : {SIGSEGV, SIGABRT, SIGBUS, SIGILL, SIGFPE, SIGALRM})
|
||||
signal(sig, handler);
|
||||
}
|
||||
|
||||
void restore_request_fault_handlers()
|
||||
{
|
||||
signal(SIGSEGV, on_segfault);
|
||||
signal(SIGABRT, on_segfault);
|
||||
signal(SIGBUS, on_segfault);
|
||||
signal(SIGILL, on_segfault);
|
||||
signal(SIGFPE, on_segfault);
|
||||
signal(SIGALRM, on_segfault);
|
||||
}
|
||||
void install_request_fault_handlers() { set_request_fault_handlers(on_request_fault_signal); }
|
||||
void restore_request_fault_handlers() { set_request_fault_handlers(on_segfault); }
|
||||
|
||||
|
||||
String current_ws_scope()
|
||||
|
||||
+10
-80
@@ -22,6 +22,7 @@ static const char* WASM_DB_UNAVAILABLE =
|
||||
"database connector is not available in the wasm workspace";
|
||||
|
||||
extern "C" size_t bearer_host_mysql(const char* in, size_t in_len, char* out, size_t cap);
|
||||
extern "C" size_t bearer_host_sqlite(const char* in, size_t in_len, char* out, size_t cap);
|
||||
extern "C" size_t bearer_host_zip(const char* in, size_t in_len, char* out, size_t cap);
|
||||
extern "C" size_t bearer_host_units(const char* in, size_t in_len, char* out, size_t cap);
|
||||
extern "C" size_t bearer_host_regex_capy(const char* in, size_t in_len, char* out, size_t cap);
|
||||
@@ -43,11 +44,10 @@ static DValue wasm_sized_hostcall(DValue request, size_t (*hostcall)(const char*
|
||||
return(response);
|
||||
}
|
||||
|
||||
static DValue wasm_zip_call(DValue request)
|
||||
{
|
||||
DValue response = wasm_sized_hostcall(request, bearer_host_zip);
|
||||
return(response);
|
||||
}
|
||||
static DValue wasm_zip_call(DValue request) { return(wasm_sized_hostcall(request, bearer_host_zip)); }
|
||||
static DValue wasm_units_call(DValue request) { return(wasm_sized_hostcall(request, bearer_host_units)); }
|
||||
static DValue wasm_mysql_call(DValue request) { return(wasm_sized_hostcall(request, bearer_host_mysql)); }
|
||||
static DValue wasm_sqlite_call(DValue request) { return(wasm_sized_hostcall(request, bearer_host_sqlite)); }
|
||||
|
||||
static bool wasm_zip_apply(DValue request, DValue& response)
|
||||
{
|
||||
@@ -114,11 +114,6 @@ String gz_uncompress(String compressed)
|
||||
return(response["result"].to_string());
|
||||
}
|
||||
|
||||
static DValue wasm_units_call(DValue request)
|
||||
{
|
||||
return(wasm_sized_hostcall(request, bearer_host_units));
|
||||
}
|
||||
|
||||
DValue unit_info(String path)
|
||||
{
|
||||
DValue request;
|
||||
@@ -171,11 +166,6 @@ static size_t bearer_copy_staged(String& staged, char* out, size_t cap);
|
||||
static bool bearer_decode_brrb_span(const char* value, size_t value_len, DValue& decoded);
|
||||
static String wasm_unit_call_encoded_result;
|
||||
|
||||
static DValue wasm_mysql_call(DValue request)
|
||||
{
|
||||
return(wasm_sized_hostcall(request, bearer_host_mysql));
|
||||
}
|
||||
|
||||
bool MySQL::connect(String host, String username, String password, String database)
|
||||
{
|
||||
request_host = host;
|
||||
@@ -317,34 +307,10 @@ String MySQL::parse_query_parameters(String query, StringMap map)
|
||||
return(result);
|
||||
}
|
||||
|
||||
static bool wasm_mysql_has_unquoted_positional_placeholder(String query)
|
||||
{
|
||||
char quote = 0;
|
||||
bool line_comment = false, block_comment = false;
|
||||
for(size_t i = 0; i < query.size(); i++)
|
||||
{
|
||||
char c = query[i], next = i + 1 < query.size() ? query[i + 1] : 0;
|
||||
if(line_comment) { if(c == '\n' || c == '\r') line_comment = false; continue; }
|
||||
if(block_comment) { if(c == '*' && next == '/') { block_comment = false; i++; } continue; }
|
||||
if(quote)
|
||||
{
|
||||
if(c == '\\') { if(next) i++; continue; }
|
||||
if(c == quote) { if(next == quote) i++; else quote = 0; }
|
||||
continue;
|
||||
}
|
||||
if(c == '\'' || c == '"' || c == '`') { quote = c; continue; }
|
||||
if(c == '#') { line_comment = true; continue; }
|
||||
if(c == '-' && next == '-' && (i + 2 >= query.size() || isspace((unsigned char)query[i + 2]))) { line_comment = true; i++; continue; }
|
||||
if(c == '/' && next == '*') { block_comment = true; i++; continue; }
|
||||
if(c == '?') return(true);
|
||||
}
|
||||
return(false);
|
||||
}
|
||||
|
||||
DValue MySQL::query(String q)
|
||||
{
|
||||
affected_rows = 0;
|
||||
if(!connection && wasm_mysql_has_unquoted_positional_placeholder(q))
|
||||
if(!connection && mysql_has_unquoted_positional_placeholder(q, false))
|
||||
{
|
||||
_preload_next_error_code = 2000;
|
||||
statement_info = "mysql positional ? placeholders are not supported; use named :name placeholders";
|
||||
@@ -373,7 +339,7 @@ DValue MySQL::query(String q)
|
||||
|
||||
DValue MySQL::query(String q, StringMap params)
|
||||
{
|
||||
if(!connection && wasm_mysql_has_unquoted_positional_placeholder(q))
|
||||
if(!connection && mysql_has_unquoted_positional_placeholder(q, false))
|
||||
{
|
||||
_preload_next_error_code = 2000;
|
||||
statement_info = "mysql positional ? placeholders are not supported; use named :name placeholders";
|
||||
@@ -405,24 +371,6 @@ DValue MySQL::get_pending_result() { return(DValue()); }
|
||||
// a per-workspace handle table). One BRRB2-marshalled hostcall carries
|
||||
// {op,handle,path,query,params} in and {handle,result,insert_id,affected,
|
||||
// error_code,statement_info} out. `connection` holds the host handle (>0).
|
||||
extern "C" size_t bearer_host_sqlite(const char* in, size_t in_len, char* out, size_t cap);
|
||||
|
||||
static DValue wasm_sqlite_call(DValue request)
|
||||
{
|
||||
String encoded = brb_encode(request);
|
||||
size_t need = bearer_host_sqlite(encoded.data(), encoded.size(), 0, 0);
|
||||
if(need == 0)
|
||||
return(DValue());
|
||||
String buffer(need, 0);
|
||||
size_t got = bearer_host_sqlite(encoded.data(), encoded.size(), &buffer[0], need);
|
||||
if(got == 0 || got > need)
|
||||
return(DValue());
|
||||
DValue response;
|
||||
String error;
|
||||
brb_decode(String(buffer.data(), got), response, &error);
|
||||
return(response);
|
||||
}
|
||||
|
||||
void SQLite::set_error(s32 code, String info) { error_code = code; statement_info = info; }
|
||||
|
||||
bool SQLite::connect(String path)
|
||||
@@ -1695,13 +1643,7 @@ size_t bearer_file_read(u64 handle, u64 length, char* out, size_t cap)
|
||||
}
|
||||
return(wasm_file_read_result.size());
|
||||
}
|
||||
if(cap < wasm_file_read_result.size())
|
||||
return(wasm_file_read_result.size());
|
||||
if(!wasm_file_read_result.empty())
|
||||
memcpy(out, wasm_file_read_result.data(), wasm_file_read_result.size());
|
||||
size_t size = wasm_file_read_result.size();
|
||||
wasm_file_read_result.clear();
|
||||
return(size);
|
||||
return(bearer_copy_staged(wasm_file_read_result, out, cap));
|
||||
}
|
||||
|
||||
u64 bearer_file_write(u64 handle, const char* data, size_t data_len)
|
||||
@@ -1736,13 +1678,7 @@ size_t bearer_file_temp(const char* prefix, size_t prefix_len, char* out, size_t
|
||||
wasm_file_temp_result = file_temp(String(prefix ? prefix : "", prefix ? prefix_len : 0));
|
||||
return(wasm_file_temp_result.size());
|
||||
}
|
||||
if(cap < wasm_file_temp_result.size())
|
||||
return(wasm_file_temp_result.size());
|
||||
if(!wasm_file_temp_result.empty())
|
||||
memcpy(out, wasm_file_temp_result.data(), wasm_file_temp_result.size());
|
||||
size_t size = wasm_file_temp_result.size();
|
||||
wasm_file_temp_result.clear();
|
||||
return(size);
|
||||
return(bearer_copy_staged(wasm_file_temp_result, out, cap));
|
||||
}
|
||||
|
||||
void bearer_file_unlink(const char* path, size_t path_len)
|
||||
@@ -1867,13 +1803,7 @@ static size_t bearer_component_capture_impl(const char* target, size_t target_le
|
||||
}
|
||||
return(wasm_component_capture_result.size());
|
||||
}
|
||||
if(cap < wasm_component_capture_result.size())
|
||||
return(wasm_component_capture_result.size());
|
||||
if(!wasm_component_capture_result.empty())
|
||||
memcpy(out, wasm_component_capture_result.data(), wasm_component_capture_result.size());
|
||||
size_t size = wasm_component_capture_result.size();
|
||||
wasm_component_capture_result.clear();
|
||||
return(size);
|
||||
return(bearer_copy_staged(wasm_component_capture_result, out, cap));
|
||||
}
|
||||
|
||||
size_t bearer_component_capture(const char* target, size_t target_len, char* out, size_t cap)
|
||||
|
||||
Reference in new issue
Block a user