This commit is contained in:
Jorijn van der Graaf 2025-11-11 00:21:11 +01:00
commit 98d0af014d
7 changed files with 132 additions and 57 deletions

View file

@ -78,4 +78,30 @@ int main(){
Save and close, then run ``crafter-build build executable && caddy file-server --listen :8080 --root bin/executable``. if you have caddy installed, if not use your favorite static file server instead. Now you can open the browser at ``http://localhost:8080`` and ``Hello World!`` will appear in the browser. Save and close, then run ``crafter-build build executable && caddy file-server --listen :8080 --root bin/executable``. if you have caddy installed, if not use your favorite static file server instead. Now you can open the browser at ``http://localhost:8080`` and ``Hello World!`` will appear in the browser.
This sample can also be viewed in the [HelloElement example](https://forgejo.catcrafts.net/Catcrafts/Crafter.CppDOM/src/branch/master/examples) This sample can also be viewed in the [HelloElement example](https://forgejo.catcrafts.net/Catcrafts/Crafter.CppDOM/src/branch/master/examples)
# Fetch Functionality
The library now includes support for making HTTP requests using the `fetch` function:
```cpp
import Crafter.CppDOM;
using namespace Crafter::CppDOMBindings;
int main(){
// Make a POST request with body data
std::string result = Fetch("https://httpbin.org/post", "{\"test\": \"data\"}");
// Or make a request without body data
std::string result = Fetch("https://httpbin.org/get");
// Handle the response
if (!result.empty()) {
// Process the response
HtmlElementView body("body");
body.SetInnerHTML("Response: " + result);
}
}
```
This feature allows you to make HTTP requests directly from C++ code running in WebAssembly, which can be useful for communicating with APIs or backend services.

View file

@ -678,6 +678,27 @@ let env = {
removeDragEnterListener: removeDragEnterListener, removeDragEnterListener: removeDragEnterListener,
addDragLeaveListener: addDragLeaveListener, addDragLeaveListener: addDragLeaveListener,
removeDragLeaveListener: removeDragLeaveListener, removeDragLeaveListener: removeDragLeaveListener,
fetch: async function(url, urlLenght, handlerID) {
try {
const urlStr = decoder.decode(new Int8Array(window.crafter_webbuild_wasi.instance.exports.memory.buffer, url, urlLenght));
const response = await fetch(urlStr);
const result = await response.text();
console.log(result);
const ptr = writeStringToWasm(result);
console.log(ptr);
const { ExecuteFetchHandler} = window.crafter_webbuild_wasi.instance.exports;
console.log("callback");
ExecuteFetchHandler(handlerID, ptr);
WasmFree(ptr);
} catch (error) {
return 0;
}
}
} }
window.crafter_webbuild_env = env; window.crafter_webbuild_env = env;

View file

@ -0,0 +1,18 @@
import Crafter.CppDOM;
import std;
using namespace Crafter::CppDOMBindings;
int main(){
void* body = GetElementById("body");
SetInnerHTML(body, "<h1>Fetch Example</h1><p>Testing HTTP requests...</p>");
Fetch("https://httpbin.org/get", [body](std::string result){
std::cout << "callback recieved2" << std::endl;
if (!result.empty()) {
SetInnerHTML(body, "<h1>Fetch Example</h1><p>Response: " + result + "</p>");
} else {
SetInnerHTML(body, "<h1>Fetch Example</h1><p>Failed to fetch data</p>");
}
FreeJs(body);
});
}

View file

@ -0,0 +1,17 @@
{
"name": "main",
"configurations": [
{
"name": "executable",
"implementations": ["main"],
"target": "wasm32-wasi",
"debug" : true,
"dependencies": [
{
"path":"../../project.json",
"configuration":"lib-debug"
}
]
}
]
}

1
examples/FetchExample/run.sh Executable file
View file

@ -0,0 +1 @@
caddy file-server --listen :8080 --root bin/executable

View file

@ -24,76 +24,79 @@ import :EventTypes;
export namespace Crafter::CppDOMBindings { export namespace Crafter::CppDOMBindings {
std::int32_t clickHandlerMaxId = 0; std::int32_t clickHandlerMaxId = 0;
std::unordered_map<int, std::function<void(Crafter::MouseEvent)>>* clickHandlers = new std::unordered_map<int, std::function<void(Crafter::MouseEvent)>>(); std::unordered_map<std::int32_t, std::function<void(Crafter::MouseEvent)>>* clickHandlers = new std::unordered_map<std::int32_t, std::function<void(Crafter::MouseEvent)>>();
std::int32_t mouseOverHandlerMaxId = 0; std::int32_t mouseOverHandlerMaxId = 0;
std::unordered_map<int, std::function<void(Crafter::MouseEvent)>>* mouseOverHandlers = new std::unordered_map<int, std::function<void(Crafter::MouseEvent)>>(); std::unordered_map<std::int32_t, std::function<void(Crafter::MouseEvent)>>* mouseOverHandlers = new std::unordered_map<std::int32_t, std::function<void(Crafter::MouseEvent)>>();
std::int32_t mouseOutHandlerMaxId = 0; std::int32_t mouseOutHandlerMaxId = 0;
std::unordered_map<int, std::function<void(Crafter::MouseEvent)>>* mouseOutHandlers = new std::unordered_map<int, std::function<void(Crafter::MouseEvent)>>(); std::unordered_map<std::int32_t, std::function<void(Crafter::MouseEvent)>>* mouseOutHandlers = new std::unordered_map<std::int32_t, std::function<void(Crafter::MouseEvent)>>();
std::int32_t mouseMoveHandlerMaxId = 0; std::int32_t mouseMoveHandlerMaxId = 0;
std::unordered_map<int, std::function<void(Crafter::MouseEvent)>>* mouseMoveHandlers = new std::unordered_map<int, std::function<void(Crafter::MouseEvent)>>(); std::unordered_map<std::int32_t, std::function<void(Crafter::MouseEvent)>>* mouseMoveHandlers = new std::unordered_map<std::int32_t, std::function<void(Crafter::MouseEvent)>>();
std::int32_t mouseDownHandlerMaxId = 0; std::int32_t mouseDownHandlerMaxId = 0;
std::unordered_map<int, std::function<void(Crafter::MouseEvent)>>* mouseDownHandlers = new std::unordered_map<int, std::function<void(Crafter::MouseEvent)>>(); std::unordered_map<std::int32_t, std::function<void(Crafter::MouseEvent)>>* mouseDownHandlers = new std::unordered_map<std::int32_t, std::function<void(Crafter::MouseEvent)>>();
std::int32_t mouseUpHandlerMaxId = 0; std::int32_t mouseUpHandlerMaxId = 0;
std::unordered_map<int, std::function<void(Crafter::MouseEvent)>>* mouseUpHandlers = new std::unordered_map<int, std::function<void(Crafter::MouseEvent)>>(); std::unordered_map<std::int32_t, std::function<void(Crafter::MouseEvent)>>* mouseUpHandlers = new std::unordered_map<std::int32_t, std::function<void(Crafter::MouseEvent)>>();
std::int32_t focusHandlerMaxId = 0; std::int32_t focusHandlerMaxId = 0;
std::unordered_map<int, std::function<void(Crafter::FocusEvent)>>* focusHandlers = new std::unordered_map<int, std::function<void(Crafter::FocusEvent)>>(); std::unordered_map<std::int32_t, std::function<void(Crafter::FocusEvent)>>* focusHandlers = new std::unordered_map<std::int32_t, std::function<void(Crafter::FocusEvent)>>();
std::int32_t blurHandlerMaxId = 0; std::int32_t blurHandlerMaxId = 0;
std::unordered_map<int, std::function<void(Crafter::FocusEvent)>>* blurHandlers = new std::unordered_map<int, std::function<void(Crafter::FocusEvent)>>(); std::unordered_map<std::int32_t, std::function<void(Crafter::FocusEvent)>>* blurHandlers = new std::unordered_map<std::int32_t, std::function<void(Crafter::FocusEvent)>>();
std::int32_t keyDownHandlerMaxId = 0; std::int32_t keyDownHandlerMaxId = 0;
std::unordered_map<int, std::function<void(Crafter::KeyboardEvent)>>* keyDownHandlers = new std::unordered_map<int, std::function<void(Crafter::KeyboardEvent)>>(); std::unordered_map<std::int32_t, std::function<void(Crafter::KeyboardEvent)>>* keyDownHandlers = new std::unordered_map<std::int32_t, std::function<void(Crafter::KeyboardEvent)>>();
std::int32_t keyUpHandlerMaxId = 0; std::int32_t keyUpHandlerMaxId = 0;
std::unordered_map<int, std::function<void(Crafter::KeyboardEvent)>>* keyUpHandlers = new std::unordered_map<int, std::function<void(Crafter::KeyboardEvent)>>(); std::unordered_map<std::int32_t, std::function<void(Crafter::KeyboardEvent)>>* keyUpHandlers = new std::unordered_map<std::int32_t, std::function<void(Crafter::KeyboardEvent)>>();
std::int32_t keyPressHandlerMaxId = 0; std::int32_t keyPressHandlerMaxId = 0;
std::unordered_map<int, std::function<void(Crafter::KeyboardEvent)>>* keyPressHandlers = new std::unordered_map<int, std::function<void(Crafter::KeyboardEvent)>>(); std::unordered_map<std::int32_t, std::function<void(Crafter::KeyboardEvent)>>* keyPressHandlers = new std::unordered_map<std::int32_t, std::function<void(Crafter::KeyboardEvent)>>();
std::int32_t changeHandlerMaxId = 0; std::int32_t changeHandlerMaxId = 0;
std::unordered_map<int, std::function<void(Crafter::ChangeEvent)>>* changeHandlers = new std::unordered_map<int, std::function<void(Crafter::ChangeEvent)>>(); std::unordered_map<std::int32_t, std::function<void(Crafter::ChangeEvent)>>* changeHandlers = new std::unordered_map<std::int32_t, std::function<void(Crafter::ChangeEvent)>>();
std::int32_t submitHandlerMaxId = 0; std::int32_t submitHandlerMaxId = 0;
std::unordered_map<int, std::function<void(void)>>* submitHandlers = new std::unordered_map<int, std::function<void(void)>>(); std::unordered_map<std::int32_t, std::function<void(void)>>* submitHandlers = new std::unordered_map<std::int32_t, std::function<void(void)>>();
std::int32_t inputHandlerMaxId = 0; std::int32_t inputHandlerMaxId = 0;
std::unordered_map<int, std::function<void(Crafter::InputEvent)>>* inputHandlers = new std::unordered_map<int, std::function<void(Crafter::InputEvent)>>(); std::unordered_map<std::int32_t, std::function<void(Crafter::InputEvent)>>* inputHandlers = new std::unordered_map<std::int32_t, std::function<void(Crafter::InputEvent)>>();
std::int32_t resizeHandlerMaxId = 0; std::int32_t resizeHandlerMaxId = 0;
std::unordered_map<int, std::function<void(Crafter::ResizeEvent)>>* resizeHandlers = new std::unordered_map<int, std::function<void(Crafter::ResizeEvent)>>(); std::unordered_map<std::int32_t, std::function<void(Crafter::ResizeEvent)>>* resizeHandlers = new std::unordered_map<std::int32_t, std::function<void(Crafter::ResizeEvent)>>();
std::int32_t scrollHandlerMaxId = 0; std::int32_t scrollHandlerMaxId = 0;
std::unordered_map<int, std::function<void(Crafter::ScrollEvent)>>* scrollHandlers = new std::unordered_map<int, std::function<void(Crafter::ScrollEvent)>>(); std::unordered_map<std::int32_t, std::function<void(Crafter::ScrollEvent)>>* scrollHandlers = new std::unordered_map<std::int32_t, std::function<void(Crafter::ScrollEvent)>>();
std::int32_t contextMenuHandlerMaxId = 0; std::int32_t contextMenuHandlerMaxId = 0;
std::unordered_map<int, std::function<void(Crafter::MouseEvent)>>* contextMenuHandlers = new std::unordered_map<int, std::function<void(Crafter::MouseEvent)>>(); std::unordered_map<std::int32_t, std::function<void(Crafter::MouseEvent)>>* contextMenuHandlers = new std::unordered_map<std::int32_t, std::function<void(Crafter::MouseEvent)>>();
std::int32_t dragStartHandlerMaxId = 0; std::int32_t dragStartHandlerMaxId = 0;
std::unordered_map<int, std::function<void(Crafter::MouseEvent)>>* dragStartHandlers = new std::unordered_map<int, std::function<void(Crafter::MouseEvent)>>(); std::unordered_map<std::int32_t, std::function<void(Crafter::MouseEvent)>>* dragStartHandlers = new std::unordered_map<std::int32_t, std::function<void(Crafter::MouseEvent)>>();
std::int32_t dragEndHandlerMaxId = 0; std::int32_t dragEndHandlerMaxId = 0;
std::unordered_map<int, std::function<void(Crafter::MouseEvent)>>* dragEndHandlers = new std::unordered_map<int, std::function<void(Crafter::MouseEvent)>>(); std::unordered_map<std::int32_t, std::function<void(Crafter::MouseEvent)>>* dragEndHandlers = new std::unordered_map<std::int32_t, std::function<void(Crafter::MouseEvent)>>();
std::int32_t dropHandlerMaxId = 0; std::int32_t dropHandlerMaxId = 0;
std::unordered_map<int, std::function<void(Crafter::MouseEvent)>>* dropHandlers = new std::unordered_map<int, std::function<void(Crafter::MouseEvent)>>(); std::unordered_map<std::int32_t, std::function<void(Crafter::MouseEvent)>>* dropHandlers = new std::unordered_map<std::int32_t, std::function<void(Crafter::MouseEvent)>>();
std::int32_t wheelHandlerMaxId = 0; std::int32_t wheelHandlerMaxId = 0;
std::unordered_map<int, std::function<void(Crafter::WheelEvent)>>* wheelHandlers = new std::unordered_map<int, std::function<void(Crafter::WheelEvent)>>(); std::unordered_map<std::int32_t, std::function<void(Crafter::WheelEvent)>>* wheelHandlers = new std::unordered_map<std::int32_t, std::function<void(Crafter::WheelEvent)>>();
std::int32_t dragOverHandlerMaxId = 0; std::int32_t dragOverHandlerMaxId = 0;
std::unordered_map<int, std::function<void(Crafter::MouseEvent)>>* dragOverHandlers = new std::unordered_map<int, std::function<void(Crafter::MouseEvent)>>(); std::unordered_map<std::int32_t, std::function<void(Crafter::MouseEvent)>>* dragOverHandlers = new std::unordered_map<std::int32_t, std::function<void(Crafter::MouseEvent)>>();
std::int32_t dragEnterHandlerMaxId = 0; std::int32_t dragEnterHandlerMaxId = 0;
std::unordered_map<int, std::function<void(Crafter::MouseEvent)>>* dragEnterHandlers = new std::unordered_map<int, std::function<void(Crafter::MouseEvent)>>(); std::unordered_map<std::int32_t, std::function<void(Crafter::MouseEvent)>>* dragEnterHandlers = new std::unordered_map<std::int32_t, std::function<void(Crafter::MouseEvent)>>();
std::int32_t dragLeaveHandlerMaxId = 0; std::int32_t dragLeaveHandlerMaxId = 0;
std::unordered_map<int, std::function<void(Crafter::MouseEvent)>>* dragLeaveHandlers = new std::unordered_map<int, std::function<void(Crafter::MouseEvent)>>(); std::unordered_map<std::int32_t, std::function<void(Crafter::MouseEvent)>>* dragLeaveHandlers = new std::unordered_map<std::int32_t, std::function<void(Crafter::MouseEvent)>>();
std::int32_t fetchHandlerMaxId = 0;
std::unordered_map<std::int32_t, std::function<void(std::string)>>* fetchHandlers = new std::unordered_map<std::int32_t, std::function<void(std::string)>>();
} }
extern "C" { extern "C" {
@ -204,30 +207,19 @@ extern "C" {
__attribute__((export_name("ExecuteDragLeaveHandler"))) void ExecuteDragLeaveHandler(std::int32_t handlerID, double clientX, double clientY, double screenX, double screenY, std::int32_t button, std::int32_t buttons, bool altKey, bool ctrlKey, bool shiftKey, bool metaKey) { __attribute__((export_name("ExecuteDragLeaveHandler"))) void ExecuteDragLeaveHandler(std::int32_t handlerID, double clientX, double clientY, double screenX, double screenY, std::int32_t button, std::int32_t buttons, bool altKey, bool ctrlKey, bool shiftKey, bool metaKey) {
Crafter::CppDOMBindings::dragLeaveHandlers->find(handlerID)->second(Crafter::MouseEvent(clientX, clientY, screenX, screenY, button, buttons, altKey, ctrlKey, shiftKey, metaKey)); Crafter::CppDOMBindings::dragLeaveHandlers->find(handlerID)->second(Crafter::MouseEvent(clientX, clientY, screenX, screenY, button, buttons, altKey, ctrlKey, shiftKey, metaKey));
} }
// Style functions __attribute__((export_name("ExecuteFetchHandler"))) void ExecuteFetchHandler(std::int32_t handlerID, const char* response) {
__attribute__((export_name("setStyle"))) void SetStyle(void* ptr, const char* style, std::size_t styleLength) { std::cout << handlerID << std::endl;
// This will be implemented in JavaScript Crafter::CppDOMBindings::fetchHandlers->find(handlerID)->second(response);
Crafter::CppDOMBindings::fetchHandlers->erase(handlerID);
} }
}
__attribute__((export_name("setProperty"))) void SetProperty(void* ptr, const char* property, std::size_t propertyLength, const char* value, std::size_t valueLength) {
// This will be implemented in JavaScript export namespace Crafter::CppDOMBindings {
} __attribute__((import_module("env"), import_name("fetch"))) void Fetch(const char* url, std::int32_t urlLenght, std::int32_t handlerID);
void Fetch(const std::string_view url, std::function<void(std::string)> callback) {
__attribute__((export_name("addClass"))) void AddClass(void* ptr, const char* className, std::size_t classNameLength) { std::int32_t id = fetchHandlerMaxId++;
// This will be implemented in JavaScript CppDOMBindings::fetchHandlers->insert({id, callback});
} Fetch(url.data(), url.size(), id);
__attribute__((export_name("removeClass"))) void RemoveClass(void* ptr, const char* className, std::size_t classNameLength) {
// This will be implemented in JavaScript
}
__attribute__((export_name("toggleClass"))) void ToggleClass(void* ptr, const char* className, std::size_t classNameLength) {
// This will be implemented in JavaScript
}
__attribute__((export_name("hasClass"))) bool HasClass(void* ptr, const char* className, std::size_t classNameLength) {
// This will be implemented in JavaScript
return false;
} }
} }

