# WebAssembly Runtime
# Description
- Loading Module & Asyncify.
- Fully describe all required imports and exports and desired functionality (and env vars).
- Data Translation bindings.
- Additional build requirements (shared memory).
# Outline
- [ ] Explain module loading
- [ ] Asyncify instantiation
- [ ] Environment encoding/passing
- [ ] Invocation flow
- [ ] Imports/Exports
# Overview
## Loading Wasm Module
The client reads the `wrap.wasm` file, creates an isolated page of shared module memory, and instantiates the module with all necessary imports.
TODO: note on this edge case somewhere https://github.com/polywrap/monorepo/blob/origin/packages/js/asyncify/src/AsyncWasmInstance.ts#L48-L72
TODO: more useful details about the startup procedure
## Asyncify
When the module is built, it is built with Binaryen's asyncify passes; which inject the Asyncify exports in the Wasm instance. These exports are later used by the client to enable async/await-like support in Wasm code.
1. Execution stack happens sequentially until a promise is found
2. `asyncify_start_unwind` export is called and the execution "sleeps"
3. The execution flow does not await the promise and continues until it reaches a `asyncify_stop_unwind` call
4. When the promise is resolved, `asyncify_start_rewind` is called and the "async/main/containing" function is called again
5. When a `asyncify_stop_rewind` instruction is reached and the execution "resumes".
## Invocation
The Wasm module exposes an export (`_wrap_invoke`) to perform/start a module method invocation.
The Wasm invokable implementation uses a provided environment configuration object that matches the invocation's URI, and encodes it to MsgPack. It then encodes the arguments to MsgPack
The invoker calls the `_wrap_invoke` export, and inside of it, the `__wrap_invoke_args` import is called, which makes the invoker write the invoked method's name (as a UTF-8 string) and its arguments (MsgPack encoded) to shared memory. The Wasm module then reads the method name, env and arguments from memory.
The Wasm module firstly decodes the method name. If a method with the supplied method's name is not found, then `__wrap_invoke_error` is invoked, and an error message is written (as a UTF-8 string) to shared memory, and the `_wrap_invoke` returns false. If a method with the supplied name is found, the environment (if the invoked method uses an env), and the method's arguments are deserialized based on that method's deserialization function.
Then, the Wasm module uses the method name, arguments and env to execute the invoked method. The result is then serialized to MsgPack and written to shared memory. For more information about serialization/deserialization check [Data Translation Standard](/hpwh7m7MRoKJLH_fOowYWg)
After that, the `__wrap_invoke_result` import is called, which makes the invoker read the result from shared memory. The `_wrap_invoke` finishes by returning a boolean
Host side decodes result (optional)
```mermaid
sequenceDiagram
actor Invoker
participant WrapperRuntime
participant SharedMemory
participant WasmRuntime
Invoker->>+WrapperRuntime: invoke(method, args)
WrapperRuntime->>WrapperRuntime: encode method and args (if not encoded)
WrapperRuntime->>+WasmRuntime: _wrap_invoke( size of encoded method, args and env)
WasmRuntime->>+SharedMemory: create buffers for encoded method and args
SharedMemory->>-WasmRuntime: pointers to buffers of created method and args
WasmRuntime->>+WrapperRuntime: __wasm_invoke_args(pointers to buffers of encoded name and args)
WrapperRuntime->>-SharedMemory: store encoded method and args
SharedMemory->>WasmRuntime: Get encoded method and args
WasmRuntime->>WasmRuntime: decode method name, args and env
WasmRuntime->>WasmRuntime: call the invoked method with deserialized args and env
WasmRuntime->>+SharedMemory: create buffer for encoded result
SharedMemory->>-WasmRuntime: pointer to result buffer
WasmRuntime->>WasmRuntime: encode result to buffer
WasmRuntime->>WrapperRuntime: __wrap_invoke_result(pointer to result buffer)
SharedMemory->>WrapperRuntime: read result buffer
WasmRuntime->>-WrapperRuntime: return success boolean
WrapperRuntime->>-Invoker: result buffer
```
## Imports
Allows to execute host actions from WASM runtime, it is defined as a [foreign function interface](https://en.wikipedia.org/wiki/Foreign_function_interface) and uses double under score syntaxis for naming (ie: `__wrap_method`). When the WASM instance is created, we need to pass the implementations of the signature to the instance object, the signatures and implementations must match, or an error in runtime should be expected.
## Exports
Allows to execute WASM actions in host runtime, it is defined as an exported function from `.wasm` file and uses one under score sintaxys for naming (ie: `_wrap_invoke`) . When the WASM instance is created, a list of required exports needs to be passed
`_wrap_invoke: (nameLen: u32, argsLen: u32, envLen: u32) => boolean;`
## List of imports
### Invoke
`__wrap_invoke_args`:
__wrap_invoke_result
__wrap_invoke_error
### Implementation
__wrap_getImplementations
__wrap_getImplementations_result_len
__wrap_getImplementations_result
### Subinvoke
__wrap_subinvoke
__wrap_subinvoke_result_len
__wrap_subinvoke_result
__wrap_subinvoke_error_len
__wrap_subinvoke_error
__wrap_subinvokeImplementation
__wrap_subinvokeImplementation_result_len
__wrap_subinvokeImplementation_result
__wrap_subinvokeImplementation_error_len
__wrap_subinvokeImplementation_error
### Env
__wrap_load_env
### Abort
__wrap_abort
### Logging
__wrap_debug_log
### Notes
1. Imports can start unwind or stop rewind depending on the status (Wasm calls the host's async imports)
2. Exports can stop unwind or start rewind (Once Host has result, host calls back into Wasm using Wasm Exports)
3. So for every async function we need 1 import and 1 export function.
:::info
**Initial Workshop (Jul 29, 2022)**
- [x] Define Overview/Description
- [x] Define Standard Categories
- [x] Define Qualities
- [ ] Define Outline
* [*List of Standard Categories and Qualities*](https://github.com/polywrap/technical-council/issues/labels)
:::
:::warning
**Workshop Activity**
- [x] Workshop 1: Jul 29, 2022
- additional research
- schedule next workshop
- [ ] Workshop 2: Aug 5, 2022
:::
10 August Final Notes:
- Explain procedurally, describing the crossing of the boundary, referencing imports, exports.
- Mention the encoding of the data at each point in time, where it'd be relevant, as well as shared memory but don't explain the actual encoding/decoding process
11 August Final Notes:
- Explain environment flow here
- Draft section to, at least briefly, explain imports/exports
- Touch on subinvocation and implementation imports/exports/flow