wasmer_wasix/
lib.rs

1// FIXME: merge with ./lib.rs_upstream
2
3#![allow(clippy::result_large_err)]
4#![doc(html_favicon_url = "https://wasmer.io/images/icons/favicon-32x32.png")]
5#![doc(html_logo_url = "https://github.com/wasmerio.png?size=200")]
6#![cfg_attr(docsrs, feature(doc_cfg))]
7
8//! Wasmer's WASI implementation
9//!
10//! Use `generate_import_object` to create an [`Imports`].  This [`Imports`]
11//! can be combined with a module to create an `Instance` which can execute WASI
12//! Wasm functions.
13//!
14//! See `state` for the experimental WASI FS API.  Also see the
15//! [WASI plugin example](https://github.com/wasmerio/wasmer/blob/main/examples/plugin.rs)
16//! for an example of how to extend WASI using the WASI FS API.
17
18#[cfg(feature = "enable-serde")]
19const _: () = {
20    #[deprecated(
21        note = "The `enable-serde` feature is deprecated and will be removed in the next major release of Wasmer."
22    )]
23    fn __enable_serde_deprecated() {}
24    let _ = __enable_serde_deprecated;
25};
26
27#[cfg(all(
28    not(feature = "sys"),
29    not(feature = "js"),
30    not(feature = "sys-minimal")
31))]
32compile_error!(
33    "At least the `sys` or the `js` or `sys-minimal` feature must be enabled. Please, pick one."
34);
35
36#[cfg(any(
37    all(feature = "js", feature = "sys"),
38    all(feature = "js", feature = "sys-minimal")
39))]
40compile_error!(
41    "Cannot have both `sys` and `js` or `sys-minimal` and `sys` features enabled at the same time. Please, pick one."
42);
43
44#[cfg(all(feature = "sys", target_arch = "wasm32"))]
45compile_error!("The `sys` feature must be enabled only for non-`wasm32` target.");
46
47#[cfg(all(feature = "js", not(target_arch = "wasm32")))]
48compile_error!(
49    "The `js` feature must be enabled only for the `wasm32` target (either `wasm32-unknown-unknown` or `wasm32-wasip1`)."
50);
51
52#[cfg(all(test, target_arch = "wasm32"))]
53wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);
54
55#[cfg(test)]
56#[macro_use]
57extern crate pretty_assertions;
58
59#[macro_use]
60mod macros;
61pub mod bin_factory;
62pub mod os;
63// TODO: should this be pub?
64pub mod net;
65// TODO: should this be pub?
66pub mod capabilities;
67pub mod fs;
68pub mod http;
69pub mod journal;
70mod rewind;
71pub mod runners;
72pub mod runtime;
73mod state;
74mod syscalls;
75mod utils;
76
77use std::sync::Arc;
78
79#[allow(unused_imports)]
80use bytes::{Bytes, BytesMut};
81use os::task::control_plane::ControlPlaneError;
82use thiserror::Error;
83// re-exports needed for OS
84pub use wasmer;
85pub use wasmer_wasix_types;
86
87use wasmer::{
88    AsStoreMut, Exports, FunctionEnv, Imports, Memory32, MemoryAccessError, MemorySize,
89    RuntimeError, imports, namespace,
90};
91
92pub use virtual_fs;
93pub use virtual_fs::{DuplexPipe, FsError, Pipe, VirtualFile, WasiBidirectionalSharedPipePair};
94pub use virtual_net;
95pub use virtual_net::{UnsupportedVirtualNetworking, VirtualNetworking};
96
97#[cfg(feature = "host-vnet")]
98pub use virtual_net::{
99    host::{LocalNetworking, LocalTcpListener, LocalTcpStream, LocalUdpSocket},
100    io_err_into_net_error,
101};
102use wasmer_wasix_types::wasi::{Errno, ExitCode};
103
104pub use crate::{
105    fs::{Fd, VIRTUAL_ROOT_FD, WasiFs, WasiInodes, default_fs_backing},
106    os::{
107        WasiTtyState,
108        command::{BuiltinCommand, VirtualCommand},
109        task::{
110            control_plane::WasiControlPlane,
111            process::{WasiProcess, WasiProcessId},
112            thread::{WasiThread, WasiThreadError, WasiThreadHandle, WasiThreadId},
113        },
114    },
115    rewind::*,
116    runtime::{PluggableRuntime, Runtime, task_manager::VirtualTaskManager},
117    state::{
118        ALL_RIGHTS, WasiEnv, WasiEnvBuilder, WasiEnvInit, WasiFunctionEnv,
119        WasiModuleInstanceHandles, WasiModuleTreeHandles, WasiStateCreationError,
120    },
121    syscalls::{journal::wait_for_snapshot, rewind, rewind_ext, types, unwind},
122    utils::is_wasix_module,
123    utils::{
124        WasiVersion, get_wasi_version, get_wasi_versions, is_wasi_module,
125        store::{StoreSnapshot, capture_store_snapshot, restore_store_snapshot},
126    },
127};
128
129/// This is returned in `RuntimeError`.
130/// Use `downcast` or `downcast_ref` to retrieve the `ExitCode`.
131#[derive(Error, Debug)]
132pub enum WasiError {
133    #[error("WASI exited with code: {0}")]
134    Exit(ExitCode),
135    #[error("WASI thread exited")]
136    ThreadExit,
137    #[error("WASI deep sleep: {0:?}")]
138    DeepSleep(DeepSleepWork),
139    #[error("The WASI version could not be determined")]
140    UnknownWasiVersion,
141    #[error("Dynamically-linked symbol not found or has bad type: {0}")]
142    DlSymbolResolutionFailed(String),
143}
144
145pub type WasiResult<T> = Result<Result<T, Errno>, WasiError>;
146
147#[deny(unused, dead_code)]
148#[derive(Error, Debug)]
149pub enum SpawnError {
150    /// Failed during serialization
151    #[error("serialization failed")]
152    Serialization,
153    /// Failed during deserialization
154    #[error("deserialization failed")]
155    Deserialization,
156    /// Invalid Wasmer process
157    #[error("invalid wasmer")]
158    InvalidWasmer,
159    /// Failed to fetch the Wasmer process
160    #[error("fetch failed")]
161    FetchFailed,
162    #[error(transparent)]
163    CacheError(crate::runtime::module_cache::CacheError),
164    /// Failed to compile the Wasmer process
165    #[error("compile error: {error:?}")]
166    CompileError {
167        module_hash: wasmer_types::ModuleHash,
168        error: wasmer::CompileError,
169    },
170    /// Invalid ABI
171    #[error("Wasmer process has an invalid ABI")]
172    InvalidABI,
173    /// Bad handle
174    #[error("bad handle")]
175    BadHandle,
176    /// Call is unsupported
177    #[error("unsupported")]
178    Unsupported,
179    /// Not found
180    #[error("not found: {message}")]
181    NotFound { message: String },
182    /// Tried to run the specified binary as a new WASI thread/process, but
183    /// the binary name was not found.
184    #[error("could not find binary '{binary}'")]
185    BinaryNotFound { binary: String },
186    #[error("could not find an entrypoint in the package '{package_id}'")]
187    MissingEntrypoint {
188        package_id: wasmer_config::package::PackageId,
189    },
190    #[error("could not load ")]
191    ModuleLoad { message: String },
192    /// Bad request
193    #[error("bad request")]
194    BadRequest,
195    /// Access denied
196    #[error("access denied")]
197    AccessDenied,
198    /// Internal error has occurred
199    #[error("internal error")]
200    InternalError,
201    /// An error occurred while preparing the file system
202    #[error(transparent)]
203    FileSystemError(ExtendedFsError),
204    /// Memory allocation failed
205    #[error("memory allocation failed")]
206    MemoryAllocationFailed,
207    /// Memory access violation
208    #[error("memory access violation")]
209    MemoryAccessViolation,
210    /// Some other unhandled error. If you see this, it's probably a bug.
211    #[error("unknown error found")]
212    UnknownError,
213    #[error("runtime error")]
214    Runtime(#[from] WasiRuntimeError),
215    #[error(transparent)]
216    Other(#[from] Box<dyn std::error::Error + Send + Sync>),
217}
218
219#[derive(Debug)]
220pub struct ExtendedFsError {
221    pub error: virtual_fs::FsError,
222    pub message: Option<String>,
223}
224
225impl ExtendedFsError {
226    pub fn with_msg(error: virtual_fs::FsError, msg: impl Into<String>) -> Self {
227        Self {
228            error,
229            message: Some(msg.into()),
230        }
231    }
232
233    pub fn new(error: virtual_fs::FsError) -> Self {
234        Self {
235            error,
236            message: None,
237        }
238    }
239}
240
241impl std::fmt::Display for ExtendedFsError {
242    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
243        write!(f, "fs error: {}", self.error)?;
244
245        if let Some(msg) = &self.message {
246            write!(f, " | {msg}")?;
247        }
248
249        Ok(())
250    }
251}
252
253impl std::error::Error for ExtendedFsError {
254    fn cause(&self) -> Option<&dyn std::error::Error> {
255        Some(&self.error)
256    }
257}
258
259impl SpawnError {
260    /// Returns `true` if the spawn error is [`NotFound`].
261    ///
262    /// [`NotFound`]: SpawnError::NotFound
263    #[must_use]
264    pub fn is_not_found(&self) -> bool {
265        matches!(
266            self,
267            Self::NotFound { .. } | Self::MissingEntrypoint { .. } | Self::BinaryNotFound { .. }
268        )
269    }
270}
271
272#[derive(thiserror::Error, Debug)]
273pub enum WasiRuntimeError {
274    #[error("WASI state setup failed: {0}")]
275    Init(#[from] WasiStateCreationError),
276    #[error("Loading exports failed: {0}")]
277    Export(#[from] wasmer::ExportError),
278    #[error("Instantiation failed: {0}")]
279    Instantiation(#[from] wasmer::InstantiationError),
280    #[error("WASI error: {0}")]
281    Wasi(#[from] WasiError),
282    #[error("Process manager error: {0}")]
283    ControlPlane(#[from] ControlPlaneError),
284    #[error("{0}")]
285    Runtime(#[from] RuntimeError),
286    #[error("Memory access error: {0}")]
287    Thread(#[from] WasiThreadError),
288    #[error("{0}")]
289    Anyhow(#[from] Arc<anyhow::Error>),
290}
291
292impl WasiRuntimeError {
293    /// Retrieve the concrete exit code returned by an instance.
294    ///
295    /// Returns [`None`] if a general execution error occurred.
296    pub fn as_exit_code(&self) -> Option<ExitCode> {
297        if let WasiRuntimeError::Wasi(WasiError::Exit(code)) = self {
298            Some(*code)
299        } else if let WasiRuntimeError::Runtime(err) = self {
300            if let Some(WasiError::Exit(code)) = err.downcast_ref() {
301                Some(*code)
302            } else {
303                None
304            }
305        } else {
306            None
307        }
308    }
309
310    pub fn display<'a>(&'a self, store: &'a mut impl AsStoreMut) -> WasiRuntimeErrorDisplay<'a> {
311        if let WasiRuntimeError::Runtime(err) = self {
312            WasiRuntimeErrorDisplay::Runtime(err.display(store))
313        } else {
314            WasiRuntimeErrorDisplay::Other(self)
315        }
316    }
317}
318
319pub enum WasiRuntimeErrorDisplay<'a> {
320    Runtime(wasmer::RuntimeErrorDisplay<'a>),
321    Other(&'a WasiRuntimeError),
322}
323
324impl std::fmt::Display for WasiRuntimeErrorDisplay<'_> {
325    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
326        match self {
327            WasiRuntimeErrorDisplay::Runtime(display) => write!(f, "{display}"),
328            WasiRuntimeErrorDisplay::Other(err) => write!(f, "{err}"),
329        }
330    }
331}
332
333#[derive(Debug)]
334pub struct WasiVFork {
335    /// The information needed to rewind the stack with asyncify
336    pub asyncify: Option<WasiVForkAsyncify>,
337
338    /// The environment before the vfork occurred
339    pub env: Box<WasiEnv>,
340
341    /// Handle of the thread we have forked (dropping this handle
342    /// will signal that the thread is dead)
343    pub handle: WasiThreadHandle,
344}
345
346#[derive(Debug, Clone)]
347pub struct WasiVForkAsyncify {
348    /// The unwound stack before the vfork occurred
349    pub rewind_stack: BytesMut,
350    /// The mutable parts of the store
351    pub store_data: Bytes,
352    /// Whether the store is 64-bit
353    pub is_64bit: bool,
354}
355
356impl Clone for WasiVFork {
357    fn clone(&self) -> Self {
358        Self {
359            asyncify: self.asyncify.clone(),
360            env: Box::new(self.env.as_ref().clone()),
361            handle: self.handle.clone(),
362        }
363    }
364}
365
366/// Create an [`Imports`] with an existing [`WasiEnv`]. [`WasiEnv`] values are
367/// typically constructed with [`WasiEnvBuilder`].
368pub fn generate_import_object_from_env(
369    store: &mut impl AsStoreMut,
370    ctx: &FunctionEnv<WasiEnv>,
371    version: WasiVersion,
372) -> Imports {
373    let mut imports = match version {
374        WasiVersion::Snapshot0 => generate_import_object_snapshot0(store, ctx),
375        WasiVersion::Snapshot1 | WasiVersion::Latest => {
376            generate_import_object_snapshot1(store, ctx)
377        }
378        WasiVersion::Wasix32v1 => generate_import_object_wasix32_v1(store, ctx),
379        WasiVersion::Wasix64v1 => generate_import_object_wasix64_v1(store, ctx),
380    };
381
382    let exports_wasi_generic = wasi_exports_generic(store, ctx);
383
384    let imports_wasi_generic = imports! {
385        "wasi" => exports_wasi_generic,
386    };
387
388    imports.extend(&imports_wasi_generic);
389
390    imports
391}
392
393fn wasi_exports_generic(mut store: &mut impl AsStoreMut, env: &FunctionEnv<WasiEnv>) -> Exports {
394    use syscalls::*;
395    let namespace = namespace! {
396        "thread-spawn" => Function::new_typed_with_env(&mut store, env, thread_spawn::<Memory32>),
397    };
398    namespace
399}
400
401fn wasi_unstable_exports(mut store: &mut impl AsStoreMut, env: &FunctionEnv<WasiEnv>) -> Exports {
402    use syscalls::*;
403    let namespace = namespace! {
404        "args_get" => Function::new_typed_with_env(&mut store, env, args_get::<Memory32>),
405        "args_sizes_get" => Function::new_typed_with_env(&mut store, env, args_sizes_get::<Memory32>),
406        "clock_res_get" => Function::new_typed_with_env(&mut store, env, clock_res_get::<Memory32>),
407        "clock_time_get" => Function::new_typed_with_env(&mut store, env, clock_time_get::<Memory32>),
408        "environ_get" => Function::new_typed_with_env(&mut store, env, environ_get::<Memory32>),
409        "environ_sizes_get" => Function::new_typed_with_env(&mut store, env, environ_sizes_get::<Memory32>),
410        "fd_advise" => Function::new_typed_with_env(&mut store, env, fd_advise),
411        "fd_allocate" => Function::new_typed_with_env(&mut store, env, fd_allocate),
412        "fd_close" => Function::new_typed_with_env(&mut store, env, fd_close),
413        "fd_datasync" => Function::new_typed_with_env(&mut store, env, fd_datasync),
414        "fd_fdstat_get" => Function::new_typed_with_env(&mut store, env, fd_fdstat_get::<Memory32>),
415        "fd_fdstat_set_flags" => Function::new_typed_with_env(&mut store, env, fd_fdstat_set_flags),
416        "fd_fdstat_set_rights" => Function::new_typed_with_env(&mut store, env, fd_fdstat_set_rights),
417        "fd_filestat_get" => Function::new_typed_with_env(&mut store, env, legacy::snapshot0::fd_filestat_get),
418        "fd_filestat_set_size" => Function::new_typed_with_env(&mut store, env, fd_filestat_set_size),
419        "fd_filestat_set_times" => Function::new_typed_with_env(&mut store, env, fd_filestat_set_times),
420        "fd_pread" => Function::new_typed_with_env(&mut store, env, fd_pread::<Memory32>),
421        "fd_prestat_get" => Function::new_typed_with_env(&mut store, env, fd_prestat_get::<Memory32>),
422        "fd_prestat_dir_name" => Function::new_typed_with_env(&mut store, env, fd_prestat_dir_name::<Memory32>),
423        "fd_pwrite" => Function::new_typed_with_env(&mut store, env, fd_pwrite::<Memory32>),
424        "fd_read" => Function::new_typed_with_env(&mut store, env, fd_read::<Memory32>),
425        "fd_readdir" => Function::new_typed_with_env(&mut store, env, fd_readdir::<Memory32>),
426        "fd_renumber" => Function::new_typed_with_env(&mut store, env, fd_renumber),
427        "fd_seek" => Function::new_typed_with_env(&mut store, env, legacy::snapshot0::fd_seek),
428        "fd_sync" => Function::new_typed_with_env(&mut store, env, fd_sync),
429        "fd_tell" => Function::new_typed_with_env(&mut store, env, fd_tell::<Memory32>),
430        "fd_write" => Function::new_typed_with_env(&mut store, env, fd_write::<Memory32>),
431        "path_create_directory" => Function::new_typed_with_env(&mut store, env, path_create_directory::<Memory32>),
432        "path_filestat_get" => Function::new_typed_with_env(&mut store, env, legacy::snapshot0::path_filestat_get),
433        "path_filestat_set_times" => Function::new_typed_with_env(&mut store, env, path_filestat_set_times::<Memory32>),
434        "path_link" => Function::new_typed_with_env(&mut store, env, path_link::<Memory32>),
435        "path_open" => Function::new_typed_with_env(&mut store, env, path_open::<Memory32>),
436        "path_readlink" => Function::new_typed_with_env(&mut store, env, path_readlink::<Memory32>),
437        "path_remove_directory" => Function::new_typed_with_env(&mut store, env, path_remove_directory::<Memory32>),
438        "path_rename" => Function::new_typed_with_env(&mut store, env, path_rename::<Memory32>),
439        "path_symlink" => Function::new_typed_with_env(&mut store, env, path_symlink::<Memory32>),
440        "path_unlink_file" => Function::new_typed_with_env(&mut store, env, path_unlink_file::<Memory32>),
441        "poll_oneoff" => Function::new_typed_with_env(&mut store, env, legacy::snapshot0::poll_oneoff::<Memory32>),
442        "proc_exit" => Function::new_typed_with_env(&mut store, env, proc_exit::<Memory32>),
443        "proc_raise" => Function::new_typed_with_env(&mut store, env, proc_raise),
444        "random_get" => Function::new_typed_with_env(&mut store, env, random_get::<Memory32>),
445        "sched_yield" => Function::new_typed_with_env(&mut store, env, sched_yield::<Memory32>),
446        "sock_recv" => Function::new_typed_with_env(&mut store, env, sock_recv::<Memory32>),
447        "sock_send" => Function::new_typed_with_env(&mut store, env, sock_send::<Memory32>),
448        "sock_shutdown" => Function::new_typed_with_env(&mut store, env, sock_shutdown),
449        "thread-spawn" => Function::new_typed_with_env(&mut store, env, thread_spawn::<Memory32>),
450    };
451    namespace
452}
453
454fn wasi_snapshot_preview1_exports(
455    mut store: &mut impl AsStoreMut,
456    env: &FunctionEnv<WasiEnv>,
457) -> Exports {
458    use syscalls::*;
459    let namespace = namespace! {
460        "args_get" => Function::new_typed_with_env(&mut store, env, args_get::<Memory32>),
461        "args_sizes_get" => Function::new_typed_with_env(&mut store, env, args_sizes_get::<Memory32>),
462        "clock_res_get" => Function::new_typed_with_env(&mut store, env, clock_res_get::<Memory32>),
463        "clock_time_get" => Function::new_typed_with_env(&mut store, env, clock_time_get::<Memory32>),
464        "environ_get" => Function::new_typed_with_env(&mut store, env, environ_get::<Memory32>),
465        "environ_sizes_get" => Function::new_typed_with_env(&mut store, env, environ_sizes_get::<Memory32>),
466        "fd_advise" => Function::new_typed_with_env(&mut store, env, fd_advise),
467        "fd_allocate" => Function::new_typed_with_env(&mut store, env, fd_allocate),
468        "fd_close" => Function::new_typed_with_env(&mut store, env, fd_close),
469        "fd_datasync" => Function::new_typed_with_env(&mut store, env, fd_datasync),
470        "fd_fdstat_get" => Function::new_typed_with_env(&mut store, env, fd_fdstat_get::<Memory32>),
471        "fd_fdstat_set_flags" => Function::new_typed_with_env(&mut store, env, fd_fdstat_set_flags),
472        "fd_fdstat_set_rights" => Function::new_typed_with_env(&mut store, env, fd_fdstat_set_rights),
473        "fd_filestat_get" => Function::new_typed_with_env(&mut store, env, fd_filestat_get::<Memory32>),
474        "fd_filestat_set_size" => Function::new_typed_with_env(&mut store, env, fd_filestat_set_size),
475        "fd_filestat_set_times" => Function::new_typed_with_env(&mut store, env, fd_filestat_set_times),
476        "fd_pread" => Function::new_typed_with_env(&mut store, env, fd_pread::<Memory32>),
477        "fd_prestat_get" => Function::new_typed_with_env(&mut store, env, fd_prestat_get::<Memory32>),
478        "fd_prestat_dir_name" => Function::new_typed_with_env(&mut store, env, fd_prestat_dir_name::<Memory32>),
479        "fd_pwrite" => Function::new_typed_with_env(&mut store, env, fd_pwrite::<Memory32>),
480        "fd_read" => Function::new_typed_with_env(&mut store, env, fd_read::<Memory32>),
481        "fd_readdir" => Function::new_typed_with_env(&mut store, env, fd_readdir::<Memory32>),
482        "fd_renumber" => Function::new_typed_with_env(&mut store, env, fd_renumber),
483        "fd_seek" => Function::new_typed_with_env(&mut store, env, fd_seek::<Memory32>),
484        "fd_sync" => Function::new_typed_with_env(&mut store, env, fd_sync),
485        "fd_tell" => Function::new_typed_with_env(&mut store, env, fd_tell::<Memory32>),
486        "fd_write" => Function::new_typed_with_env(&mut store, env, fd_write::<Memory32>),
487        "path_create_directory" => Function::new_typed_with_env(&mut store, env, path_create_directory::<Memory32>),
488        "path_filestat_get" => Function::new_typed_with_env(&mut store, env, path_filestat_get::<Memory32>),
489        "path_filestat_set_times" => Function::new_typed_with_env(&mut store, env, path_filestat_set_times::<Memory32>),
490        "path_link" => Function::new_typed_with_env(&mut store, env, path_link::<Memory32>),
491        "path_open" => Function::new_typed_with_env(&mut store, env, path_open::<Memory32>),
492        "path_readlink" => Function::new_typed_with_env(&mut store, env, path_readlink::<Memory32>),
493        "path_remove_directory" => Function::new_typed_with_env(&mut store, env, path_remove_directory::<Memory32>),
494        "path_rename" => Function::new_typed_with_env(&mut store, env, path_rename::<Memory32>),
495        "path_symlink" => Function::new_typed_with_env(&mut store, env, path_symlink::<Memory32>),
496        "path_unlink_file" => Function::new_typed_with_env(&mut store, env, path_unlink_file::<Memory32>),
497        "poll_oneoff" => Function::new_typed_with_env(&mut store, env, poll_oneoff::<Memory32>),
498        "proc_exit" => Function::new_typed_with_env(&mut store, env, proc_exit::<Memory32>),
499        "proc_raise" => Function::new_typed_with_env(&mut store, env, proc_raise),
500        "random_get" => Function::new_typed_with_env(&mut store, env, random_get::<Memory32>),
501        "sched_yield" => Function::new_typed_with_env(&mut store, env, sched_yield::<Memory32>),
502        "sock_accept" => Function::new_typed_with_env(&mut store, env, sock_accept::<Memory32>),
503        "sock_recv" => Function::new_typed_with_env(&mut store, env, sock_recv::<Memory32>),
504        "sock_send" => Function::new_typed_with_env(&mut store, env, sock_send::<Memory32>),
505        "sock_shutdown" => Function::new_typed_with_env(&mut store, env, sock_shutdown),
506        "thread-spawn" => Function::new_typed_with_env(&mut store, env, thread_spawn::<Memory32>),
507    };
508    namespace
509}
510
511fn wasix_exports_32(mut store: &mut impl AsStoreMut, env: &FunctionEnv<WasiEnv>) -> Exports {
512    let engine_supports_async = store.as_store_ref().engine().supports_async();
513
514    use syscalls::*;
515    let namespace = namespace! {
516        "args_get" => Function::new_typed_with_env(&mut store, env, args_get::<Memory32>),
517        "args_sizes_get" => Function::new_typed_with_env(&mut store, env, args_sizes_get::<Memory32>),
518        "call_dynamic" => Function::new_typed_with_env(&mut store, env, call_dynamic::<Memory32>),
519        "reflect_signature" => Function::new_typed_with_env(&mut store, env, reflect_signature::<Memory32>),
520        "clock_res_get" => Function::new_typed_with_env(&mut store, env, clock_res_get::<Memory32>),
521        "clock_time_get" => Function::new_typed_with_env(&mut store, env, clock_time_get::<Memory32>),
522        "clock_time_set" => Function::new_typed_with_env(&mut store, env, clock_time_set),
523        "closure_prepare" => Function::new_typed_with_env(&mut store, env, closure_prepare::<Memory32>),
524        "closure_allocate" => Function::new_typed_with_env(&mut store, env, closure_allocate::<Memory32>),
525        "closure_free" => Function::new_typed_with_env(&mut store, env, closure_free),
526        "environ_get" => Function::new_typed_with_env(&mut store, env, environ_get::<Memory32>),
527        "environ_sizes_get" => Function::new_typed_with_env(&mut store, env, environ_sizes_get::<Memory32>),
528        "epoll_create" => Function::new_typed_with_env(&mut store, env, epoll_create::<Memory32>),
529        "epoll_ctl" => Function::new_typed_with_env(&mut store, env, epoll_ctl::<Memory32>),
530        "epoll_wait" => Function::new_typed_with_env(&mut store, env, epoll_wait::<Memory32>),
531        "fd_advise" => Function::new_typed_with_env(&mut store, env, fd_advise),
532        "fd_allocate" => Function::new_typed_with_env(&mut store, env, fd_allocate),
533        "fd_close" => Function::new_typed_with_env(&mut store, env, fd_close),
534        "fd_datasync" => Function::new_typed_with_env(&mut store, env, fd_datasync),
535        "fd_fdstat_get" => Function::new_typed_with_env(&mut store, env, fd_fdstat_get::<Memory32>),
536        "fd_fdstat_set_flags" => Function::new_typed_with_env(&mut store, env, fd_fdstat_set_flags),
537        "fd_fdstat_set_rights" => Function::new_typed_with_env(&mut store, env, fd_fdstat_set_rights),
538        "fd_filestat_get" => Function::new_typed_with_env(&mut store, env, fd_filestat_get::<Memory32>),
539        "fd_filestat_set_size" => Function::new_typed_with_env(&mut store, env, fd_filestat_set_size),
540        "fd_filestat_set_times" => Function::new_typed_with_env(&mut store, env, fd_filestat_set_times),
541        "fd_pread" => Function::new_typed_with_env(&mut store, env, fd_pread::<Memory32>),
542        "fd_prestat_get" => Function::new_typed_with_env(&mut store, env, fd_prestat_get::<Memory32>),
543        "fd_prestat_dir_name" => Function::new_typed_with_env(&mut store, env, fd_prestat_dir_name::<Memory32>),
544        "fd_pwrite" => Function::new_typed_with_env(&mut store, env, fd_pwrite::<Memory32>),
545        "fd_read" => Function::new_typed_with_env(&mut store, env, fd_read::<Memory32>),
546        "fd_readdir" => Function::new_typed_with_env(&mut store, env, fd_readdir::<Memory32>),
547        "fd_renumber" => Function::new_typed_with_env(&mut store, env, fd_renumber),
548        "fd_dup" => Function::new_typed_with_env(&mut store, env, fd_dup::<Memory32>),
549        "fd_dup2" => Function::new_typed_with_env(&mut store, env, fd_dup2::<Memory32>),
550        "fd_fdflags_get" => Function::new_typed_with_env(&mut store, env, fd_fdflags_get::<Memory32>),
551        "fd_fdflags_set" => Function::new_typed_with_env(&mut store, env, fd_fdflags_set),
552        "fd_event" => Function::new_typed_with_env(&mut store, env, fd_event::<Memory32>),
553        "fd_seek" => Function::new_typed_with_env(&mut store, env, fd_seek::<Memory32>),
554        "fd_sync" => Function::new_typed_with_env(&mut store, env, fd_sync),
555        "fd_tell" => Function::new_typed_with_env(&mut store, env, fd_tell::<Memory32>),
556        "fd_write" => Function::new_typed_with_env(&mut store, env, fd_write::<Memory32>),
557        "fd_pipe" => Function::new_typed_with_env(&mut store, env, fd_pipe::<Memory32>),
558        "path_create_directory" => Function::new_typed_with_env(&mut store, env, path_create_directory::<Memory32>),
559        "path_filestat_get" => Function::new_typed_with_env(&mut store, env, path_filestat_get::<Memory32>),
560        "path_filestat_set_times" => Function::new_typed_with_env(&mut store, env, path_filestat_set_times::<Memory32>),
561        "path_link" => Function::new_typed_with_env(&mut store, env, path_link::<Memory32>),
562        "path_open" => Function::new_typed_with_env(&mut store, env, path_open::<Memory32>),
563        "path_open2" => Function::new_typed_with_env(&mut store, env, path_open2::<Memory32>),
564        "path_readlink" => Function::new_typed_with_env(&mut store, env, path_readlink::<Memory32>),
565        "path_remove_directory" => Function::new_typed_with_env(&mut store, env, path_remove_directory::<Memory32>),
566        "path_rename" => Function::new_typed_with_env(&mut store, env, path_rename::<Memory32>),
567        "path_symlink" => Function::new_typed_with_env(&mut store, env, path_symlink::<Memory32>),
568        "path_unlink_file" => Function::new_typed_with_env(&mut store, env, path_unlink_file::<Memory32>),
569        "poll_oneoff" => Function::new_typed_with_env(&mut store, env, poll_oneoff::<Memory32>),
570        "proc_exit" => Function::new_typed_with_env(&mut store, env, proc_exit::<Memory32>),
571        "proc_fork" => Function::new_typed_with_env(&mut store, env, proc_fork::<Memory32>),
572        "proc_fork_env" => Function::new_typed_with_env(&mut store, env, proc_fork_env::<Memory32>),
573        "proc_join" => Function::new_typed_with_env(&mut store, env, proc_join::<Memory32>),
574        "proc_signal" => Function::new_typed_with_env(&mut store, env, proc_signal),
575        "proc_signals_get" => Function::new_typed_with_env(&mut store, env, proc_signals_get::<Memory32>),
576        "proc_signals_sizes_get" => Function::new_typed_with_env(&mut store, env, proc_signals_sizes_get::<Memory32>),
577        "proc_exec" => Function::new_typed_with_env(&mut store, env, proc_exec::<Memory32>),
578        "proc_exec2" => Function::new_typed_with_env(&mut store, env, proc_exec2::<Memory32>),
579        "proc_exec3" => Function::new_typed_with_env(&mut store, env, proc_exec3::<Memory32>),
580        "proc_exec4" => Function::new_typed_with_env(&mut store, env, proc_exec4::<Memory32>),
581        "proc_exit2" => Function::new_typed_with_env(&mut store, env, proc_exit2::<Memory32>),
582        "proc_raise" => Function::new_typed_with_env(&mut store, env, proc_raise),
583        "proc_raise_interval" => Function::new_typed_with_env(&mut store, env, proc_raise_interval),
584        "proc_snapshot" => Function::new_typed_with_env(&mut store, env, proc_snapshot::<Memory32>),
585        "proc_spawn" => Function::new_typed_with_env(&mut store, env, proc_spawn::<Memory32>),
586        "proc_spawn2" => Function::new_typed_with_env(&mut store, env, proc_spawn2::<Memory32>),
587        "proc_spawn3" => Function::new_typed_with_env(&mut store, env, proc_spawn3::<Memory32>),
588        "proc_id" => Function::new_typed_with_env(&mut store, env, proc_id::<Memory32>),
589        "proc_parent" => Function::new_typed_with_env(&mut store, env, proc_parent::<Memory32>),
590        "random_get" => Function::new_typed_with_env(&mut store, env, random_get::<Memory32>),
591        "tty_get" => Function::new_typed_with_env(&mut store, env, tty_get::<Memory32>),
592        "tty_set" => Function::new_typed_with_env(&mut store, env, tty_set::<Memory32>),
593        "getcwd" => Function::new_typed_with_env(&mut store, env, getcwd::<Memory32>),
594        "chdir" => Function::new_typed_with_env(&mut store, env, chdir::<Memory32>),
595        "dl_invalid_handle" => Function::new_typed_with_env(&mut store, env, dl_invalid_handle),
596        "dlopen" => Function::new_typed_with_env(&mut store, env, dlopen::<Memory32>),
597        "dlsym" => Function::new_typed_with_env(&mut store, env, dlsym::<Memory32>),
598        "callback_signal" => Function::new_typed_with_env(&mut store, env, callback_signal::<Memory32>),
599        "thread_spawn" => Function::new_typed_with_env(&mut store, env, thread_spawn_v2::<Memory32>),
600        "thread_spawn_v2" => Function::new_typed_with_env(&mut store, env, thread_spawn_v2::<Memory32>),
601        "thread_sleep" => Function::new_typed_with_env(&mut store, env, thread_sleep::<Memory32>),
602        "thread_id" => Function::new_typed_with_env(&mut store, env, thread_id::<Memory32>),
603        "thread_signal" => Function::new_typed_with_env(&mut store, env, thread_signal),
604        "thread_join" => Function::new_typed_with_env(&mut store, env, thread_join::<Memory32>),
605        "thread_parallelism" => Function::new_typed_with_env(&mut store, env, thread_parallelism::<Memory32>),
606        "thread_exit" => Function::new_typed_with_env(&mut store, env, thread_exit),
607        "sched_yield" => Function::new_typed_with_env(&mut store, env, sched_yield::<Memory32>),
608        "stack_checkpoint" => Function::new_typed_with_env(&mut store, env, stack_checkpoint::<Memory32>),
609        "stack_restore" => Function::new_typed_with_env(&mut store, env, stack_restore::<Memory32>),
610        "context_create" => Function::new_typed_with_env(&mut store, env, context_create::<Memory32>),
611        "context_switch" => if engine_supports_async { Function::new_typed_with_env_async(&mut store, env, context_switch) } else { Function::new_typed_with_env(&mut store, env, context_switch_not_supported) },
612        "context_destroy" => Function::new_typed_with_env(&mut store, env, context_destroy),
613        "futex_wait" => Function::new_typed_with_env(&mut store, env, futex_wait::<Memory32>),
614        "futex_wake" => Function::new_typed_with_env(&mut store, env, futex_wake::<Memory32>),
615        "futex_wake_all" => Function::new_typed_with_env(&mut store, env, futex_wake_all::<Memory32>),
616        "port_bridge" => Function::new_typed_with_env(&mut store, env, port_bridge::<Memory32>),
617        "port_unbridge" => Function::new_typed_with_env(&mut store, env, port_unbridge),
618        "port_dhcp_acquire" => Function::new_typed_with_env(&mut store, env, port_dhcp_acquire),
619        "port_addr_add" => Function::new_typed_with_env(&mut store, env, port_addr_add::<Memory32>),
620        "port_addr_remove" => Function::new_typed_with_env(&mut store, env, port_addr_remove::<Memory32>),
621        "port_addr_clear" => Function::new_typed_with_env(&mut store, env, port_addr_clear),
622        "port_addr_list" => Function::new_typed_with_env(&mut store, env, port_addr_list::<Memory32>),
623        "port_mac" => Function::new_typed_with_env(&mut store, env, port_mac::<Memory32>),
624        "port_gateway_set" => Function::new_typed_with_env(&mut store, env, port_gateway_set::<Memory32>),
625        "port_route_add" => Function::new_typed_with_env(&mut store, env, port_route_add::<Memory32>),
626        "port_route_remove" => Function::new_typed_with_env(&mut store, env, port_route_remove::<Memory32>),
627        "port_route_clear" => Function::new_typed_with_env(&mut store, env, port_route_clear),
628        "port_route_list" => Function::new_typed_with_env(&mut store, env, port_route_list::<Memory32>),
629        "sock_status" => Function::new_typed_with_env(&mut store, env, sock_status::<Memory32>),
630        "sock_addr_local" => Function::new_typed_with_env(&mut store, env, sock_addr_local::<Memory32>),
631        "sock_addr_peer" => Function::new_typed_with_env(&mut store, env, sock_addr_peer::<Memory32>),
632        "sock_open" => Function::new_typed_with_env(&mut store, env, sock_open::<Memory32>),
633        "sock_pair" => Function::new_typed_with_env(&mut store, env, sock_pair::<Memory32>),
634        "sock_set_opt_flag" => Function::new_typed_with_env(&mut store, env, sock_set_opt_flag),
635        "sock_get_opt_flag" => Function::new_typed_with_env(&mut store, env, sock_get_opt_flag::<Memory32>),
636        "sock_set_opt_time" => Function::new_typed_with_env(&mut store, env, sock_set_opt_time::<Memory32>),
637        "sock_get_opt_time" => Function::new_typed_with_env(&mut store, env, sock_get_opt_time::<Memory32>),
638        "sock_set_opt_size" => Function::new_typed_with_env(&mut store, env, sock_set_opt_size),
639        "sock_get_opt_size" => Function::new_typed_with_env(&mut store, env, sock_get_opt_size::<Memory32>),
640        "sock_join_multicast_v4" => Function::new_typed_with_env(&mut store, env, sock_join_multicast_v4::<Memory32>),
641        "sock_leave_multicast_v4" => Function::new_typed_with_env(&mut store, env, sock_leave_multicast_v4::<Memory32>),
642        "sock_join_multicast_v6" => Function::new_typed_with_env(&mut store, env, sock_join_multicast_v6::<Memory32>),
643        "sock_leave_multicast_v6" => Function::new_typed_with_env(&mut store, env, sock_leave_multicast_v6::<Memory32>),
644        "sock_bind" => Function::new_typed_with_env(&mut store, env, sock_bind::<Memory32>),
645        "sock_listen" => Function::new_typed_with_env(&mut store, env, sock_listen::<Memory32>),
646        "sock_accept" => Function::new_typed_with_env(&mut store, env, sock_accept_v2::<Memory32>),
647        "sock_accept_v2" => Function::new_typed_with_env(&mut store, env, sock_accept_v2::<Memory32>),
648        "sock_connect" => Function::new_typed_with_env(&mut store, env, sock_connect::<Memory32>),
649        "sock_recv" => Function::new_typed_with_env(&mut store, env, sock_recv::<Memory32>),
650        "sock_recv_from" => Function::new_typed_with_env(&mut store, env, sock_recv_from::<Memory32>),
651        "sock_send" => Function::new_typed_with_env(&mut store, env, sock_send::<Memory32>),
652        "sock_send_to" => Function::new_typed_with_env(&mut store, env, sock_send_to::<Memory32>),
653        "sock_send_file" => Function::new_typed_with_env(&mut store, env, sock_send_file::<Memory32>),
654        "sock_shutdown" => Function::new_typed_with_env(&mut store, env, sock_shutdown),
655        "resolve" => Function::new_typed_with_env(&mut store, env, resolve::<Memory32>),
656    };
657    namespace
658}
659
660fn wasix_exports_64(mut store: &mut impl AsStoreMut, env: &FunctionEnv<WasiEnv>) -> Exports {
661    let engine_supports_async = store.as_store_ref().engine().supports_async();
662
663    use syscalls::*;
664    let namespace = namespace! {
665        "args_get" => Function::new_typed_with_env(&mut store, env, args_get::<Memory64>),
666        "args_sizes_get" => Function::new_typed_with_env(&mut store, env, args_sizes_get::<Memory64>),
667        "call_dynamic" => Function::new_typed_with_env(&mut store, env, call_dynamic::<Memory64>),
668        "reflect_signature" => Function::new_typed_with_env(&mut store, env, reflect_signature::<Memory64>),
669        "clock_res_get" => Function::new_typed_with_env(&mut store, env, clock_res_get::<Memory64>),
670        "clock_time_get" => Function::new_typed_with_env(&mut store, env, clock_time_get::<Memory64>),
671        "clock_time_set" => Function::new_typed_with_env(&mut store, env, clock_time_set),
672        "closure_prepare" => Function::new_typed_with_env(&mut store, env, closure_prepare::<Memory64>),
673        "closure_allocate" => Function::new_typed_with_env(&mut store, env, closure_allocate::<Memory64>),
674        "closure_free" => Function::new_typed_with_env(&mut store, env, closure_free),
675        "environ_get" => Function::new_typed_with_env(&mut store, env, environ_get::<Memory64>),
676        "environ_sizes_get" => Function::new_typed_with_env(&mut store, env, environ_sizes_get::<Memory64>),
677        "epoll_create" => Function::new_typed_with_env(&mut store, env, epoll_create::<Memory64>),
678        "epoll_ctl" => Function::new_typed_with_env(&mut store, env, epoll_ctl::<Memory64>),
679        "epoll_wait" => Function::new_typed_with_env(&mut store, env, epoll_wait::<Memory64>),
680        "fd_advise" => Function::new_typed_with_env(&mut store, env, fd_advise),
681        "fd_allocate" => Function::new_typed_with_env(&mut store, env, fd_allocate),
682        "fd_close" => Function::new_typed_with_env(&mut store, env, fd_close),
683        "fd_datasync" => Function::new_typed_with_env(&mut store, env, fd_datasync),
684        "fd_fdstat_get" => Function::new_typed_with_env(&mut store, env, fd_fdstat_get::<Memory64>),
685        "fd_fdstat_set_flags" => Function::new_typed_with_env(&mut store, env, fd_fdstat_set_flags),
686        "fd_fdstat_set_rights" => Function::new_typed_with_env(&mut store, env, fd_fdstat_set_rights),
687        "fd_filestat_get" => Function::new_typed_with_env(&mut store, env, fd_filestat_get::<Memory64>),
688        "fd_filestat_set_size" => Function::new_typed_with_env(&mut store, env, fd_filestat_set_size),
689        "fd_filestat_set_times" => Function::new_typed_with_env(&mut store, env, fd_filestat_set_times),
690        "fd_pread" => Function::new_typed_with_env(&mut store, env, fd_pread::<Memory64>),
691        "fd_prestat_get" => Function::new_typed_with_env(&mut store, env, fd_prestat_get::<Memory64>),
692        "fd_prestat_dir_name" => Function::new_typed_with_env(&mut store, env, fd_prestat_dir_name::<Memory64>),
693        "fd_pwrite" => Function::new_typed_with_env(&mut store, env, fd_pwrite::<Memory64>),
694        "fd_read" => Function::new_typed_with_env(&mut store, env, fd_read::<Memory64>),
695        "fd_readdir" => Function::new_typed_with_env(&mut store, env, fd_readdir::<Memory64>),
696        "fd_renumber" => Function::new_typed_with_env(&mut store, env, fd_renumber),
697        "fd_dup" => Function::new_typed_with_env(&mut store, env, fd_dup::<Memory64>),
698        "fd_dup2" => Function::new_typed_with_env(&mut store, env, fd_dup2::<Memory64>),
699        "fd_fdflags_get" => Function::new_typed_with_env(&mut store, env, fd_fdflags_get::<Memory64>),
700        "fd_fdflags_set" => Function::new_typed_with_env(&mut store, env, fd_fdflags_set),
701        "fd_event" => Function::new_typed_with_env(&mut store, env, fd_event::<Memory64>),
702        "fd_seek" => Function::new_typed_with_env(&mut store, env, fd_seek::<Memory64>),
703        "fd_sync" => Function::new_typed_with_env(&mut store, env, fd_sync),
704        "fd_tell" => Function::new_typed_with_env(&mut store, env, fd_tell::<Memory64>),
705        "fd_write" => Function::new_typed_with_env(&mut store, env, fd_write::<Memory64>),
706        "fd_pipe" => Function::new_typed_with_env(&mut store, env, fd_pipe::<Memory64>),
707        "path_create_directory" => Function::new_typed_with_env(&mut store, env, path_create_directory::<Memory64>),
708        "path_filestat_get" => Function::new_typed_with_env(&mut store, env, path_filestat_get::<Memory64>),
709        "path_filestat_set_times" => Function::new_typed_with_env(&mut store, env, path_filestat_set_times::<Memory64>),
710        "path_link" => Function::new_typed_with_env(&mut store, env, path_link::<Memory64>),
711        "path_open" => Function::new_typed_with_env(&mut store, env, path_open::<Memory64>),
712        "path_open2" => Function::new_typed_with_env(&mut store, env, path_open2::<Memory64>),
713        "path_readlink" => Function::new_typed_with_env(&mut store, env, path_readlink::<Memory64>),
714        "path_remove_directory" => Function::new_typed_with_env(&mut store, env, path_remove_directory::<Memory64>),
715        "path_rename" => Function::new_typed_with_env(&mut store, env, path_rename::<Memory64>),
716        "path_symlink" => Function::new_typed_with_env(&mut store, env, path_symlink::<Memory64>),
717        "path_unlink_file" => Function::new_typed_with_env(&mut store, env, path_unlink_file::<Memory64>),
718        "poll_oneoff" => Function::new_typed_with_env(&mut store, env, poll_oneoff::<Memory64>),
719        "proc_exit" => Function::new_typed_with_env(&mut store, env, proc_exit::<Memory64>),
720        "proc_fork" => Function::new_typed_with_env(&mut store, env, proc_fork::<Memory64>),
721        "proc_fork_env" => Function::new_typed_with_env(&mut store, env, proc_fork_env::<Memory64>),
722        "proc_join" => Function::new_typed_with_env(&mut store, env, proc_join::<Memory64>),
723        "proc_signal" => Function::new_typed_with_env(&mut store, env, proc_signal),
724        "proc_signals_get" => Function::new_typed_with_env(&mut store, env, proc_signals_get::<Memory64>),
725        "proc_signals_sizes_get" => Function::new_typed_with_env(&mut store, env, proc_signals_sizes_get::<Memory64>),
726        "proc_exec" => Function::new_typed_with_env(&mut store, env, proc_exec::<Memory64>),
727        "proc_exec2" => Function::new_typed_with_env(&mut store, env, proc_exec2::<Memory64>),
728        "proc_exec3" => Function::new_typed_with_env(&mut store, env, proc_exec3::<Memory64>),
729        "proc_exec4" => Function::new_typed_with_env(&mut store, env, proc_exec4::<Memory64>),
730        "proc_exit2" => Function::new_typed_with_env(&mut store, env, proc_exit2::<Memory64>),
731        "proc_raise" => Function::new_typed_with_env(&mut store, env, proc_raise),
732        "proc_raise_interval" => Function::new_typed_with_env(&mut store, env, proc_raise_interval),
733        "proc_snapshot" => Function::new_typed_with_env(&mut store, env, proc_snapshot::<Memory64>),
734        "proc_spawn" => Function::new_typed_with_env(&mut store, env, proc_spawn::<Memory64>),
735        "proc_spawn2" => Function::new_typed_with_env(&mut store, env, proc_spawn2::<Memory64>),
736        "proc_spawn3" => Function::new_typed_with_env(&mut store, env, proc_spawn3::<Memory64>),
737        "proc_id" => Function::new_typed_with_env(&mut store, env, proc_id::<Memory64>),
738        "proc_parent" => Function::new_typed_with_env(&mut store, env, proc_parent::<Memory64>),
739        "random_get" => Function::new_typed_with_env(&mut store, env, random_get::<Memory64>),
740        "tty_get" => Function::new_typed_with_env(&mut store, env, tty_get::<Memory64>),
741        "tty_set" => Function::new_typed_with_env(&mut store, env, tty_set::<Memory64>),
742        "getcwd" => Function::new_typed_with_env(&mut store, env, getcwd::<Memory64>),
743        "chdir" => Function::new_typed_with_env(&mut store, env, chdir::<Memory64>),
744        "dl_invalid_handle" => Function::new_typed_with_env(&mut store, env, dl_invalid_handle),
745        "dlopen" => Function::new_typed_with_env(&mut store, env, dlopen::<Memory64>),
746        "dlsym" => Function::new_typed_with_env(&mut store, env, dlsym::<Memory64>),
747        "callback_signal" => Function::new_typed_with_env(&mut store, env, callback_signal::<Memory64>),
748        "thread_spawn" => Function::new_typed_with_env(&mut store, env, thread_spawn_v2::<Memory64>),
749        "thread_spawn_v2" => Function::new_typed_with_env(&mut store, env, thread_spawn_v2::<Memory64>),
750        "thread_sleep" => Function::new_typed_with_env(&mut store, env, thread_sleep::<Memory64>),
751        "thread_id" => Function::new_typed_with_env(&mut store, env, thread_id::<Memory64>),
752        "thread_signal" => Function::new_typed_with_env(&mut store, env, thread_signal),
753        "thread_join" => Function::new_typed_with_env(&mut store, env, thread_join::<Memory64>),
754        "thread_parallelism" => Function::new_typed_with_env(&mut store, env, thread_parallelism::<Memory64>),
755        "thread_exit" => Function::new_typed_with_env(&mut store, env, thread_exit),
756        "sched_yield" => Function::new_typed_with_env(&mut store, env, sched_yield::<Memory64>),
757        "stack_checkpoint" => Function::new_typed_with_env(&mut store, env, stack_checkpoint::<Memory64>),
758        "stack_restore" => Function::new_typed_with_env(&mut store, env, stack_restore::<Memory64>),
759        "context_create" => Function::new_typed_with_env(&mut store, env, context_create::<Memory64>),
760        "context_switch" => if engine_supports_async { Function::new_typed_with_env_async(&mut store, env, context_switch) } else { Function::new_typed_with_env(&mut store, env, context_switch_not_supported) },
761        "context_destroy" => Function::new_typed_with_env(&mut store, env, context_destroy),
762        "futex_wait" => Function::new_typed_with_env(&mut store, env, futex_wait::<Memory64>),
763        "futex_wake" => Function::new_typed_with_env(&mut store, env, futex_wake::<Memory64>),
764        "futex_wake_all" => Function::new_typed_with_env(&mut store, env, futex_wake_all::<Memory64>),
765        "port_bridge" => Function::new_typed_with_env(&mut store, env, port_bridge::<Memory64>),
766        "port_unbridge" => Function::new_typed_with_env(&mut store, env, port_unbridge),
767        "port_dhcp_acquire" => Function::new_typed_with_env(&mut store, env, port_dhcp_acquire),
768        "port_addr_add" => Function::new_typed_with_env(&mut store, env, port_addr_add::<Memory64>),
769        "port_addr_remove" => Function::new_typed_with_env(&mut store, env, port_addr_remove::<Memory64>),
770        "port_addr_clear" => Function::new_typed_with_env(&mut store, env, port_addr_clear),
771        "port_addr_list" => Function::new_typed_with_env(&mut store, env, port_addr_list::<Memory64>),
772        "port_mac" => Function::new_typed_with_env(&mut store, env, port_mac::<Memory64>),
773        "port_gateway_set" => Function::new_typed_with_env(&mut store, env, port_gateway_set::<Memory64>),
774        "port_route_add" => Function::new_typed_with_env(&mut store, env, port_route_add::<Memory64>),
775        "port_route_remove" => Function::new_typed_with_env(&mut store, env, port_route_remove::<Memory64>),
776        "port_route_clear" => Function::new_typed_with_env(&mut store, env, port_route_clear),
777        "port_route_list" => Function::new_typed_with_env(&mut store, env, port_route_list::<Memory64>),
778        "sock_status" => Function::new_typed_with_env(&mut store, env, sock_status::<Memory64>),
779        "sock_addr_local" => Function::new_typed_with_env(&mut store, env, sock_addr_local::<Memory64>),
780        "sock_addr_peer" => Function::new_typed_with_env(&mut store, env, sock_addr_peer::<Memory64>),
781        "sock_open" => Function::new_typed_with_env(&mut store, env, sock_open::<Memory64>),
782        "sock_pair" => Function::new_typed_with_env(&mut store, env, sock_pair::<Memory64>),
783        "sock_set_opt_flag" => Function::new_typed_with_env(&mut store, env, sock_set_opt_flag),
784        "sock_get_opt_flag" => Function::new_typed_with_env(&mut store, env, sock_get_opt_flag::<Memory64>),
785        "sock_set_opt_time" => Function::new_typed_with_env(&mut store, env, sock_set_opt_time::<Memory64>),
786        "sock_get_opt_time" => Function::new_typed_with_env(&mut store, env, sock_get_opt_time::<Memory64>),
787        "sock_set_opt_size" => Function::new_typed_with_env(&mut store, env, sock_set_opt_size),
788        "sock_get_opt_size" => Function::new_typed_with_env(&mut store, env, sock_get_opt_size::<Memory64>),
789        "sock_join_multicast_v4" => Function::new_typed_with_env(&mut store, env, sock_join_multicast_v4::<Memory64>),
790        "sock_leave_multicast_v4" => Function::new_typed_with_env(&mut store, env, sock_leave_multicast_v4::<Memory64>),
791        "sock_join_multicast_v6" => Function::new_typed_with_env(&mut store, env, sock_join_multicast_v6::<Memory64>),
792        "sock_leave_multicast_v6" => Function::new_typed_with_env(&mut store, env, sock_leave_multicast_v6::<Memory64>),
793        "sock_bind" => Function::new_typed_with_env(&mut store, env, sock_bind::<Memory64>),
794        "sock_listen" => Function::new_typed_with_env(&mut store, env, sock_listen::<Memory64>),
795        "sock_accept" => Function::new_typed_with_env(&mut store, env, sock_accept_v2::<Memory64>),
796        "sock_accept_v2" => Function::new_typed_with_env(&mut store, env, sock_accept_v2::<Memory64>),
797        "sock_connect" => Function::new_typed_with_env(&mut store, env, sock_connect::<Memory64>),
798        "sock_recv" => Function::new_typed_with_env(&mut store, env, sock_recv::<Memory64>),
799        "sock_recv_from" => Function::new_typed_with_env(&mut store, env, sock_recv_from::<Memory64>),
800        "sock_send" => Function::new_typed_with_env(&mut store, env, sock_send::<Memory64>),
801        "sock_send_to" => Function::new_typed_with_env(&mut store, env, sock_send_to::<Memory64>),
802        "sock_send_file" => Function::new_typed_with_env(&mut store, env, sock_send_file::<Memory64>),
803        "sock_shutdown" => Function::new_typed_with_env(&mut store, env, sock_shutdown),
804        "resolve" => Function::new_typed_with_env(&mut store, env, resolve::<Memory64>),
805    };
806    namespace
807}
808
809// TODO: split function into two variants, one for JS and one for sys.
810// (this will make code less messy)
811fn import_object_for_all_wasi_versions(
812    _module: &wasmer::Module,
813    store: &mut impl AsStoreMut,
814    env: &FunctionEnv<WasiEnv>,
815) -> Imports {
816    let exports_wasi_generic = wasi_exports_generic(store, env);
817    let exports_wasi_unstable = wasi_unstable_exports(store, env);
818    let exports_wasi_snapshot_preview1 = wasi_snapshot_preview1_exports(store, env);
819    let exports_wasix_32v1 = wasix_exports_32(store, env);
820    let exports_wasix_64v1 = wasix_exports_64(store, env);
821
822    // Allowed due to JS feature flag complications.
823    #[allow(unused_mut)]
824    let mut imports = imports! {
825        "wasi" => exports_wasi_generic,
826        "wasi_unstable" => exports_wasi_unstable,
827        "wasi_snapshot_preview1" => exports_wasi_snapshot_preview1,
828        "wasix_32v1" => exports_wasix_32v1,
829        "wasix_64v1" => exports_wasix_64v1,
830    };
831
832    imports
833}
834
835/// Combines a state generating function with the import list for legacy WASI
836fn generate_import_object_snapshot0(
837    store: &mut impl AsStoreMut,
838    env: &FunctionEnv<WasiEnv>,
839) -> Imports {
840    let exports_unstable = wasi_unstable_exports(store, env);
841    imports! {
842        "wasi_unstable" => exports_unstable
843    }
844}
845
846fn generate_import_object_snapshot1(
847    store: &mut impl AsStoreMut,
848    env: &FunctionEnv<WasiEnv>,
849) -> Imports {
850    let exports_wasi_snapshot_preview1 = wasi_snapshot_preview1_exports(store, env);
851    imports! {
852        "wasi_snapshot_preview1" => exports_wasi_snapshot_preview1
853    }
854}
855
856/// Combines a state generating function with the import list for snapshot 1
857fn generate_import_object_wasix32_v1(
858    store: &mut impl AsStoreMut,
859    env: &FunctionEnv<WasiEnv>,
860) -> Imports {
861    let exports_wasix_32v1 = wasix_exports_32(store, env);
862    imports! {
863        "wasix_32v1" => exports_wasix_32v1
864    }
865}
866
867fn generate_import_object_wasix64_v1(
868    store: &mut impl AsStoreMut,
869    env: &FunctionEnv<WasiEnv>,
870) -> Imports {
871    let exports_wasix_64v1 = wasix_exports_64(store, env);
872    imports! {
873        "wasix_64v1" => exports_wasix_64v1
874    }
875}
876
877fn mem_error_to_wasi(err: MemoryAccessError) -> Errno {
878    match err {
879        MemoryAccessError::HeapOutOfBounds => Errno::Memviolation,
880        MemoryAccessError::Overflow => Errno::Overflow,
881        MemoryAccessError::NonUtf8String => Errno::Inval,
882        _ => Errno::Unknown,
883    }
884}
885
886/// Run a synchronous function that would normally be blocking.
887///
888/// When the `sys-thread` feature is enabled, this will call
889/// [`tokio::task::block_in_place()`]. Otherwise, it calls the function
890/// immediately.
891pub(crate) fn block_in_place<Ret>(thunk: impl FnOnce() -> Ret) -> Ret {
892    cfg_if::cfg_if! {
893        if #[cfg(feature = "sys-thread")] {
894            tokio::task::block_in_place(thunk)
895        } else {
896            thunk()
897        }
898    }
899}
900
901/// Spawns a new blocking task that runs the provided closure.
902///
903/// The closure is executed on a separate thread, allowing it to perform blocking operations
904/// without blocking the main thread. The closure is wrapped in a `Future` that resolves to the
905/// result of the closure's execution.
906pub(crate) async fn spawn_blocking<F, R>(f: F) -> Result<R, tokio::task::JoinError>
907where
908    F: FnOnce() -> R + Send + 'static,
909    R: Send + 'static,
910{
911    cfg_if::cfg_if! {
912        if #[cfg(target_arch = "wasm32")] {
913            Ok(block_in_place(f))
914        } else {
915            tokio::task::spawn_blocking(f).await
916        }
917    }
918}
919
920pub(crate) fn flatten_runtime_error(err: RuntimeError) -> RuntimeError {
921    let e_ref = err.downcast_ref::<WasiRuntimeError>();
922    match e_ref {
923        Some(WasiRuntimeError::Wasi(_)) => {
924            let Ok(WasiRuntimeError::Wasi(err)) = err.downcast::<WasiRuntimeError>() else {
925                unreachable!()
926            };
927            RuntimeError::user(Box::new(err))
928        }
929        Some(WasiRuntimeError::Runtime(_)) => {
930            let Ok(WasiRuntimeError::Runtime(err)) = err.downcast::<WasiRuntimeError>() else {
931                unreachable!()
932            };
933            flatten_runtime_error(err)
934        }
935        _ => err,
936    }
937}