Skip to main content

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    /// The file is a script, but its shebang line cannot be used.
174    #[error("invalid shebang line in '{path}'")]
175    InvalidShebang { path: String },
176    /// A script's shebang chain never reached anything executable.
177    #[error("too many levels of shebang indirection")]
178    ShebangLoop,
179    /// Bad handle
180    #[error("bad handle")]
181    BadHandle,
182    /// Call is unsupported
183    #[error("unsupported")]
184    Unsupported,
185    /// Not found
186    #[error("not found: {message}")]
187    NotFound { message: String },
188    /// Tried to run the specified binary as a new WASI thread/process, but
189    /// the binary name was not found.
190    #[error("could not find binary '{binary}'")]
191    BinaryNotFound { binary: String },
192    #[error("could not find an entrypoint in the package '{package_id}'")]
193    MissingEntrypoint {
194        package_id: wasmer_config::package::PackageId,
195    },
196    #[error("could not load ")]
197    ModuleLoad { message: String },
198    /// Bad request
199    #[error("bad request")]
200    BadRequest,
201    /// Access denied
202    #[error("access denied")]
203    AccessDenied,
204    /// Internal error has occurred
205    #[error("internal error")]
206    InternalError,
207    /// An error occurred while preparing the file system
208    #[error(transparent)]
209    FileSystemError(ExtendedFsError),
210    /// Memory allocation failed
211    #[error("memory allocation failed")]
212    MemoryAllocationFailed,
213    /// Memory access violation
214    #[error("memory access violation")]
215    MemoryAccessViolation,
216    /// Some other unhandled error. If you see this, it's probably a bug.
217    #[error("unknown error found")]
218    UnknownError,
219    #[error("runtime error")]
220    Runtime(#[from] WasiRuntimeError),
221    #[error(transparent)]
222    Other(#[from] Box<dyn std::error::Error + Send + Sync>),
223}
224
225#[derive(Debug)]
226pub struct ExtendedFsError {
227    pub error: virtual_fs::FsError,
228    pub message: Option<String>,
229}
230
231impl ExtendedFsError {
232    pub fn with_msg(error: virtual_fs::FsError, msg: impl Into<String>) -> Self {
233        Self {
234            error,
235            message: Some(msg.into()),
236        }
237    }
238
239    pub fn new(error: virtual_fs::FsError) -> Self {
240        Self {
241            error,
242            message: None,
243        }
244    }
245}
246
247impl std::fmt::Display for ExtendedFsError {
248    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
249        write!(f, "fs error: {}", self.error)?;
250
251        if let Some(msg) = &self.message {
252            write!(f, " | {msg}")?;
253        }
254
255        Ok(())
256    }
257}
258
259impl std::error::Error for ExtendedFsError {
260    fn cause(&self) -> Option<&dyn std::error::Error> {
261        Some(&self.error)
262    }
263}
264
265impl SpawnError {
266    /// Returns `true` if the spawn error is [`NotFound`].
267    ///
268    /// [`NotFound`]: SpawnError::NotFound
269    #[must_use]
270    pub fn is_not_found(&self) -> bool {
271        matches!(
272            self,
273            Self::NotFound { .. } | Self::MissingEntrypoint { .. } | Self::BinaryNotFound { .. }
274        )
275    }
276}
277
278#[derive(thiserror::Error, Debug)]
279pub enum WasiRuntimeError {
280    #[error("WASI state setup failed: {0}")]
281    Init(#[from] WasiStateCreationError),
282    #[error("Loading exports failed: {0}")]
283    Export(#[from] wasmer::ExportError),
284    #[error("Instantiation failed: {0}")]
285    Instantiation(#[from] wasmer::InstantiationError),
286    #[error("WASI error: {0}")]
287    Wasi(#[from] WasiError),
288    #[error("Process manager error: {0}")]
289    ControlPlane(#[from] ControlPlaneError),
290    #[error("{0}")]
291    Runtime(#[from] RuntimeError),
292    #[error("Memory access error: {0}")]
293    Thread(#[from] WasiThreadError),
294    #[error("{0}")]
295    Anyhow(#[from] Arc<anyhow::Error>),
296}
297
298impl WasiRuntimeError {
299    /// Retrieve the concrete exit code returned by an instance.
300    ///
301    /// Returns [`None`] if a general execution error occurred.
302    pub fn as_exit_code(&self) -> Option<ExitCode> {
303        if let WasiRuntimeError::Wasi(WasiError::Exit(code)) = self {
304            Some(*code)
305        } else if let WasiRuntimeError::Runtime(err) = self {
306            if let Some(WasiError::Exit(code)) = err.downcast_ref() {
307                Some(*code)
308            } else {
309                None
310            }
311        } else {
312            None
313        }
314    }
315
316    pub fn display<'a>(&'a self, store: &'a mut impl AsStoreMut) -> WasiRuntimeErrorDisplay<'a> {
317        if let WasiRuntimeError::Runtime(err) = self {
318            WasiRuntimeErrorDisplay::Runtime(err.display(store))
319        } else {
320            WasiRuntimeErrorDisplay::Other(self)
321        }
322    }
323}
324
325pub enum WasiRuntimeErrorDisplay<'a> {
326    Runtime(wasmer::RuntimeErrorDisplay<'a>),
327    Other(&'a WasiRuntimeError),
328}
329
330impl std::fmt::Display for WasiRuntimeErrorDisplay<'_> {
331    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
332        match self {
333            WasiRuntimeErrorDisplay::Runtime(display) => write!(f, "{display}"),
334            WasiRuntimeErrorDisplay::Other(err) => write!(f, "{err}"),
335        }
336    }
337}
338
339#[derive(Debug)]
340pub struct WasiVFork {
341    /// The information needed to rewind the stack with asyncify
342    pub asyncify: Option<WasiVForkAsyncify>,
343
344    /// The environment before the vfork occurred
345    pub env: Box<WasiEnv>,
346
347    /// Handle of the thread we have forked (dropping this handle
348    /// will signal that the thread is dead)
349    pub handle: WasiThreadHandle,
350}
351
352#[derive(Debug, Clone)]
353pub struct WasiVForkAsyncify {
354    /// The unwound stack before the vfork occurred
355    pub rewind_stack: BytesMut,
356    /// The mutable parts of the store
357    pub store_data: Bytes,
358    /// Whether the store is 64-bit
359    pub is_64bit: bool,
360}
361
362impl Clone for WasiVFork {
363    fn clone(&self) -> Self {
364        Self {
365            asyncify: self.asyncify.clone(),
366            env: Box::new(self.env.as_ref().clone()),
367            handle: self.handle.clone(),
368        }
369    }
370}
371
372/// Create an [`Imports`] with an existing [`WasiEnv`]. [`WasiEnv`] values are
373/// typically constructed with [`WasiEnvBuilder`].
374pub fn generate_import_object_from_env(
375    store: &mut impl AsStoreMut,
376    ctx: &FunctionEnv<WasiEnv>,
377    version: WasiVersion,
378) -> Imports {
379    let mut imports = match version {
380        WasiVersion::Snapshot0 => generate_import_object_snapshot0(store, ctx),
381        WasiVersion::Snapshot1 | WasiVersion::Latest => {
382            generate_import_object_snapshot1(store, ctx)
383        }
384        WasiVersion::Wasix32v1 => generate_import_object_wasix32_v1(store, ctx),
385        WasiVersion::Wasix64v1 => generate_import_object_wasix64_v1(store, ctx),
386    };
387
388    let exports_wasi_generic = wasi_exports_generic(store, ctx);
389
390    let imports_wasi_generic = imports! {
391        "wasi" => exports_wasi_generic,
392    };
393
394    imports.extend(&imports_wasi_generic);
395
396    imports
397}
398
399fn wasi_exports_generic(mut store: &mut impl AsStoreMut, env: &FunctionEnv<WasiEnv>) -> Exports {
400    use syscalls::*;
401    let namespace = namespace! {
402        "thread-spawn" => Function::new_typed_with_env(&mut store, env, thread_spawn::<Memory32>),
403    };
404    namespace
405}
406
407fn wasi_unstable_exports(mut store: &mut impl AsStoreMut, env: &FunctionEnv<WasiEnv>) -> Exports {
408    use syscalls::*;
409    let namespace = namespace! {
410        "args_get" => Function::new_typed_with_env(&mut store, env, args_get::<Memory32>),
411        "args_sizes_get" => Function::new_typed_with_env(&mut store, env, args_sizes_get::<Memory32>),
412        "clock_res_get" => Function::new_typed_with_env(&mut store, env, clock_res_get::<Memory32>),
413        "clock_time_get" => Function::new_typed_with_env(&mut store, env, clock_time_get::<Memory32>),
414        "environ_get" => Function::new_typed_with_env(&mut store, env, environ_get::<Memory32>),
415        "environ_sizes_get" => Function::new_typed_with_env(&mut store, env, environ_sizes_get::<Memory32>),
416        "fd_advise" => Function::new_typed_with_env(&mut store, env, fd_advise),
417        "fd_allocate" => Function::new_typed_with_env(&mut store, env, fd_allocate),
418        "fd_close" => Function::new_typed_with_env(&mut store, env, fd_close),
419        "fd_datasync" => Function::new_typed_with_env(&mut store, env, fd_datasync),
420        "fd_fdstat_get" => Function::new_typed_with_env(&mut store, env, fd_fdstat_get::<Memory32>),
421        "fd_fdstat_set_flags" => Function::new_typed_with_env(&mut store, env, fd_fdstat_set_flags),
422        "fd_fdstat_set_rights" => Function::new_typed_with_env(&mut store, env, fd_fdstat_set_rights),
423        "fd_filestat_get" => Function::new_typed_with_env(&mut store, env, legacy::snapshot0::fd_filestat_get),
424        "fd_filestat_set_size" => Function::new_typed_with_env(&mut store, env, fd_filestat_set_size),
425        "fd_filestat_set_times" => Function::new_typed_with_env(&mut store, env, fd_filestat_set_times),
426        "fd_pread" => Function::new_typed_with_env(&mut store, env, fd_pread::<Memory32>),
427        "fd_prestat_get" => Function::new_typed_with_env(&mut store, env, fd_prestat_get::<Memory32>),
428        "fd_prestat_dir_name" => Function::new_typed_with_env(&mut store, env, fd_prestat_dir_name::<Memory32>),
429        "fd_pwrite" => Function::new_typed_with_env(&mut store, env, fd_pwrite::<Memory32>),
430        "fd_read" => Function::new_typed_with_env(&mut store, env, fd_read::<Memory32>),
431        "fd_readdir" => Function::new_typed_with_env(&mut store, env, fd_readdir::<Memory32>),
432        "fd_renumber" => Function::new_typed_with_env(&mut store, env, fd_renumber),
433        "fd_seek" => Function::new_typed_with_env(&mut store, env, legacy::snapshot0::fd_seek),
434        "fd_sync" => Function::new_typed_with_env(&mut store, env, fd_sync),
435        "fd_tell" => Function::new_typed_with_env(&mut store, env, fd_tell::<Memory32>),
436        "fd_write" => Function::new_typed_with_env(&mut store, env, fd_write::<Memory32>),
437        "path_create_directory" => Function::new_typed_with_env(&mut store, env, path_create_directory::<Memory32>),
438        "path_filestat_get" => Function::new_typed_with_env(&mut store, env, legacy::snapshot0::path_filestat_get),
439        "path_filestat_set_times" => Function::new_typed_with_env(&mut store, env, path_filestat_set_times::<Memory32>),
440        "path_link" => Function::new_typed_with_env(&mut store, env, path_link::<Memory32>),
441        "path_open" => Function::new_typed_with_env(&mut store, env, path_open::<Memory32>),
442        "path_readlink" => Function::new_typed_with_env(&mut store, env, path_readlink::<Memory32>),
443        "path_remove_directory" => Function::new_typed_with_env(&mut store, env, path_remove_directory::<Memory32>),
444        "path_rename" => Function::new_typed_with_env(&mut store, env, path_rename::<Memory32>),
445        "path_symlink" => Function::new_typed_with_env(&mut store, env, path_symlink::<Memory32>),
446        "path_unlink_file" => Function::new_typed_with_env(&mut store, env, path_unlink_file::<Memory32>),
447        "poll_oneoff" => Function::new_typed_with_env(&mut store, env, legacy::snapshot0::poll_oneoff::<Memory32>),
448        "proc_exit" => Function::new_typed_with_env(&mut store, env, proc_exit::<Memory32>),
449        "proc_raise" => Function::new_typed_with_env(&mut store, env, proc_raise),
450        "random_get" => Function::new_typed_with_env(&mut store, env, random_get::<Memory32>),
451        "sched_yield" => Function::new_typed_with_env(&mut store, env, sched_yield::<Memory32>),
452        "sock_recv" => Function::new_typed_with_env(&mut store, env, sock_recv::<Memory32>),
453        "sock_send" => Function::new_typed_with_env(&mut store, env, sock_send::<Memory32>),
454        "sock_shutdown" => Function::new_typed_with_env(&mut store, env, sock_shutdown),
455        "thread-spawn" => Function::new_typed_with_env(&mut store, env, thread_spawn::<Memory32>),
456    };
457    namespace
458}
459
460fn wasi_snapshot_preview1_exports(
461    mut store: &mut impl AsStoreMut,
462    env: &FunctionEnv<WasiEnv>,
463) -> Exports {
464    use syscalls::*;
465    let namespace = namespace! {
466        "args_get" => Function::new_typed_with_env(&mut store, env, args_get::<Memory32>),
467        "args_sizes_get" => Function::new_typed_with_env(&mut store, env, args_sizes_get::<Memory32>),
468        "clock_res_get" => Function::new_typed_with_env(&mut store, env, clock_res_get::<Memory32>),
469        "clock_time_get" => Function::new_typed_with_env(&mut store, env, clock_time_get::<Memory32>),
470        "environ_get" => Function::new_typed_with_env(&mut store, env, environ_get::<Memory32>),
471        "environ_sizes_get" => Function::new_typed_with_env(&mut store, env, environ_sizes_get::<Memory32>),
472        "fd_advise" => Function::new_typed_with_env(&mut store, env, fd_advise),
473        "fd_allocate" => Function::new_typed_with_env(&mut store, env, fd_allocate),
474        "fd_close" => Function::new_typed_with_env(&mut store, env, fd_close),
475        "fd_datasync" => Function::new_typed_with_env(&mut store, env, fd_datasync),
476        "fd_fdstat_get" => Function::new_typed_with_env(&mut store, env, fd_fdstat_get::<Memory32>),
477        "fd_fdstat_set_flags" => Function::new_typed_with_env(&mut store, env, fd_fdstat_set_flags),
478        "fd_fdstat_set_rights" => Function::new_typed_with_env(&mut store, env, fd_fdstat_set_rights),
479        "fd_filestat_get" => Function::new_typed_with_env(&mut store, env, fd_filestat_get::<Memory32>),
480        "fd_filestat_set_size" => Function::new_typed_with_env(&mut store, env, fd_filestat_set_size),
481        "fd_filestat_set_times" => Function::new_typed_with_env(&mut store, env, fd_filestat_set_times),
482        "fd_pread" => Function::new_typed_with_env(&mut store, env, fd_pread::<Memory32>),
483        "fd_prestat_get" => Function::new_typed_with_env(&mut store, env, fd_prestat_get::<Memory32>),
484        "fd_prestat_dir_name" => Function::new_typed_with_env(&mut store, env, fd_prestat_dir_name::<Memory32>),
485        "fd_pwrite" => Function::new_typed_with_env(&mut store, env, fd_pwrite::<Memory32>),
486        "fd_read" => Function::new_typed_with_env(&mut store, env, fd_read::<Memory32>),
487        "fd_readdir" => Function::new_typed_with_env(&mut store, env, fd_readdir::<Memory32>),
488        "fd_renumber" => Function::new_typed_with_env(&mut store, env, fd_renumber),
489        "fd_seek" => Function::new_typed_with_env(&mut store, env, fd_seek::<Memory32>),
490        "fd_sync" => Function::new_typed_with_env(&mut store, env, fd_sync),
491        "fd_tell" => Function::new_typed_with_env(&mut store, env, fd_tell::<Memory32>),
492        "fd_write" => Function::new_typed_with_env(&mut store, env, fd_write::<Memory32>),
493        "path_create_directory" => Function::new_typed_with_env(&mut store, env, path_create_directory::<Memory32>),
494        "path_filestat_get" => Function::new_typed_with_env(&mut store, env, path_filestat_get::<Memory32>),
495        "path_filestat_set_times" => Function::new_typed_with_env(&mut store, env, path_filestat_set_times::<Memory32>),
496        "path_link" => Function::new_typed_with_env(&mut store, env, path_link::<Memory32>),
497        "path_open" => Function::new_typed_with_env(&mut store, env, path_open::<Memory32>),
498        "path_readlink" => Function::new_typed_with_env(&mut store, env, path_readlink::<Memory32>),
499        "path_remove_directory" => Function::new_typed_with_env(&mut store, env, path_remove_directory::<Memory32>),
500        "path_rename" => Function::new_typed_with_env(&mut store, env, path_rename::<Memory32>),
501        "path_symlink" => Function::new_typed_with_env(&mut store, env, path_symlink::<Memory32>),
502        "path_unlink_file" => Function::new_typed_with_env(&mut store, env, path_unlink_file::<Memory32>),
503        "poll_oneoff" => Function::new_typed_with_env(&mut store, env, poll_oneoff::<Memory32>),
504        "proc_exit" => Function::new_typed_with_env(&mut store, env, proc_exit::<Memory32>),
505        "proc_raise" => Function::new_typed_with_env(&mut store, env, proc_raise),
506        "random_get" => Function::new_typed_with_env(&mut store, env, random_get::<Memory32>),
507        "sched_yield" => Function::new_typed_with_env(&mut store, env, sched_yield::<Memory32>),
508        "sock_accept" => Function::new_typed_with_env(&mut store, env, sock_accept::<Memory32>),
509        "sock_recv" => Function::new_typed_with_env(&mut store, env, sock_recv::<Memory32>),
510        "sock_send" => Function::new_typed_with_env(&mut store, env, sock_send::<Memory32>),
511        "sock_shutdown" => Function::new_typed_with_env(&mut store, env, sock_shutdown),
512        "thread-spawn" => Function::new_typed_with_env(&mut store, env, thread_spawn::<Memory32>),
513    };
514    namespace
515}
516
517fn wasix_exports_32(mut store: &mut impl AsStoreMut, env: &FunctionEnv<WasiEnv>) -> Exports {
518    let engine_supports_async = store.as_store_ref().engine().supports_async();
519
520    use syscalls::*;
521    let namespace = namespace! {
522        "args_get" => Function::new_typed_with_env(&mut store, env, args_get::<Memory32>),
523        "args_sizes_get" => Function::new_typed_with_env(&mut store, env, args_sizes_get::<Memory32>),
524        "call_dynamic" => Function::new_typed_with_env(&mut store, env, call_dynamic::<Memory32>),
525        "reflect_signature" => Function::new_typed_with_env(&mut store, env, reflect_signature::<Memory32>),
526        "clock_res_get" => Function::new_typed_with_env(&mut store, env, clock_res_get::<Memory32>),
527        "clock_time_get" => Function::new_typed_with_env(&mut store, env, clock_time_get::<Memory32>),
528        "clock_time_set" => Function::new_typed_with_env(&mut store, env, clock_time_set),
529        "closure_prepare" => Function::new_typed_with_env(&mut store, env, closure_prepare::<Memory32>),
530        "closure_allocate" => Function::new_typed_with_env(&mut store, env, closure_allocate::<Memory32>),
531        "closure_free" => Function::new_typed_with_env(&mut store, env, closure_free),
532        "environ_get" => Function::new_typed_with_env(&mut store, env, environ_get::<Memory32>),
533        "environ_sizes_get" => Function::new_typed_with_env(&mut store, env, environ_sizes_get::<Memory32>),
534        "epoll_create" => Function::new_typed_with_env(&mut store, env, epoll_create::<Memory32>),
535        "epoll_ctl" => Function::new_typed_with_env(&mut store, env, epoll_ctl::<Memory32>),
536        "epoll_wait" => Function::new_typed_with_env(&mut store, env, epoll_wait::<Memory32>),
537        "fd_advise" => Function::new_typed_with_env(&mut store, env, fd_advise),
538        "fd_allocate" => Function::new_typed_with_env(&mut store, env, fd_allocate),
539        "fd_close" => Function::new_typed_with_env(&mut store, env, fd_close),
540        "fd_datasync" => Function::new_typed_with_env(&mut store, env, fd_datasync),
541        "fd_fdstat_get" => Function::new_typed_with_env(&mut store, env, fd_fdstat_get::<Memory32>),
542        "fd_fdstat_set_flags" => Function::new_typed_with_env(&mut store, env, fd_fdstat_set_flags),
543        "fd_fdstat_set_rights" => Function::new_typed_with_env(&mut store, env, fd_fdstat_set_rights),
544        "fd_filestat_get" => Function::new_typed_with_env(&mut store, env, fd_filestat_get::<Memory32>),
545        "fd_filestat_set_size" => Function::new_typed_with_env(&mut store, env, fd_filestat_set_size),
546        "fd_filestat_set_times" => Function::new_typed_with_env(&mut store, env, fd_filestat_set_times),
547        "fd_pread" => Function::new_typed_with_env(&mut store, env, fd_pread::<Memory32>),
548        "fd_prestat_get" => Function::new_typed_with_env(&mut store, env, fd_prestat_get::<Memory32>),
549        "fd_prestat_dir_name" => Function::new_typed_with_env(&mut store, env, fd_prestat_dir_name::<Memory32>),
550        "fd_pwrite" => Function::new_typed_with_env(&mut store, env, fd_pwrite::<Memory32>),
551        "fd_read" => Function::new_typed_with_env(&mut store, env, fd_read::<Memory32>),
552        "fd_readdir" => Function::new_typed_with_env(&mut store, env, fd_readdir::<Memory32>),
553        "fd_renumber" => Function::new_typed_with_env(&mut store, env, fd_renumber),
554        "fd_dup" => Function::new_typed_with_env(&mut store, env, fd_dup::<Memory32>),
555        "fd_dup2" => Function::new_typed_with_env(&mut store, env, fd_dup2::<Memory32>),
556        "fd_fdflags_get" => Function::new_typed_with_env(&mut store, env, fd_fdflags_get::<Memory32>),
557        "fd_fdflags_set" => Function::new_typed_with_env(&mut store, env, fd_fdflags_set),
558        "fd_event" => Function::new_typed_with_env(&mut store, env, fd_event::<Memory32>),
559        "fd_seek" => Function::new_typed_with_env(&mut store, env, fd_seek::<Memory32>),
560        "fd_sync" => Function::new_typed_with_env(&mut store, env, fd_sync),
561        "fd_tell" => Function::new_typed_with_env(&mut store, env, fd_tell::<Memory32>),
562        "fd_write" => Function::new_typed_with_env(&mut store, env, fd_write::<Memory32>),
563        "fd_pipe" => Function::new_typed_with_env(&mut store, env, fd_pipe::<Memory32>),
564        "path_create_directory" => Function::new_typed_with_env(&mut store, env, path_create_directory::<Memory32>),
565        "path_filestat_get" => Function::new_typed_with_env(&mut store, env, path_filestat_get::<Memory32>),
566        "path_filestat_set_times" => Function::new_typed_with_env(&mut store, env, path_filestat_set_times::<Memory32>),
567        "path_link" => Function::new_typed_with_env(&mut store, env, path_link::<Memory32>),
568        "path_open" => Function::new_typed_with_env(&mut store, env, path_open::<Memory32>),
569        "path_open2" => Function::new_typed_with_env(&mut store, env, path_open2::<Memory32>),
570        "path_readlink" => Function::new_typed_with_env(&mut store, env, path_readlink::<Memory32>),
571        "path_remove_directory" => Function::new_typed_with_env(&mut store, env, path_remove_directory::<Memory32>),
572        "path_rename" => Function::new_typed_with_env(&mut store, env, path_rename::<Memory32>),
573        "path_symlink" => Function::new_typed_with_env(&mut store, env, path_symlink::<Memory32>),
574        "path_unlink_file" => Function::new_typed_with_env(&mut store, env, path_unlink_file::<Memory32>),
575        "poll_oneoff" => Function::new_typed_with_env(&mut store, env, poll_oneoff::<Memory32>),
576        "proc_exit" => Function::new_typed_with_env(&mut store, env, proc_exit::<Memory32>),
577        "proc_fork" => Function::new_typed_with_env(&mut store, env, proc_fork::<Memory32>),
578        "proc_fork_env" => Function::new_typed_with_env(&mut store, env, proc_fork_env::<Memory32>),
579        "proc_join" => Function::new_typed_with_env(&mut store, env, proc_join::<Memory32>),
580        "proc_signal" => Function::new_typed_with_env(&mut store, env, proc_signal),
581        "proc_signals_get" => Function::new_typed_with_env(&mut store, env, proc_signals_get::<Memory32>),
582        "proc_signals_sizes_get" => Function::new_typed_with_env(&mut store, env, proc_signals_sizes_get::<Memory32>),
583        "proc_exec" => Function::new_typed_with_env(&mut store, env, proc_exec::<Memory32>),
584        "proc_exec2" => Function::new_typed_with_env(&mut store, env, proc_exec2::<Memory32>),
585        "proc_exec3" => Function::new_typed_with_env(&mut store, env, proc_exec3::<Memory32>),
586        "proc_exec4" => Function::new_typed_with_env(&mut store, env, proc_exec4::<Memory32>),
587        "proc_exit2" => Function::new_typed_with_env(&mut store, env, proc_exit2::<Memory32>),
588        "proc_raise" => Function::new_typed_with_env(&mut store, env, proc_raise),
589        "proc_raise_interval" => Function::new_typed_with_env(&mut store, env, proc_raise_interval),
590        "proc_snapshot" => Function::new_typed_with_env(&mut store, env, proc_snapshot::<Memory32>),
591        "proc_spawn" => Function::new_typed_with_env(&mut store, env, proc_spawn::<Memory32>),
592        "proc_spawn2" => Function::new_typed_with_env(&mut store, env, proc_spawn2::<Memory32>),
593        "proc_spawn3" => Function::new_typed_with_env(&mut store, env, proc_spawn3::<Memory32>),
594        "proc_id" => Function::new_typed_with_env(&mut store, env, proc_id::<Memory32>),
595        "proc_parent" => Function::new_typed_with_env(&mut store, env, proc_parent::<Memory32>),
596        "random_get" => Function::new_typed_with_env(&mut store, env, random_get::<Memory32>),
597        "tty_get" => Function::new_typed_with_env(&mut store, env, tty_get::<Memory32>),
598        "tty_set" => Function::new_typed_with_env(&mut store, env, tty_set::<Memory32>),
599        "getcwd" => Function::new_typed_with_env(&mut store, env, getcwd::<Memory32>),
600        "chdir" => Function::new_typed_with_env(&mut store, env, chdir::<Memory32>),
601        "dl_invalid_handle" => Function::new_typed_with_env(&mut store, env, dl_invalid_handle),
602        "dlopen" => Function::new_typed_with_env(&mut store, env, dlopen::<Memory32>),
603        "dlsym" => Function::new_typed_with_env(&mut store, env, dlsym::<Memory32>),
604        "callback_signal" => Function::new_typed_with_env(&mut store, env, callback_signal::<Memory32>),
605        "thread_spawn" => Function::new_typed_with_env(&mut store, env, thread_spawn_v2::<Memory32>),
606        "thread_spawn_v2" => Function::new_typed_with_env(&mut store, env, thread_spawn_v2::<Memory32>),
607        "thread_sleep" => Function::new_typed_with_env(&mut store, env, thread_sleep::<Memory32>),
608        "thread_id" => Function::new_typed_with_env(&mut store, env, thread_id::<Memory32>),
609        "thread_signal" => Function::new_typed_with_env(&mut store, env, thread_signal),
610        "thread_join" => Function::new_typed_with_env(&mut store, env, thread_join::<Memory32>),
611        "thread_parallelism" => Function::new_typed_with_env(&mut store, env, thread_parallelism::<Memory32>),
612        "thread_exit" => Function::new_typed_with_env(&mut store, env, thread_exit),
613        "sched_yield" => Function::new_typed_with_env(&mut store, env, sched_yield::<Memory32>),
614        "stack_checkpoint" => Function::new_typed_with_env(&mut store, env, stack_checkpoint::<Memory32>),
615        "stack_restore" => Function::new_typed_with_env(&mut store, env, stack_restore::<Memory32>),
616        "context_create" => Function::new_typed_with_env(&mut store, env, context_create::<Memory32>),
617        "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) },
618        "context_destroy" => Function::new_typed_with_env(&mut store, env, context_destroy),
619        "futex_wait" => Function::new_typed_with_env(&mut store, env, futex_wait::<Memory32>),
620        "futex_wake" => Function::new_typed_with_env(&mut store, env, futex_wake::<Memory32>),
621        "futex_wake_all" => Function::new_typed_with_env(&mut store, env, futex_wake_all::<Memory32>),
622        "port_bridge" => Function::new_typed_with_env(&mut store, env, port_bridge::<Memory32>),
623        "port_unbridge" => Function::new_typed_with_env(&mut store, env, port_unbridge),
624        "port_dhcp_acquire" => Function::new_typed_with_env(&mut store, env, port_dhcp_acquire),
625        "port_addr_add" => Function::new_typed_with_env(&mut store, env, port_addr_add::<Memory32>),
626        "port_addr_remove" => Function::new_typed_with_env(&mut store, env, port_addr_remove::<Memory32>),
627        "port_addr_clear" => Function::new_typed_with_env(&mut store, env, port_addr_clear),
628        "port_addr_list" => Function::new_typed_with_env(&mut store, env, port_addr_list::<Memory32>),
629        "port_mac" => Function::new_typed_with_env(&mut store, env, port_mac::<Memory32>),
630        "port_gateway_set" => Function::new_typed_with_env(&mut store, env, port_gateway_set::<Memory32>),
631        "port_route_add" => Function::new_typed_with_env(&mut store, env, port_route_add::<Memory32>),
632        "port_route_remove" => Function::new_typed_with_env(&mut store, env, port_route_remove::<Memory32>),
633        "port_route_clear" => Function::new_typed_with_env(&mut store, env, port_route_clear),
634        "port_route_list" => Function::new_typed_with_env(&mut store, env, port_route_list::<Memory32>),
635        "sock_status" => Function::new_typed_with_env(&mut store, env, sock_status::<Memory32>),
636        "sock_addr_local" => Function::new_typed_with_env(&mut store, env, sock_addr_local::<Memory32>),
637        "sock_addr_peer" => Function::new_typed_with_env(&mut store, env, sock_addr_peer::<Memory32>),
638        "sock_open" => Function::new_typed_with_env(&mut store, env, sock_open::<Memory32>),
639        "sock_pair" => Function::new_typed_with_env(&mut store, env, sock_pair::<Memory32>),
640        "sock_set_opt_flag" => Function::new_typed_with_env(&mut store, env, sock_set_opt_flag),
641        "sock_get_opt_flag" => Function::new_typed_with_env(&mut store, env, sock_get_opt_flag::<Memory32>),
642        "sock_set_opt_time" => Function::new_typed_with_env(&mut store, env, sock_set_opt_time::<Memory32>),
643        "sock_get_opt_time" => Function::new_typed_with_env(&mut store, env, sock_get_opt_time::<Memory32>),
644        "sock_set_opt_size" => Function::new_typed_with_env(&mut store, env, sock_set_opt_size),
645        "sock_get_opt_size" => Function::new_typed_with_env(&mut store, env, sock_get_opt_size::<Memory32>),
646        "sock_join_multicast_v4" => Function::new_typed_with_env(&mut store, env, sock_join_multicast_v4::<Memory32>),
647        "sock_leave_multicast_v4" => Function::new_typed_with_env(&mut store, env, sock_leave_multicast_v4::<Memory32>),
648        "sock_join_multicast_v6" => Function::new_typed_with_env(&mut store, env, sock_join_multicast_v6::<Memory32>),
649        "sock_leave_multicast_v6" => Function::new_typed_with_env(&mut store, env, sock_leave_multicast_v6::<Memory32>),
650        "sock_bind" => Function::new_typed_with_env(&mut store, env, sock_bind::<Memory32>),
651        "sock_listen" => Function::new_typed_with_env(&mut store, env, sock_listen::<Memory32>),
652        "sock_accept" => Function::new_typed_with_env(&mut store, env, sock_accept_v2::<Memory32>),
653        "sock_accept_v2" => Function::new_typed_with_env(&mut store, env, sock_accept_v2::<Memory32>),
654        "sock_connect" => Function::new_typed_with_env(&mut store, env, sock_connect::<Memory32>),
655        "sock_recv" => Function::new_typed_with_env(&mut store, env, sock_recv::<Memory32>),
656        "sock_recv_from" => Function::new_typed_with_env(&mut store, env, sock_recv_from::<Memory32>),
657        "sock_send" => Function::new_typed_with_env(&mut store, env, sock_send::<Memory32>),
658        "sock_send_to" => Function::new_typed_with_env(&mut store, env, sock_send_to::<Memory32>),
659        "sock_send_file" => Function::new_typed_with_env(&mut store, env, sock_send_file::<Memory32>),
660        "sock_shutdown" => Function::new_typed_with_env(&mut store, env, sock_shutdown),
661        "resolve" => Function::new_typed_with_env(&mut store, env, resolve::<Memory32>),
662    };
663    namespace
664}
665
666fn wasix_exports_64(mut store: &mut impl AsStoreMut, env: &FunctionEnv<WasiEnv>) -> Exports {
667    let engine_supports_async = store.as_store_ref().engine().supports_async();
668
669    use syscalls::*;
670    let namespace = namespace! {
671        "args_get" => Function::new_typed_with_env(&mut store, env, args_get::<Memory64>),
672        "args_sizes_get" => Function::new_typed_with_env(&mut store, env, args_sizes_get::<Memory64>),
673        "call_dynamic" => Function::new_typed_with_env(&mut store, env, call_dynamic::<Memory64>),
674        "reflect_signature" => Function::new_typed_with_env(&mut store, env, reflect_signature::<Memory64>),
675        "clock_res_get" => Function::new_typed_with_env(&mut store, env, clock_res_get::<Memory64>),
676        "clock_time_get" => Function::new_typed_with_env(&mut store, env, clock_time_get::<Memory64>),
677        "clock_time_set" => Function::new_typed_with_env(&mut store, env, clock_time_set),
678        "closure_prepare" => Function::new_typed_with_env(&mut store, env, closure_prepare::<Memory64>),
679        "closure_allocate" => Function::new_typed_with_env(&mut store, env, closure_allocate::<Memory64>),
680        "closure_free" => Function::new_typed_with_env(&mut store, env, closure_free),
681        "environ_get" => Function::new_typed_with_env(&mut store, env, environ_get::<Memory64>),
682        "environ_sizes_get" => Function::new_typed_with_env(&mut store, env, environ_sizes_get::<Memory64>),
683        "epoll_create" => Function::new_typed_with_env(&mut store, env, epoll_create::<Memory64>),
684        "epoll_ctl" => Function::new_typed_with_env(&mut store, env, epoll_ctl::<Memory64>),
685        "epoll_wait" => Function::new_typed_with_env(&mut store, env, epoll_wait::<Memory64>),
686        "fd_advise" => Function::new_typed_with_env(&mut store, env, fd_advise),
687        "fd_allocate" => Function::new_typed_with_env(&mut store, env, fd_allocate),
688        "fd_close" => Function::new_typed_with_env(&mut store, env, fd_close),
689        "fd_datasync" => Function::new_typed_with_env(&mut store, env, fd_datasync),
690        "fd_fdstat_get" => Function::new_typed_with_env(&mut store, env, fd_fdstat_get::<Memory64>),
691        "fd_fdstat_set_flags" => Function::new_typed_with_env(&mut store, env, fd_fdstat_set_flags),
692        "fd_fdstat_set_rights" => Function::new_typed_with_env(&mut store, env, fd_fdstat_set_rights),
693        "fd_filestat_get" => Function::new_typed_with_env(&mut store, env, fd_filestat_get::<Memory64>),
694        "fd_filestat_set_size" => Function::new_typed_with_env(&mut store, env, fd_filestat_set_size),
695        "fd_filestat_set_times" => Function::new_typed_with_env(&mut store, env, fd_filestat_set_times),
696        "fd_pread" => Function::new_typed_with_env(&mut store, env, fd_pread::<Memory64>),
697        "fd_prestat_get" => Function::new_typed_with_env(&mut store, env, fd_prestat_get::<Memory64>),
698        "fd_prestat_dir_name" => Function::new_typed_with_env(&mut store, env, fd_prestat_dir_name::<Memory64>),
699        "fd_pwrite" => Function::new_typed_with_env(&mut store, env, fd_pwrite::<Memory64>),
700        "fd_read" => Function::new_typed_with_env(&mut store, env, fd_read::<Memory64>),
701        "fd_readdir" => Function::new_typed_with_env(&mut store, env, fd_readdir::<Memory64>),
702        "fd_renumber" => Function::new_typed_with_env(&mut store, env, fd_renumber),
703        "fd_dup" => Function::new_typed_with_env(&mut store, env, fd_dup::<Memory64>),
704        "fd_dup2" => Function::new_typed_with_env(&mut store, env, fd_dup2::<Memory64>),
705        "fd_fdflags_get" => Function::new_typed_with_env(&mut store, env, fd_fdflags_get::<Memory64>),
706        "fd_fdflags_set" => Function::new_typed_with_env(&mut store, env, fd_fdflags_set),
707        "fd_event" => Function::new_typed_with_env(&mut store, env, fd_event::<Memory64>),
708        "fd_seek" => Function::new_typed_with_env(&mut store, env, fd_seek::<Memory64>),
709        "fd_sync" => Function::new_typed_with_env(&mut store, env, fd_sync),
710        "fd_tell" => Function::new_typed_with_env(&mut store, env, fd_tell::<Memory64>),
711        "fd_write" => Function::new_typed_with_env(&mut store, env, fd_write::<Memory64>),
712        "fd_pipe" => Function::new_typed_with_env(&mut store, env, fd_pipe::<Memory64>),
713        "path_create_directory" => Function::new_typed_with_env(&mut store, env, path_create_directory::<Memory64>),
714        "path_filestat_get" => Function::new_typed_with_env(&mut store, env, path_filestat_get::<Memory64>),
715        "path_filestat_set_times" => Function::new_typed_with_env(&mut store, env, path_filestat_set_times::<Memory64>),
716        "path_link" => Function::new_typed_with_env(&mut store, env, path_link::<Memory64>),
717        "path_open" => Function::new_typed_with_env(&mut store, env, path_open::<Memory64>),
718        "path_open2" => Function::new_typed_with_env(&mut store, env, path_open2::<Memory64>),
719        "path_readlink" => Function::new_typed_with_env(&mut store, env, path_readlink::<Memory64>),
720        "path_remove_directory" => Function::new_typed_with_env(&mut store, env, path_remove_directory::<Memory64>),
721        "path_rename" => Function::new_typed_with_env(&mut store, env, path_rename::<Memory64>),
722        "path_symlink" => Function::new_typed_with_env(&mut store, env, path_symlink::<Memory64>),
723        "path_unlink_file" => Function::new_typed_with_env(&mut store, env, path_unlink_file::<Memory64>),
724        "poll_oneoff" => Function::new_typed_with_env(&mut store, env, poll_oneoff::<Memory64>),
725        "proc_exit" => Function::new_typed_with_env(&mut store, env, proc_exit::<Memory64>),
726        "proc_fork" => Function::new_typed_with_env(&mut store, env, proc_fork::<Memory64>),
727        "proc_fork_env" => Function::new_typed_with_env(&mut store, env, proc_fork_env::<Memory64>),
728        "proc_join" => Function::new_typed_with_env(&mut store, env, proc_join::<Memory64>),
729        "proc_signal" => Function::new_typed_with_env(&mut store, env, proc_signal),
730        "proc_signals_get" => Function::new_typed_with_env(&mut store, env, proc_signals_get::<Memory64>),
731        "proc_signals_sizes_get" => Function::new_typed_with_env(&mut store, env, proc_signals_sizes_get::<Memory64>),
732        "proc_exec" => Function::new_typed_with_env(&mut store, env, proc_exec::<Memory64>),
733        "proc_exec2" => Function::new_typed_with_env(&mut store, env, proc_exec2::<Memory64>),
734        "proc_exec3" => Function::new_typed_with_env(&mut store, env, proc_exec3::<Memory64>),
735        "proc_exec4" => Function::new_typed_with_env(&mut store, env, proc_exec4::<Memory64>),
736        "proc_exit2" => Function::new_typed_with_env(&mut store, env, proc_exit2::<Memory64>),
737        "proc_raise" => Function::new_typed_with_env(&mut store, env, proc_raise),
738        "proc_raise_interval" => Function::new_typed_with_env(&mut store, env, proc_raise_interval),
739        "proc_snapshot" => Function::new_typed_with_env(&mut store, env, proc_snapshot::<Memory64>),
740        "proc_spawn" => Function::new_typed_with_env(&mut store, env, proc_spawn::<Memory64>),
741        "proc_spawn2" => Function::new_typed_with_env(&mut store, env, proc_spawn2::<Memory64>),
742        "proc_spawn3" => Function::new_typed_with_env(&mut store, env, proc_spawn3::<Memory64>),
743        "proc_id" => Function::new_typed_with_env(&mut store, env, proc_id::<Memory64>),
744        "proc_parent" => Function::new_typed_with_env(&mut store, env, proc_parent::<Memory64>),
745        "random_get" => Function::new_typed_with_env(&mut store, env, random_get::<Memory64>),
746        "tty_get" => Function::new_typed_with_env(&mut store, env, tty_get::<Memory64>),
747        "tty_set" => Function::new_typed_with_env(&mut store, env, tty_set::<Memory64>),
748        "getcwd" => Function::new_typed_with_env(&mut store, env, getcwd::<Memory64>),
749        "chdir" => Function::new_typed_with_env(&mut store, env, chdir::<Memory64>),
750        "dl_invalid_handle" => Function::new_typed_with_env(&mut store, env, dl_invalid_handle),
751        "dlopen" => Function::new_typed_with_env(&mut store, env, dlopen::<Memory64>),
752        "dlsym" => Function::new_typed_with_env(&mut store, env, dlsym::<Memory64>),
753        "callback_signal" => Function::new_typed_with_env(&mut store, env, callback_signal::<Memory64>),
754        "thread_spawn" => Function::new_typed_with_env(&mut store, env, thread_spawn_v2::<Memory64>),
755        "thread_spawn_v2" => Function::new_typed_with_env(&mut store, env, thread_spawn_v2::<Memory64>),
756        "thread_sleep" => Function::new_typed_with_env(&mut store, env, thread_sleep::<Memory64>),
757        "thread_id" => Function::new_typed_with_env(&mut store, env, thread_id::<Memory64>),
758        "thread_signal" => Function::new_typed_with_env(&mut store, env, thread_signal),
759        "thread_join" => Function::new_typed_with_env(&mut store, env, thread_join::<Memory64>),
760        "thread_parallelism" => Function::new_typed_with_env(&mut store, env, thread_parallelism::<Memory64>),
761        "thread_exit" => Function::new_typed_with_env(&mut store, env, thread_exit),
762        "sched_yield" => Function::new_typed_with_env(&mut store, env, sched_yield::<Memory64>),
763        "stack_checkpoint" => Function::new_typed_with_env(&mut store, env, stack_checkpoint::<Memory64>),
764        "stack_restore" => Function::new_typed_with_env(&mut store, env, stack_restore::<Memory64>),
765        "context_create" => Function::new_typed_with_env(&mut store, env, context_create::<Memory64>),
766        "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) },
767        "context_destroy" => Function::new_typed_with_env(&mut store, env, context_destroy),
768        "futex_wait" => Function::new_typed_with_env(&mut store, env, futex_wait::<Memory64>),
769        "futex_wake" => Function::new_typed_with_env(&mut store, env, futex_wake::<Memory64>),
770        "futex_wake_all" => Function::new_typed_with_env(&mut store, env, futex_wake_all::<Memory64>),
771        "port_bridge" => Function::new_typed_with_env(&mut store, env, port_bridge::<Memory64>),
772        "port_unbridge" => Function::new_typed_with_env(&mut store, env, port_unbridge),
773        "port_dhcp_acquire" => Function::new_typed_with_env(&mut store, env, port_dhcp_acquire),
774        "port_addr_add" => Function::new_typed_with_env(&mut store, env, port_addr_add::<Memory64>),
775        "port_addr_remove" => Function::new_typed_with_env(&mut store, env, port_addr_remove::<Memory64>),
776        "port_addr_clear" => Function::new_typed_with_env(&mut store, env, port_addr_clear),
777        "port_addr_list" => Function::new_typed_with_env(&mut store, env, port_addr_list::<Memory64>),
778        "port_mac" => Function::new_typed_with_env(&mut store, env, port_mac::<Memory64>),
779        "port_gateway_set" => Function::new_typed_with_env(&mut store, env, port_gateway_set::<Memory64>),
780        "port_route_add" => Function::new_typed_with_env(&mut store, env, port_route_add::<Memory64>),
781        "port_route_remove" => Function::new_typed_with_env(&mut store, env, port_route_remove::<Memory64>),
782        "port_route_clear" => Function::new_typed_with_env(&mut store, env, port_route_clear),
783        "port_route_list" => Function::new_typed_with_env(&mut store, env, port_route_list::<Memory64>),
784        "sock_status" => Function::new_typed_with_env(&mut store, env, sock_status::<Memory64>),
785        "sock_addr_local" => Function::new_typed_with_env(&mut store, env, sock_addr_local::<Memory64>),
786        "sock_addr_peer" => Function::new_typed_with_env(&mut store, env, sock_addr_peer::<Memory64>),
787        "sock_open" => Function::new_typed_with_env(&mut store, env, sock_open::<Memory64>),
788        "sock_pair" => Function::new_typed_with_env(&mut store, env, sock_pair::<Memory64>),
789        "sock_set_opt_flag" => Function::new_typed_with_env(&mut store, env, sock_set_opt_flag),
790        "sock_get_opt_flag" => Function::new_typed_with_env(&mut store, env, sock_get_opt_flag::<Memory64>),
791        "sock_set_opt_time" => Function::new_typed_with_env(&mut store, env, sock_set_opt_time::<Memory64>),
792        "sock_get_opt_time" => Function::new_typed_with_env(&mut store, env, sock_get_opt_time::<Memory64>),
793        "sock_set_opt_size" => Function::new_typed_with_env(&mut store, env, sock_set_opt_size),
794        "sock_get_opt_size" => Function::new_typed_with_env(&mut store, env, sock_get_opt_size::<Memory64>),
795        "sock_join_multicast_v4" => Function::new_typed_with_env(&mut store, env, sock_join_multicast_v4::<Memory64>),
796        "sock_leave_multicast_v4" => Function::new_typed_with_env(&mut store, env, sock_leave_multicast_v4::<Memory64>),
797        "sock_join_multicast_v6" => Function::new_typed_with_env(&mut store, env, sock_join_multicast_v6::<Memory64>),
798        "sock_leave_multicast_v6" => Function::new_typed_with_env(&mut store, env, sock_leave_multicast_v6::<Memory64>),
799        "sock_bind" => Function::new_typed_with_env(&mut store, env, sock_bind::<Memory64>),
800        "sock_listen" => Function::new_typed_with_env(&mut store, env, sock_listen::<Memory64>),
801        "sock_accept" => Function::new_typed_with_env(&mut store, env, sock_accept_v2::<Memory64>),
802        "sock_accept_v2" => Function::new_typed_with_env(&mut store, env, sock_accept_v2::<Memory64>),
803        "sock_connect" => Function::new_typed_with_env(&mut store, env, sock_connect::<Memory64>),
804        "sock_recv" => Function::new_typed_with_env(&mut store, env, sock_recv::<Memory64>),
805        "sock_recv_from" => Function::new_typed_with_env(&mut store, env, sock_recv_from::<Memory64>),
806        "sock_send" => Function::new_typed_with_env(&mut store, env, sock_send::<Memory64>),
807        "sock_send_to" => Function::new_typed_with_env(&mut store, env, sock_send_to::<Memory64>),
808        "sock_send_file" => Function::new_typed_with_env(&mut store, env, sock_send_file::<Memory64>),
809        "sock_shutdown" => Function::new_typed_with_env(&mut store, env, sock_shutdown),
810        "resolve" => Function::new_typed_with_env(&mut store, env, resolve::<Memory64>),
811    };
812    namespace
813}
814
815// TODO: split function into two variants, one for JS and one for sys.
816// (this will make code less messy)
817fn import_object_for_all_wasi_versions(
818    _module: &wasmer::Module,
819    store: &mut impl AsStoreMut,
820    env: &FunctionEnv<WasiEnv>,
821) -> Imports {
822    let exports_wasi_generic = wasi_exports_generic(store, env);
823    let exports_wasi_unstable = wasi_unstable_exports(store, env);
824    let exports_wasi_snapshot_preview1 = wasi_snapshot_preview1_exports(store, env);
825    let exports_wasix_32v1 = wasix_exports_32(store, env);
826    let exports_wasix_64v1 = wasix_exports_64(store, env);
827
828    // Allowed due to JS feature flag complications.
829    #[allow(unused_mut)]
830    let mut imports = imports! {
831        "wasi" => exports_wasi_generic,
832        "wasi_unstable" => exports_wasi_unstable,
833        "wasi_snapshot_preview1" => exports_wasi_snapshot_preview1,
834        "wasix_32v1" => exports_wasix_32v1,
835        "wasix_64v1" => exports_wasix_64v1,
836    };
837
838    imports
839}
840
841/// Combines a state generating function with the import list for legacy WASI
842fn generate_import_object_snapshot0(
843    store: &mut impl AsStoreMut,
844    env: &FunctionEnv<WasiEnv>,
845) -> Imports {
846    let exports_unstable = wasi_unstable_exports(store, env);
847    imports! {
848        "wasi_unstable" => exports_unstable
849    }
850}
851
852fn generate_import_object_snapshot1(
853    store: &mut impl AsStoreMut,
854    env: &FunctionEnv<WasiEnv>,
855) -> Imports {
856    let exports_wasi_snapshot_preview1 = wasi_snapshot_preview1_exports(store, env);
857    imports! {
858        "wasi_snapshot_preview1" => exports_wasi_snapshot_preview1
859    }
860}
861
862/// Combines a state generating function with the import list for snapshot 1
863fn generate_import_object_wasix32_v1(
864    store: &mut impl AsStoreMut,
865    env: &FunctionEnv<WasiEnv>,
866) -> Imports {
867    let exports_wasix_32v1 = wasix_exports_32(store, env);
868    imports! {
869        "wasix_32v1" => exports_wasix_32v1
870    }
871}
872
873fn generate_import_object_wasix64_v1(
874    store: &mut impl AsStoreMut,
875    env: &FunctionEnv<WasiEnv>,
876) -> Imports {
877    let exports_wasix_64v1 = wasix_exports_64(store, env);
878    imports! {
879        "wasix_64v1" => exports_wasix_64v1
880    }
881}
882
883fn mem_error_to_wasi(err: MemoryAccessError) -> Errno {
884    match err {
885        MemoryAccessError::HeapOutOfBounds => Errno::Memviolation,
886        MemoryAccessError::Overflow => Errno::Overflow,
887        MemoryAccessError::NonUtf8String => Errno::Inval,
888        _ => Errno::Unknown,
889    }
890}
891
892/// Run a synchronous function that would normally be blocking.
893///
894/// When the `sys-thread` feature is enabled, this will call
895/// [`tokio::task::block_in_place()`]. Otherwise, it calls the function
896/// immediately.
897pub(crate) fn block_in_place<Ret>(thunk: impl FnOnce() -> Ret) -> Ret {
898    cfg_select! {
899        feature = "sys-thread" => {
900            tokio::task::block_in_place(thunk)
901        }
902        _ => {
903            thunk()
904        }
905    }
906}
907
908/// Spawns a new blocking task that runs the provided closure.
909///
910/// The closure is executed on a separate thread, allowing it to perform blocking operations
911/// without blocking the main thread. The closure is wrapped in a `Future` that resolves to the
912/// result of the closure's execution.
913pub(crate) async fn spawn_blocking<F, R>(f: F) -> Result<R, tokio::task::JoinError>
914where
915    F: FnOnce() -> R + Send + 'static,
916    R: Send + 'static,
917{
918    cfg_select! {
919        target_arch = "wasm32" => {
920            Ok(block_in_place(f))
921        }
922        _ => {
923            tokio::task::spawn_blocking(f).await
924        }
925    }
926}
927
928pub(crate) fn flatten_runtime_error(err: RuntimeError) -> RuntimeError {
929    let e_ref = err.downcast_ref::<WasiRuntimeError>();
930    match e_ref {
931        Some(WasiRuntimeError::Wasi(_)) => {
932            let Ok(WasiRuntimeError::Wasi(err)) = err.downcast::<WasiRuntimeError>() else {
933                unreachable!()
934            };
935            RuntimeError::user(Box::new(err))
936        }
937        Some(WasiRuntimeError::Runtime(_)) => {
938            let Ok(WasiRuntimeError::Runtime(err)) = err.downcast::<WasiRuntimeError>() else {
939                unreachable!()
940            };
941            flatten_runtime_error(err)
942        }
943        _ => err,
944    }
945}