View file

@ -24,11 +24,11 @@ import :EventTypes;
export namespace Crafter::CppDOMBindings { export namespace Crafter::CppDOMBindings {
__attribute__((import_module("env"), import_name("freeJs"))) void FreeJs(void* ptr); __attribute__((import_module("env"), import_name("freeJs"))) void FreeJs(void* ptr);
__attribute__((import_module("env"), import_name("getElementById"))) void* GetElementById(const char* id, std::size_t idLenght); __attribute__((import_module("env"), import_name("getElementById"))) void* GetElementById(const char* id, std::int32_t idLenght);
void* GetElementById(const std::string_view id) { void* GetElementById(const std::string_view id) {
return GetElementById(id.data(), id.size()); return GetElementById(id.data(), id.size());
} }
__attribute__((import_module("env"), import_name("setInnerHTML"))) void SetInnerHTML(void* ptr, const char* html, std::size_t htmlLenght); __attribute__((import_module("env"), import_name("setInnerHTML"))) void SetInnerHTML(void* ptr, const char* html, std::int32_t htmlLenght);
void SetInnerHTML(void* ptr, const std::string_view html) { void SetInnerHTML(void* ptr, const std::string_view html) {
SetInnerHTML(ptr, html.data(), html.size()); SetInnerHTML(ptr, html.data(), html.size());
} }
@ -107,32 +107,32 @@ export namespace Crafter::CppDOMBindings {
__attribute__((import_module("env"), import_name("removeDragLeaveListener"))) void RemoveDragLeaveListener(void* ptr, int id); __attribute__((import_module("env"), import_name("removeDragLeaveListener"))) void RemoveDragLeaveListener(void* ptr, int id);
// Style functions // Style functions
__attribute__((import_module("env"), import_name("setStyle"))) void SetStyle(void* ptr, const char* style, std::size_t styleLength); __attribute__((import_module("env"), import_name("setStyle"))) void SetStyle(void* ptr, const char* style, std::int32_t styleLength);
void SetStyle(void* ptr, const std::string_view style) { void SetStyle(void* ptr, const std::string_view style) {
SetStyle(ptr, style.data(), style.size()); SetStyle(ptr, style.data(), style.size());
} }
__attribute__((import_module("env"), import_name("setProperty"))) void SetProperty(void* ptr, const char* property, std::size_t propertyLength, const char* value, std::size_t valueLength); __attribute__((import_module("env"), import_name("setProperty"))) void SetProperty(void* ptr, const char* property, std::int32_t propertyLength, const char* value, std::int32_t valueLength);
void SetProperty(void* ptr, const std::string_view property, const std::string_view value) { void SetProperty(void* ptr, const std::string_view property, const std::string_view value) {
SetProperty(ptr, property.data(), property.size(), value.data(), value.size()); SetProperty(ptr, property.data(), property.size(), value.data(), value.size());
} }
__attribute__((import_module("env"), import_name("addClass"))) void AddClass(void* ptr, const char* className, std::size_t classNameLength); __attribute__((import_module("env"), import_name("addClass"))) void AddClass(void* ptr, const char* className, std::int32_t classNameLength);
void AddClass(void* ptr, const std::string_view className) { void AddClass(void* ptr, const std::string_view className) {
AddClass(ptr, className.data(), className.size()); AddClass(ptr, className.data(), className.size());
} }
__attribute__((import_module("env"), import_name("removeClass"))) void RemoveClass(void* ptr, const char* className, std::size_t classNameLength); __attribute__((import_module("env"), import_name("removeClass"))) void RemoveClass(void* ptr, const char* className, std::int32_t classNameLength);
void RemoveClass(void* ptr, const std::string_view className) { void RemoveClass(void* ptr, const std::string_view className) {
RemoveClass(ptr, className.data(), className.size()); RemoveClass(ptr, className.data(), className.size());
} }
__attribute__((import_module("env"), import_name("toggleClass"))) void ToggleClass(void* ptr, const char* className, std::size_t classNameLength); __attribute__((import_module("env"), import_name("toggleClass"))) void ToggleClass(void* ptr, const char* className, std::int32_t classNameLength);
void ToggleClass(void* ptr, const std::string_view className) { void ToggleClass(void* ptr, const std::string_view className) {
ToggleClass(ptr, className.data(), className.size()); ToggleClass(ptr, className.data(), className.size());
} }
__attribute__((import_module("env"), import_name("hasClass"))) bool HasClass(void* ptr, const char* className, std::size_t classNameLength); __attribute__((import_module("env"), import_name("hasClass"))) bool HasClass(void* ptr, const char* className, std::int32_t classNameLength);
bool HasClass(void* ptr, const std::string_view className) { bool HasClass(void* ptr, const std::string_view className) {
return HasClass(ptr, className.data(), className.size()); return HasClass(ptr, className.data(), className.size());
} }