1pub mod module_cache;
2pub mod package_loader;
3pub mod resolver;
4pub mod task_manager;
5
6use self::module_cache::CacheError;
7pub use self::task_manager::{SpawnType, VirtualTaskManager};
8use module_cache::HashedModuleData;
9use wasmer_types::{CompilationProgressCallback, ModuleHash};
10
11use std::{
12 borrow::Cow,
13 fmt,
14 ops::Deref,
15 sync::{Arc, Mutex},
16};
17
18use futures::future::BoxFuture;
19use virtual_mio::block_on;
20use virtual_net::{DynVirtualNetworking, VirtualNetworking};
21use wasmer::{Engine, Module, RuntimeError};
22use wasmer_wasix_types::wasi::ExitCode;
23
24#[cfg(feature = "journal")]
25use crate::journal::{DynJournal, DynReadableJournal};
26use crate::{
27 SpawnError, WasiTtyState,
28 bin_factory::BinaryPackageCommand,
29 http::{DynHttpClient, HttpClient},
30 os::TtyBridge,
31 runtime::{
32 module_cache::{
33 ModuleCache, ThreadLocalCache,
34 progress::{ModuleLoadProgress, ModuleLoadProgressReporter},
35 },
36 package_loader::{PackageLoader, UnsupportedPackageLoader},
37 resolver::{BackendSource, MultiSource, Source},
38 },
39};
40
41pub type MakeImportCallback = dyn Fn(&wasmer::Module, &mut wasmer::StoreMut) -> anyhow::Result<wasmer::Imports>
42 + Send
43 + Sync
44 + 'static;
45pub type ConfigureInstanceCallback = dyn Fn(
46 &wasmer::Module,
47 &mut wasmer::StoreMut,
48 &wasmer::Instance,
49 Option<&wasmer::Memory>,
50 ) -> anyhow::Result<()>
51 + Send
52 + Sync
53 + 'static;
54
55#[derive(Clone)]
56pub struct ImportCallback(pub Arc<MakeImportCallback>);
57
58impl fmt::Debug for ImportCallback {
59 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60 f.write_str("ImportCallback(..)")
61 }
62}
63
64#[derive(Clone)]
65pub struct InstanceCallback(pub Arc<ConfigureInstanceCallback>);
66
67impl fmt::Debug for InstanceCallback {
68 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
69 f.write_str("InstanceCallback(..)")
70 }
71}
72
73#[derive(Clone)]
74pub enum TaintReason {
75 UnknownWasiVersion,
76 NonZeroExitCode(ExitCode),
77 RuntimeError(RuntimeError),
78 DlSymbolResolutionFailed(String),
79}
80
81#[allow(clippy::large_enum_variant)]
88pub enum ModuleInput<'a> {
89 Bytes(Cow<'a, [u8]>),
91 Hashed(Cow<'a, HashedModuleData>),
93 Command(Cow<'a, BinaryPackageCommand>),
95}
96
97impl<'a> ModuleInput<'a> {
98 pub fn to_owned(&'a self) -> ModuleInput<'static> {
100 match self {
102 Self::Bytes(Cow::Borrowed(b)) => {
103 let v: Vec<u8> = (*b).to_owned();
104 let c: Cow<'static, [u8]> = Cow::from(v);
105 ModuleInput::Bytes(c)
106 }
107 Self::Bytes(Cow::Owned(b)) => ModuleInput::Bytes(Cow::Owned((*b).clone())),
108 Self::Hashed(Cow::Borrowed(h)) => ModuleInput::Hashed(Cow::Owned((*h).clone())),
109 Self::Hashed(Cow::Owned(h)) => ModuleInput::Hashed(Cow::Owned(h.clone())),
110 Self::Command(Cow::Borrowed(c)) => ModuleInput::Command(Cow::Owned((*c).clone())),
111 Self::Command(Cow::Owned(c)) => ModuleInput::Command(Cow::Owned(c.clone())),
112 }
113 }
114
115 pub fn hash(&self) -> ModuleHash {
119 match self {
120 Self::Bytes(b) => {
121 ModuleHash::new(b)
123 }
124 Self::Hashed(hashed) => *hashed.hash(),
125 Self::Command(cmd) => *cmd.hash(),
126 }
127 }
128
129 pub fn wasm(&self) -> &[u8] {
131 match self {
132 Self::Bytes(b) => b,
133 Self::Hashed(hashed) => hashed.wasm().as_ref(),
134 Self::Command(cmd) => cmd.atom_ref().as_ref(),
135 }
136 }
137
138 pub fn to_hashed(&self) -> HashedModuleData {
142 match self {
143 Self::Bytes(b) => HashedModuleData::new(b.as_ref()),
144 Self::Hashed(hashed) => hashed.as_ref().clone(),
145 Self::Command(cmd) => HashedModuleData::from_command(cmd),
146 }
147 }
148}
149
150#[allow(unused_variables)]
154pub trait Runtime
155where
156 Self: fmt::Debug,
157{
158 fn networking(&self) -> &DynVirtualNetworking;
160
161 fn task_manager(&self) -> &Arc<dyn VirtualTaskManager>;
163
164 fn package_loader(&self) -> Arc<dyn PackageLoader + Send + Sync> {
166 Arc::new(UnsupportedPackageLoader)
167 }
168
169 fn module_cache(&self) -> Arc<dyn ModuleCache + Send + Sync> {
171 Arc::new(ThreadLocalCache::default())
178 }
179
180 fn source(&self) -> Arc<dyn Source + Send + Sync>;
182
183 fn engine(&self) -> Engine {
185 Engine::default()
186 }
187
188 fn new_store(&self) -> wasmer::Store {
190 cfg_if::cfg_if! {
191 if #[cfg(feature = "sys")] {
192 wasmer::Store::new(self.engine())
193 } else {
194 wasmer::Store::default()
195 }
196 }
197 }
198
199 fn additional_imports(
205 &self,
206 _module: &wasmer::Module,
207 _store: &mut wasmer::StoreMut,
208 ) -> anyhow::Result<wasmer::Imports> {
209 Ok(wasmer::Imports::new())
210 }
211
212 fn configure_new_instance(
214 &self,
215 _module: &wasmer::Module,
216 _store: &mut wasmer::StoreMut,
217 _instance: &wasmer::Instance,
218 _imported_memory: Option<&wasmer::Memory>,
219 ) -> anyhow::Result<()> {
220 Ok(())
221 }
222
223 fn http_client(&self) -> Option<&DynHttpClient> {
225 None
226 }
227
228 fn tty(&self) -> Option<&(dyn TtyBridge + Send + Sync)> {
230 None
231 }
232
233 fn resolve_module<'a>(
240 &'a self,
241 input: ModuleInput<'a>,
242 engine: Option<&Engine>,
243 on_progress: Option<ModuleLoadProgressReporter>,
244 ) -> BoxFuture<'a, Result<Module, SpawnError>> {
245 let data = input.to_hashed();
246
247 let engine = if let Some(e) = engine {
248 e.clone()
249 } else {
250 match &input {
251 ModuleInput::Bytes(_) => self.engine(),
252 ModuleInput::Hashed(_) => self.engine(),
253 ModuleInput::Command(cmd) => self.engine(),
254 }
255 };
256
257 let module_cache = self.module_cache();
258
259 let task = async move { load_module(&engine, &module_cache, input, on_progress).await };
260 Box::pin(task)
261 }
262
263 fn resolve_module_sync(
265 &self,
266 input: ModuleInput<'_>,
267 engine: Option<&Engine>,
268 on_progress: Option<ModuleLoadProgressReporter>,
269 ) -> Result<Module, SpawnError> {
270 block_on(self.resolve_module(input, engine, on_progress))
271 }
272
273 #[deprecated(since = "0.601.0", note = "Use `resolve_module` instead")]
280 fn load_command_module(
281 &self,
282 cmd: &BinaryPackageCommand,
283 ) -> BoxFuture<'_, Result<Module, SpawnError>> {
284 self.resolve_module(ModuleInput::Command(Cow::Owned(cmd.clone())), None, None)
285 }
286
287 #[deprecated(since = "0.601.0", note = "Use `resolve_module_sync` instead")]
289 fn load_command_module_sync(&self, cmd: &BinaryPackageCommand) -> Result<Module, SpawnError> {
290 block_on(self.resolve_module(ModuleInput::Command(Cow::Borrowed(cmd)), None, None))
291 }
292
293 #[deprecated(since = "0.601.0", note = "Use `resolve_module` instead")]
297 fn load_module<'a>(&'a self, wasm: &'a [u8]) -> BoxFuture<'a, Result<Module, SpawnError>> {
298 self.resolve_module(ModuleInput::Bytes(Cow::Borrowed(wasm)), None, None)
299 }
300
301 #[deprecated(
303 since = "0.601.0",
304 note = "Use `load_command_module` or `load_hashed_module` instead - this method can have high overhead"
305 )]
306 fn load_module_sync(&self, wasm: &[u8]) -> Result<Module, SpawnError> {
307 block_on(self.resolve_module(ModuleInput::Bytes(Cow::Borrowed(wasm)), None, None))
308 }
309
310 fn load_hashed_module(
314 &self,
315 module: HashedModuleData,
316 engine: Option<&Engine>,
317 ) -> BoxFuture<'_, Result<Module, SpawnError>> {
318 self.resolve_module(ModuleInput::Hashed(Cow::Owned(module)), engine, None)
319 }
320
321 fn load_hashed_module_sync(
323 &self,
324 wasm: HashedModuleData,
325 engine: Option<&Engine>,
326 ) -> Result<Module, SpawnError> {
327 block_on(self.resolve_module(ModuleInput::Hashed(Cow::Owned(wasm)), engine, None))
328 }
329
330 fn on_taint(&self, _reason: TaintReason) {}
333
334 #[cfg(feature = "journal")]
337 fn read_only_journals<'a>(&'a self) -> Box<dyn Iterator<Item = Arc<DynReadableJournal>> + 'a> {
338 Box::new(std::iter::empty())
339 }
340
341 #[cfg(feature = "journal")]
343 fn writable_journals<'a>(&'a self) -> Box<dyn Iterator<Item = Arc<DynJournal>> + 'a> {
344 Box::new(std::iter::empty())
345 }
346
347 #[cfg(feature = "journal")]
350 fn active_journal(&self) -> Option<&'_ DynJournal> {
351 None
352 }
353}
354
355pub type DynRuntime = dyn Runtime + Send + Sync;
356
357#[tracing::instrument(level = "debug", skip_all)]
362pub async fn load_module(
363 engine: &Engine,
364 module_cache: &(dyn ModuleCache + Send + Sync),
365 input: ModuleInput<'_>,
366 on_progress: Option<ModuleLoadProgressReporter>,
367) -> Result<Module, crate::SpawnError> {
368 let wasm_hash = input.hash();
369
370 let result = if let Some(on_progress) = &on_progress {
371 module_cache
372 .load_with_progress(wasm_hash, engine, on_progress.clone())
373 .await
374 } else {
375 module_cache.load(wasm_hash, engine).await
376 };
377
378 match result {
379 Ok(module) => return Ok(module),
380 Err(CacheError::NotFound) => {}
381 Err(other) => {
382 tracing::warn!(
383 %wasm_hash,
384 error=&other as &dyn std::error::Error,
385 "Unable to load the cached module",
386 );
387 }
388 }
389
390 let res = if let Some(progress) = on_progress {
391 #[allow(unused_variables)]
392 let p = CompilationProgressCallback::new(move |p| {
393 progress.notify(ModuleLoadProgress::CompilingModule(p))
394 });
395 #[cfg(feature = "sys-default")]
396 {
397 if engine.is_sys() {
398 use wasmer::sys::NativeEngineExt;
399 engine.new_module_with_progress(input.wasm(), p)
400 } else {
401 Module::new(&engine, input.wasm())
402 }
403 }
404 #[cfg(not(feature = "sys-default"))]
405 {
406 Module::new(&engine, input.wasm())
407 }
408 } else {
409 Module::new(&engine, input.wasm())
410 };
411
412 let module = res.map_err(|err| crate::SpawnError::CompileError {
413 module_hash: wasm_hash,
414 error: err,
415 })?;
416
417 if let Err(e) = module_cache.save(wasm_hash, engine, &module).await {
419 tracing::warn!(
420 %wasm_hash,
421 error=&e as &dyn std::error::Error,
422 "Unable to cache the compiled module",
423 );
424 }
425
426 Ok(module)
427}
428
429#[derive(Debug, Default)]
430pub struct DefaultTty {
431 state: Mutex<WasiTtyState>,
432}
433
434impl TtyBridge for DefaultTty {
435 fn reset(&self) {
436 let mut state = self.state.lock().unwrap();
437 state.echo = false;
438 state.line_buffered = false;
439 state.line_feeds = false
440 }
441
442 fn tty_get(&self) -> WasiTtyState {
443 let state = self.state.lock().unwrap();
444 state.clone()
445 }
446
447 fn tty_set(&self, tty_state: WasiTtyState) {
448 let mut state = self.state.lock().unwrap();
449 *state = tty_state;
450 }
451}
452
453#[derive(Debug, Clone)]
454pub struct PluggableRuntime {
455 pub rt: Arc<dyn VirtualTaskManager>,
456 pub networking: DynVirtualNetworking,
457 pub http_client: Option<DynHttpClient>,
458 pub package_loader: Arc<dyn PackageLoader + Send + Sync>,
459 pub source: Arc<dyn Source + Send + Sync>,
460 pub engine: Engine,
461 pub module_cache: Arc<dyn ModuleCache + Send + Sync>,
462 pub tty: Option<Arc<dyn TtyBridge + Send + Sync>>,
463 #[cfg(feature = "journal")]
464 pub read_only_journals: Vec<Arc<DynReadableJournal>>,
465 #[cfg(feature = "journal")]
466 pub writable_journals: Vec<Arc<DynJournal>>,
467 pub additional_imports: Vec<ImportCallback>,
468 pub instance_callbacks: Vec<InstanceCallback>,
469}
470
471impl PluggableRuntime {
472 pub fn new(rt: Arc<dyn VirtualTaskManager>) -> Self {
473 cfg_if::cfg_if! {
475 if #[cfg(feature = "host-vnet")] {
476 let networking = Arc::new(virtual_net::host::LocalNetworking::default());
477 } else {
478 let networking = Arc::new(virtual_net::UnsupportedVirtualNetworking::default());
479 }
480 }
481 let http_client =
482 crate::http::default_http_client().map(|client| Arc::new(client) as DynHttpClient);
483
484 let loader = UnsupportedPackageLoader;
485
486 let mut source = MultiSource::default();
487 if let Some(client) = &http_client {
488 source.add_source(BackendSource::new(
489 BackendSource::WASMER_PROD_ENDPOINT.parse().unwrap(),
490 client.clone(),
491 ));
492 }
493
494 Self {
495 rt,
496 networking,
497 http_client,
498 engine: Default::default(),
499 tty: None,
500 source: Arc::new(source),
501 package_loader: Arc::new(loader),
502 module_cache: Arc::new(module_cache::in_memory()),
503 #[cfg(feature = "journal")]
504 read_only_journals: Vec::new(),
505 #[cfg(feature = "journal")]
506 writable_journals: Vec::new(),
507 additional_imports: Vec::new(),
508 instance_callbacks: Vec::new(),
509 }
510 }
511
512 pub fn set_networking_implementation<I>(&mut self, net: I) -> &mut Self
513 where
514 I: VirtualNetworking + Sync,
515 {
516 self.networking = Arc::new(net);
517 self
518 }
519
520 pub fn set_engine(&mut self, engine: Engine) -> &mut Self {
521 self.engine = engine;
522 self
523 }
524
525 pub fn set_tty(&mut self, tty: Arc<dyn TtyBridge + Send + Sync>) -> &mut Self {
526 self.tty = Some(tty);
527 self
528 }
529
530 pub fn set_module_cache(
531 &mut self,
532 module_cache: impl ModuleCache + Send + Sync + 'static,
533 ) -> &mut Self {
534 self.module_cache = Arc::new(module_cache);
535 self
536 }
537
538 pub fn set_source(&mut self, source: impl Source + Send + 'static) -> &mut Self {
539 self.source = Arc::new(source);
540 self
541 }
542
543 pub fn set_package_loader(
544 &mut self,
545 package_loader: impl PackageLoader + 'static,
546 ) -> &mut Self {
547 self.package_loader = Arc::new(package_loader);
548 self
549 }
550
551 pub fn set_http_client(
552 &mut self,
553 client: impl HttpClient + Send + Sync + 'static,
554 ) -> &mut Self {
555 self.http_client = Some(Arc::new(client));
556 self
557 }
558
559 #[cfg(feature = "journal")]
560 pub fn add_read_only_journal(&mut self, journal: Arc<DynReadableJournal>) -> &mut Self {
561 self.read_only_journals.push(journal);
562 self
563 }
564
565 #[cfg(feature = "journal")]
566 pub fn add_writable_journal(&mut self, journal: Arc<DynJournal>) -> &mut Self {
567 self.writable_journals.push(journal);
568 self
569 }
570
571 pub fn with_additional_imports(
572 &mut self,
573 imports: impl Fn(&wasmer::Module, &mut wasmer::StoreMut) -> anyhow::Result<wasmer::Imports>
574 + Send
575 + Sync
576 + 'static,
577 ) -> &mut Self {
578 self.additional_imports
579 .push(ImportCallback(Arc::new(imports)));
580 self
581 }
582
583 pub fn with_instance_setup(
584 &mut self,
585 callback: impl Fn(
586 &wasmer::Module,
587 &mut wasmer::StoreMut,
588 &wasmer::Instance,
589 Option<&wasmer::Memory>,
590 ) -> anyhow::Result<()>
591 + Send
592 + Sync
593 + 'static,
594 ) -> &mut Self {
595 self.instance_callbacks
596 .push(InstanceCallback(Arc::new(callback)));
597 self
598 }
599}
600
601impl Runtime for PluggableRuntime {
602 fn networking(&self) -> &DynVirtualNetworking {
603 &self.networking
604 }
605
606 fn http_client(&self) -> Option<&DynHttpClient> {
607 self.http_client.as_ref()
608 }
609
610 fn package_loader(&self) -> Arc<dyn PackageLoader + Send + Sync> {
611 Arc::clone(&self.package_loader)
612 }
613
614 fn source(&self) -> Arc<dyn Source + Send + Sync> {
615 Arc::clone(&self.source)
616 }
617
618 fn engine(&self) -> Engine {
619 self.engine.clone()
620 }
621
622 fn new_store(&self) -> wasmer::Store {
623 wasmer::Store::new(self.engine.clone())
624 }
625
626 fn task_manager(&self) -> &Arc<dyn VirtualTaskManager> {
627 &self.rt
628 }
629
630 fn tty(&self) -> Option<&(dyn TtyBridge + Send + Sync)> {
631 self.tty.as_deref()
632 }
633
634 fn module_cache(&self) -> Arc<dyn ModuleCache + Send + Sync> {
635 self.module_cache.clone()
636 }
637
638 fn additional_imports(
639 &self,
640 module: &wasmer::Module,
641 store: &mut wasmer::StoreMut,
642 ) -> anyhow::Result<wasmer::Imports> {
643 let mut imports = wasmer::Imports::new();
644 for cb in &self.additional_imports {
645 imports.extend(&(*(cb.0))(module, store)?);
646 }
647 Ok(imports)
648 }
649
650 fn configure_new_instance(
651 &self,
652 module: &wasmer::Module,
653 store: &mut wasmer::StoreMut,
654 instance: &wasmer::Instance,
655 imported_memory: Option<&wasmer::Memory>,
656 ) -> anyhow::Result<()> {
657 for cb in &self.instance_callbacks {
658 (*(cb.0))(module, store, instance, imported_memory)?;
659 }
660 Ok(())
661 }
662
663 #[cfg(feature = "journal")]
664 fn read_only_journals<'a>(&'a self) -> Box<dyn Iterator<Item = Arc<DynReadableJournal>> + 'a> {
665 Box::new(self.read_only_journals.iter().cloned())
666 }
667
668 #[cfg(feature = "journal")]
669 fn writable_journals<'a>(&'a self) -> Box<dyn Iterator<Item = Arc<DynJournal>> + 'a> {
670 Box::new(self.writable_journals.iter().cloned())
671 }
672
673 #[cfg(feature = "journal")]
674 fn active_journal(&self) -> Option<&DynJournal> {
675 self.writable_journals.iter().last().map(|a| a.as_ref())
676 }
677}
678
679#[derive(Clone, Debug)]
682pub struct OverriddenRuntime {
683 inner: Arc<DynRuntime>,
684 task_manager: Option<Arc<dyn VirtualTaskManager>>,
685 networking: Option<DynVirtualNetworking>,
686 http_client: Option<DynHttpClient>,
687 package_loader: Option<Arc<dyn PackageLoader + Send + Sync>>,
688 source: Option<Arc<dyn Source + Send + Sync>>,
689 engine: Option<Engine>,
690 module_cache: Option<Arc<dyn ModuleCache + Send + Sync>>,
691 tty: Option<Arc<dyn TtyBridge + Send + Sync>>,
692 additional_imports: Vec<ImportCallback>,
693 instance_callbacks: Vec<InstanceCallback>,
694 #[cfg(feature = "journal")]
695 pub read_only_journals: Option<Vec<Arc<DynReadableJournal>>>,
696 #[cfg(feature = "journal")]
697 pub writable_journals: Option<Vec<Arc<DynJournal>>>,
698}
699
700impl OverriddenRuntime {
701 pub fn new(inner: Arc<DynRuntime>) -> Self {
702 Self {
703 inner,
704 task_manager: None,
705 networking: None,
706 http_client: None,
707 package_loader: None,
708 source: None,
709 engine: None,
710 module_cache: None,
711 tty: None,
712 additional_imports: Vec::new(),
713 instance_callbacks: Vec::new(),
714 #[cfg(feature = "journal")]
715 read_only_journals: None,
716 #[cfg(feature = "journal")]
717 writable_journals: None,
718 }
719 }
720
721 pub fn with_task_manager(mut self, task_manager: Arc<dyn VirtualTaskManager>) -> Self {
722 self.task_manager.replace(task_manager);
723 self
724 }
725
726 pub fn with_networking(mut self, networking: DynVirtualNetworking) -> Self {
727 self.networking.replace(networking);
728 self
729 }
730
731 pub fn with_http_client(mut self, http_client: DynHttpClient) -> Self {
732 self.http_client.replace(http_client);
733 self
734 }
735
736 pub fn with_package_loader(
737 mut self,
738 package_loader: Arc<dyn PackageLoader + Send + Sync>,
739 ) -> Self {
740 self.package_loader.replace(package_loader);
741 self
742 }
743
744 pub fn with_source(mut self, source: Arc<dyn Source + Send + Sync>) -> Self {
745 self.source.replace(source);
746 self
747 }
748
749 pub fn with_engine(mut self, engine: Engine) -> Self {
750 self.engine.replace(engine);
751 self
752 }
753
754 pub fn with_module_cache(mut self, module_cache: Arc<dyn ModuleCache + Send + Sync>) -> Self {
755 self.module_cache.replace(module_cache);
756 self
757 }
758
759 pub fn with_tty(mut self, tty: Arc<dyn TtyBridge + Send + Sync>) -> Self {
760 self.tty.replace(tty);
761 self
762 }
763
764 pub fn with_additional_imports(
765 mut self,
766 imports: impl Fn(&wasmer::Module, &mut wasmer::StoreMut) -> anyhow::Result<wasmer::Imports>
767 + Send
768 + Sync
769 + 'static,
770 ) -> Self {
771 self.additional_imports
772 .push(ImportCallback(Arc::new(imports)));
773 self
774 }
775
776 pub fn with_instance_setup(
777 mut self,
778 callback: impl Fn(
779 &wasmer::Module,
780 &mut wasmer::StoreMut,
781 &wasmer::Instance,
782 Option<&wasmer::Memory>,
783 ) -> anyhow::Result<()>
784 + Send
785 + Sync
786 + 'static,
787 ) -> Self {
788 self.instance_callbacks
789 .push(InstanceCallback(Arc::new(callback)));
790 self
791 }
792
793 #[cfg(feature = "journal")]
794 pub fn with_read_only_journals(mut self, journals: Vec<Arc<DynReadableJournal>>) -> Self {
795 self.read_only_journals.replace(journals);
796 self
797 }
798
799 #[cfg(feature = "journal")]
800 pub fn with_writable_journals(mut self, journals: Vec<Arc<DynJournal>>) -> Self {
801 self.writable_journals.replace(journals);
802 self
803 }
804}
805
806impl Runtime for OverriddenRuntime {
807 fn networking(&self) -> &DynVirtualNetworking {
808 if let Some(net) = self.networking.as_ref() {
809 net
810 } else {
811 self.inner.networking()
812 }
813 }
814
815 fn task_manager(&self) -> &Arc<dyn VirtualTaskManager> {
816 if let Some(rt) = self.task_manager.as_ref() {
817 rt
818 } else {
819 self.inner.task_manager()
820 }
821 }
822
823 fn source(&self) -> Arc<dyn Source + Send + Sync> {
824 if let Some(source) = self.source.clone() {
825 source
826 } else {
827 self.inner.source()
828 }
829 }
830
831 fn package_loader(&self) -> Arc<dyn PackageLoader + Send + Sync> {
832 if let Some(loader) = self.package_loader.clone() {
833 loader
834 } else {
835 self.inner.package_loader()
836 }
837 }
838
839 fn module_cache(&self) -> Arc<dyn ModuleCache + Send + Sync> {
840 if let Some(cache) = self.module_cache.clone() {
841 cache
842 } else {
843 self.inner.module_cache()
844 }
845 }
846
847 fn engine(&self) -> Engine {
848 if let Some(engine) = self.engine.clone() {
849 engine
850 } else {
851 self.inner.engine()
852 }
853 }
854
855 fn new_store(&self) -> wasmer::Store {
856 if let Some(engine) = self.engine.clone() {
857 wasmer::Store::new(engine)
858 } else {
859 self.inner.new_store()
860 }
861 }
862
863 fn additional_imports(
864 &self,
865 module: &wasmer::Module,
866 store: &mut wasmer::StoreMut,
867 ) -> anyhow::Result<wasmer::Imports> {
868 let mut imports = self.inner.additional_imports(module, store)?;
869 for cb in &self.additional_imports {
870 imports.extend(&(*(cb.0))(module, store)?);
871 }
872 Ok(imports)
873 }
874
875 fn configure_new_instance(
876 &self,
877 module: &wasmer::Module,
878 store: &mut wasmer::StoreMut,
879 instance: &wasmer::Instance,
880 imported_memory: Option<&wasmer::Memory>,
881 ) -> anyhow::Result<()> {
882 self.inner
883 .configure_new_instance(module, store, instance, imported_memory)?;
884 for cb in &self.instance_callbacks {
885 (*(cb.0))(module, store, instance, imported_memory)?;
886 }
887 Ok(())
888 }
889
890 fn http_client(&self) -> Option<&DynHttpClient> {
891 if let Some(client) = self.http_client.as_ref() {
892 Some(client)
893 } else {
894 self.inner.http_client()
895 }
896 }
897
898 fn tty(&self) -> Option<&(dyn TtyBridge + Send + Sync)> {
899 if let Some(tty) = self.tty.as_ref() {
900 Some(tty.deref())
901 } else {
902 self.inner.tty()
903 }
904 }
905
906 #[cfg(feature = "journal")]
907 fn read_only_journals<'a>(&'a self) -> Box<dyn Iterator<Item = Arc<DynReadableJournal>> + 'a> {
908 if let Some(journals) = self.read_only_journals.as_ref() {
909 Box::new(journals.iter().cloned())
910 } else {
911 self.inner.read_only_journals()
912 }
913 }
914
915 #[cfg(feature = "journal")]
916 fn writable_journals<'a>(&'a self) -> Box<dyn Iterator<Item = Arc<DynJournal>> + 'a> {
917 if let Some(journals) = self.writable_journals.as_ref() {
918 Box::new(journals.iter().cloned())
919 } else {
920 self.inner.writable_journals()
921 }
922 }
923
924 #[cfg(feature = "journal")]
925 fn active_journal(&self) -> Option<&'_ DynJournal> {
926 if let Some(journals) = self.writable_journals.as_ref() {
927 journals.iter().last().map(|a| a.as_ref())
928 } else {
929 self.inner.active_journal()
930 }
931 }
932}