#ifndef PKMNLIB_WEBASSEMBLYSCRIPTRESOLVER_HPP #define PKMNLIB_WEBASSEMBLYSCRIPTRESOLVER_HPP #include #include #include #include #include "../../Battling/Library/ScriptResolver.hpp" #include "WebAssemblyBattleScript.hpp" #include "WebAssemblyFunctionCall.hpp" #include "WebAssemblyScriptCapabilities.hpp" class WebAssemblyScriptResolver : public PkmnLib::Battling::ScriptResolver { public: WebAssemblyScriptResolver(); ~WebAssemblyScriptResolver(); u8 LoadWasmFromFile(const std::string& path); u8 LoadWasmFromBytes(std::vector); u8 LoadWatFromString(const std::string& data); void RegisterFunction(); void Finalize(); template inline std::optional> GetFunction(const ArbUt::StringView& name) const { auto res = _exportedFunctions.TryGet(name); if (!res.has_value()) { return {}; } return std::make_optional>( ArbUt::BorrowedPtr(res.value())); } std::pair AllocateMemory(u32 size, u32 align) const { auto funcOpt = GetFunction<2, 1>("allocate_mem"); auto& func = funcOpt.value(); func.Loadi32(0, size); func.Loadi32(1, align); func.Call(); auto memoryOffset = func.GetResultAsi32(); return std::make_pair(reinterpret_cast(wasm_memory_data(_memory) + memoryOffset), memoryOffset); } [[nodiscard]] inline wasm_memory_t* GetMemory() const noexcept { return _memory; } ArbUt::OptionalUniquePtr LoadScript(const ArbUt::OptionalBorrowedPtr& owner, ScriptCategory category, const ArbUt::StringView& scriptName) nullable override; [[nodiscard]] inline wasm_store_t* GetStore() const noexcept { return _store; } inline void RemoveRegisteredScript(i32 wasmPtr) { _loadedScripts.Remove(wasmPtr); } // HACK: This is a temporary way to bypass a bug in wasmer 2.2.1. As finalizers on wasm_func_new_with_env are called // twice, the environment objects of WasmHelpers::CreateFunc are deleted twice. This causes major issues. This // should be fixed in the next wasmer release. ArbUt::List Temp_WasmerBug2_2_1_Bypass; private: wasm_engine_t* _engine; wasm_store_t* _store; wasm_module_t* _module = nullptr; wasm_instance_t* _instance = nullptr; wasm_memory_t* _memory = nullptr; ArbUt::Dictionary _imports; wasm_extern_vec_t _exports = {0, nullptr}; ArbUt::Dictionary _exportedFunctions; ArbUt::Dictionary _loadedScripts; void RegisterDefaultMethods(); typedef std::pair scriptCapabilitiesKey; struct pair_hash { template std::size_t operator()(const std::pair& pair) const { return std::hash()(pair.first) ^ std::hash()(pair.second); } }; std::unordered_map, pair_hash> _scriptCapabilities; }; #endif // PKMNLIB_WEBASSEMBLYSCRIPTRESOLVER_HPP