#include "CoreMethods.hpp" #include #include "../WebAssemblyScriptResolver.hpp" #include "WasmHelperFile.hpp" #include "wasm.h" wasm_func_t* CreateErrorFunc(wasm_store_t* store, WebAssemblyScriptResolver* resolver) { // This is probably the most horrific function we need to expose. As we do not want the scripting library to be // responsible for string formatting for size reasons, we pass a lot of data separately. This includes several // strings. return WasmHelpers::CreateFunc( store, resolver, [](void* env, const wasm_val_vec_t* args, wasm_val_vec_t*) -> wasm_trap_t* { auto msg = args->data[0].of.i32; auto msg_len = args->data[1].of.i32; auto file = args->data[2].of.i32; auto file_len = args->data[3].of.i32; auto line = args->data[4].of.i32; auto position = args->data[5].of.i32; auto* resolver = (WebAssemblyScriptResolver*)env; auto* msgPointer = wasm_memory_data(resolver->GetMemory()) + msg; auto* filePointer = wasm_memory_data(resolver->GetMemory()) + file; auto msgString = std::string_view(msgPointer, msg_len); auto fileString = std::string_view(filePointer, file_len); std::stringstream fullMessage; fullMessage << "WASM Error with message: " << msgString << std::endl << "in file: " << fileString << ". Line: " << line << ":" << position; wasm_message_t message; wasm_name_new_from_string_nt(&message, fullMessage.str().c_str()); wasm_trap_t* trap = wasm_trap_new(resolver->GetStore(), &message); wasm_name_delete(&message); return trap; }); } wasm_func_t* CreatePrintFunc(wasm_store_t* store, WebAssemblyScriptResolver* resolver) { return WasmHelpers::CreateFunc( store, resolver, [](void* env, const wasm_val_vec_t* args, wasm_val_vec_t*) -> wasm_trap_t* { auto msg = args->data[0].of.i32; auto msg_len = args->data[1].of.i32; auto resolver = (WebAssemblyScriptResolver*)env; auto* msgPointer = wasm_memory_data(resolver->GetMemory()) + msg; auto msgString = std::string_view(msgPointer, msg_len); std::cout << msgString << std::endl; return nullptr; }); ; } wasm_func_t* ConstString_GetHash(wasm_store_t* store, WebAssemblyScriptResolver* resolver) { return WasmHelpers::CreateFunc2( store, resolver, std::function( [](WebAssemblyScriptResolver*, const ArbUt::StringView* sv) -> u32 { return sv->GetHash(); })); } wasm_func_t* ConstString_GetStr(wasm_store_t* store, WebAssemblyScriptResolver* resolver) { return WasmHelpers::CreateFunc( store, resolver, [](void* env, const wasm_val_vec_t* args, wasm_val_vec_t* returns) -> wasm_trap_t* { auto resolver = (WebAssemblyScriptResolver*)env; auto& constString = *(ArbUt::StringView*)args->data[0].of.i64; // To allow webassembly to access the C String, we need to allocate it inside it's memory. // Length + 1 to make room for the '\0' auto stringPointer = resolver->AllocateMemory(constString.Length() + 1, std::alignment_of()); // After we have the pointer to the memory allocated for the string, copy the string with specified length // to it, then suffix it with the null byte to end it. strncpy(reinterpret_cast(stringPointer.first), constString.c_str(), constString.Length()); stringPointer.first[constString.Length()] = '\0'; returns->data[0] = WASM_I32_VAL(stringPointer.second); return nullptr; }); } void WebAssemblyCoreMethods::Register(wasm_store_t* store, ArbUt::Dictionary& externs, WebAssemblyScriptResolver* resolver) { externs.Insert("_error", CreateErrorFunc(store, resolver)); externs.Insert("_print", CreatePrintFunc(store, resolver)); externs.Insert("arbutils_const_string_get_hash", ConstString_GetHash(store, resolver)); externs.Insert("arbutils_const_string_get_str", ConstString_GetStr(store, resolver)); }