1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#[cfg(target_arch = "wasm32")]
pub mod browser;
#[cfg(feature = "wasmtime-host")]
pub mod component;
#[cfg(feature = "native-host")]
pub mod native;
mod wasi_limits;
use crate::compiled::{Code, CompiledModule};
use crate::load::module_definition_from_parts;
use crate::{engine::EngineRef, module::Module, schema::module::low::ModuleDefinition};
use derive_more::{Display, From};
use uuid::Uuid;
#[derive(Debug, Display, From, Clone)]
pub enum LoadModuleError {
MalformedExecutable,
Internal(String),
}
impl std::error::Error for LoadModuleError {}
#[derive(Debug, Display, From)]
pub enum UnloadModuleError {
ModuleNotFound,
Internal(String),
}
impl std::error::Error for UnloadModuleError {}
use crate::limits::GuestLimits;
pub trait Executor {
fn set_engine(&mut self, engine: EngineRef);
fn name(&self) -> &'static str;
fn load_module(
&mut self,
module_definition: ModuleDefinition,
) -> Result<Box<dyn Module>, LoadModuleError>;
/// Instantiate `module`, compiled ahead by [`CompiledModule::new`] for the
/// executor its header names — this one.
///
/// The default serves an executor that loads its executable as it is: it
/// hands the module's bytes to [`load_module`](Self::load_module), and
/// refuses a module compiled for the component executor. The component
/// executors override it to instantiate the compiled code.
fn load_compiled_module(
&mut self,
module: &CompiledModule,
) -> Result<Box<dyn Module>, LoadModuleError> {
match &module.code {
Code::Executable(executable) => self.load_module(module_definition_from_parts(
module.header.clone(),
executable.as_ref().into(),
)),
#[allow(unreachable_patterns)]
_ => Err(LoadModuleError::Internal(format!(
"the {} executor cannot instantiate a module compiled for the component \
executor",
self.name()
))),
}
}
/// Whether this executor loads a module compiled ahead by
/// [`CompiledModule::new`] as it loads its bytes. The engine then compiles
/// a module loaded from its bytes first, and loads it compiled, so that
/// compiling it takes none of its load's time ([`crate::limits`]). The
/// default, `false`, keeps an executor's modules loaded from their bytes
/// through [`load_module_limited`](Self::load_module_limited); the
/// wasmtime component executor answers `true`.
fn loads_compiled_modules(&self) -> bool {
false
}
/// Load `module_definition` under `limits`, the memory and time its
/// guest may spend ([`crate::limits`]). The engine loads every module
/// that is not compiled ahead through this; the default loads it as
/// [`load_module`](Self::load_module) does, unbounded. The wasmtime
/// executors override it to bound the instance.
fn load_module_limited(
&mut self,
module_definition: ModuleDefinition,
limits: GuestLimits,
) -> Result<Box<dyn Module>, LoadModuleError> {
let _ = limits;
self.load_module(module_definition)
}
/// [`load_compiled_module`](Self::load_compiled_module) under `limits`,
/// as [`load_module_limited`](Self::load_module_limited) is
/// [`load_module`](Self::load_module) under them.
fn load_compiled_module_limited(
&mut self,
module: &CompiledModule,
limits: GuestLimits,
) -> Result<Box<dyn Module>, LoadModuleError> {
let _ = limits;
self.load_compiled_module(module)
}
fn unload_module(&mut self, module_id: Uuid) -> Result<(), UnloadModuleError>;
/// Whether the engine may drop one of this executor's modules while it
/// runs — to reload or unload it ([`Engine::reload_module`],
/// [`Engine::unload_module`]). The engine owns each module's instance, so
/// dropping it is the unload. An executor whose modules cannot be dropped
/// safely while the process runs says no, and the engine keeps them.
///
/// [`Engine::reload_module`]: crate::engine::Engine::reload_module
/// [`Engine::unload_module`]: crate::engine::Engine::unload_module
fn can_unload(&self) -> bool {
true
}
}