shape_vm/
configuration.rs1use std::collections::{HashMap, HashSet};
7use std::sync::Arc;
8use std::sync::atomic::AtomicU8;
9
10pub struct BytecodeExecutor {
15 pub(crate) extensions: Vec<shape_runtime::module_exports::ModuleExports>,
17 pub(crate) virtual_modules: HashMap<String, String>,
19 pub(crate) compiled_module_paths: HashSet<String>,
21 pub(crate) interrupt: Arc<AtomicU8>,
23 pub(crate) bytecode_cache: Option<crate::bytecode_cache::BytecodeCache>,
25 pub(crate) dependency_paths: HashMap<String, std::path::PathBuf>,
27 pub(crate) native_resolution_context:
29 Option<shape_runtime::native_resolution::NativeResolutionSet>,
30 pub(crate) root_package_key: Option<String>,
32 pub(crate) module_loader: Option<shape_runtime::module_loader::ModuleLoader>,
35 pub(crate) permission_set: Option<shape_abi_v1::PermissionSet>,
39 pub allow_internal_builtins: bool,
42}
43
44impl Default for BytecodeExecutor {
45 fn default() -> Self {
46 Self::new()
47 }
48}
49
50impl BytecodeExecutor {
51 pub fn new() -> Self {
53 let mut executor = Self {
54 extensions: Vec::new(),
55 virtual_modules: HashMap::new(),
56 compiled_module_paths: HashSet::new(),
57 interrupt: Arc::new(AtomicU8::new(0)),
58 bytecode_cache: None,
59 dependency_paths: HashMap::new(),
60 native_resolution_context: None,
61 root_package_key: None,
62 module_loader: None,
63 permission_set: None,
64 allow_internal_builtins: false,
65 };
66 executor.register_stdlib_modules();
67
68 let mut loader = shape_runtime::module_loader::ModuleLoader::new();
71 executor.register_extension_artifacts_in_loader(&mut loader);
72 executor.module_loader = Some(loader);
73
74 executor
75 }
76
77 fn register_stdlib_modules(&mut self) {
80 self.extensions
82 .extend(shape_runtime::stdlib::all_stdlib_modules());
83 self.extensions
85 .push(crate::executor::state_builtins::create_state_module());
86 self.extensions
87 .push(crate::executor::create_transport_module_exports());
88 self.extensions
89 .push(crate::executor::create_remote_module_exports());
90 }
91
92 pub fn register_extension(&mut self, module: shape_runtime::module_exports::ModuleExports) {
96 let module_name = module.name.clone();
100 for artifact in &module.module_artifacts {
101 let Some(source) = artifact.source.as_ref() else {
102 continue;
103 };
104 let module_path = artifact.module_path.clone();
105 self.virtual_modules
106 .entry(module_path)
107 .or_insert_with(|| source.clone());
108 }
109
110 for (_filename, source) in &module.shape_sources {
113 self.virtual_modules
114 .entry(module_name.clone())
115 .or_insert_with(|| source.clone());
116 }
117 self.extensions.push(module);
118 }
119
120 pub fn module_schemas(&self) -> Vec<shape_runtime::extensions::ParsedModuleSchema> {
122 self.extensions
123 .iter()
124 .map(|module| {
125 let mut functions = Vec::with_capacity(module.schemas.len());
126 for (name, schema) in &module.schemas {
127 if !module.is_export_public_surface(name, false) {
128 continue;
129 }
130 functions.push(shape_runtime::extensions::ParsedModuleFunction {
131 name: name.clone(),
132 description: schema.description.clone(),
133 params: schema.params.iter().map(|p| p.type_name.clone()).collect(),
134 return_type: schema.return_type.clone(),
135 });
136 }
137 let artifacts = module
138 .module_artifacts
139 .iter()
140 .map(|artifact| shape_runtime::extensions::ParsedModuleArtifact {
141 module_path: artifact.module_path.clone(),
142 source: artifact.source.clone(),
143 compiled: artifact.compiled.clone(),
144 })
145 .collect();
146 shape_runtime::extensions::ParsedModuleSchema {
147 module_name: module.name.clone(),
148 functions,
149 artifacts,
150 }
151 })
152 .collect()
153 }
154
155 pub fn enable_bytecode_cache(&mut self) -> bool {
159 match crate::bytecode_cache::BytecodeCache::new() {
160 Some(cache) => {
161 self.bytecode_cache = Some(cache);
162 true
163 }
164 None => false,
165 }
166 }
167
168 pub fn set_interrupt(&mut self, flag: Arc<AtomicU8>) {
170 self.interrupt = flag;
171 }
172
173 pub fn set_dependency_paths(&mut self, paths: HashMap<String, std::path::PathBuf>) {
178 self.dependency_paths = paths.clone();
179 if let Some(loader) = self.module_loader.as_mut() {
180 loader.set_dependency_paths(paths);
181 }
182 }
183
184 pub fn set_native_resolution_context(
186 &mut self,
187 resolutions: shape_runtime::native_resolution::NativeResolutionSet,
188 root_package_key: Option<String>,
189 ) {
190 self.native_resolution_context = Some(resolutions);
191 self.root_package_key = root_package_key;
192 }
193
194 pub fn clear_native_resolution_context(&mut self) {
196 self.native_resolution_context = None;
197 self.root_package_key = None;
198 }
199
200 pub fn set_permission_set(&mut self, permissions: Option<shape_abi_v1::PermissionSet>) {
205 self.permission_set = permissions;
206 }
207}
208
209#[cfg(test)]
210mod tests {
211 use super::*;
212
213 #[test]
214 fn test_new_executor_has_module_loader() {
215 let executor = BytecodeExecutor::new();
216 assert!(
217 executor.module_loader.is_some(),
218 "new() should initialize module_loader"
219 );
220 }
221}