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