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}
36
37impl Default for BytecodeExecutor {
38 fn default() -> Self {
39 Self::new()
40 }
41}
42
43impl BytecodeExecutor {
44 pub fn new() -> Self {
46 let mut executor = Self {
47 extensions: Vec::new(),
48 virtual_modules: HashMap::new(),
49 compiled_module_paths: HashSet::new(),
50 interrupt: Arc::new(AtomicU8::new(0)),
51 bytecode_cache: None,
52 dependency_paths: HashMap::new(),
53 native_resolution_context: None,
54 root_package_key: None,
55 module_loader: None,
56 };
57 executor.register_stdlib_modules();
58
59 let mut loader = shape_runtime::module_loader::ModuleLoader::new();
62 executor.register_extension_artifacts_in_loader(&mut loader);
63 executor.module_loader = Some(loader);
64
65 executor
66 }
67
68 fn register_stdlib_modules(&mut self) {
71 self.extensions
72 .push(shape_runtime::stdlib::regex::create_regex_module());
73 self.extensions
74 .push(shape_runtime::stdlib::http::create_http_module());
75 self.extensions
76 .push(shape_runtime::stdlib::crypto::create_crypto_module());
77 self.extensions
78 .push(shape_runtime::stdlib::env::create_env_module());
79 self.extensions
80 .push(shape_runtime::stdlib::json::create_json_module());
81 self.extensions
82 .push(shape_runtime::stdlib::toml_module::create_toml_module());
83 self.extensions
84 .push(shape_runtime::stdlib::yaml::create_yaml_module());
85 self.extensions
86 .push(shape_runtime::stdlib::xml::create_xml_module());
87 self.extensions
88 .push(shape_runtime::stdlib::compress::create_compress_module());
89 self.extensions
90 .push(shape_runtime::stdlib::archive::create_archive_module());
91 self.extensions
92 .push(shape_runtime::stdlib::unicode::create_unicode_module());
93 self.extensions
94 .push(shape_runtime::stdlib::csv_module::create_csv_module());
95 self.extensions
96 .push(shape_runtime::stdlib::msgpack_module::create_msgpack_module());
97 self.extensions
98 .push(shape_runtime::stdlib::set_module::create_set_module());
99 self.extensions
100 .push(crate::executor::create_transport_module_exports());
101 self.extensions
102 .push(crate::executor::create_remote_module_exports());
103 }
104
105 pub fn register_extension(&mut self, module: shape_runtime::module_exports::ModuleExports) {
109 let module_name = module.name.clone();
113 for artifact in &module.module_artifacts {
114 let Some(source) = artifact.source.as_ref() else {
115 continue;
116 };
117 let module_path = artifact.module_path.clone();
118 self.virtual_modules
119 .entry(module_path)
120 .or_insert_with(|| source.clone());
121 }
122
123 let mut registered_primary_path = false;
125 for (filename, source) in &module.shape_sources {
126 let legacy_path = format!("std::loaders::{}", module_name);
128 self.virtual_modules
129 .entry(legacy_path)
130 .or_insert_with(|| source.clone());
131
132 if !registered_primary_path {
134 self.virtual_modules
135 .entry(module_name.clone())
136 .or_insert_with(|| source.clone());
137 registered_primary_path = true;
138 } else if let Some(stem) = std::path::Path::new(filename)
139 .file_stem()
140 .and_then(|s| s.to_str())
141 {
142 let extra_path = format!("{}::{}", module_name, stem);
143 self.virtual_modules
144 .entry(extra_path)
145 .or_insert_with(|| source.clone());
146 }
147 }
148 self.extensions.push(module);
149 }
150
151 pub fn module_schemas(&self) -> Vec<shape_runtime::extensions::ParsedModuleSchema> {
153 self.extensions
154 .iter()
155 .map(|module| {
156 let mut functions = Vec::with_capacity(module.schemas.len());
157 for (name, schema) in &module.schemas {
158 if !module.is_export_public_surface(name, false) {
159 continue;
160 }
161 functions.push(shape_runtime::extensions::ParsedModuleFunction {
162 name: name.clone(),
163 description: schema.description.clone(),
164 params: schema.params.iter().map(|p| p.type_name.clone()).collect(),
165 return_type: schema.return_type.clone(),
166 });
167 }
168 let artifacts = module
169 .module_artifacts
170 .iter()
171 .map(|artifact| shape_runtime::extensions::ParsedModuleArtifact {
172 module_path: artifact.module_path.clone(),
173 source: artifact.source.clone(),
174 compiled: artifact.compiled.clone(),
175 })
176 .collect();
177 shape_runtime::extensions::ParsedModuleSchema {
178 module_name: module.name.clone(),
179 functions,
180 artifacts,
181 }
182 })
183 .collect()
184 }
185
186 pub fn enable_bytecode_cache(&mut self) -> bool {
190 match crate::bytecode_cache::BytecodeCache::new() {
191 Some(cache) => {
192 self.bytecode_cache = Some(cache);
193 true
194 }
195 None => false,
196 }
197 }
198
199 pub fn set_interrupt(&mut self, flag: Arc<AtomicU8>) {
201 self.interrupt = flag;
202 }
203
204 pub fn set_dependency_paths(&mut self, paths: HashMap<String, std::path::PathBuf>) {
209 self.dependency_paths = paths.clone();
210 if let Some(loader) = self.module_loader.as_mut() {
211 loader.set_dependency_paths(paths);
212 }
213 }
214
215 pub fn set_native_resolution_context(
217 &mut self,
218 resolutions: shape_runtime::native_resolution::NativeResolutionSet,
219 root_package_key: Option<String>,
220 ) {
221 self.native_resolution_context = Some(resolutions);
222 self.root_package_key = root_package_key;
223 }
224
225 pub fn clear_native_resolution_context(&mut self) {
227 self.native_resolution_context = None;
228 self.root_package_key = None;
229 }
230}
231
232#[cfg(test)]
233mod tests {
234 use super::*;
235
236 #[test]
237 fn test_new_executor_has_module_loader() {
238 let executor = BytecodeExecutor::new();
239 assert!(
240 executor.module_loader.is_some(),
241 "new() should initialize module_loader"
242 );
243 }
244}