1fn normalize_embedding_namespace_load_states(namespaces: &kernel::NamespaceRegistry<core::Value>) {
9 for namespace in namespaces.all() {
10 namespaces.set_load_state(
11 namespace.name().as_str(),
12 kernel::NamespaceLoadState::Loaded,
13 );
14 }
15}
16
17pub fn embedding_namespace_registry() -> kernel::NamespaceRegistry<core::Value> {
22 let namespaces = Runtime::new().namespace_registry.clone();
23 normalize_embedding_namespace_load_states(&namespaces);
24 namespaces
25}
26
27#[cfg(test)]
28mod embedding_namespace_tests {
29 use super::*;
30
31 #[test]
32 fn normalization_marks_only_materialized_namespaces_loaded() {
33 let namespaces = kernel::NamespaceRegistry::<core::Value>::new("user");
34 namespaces.find_or_create("std.foundation");
35 namespaces.set_load_state("std.foundation", kernel::NamespaceLoadState::Unloaded);
36 namespaces.set_load_state("example.lazy", kernel::NamespaceLoadState::Unloaded);
37
38 normalize_embedding_namespace_load_states(&namespaces);
39
40 assert_eq!(
41 namespaces.load_state("std.foundation"),
42 Some(kernel::NamespaceLoadState::Loaded)
43 );
44 assert_eq!(
45 namespaces.load_state("example.lazy"),
46 Some(kernel::NamespaceLoadState::Unloaded)
47 );
48 }
49
50 #[test]
51 fn exported_registry_satisfies_bootstrap_requires_without_source_provider() {
52 let namespaces = embedding_namespace_registry();
53 let form = kernel::parse_forms(
54 "(ns example.embedding (:require [std.foundation :refer :all] [std.foundation.coroutine :as coroutine]))",
55 )
56 .expect("parse embedding namespace declaration")
57 .into_iter()
58 .next()
59 .expect("embedding namespace declaration");
60 let mut environment = std::collections::HashMap::new();
61
62 core::with_namespace_registry(&namespaces, || core::eval(&form, &mut environment))
63 .expect("embedding registry must satisfy bootstrapped requires");
64
65 assert_eq!(
66 namespaces.load_state("std.foundation"),
67 Some(kernel::NamespaceLoadState::Loaded)
68 );
69 assert_eq!(
70 namespaces.load_state("std.foundation.coroutine"),
71 Some(kernel::NamespaceLoadState::Loaded)
72 );
73 assert!(namespaces.find("example.embedding").is_some());
74 }
75}
76
77#[cfg(not(feature = "raw-wasm"))]
78use wasm_bindgen::prelude::*;
79
80include!(concat!(env!("OUT_DIR"), "/embedded_hal.rs"));
81
82const EAGER_HAL_RESOURCES: &[&str] = &[
83 "std.foundation.string",
84 "std.foundation.promise",
85 "std.foundation.bytes",
86 "std.foundation.coroutine",
87 "std.foundation.pretty",
88 "std.stream.duplex",
89];
90
91fn ignore_socket_event(_event: core::SocketEvent) {}
92
93#[cfg(not(feature = "raw-wasm"))]
94#[wasm_bindgen(start)]
95pub fn init_wasm() {
96 #[cfg(target_arch = "wasm32")]
97 console_error_panic_hook::set_once();
98}
99
100#[cfg(not(feature = "raw-wasm"))]
106#[wasm_bindgen]
107pub fn instrumentation_conformance(corpus: &str) -> Result<String, JsValue> {
108 let corpus: serde_json::Value =
109 serde_json::from_str(corpus).map_err(|error| JsValue::from_str(&error.to_string()))?;
110 let report = crate::instrumentation::conformance::report(&corpus, "wasm")
111 .map_err(|error| JsValue::from_str(&error))?;
112 serde_json::to_string_pretty(&report).map_err(|error| JsValue::from_str(&error.to_string()))
113}
114
115#[cfg_attr(not(feature = "raw-wasm"), wasm_bindgen)]
116pub struct PromiseHandle {
117 promise: core::Promise,
118}
119
120#[cfg_attr(not(feature = "raw-wasm"), wasm_bindgen)]
121impl PromiseHandle {
122 fn from_promise(promise: core::Promise) -> PromiseHandle {
123 PromiseHandle { promise }
124 }
125
126 #[cfg_attr(not(feature = "raw-wasm"), wasm_bindgen(constructor))]
127 pub fn new() -> PromiseHandle {
128 PromiseHandle {
129 promise: core::Promise::new(),
130 }
131 }
132
133 pub fn state(&self) -> String {
134 match self.promise.state() {
135 core::PromiseState::Pending => "pending".into(),
136 core::PromiseState::Fulfilled(_) => "fulfilled".into(),
137 core::PromiseState::Rejected(_) => "rejected".into(),
138 }
139 }
140
141 pub fn resolve(&self, value: &str) -> bool {
142 self.promise.resolve(core::Value::String(value.into()))
143 }
144
145 pub fn reject(&self, error: &str) -> bool {
146 self.promise.reject(error)
147 }
148
149 pub fn adopt(&self, other: &PromiseHandle) -> bool {
150 self.promise.adopt(&other.promise)
151 }
152
153 pub fn value(&self) -> Result<String, JsValue> {
154 match self.promise.state() {
155 core::PromiseState::Pending => Err(JsValue::from_str("promise is pending")),
156 core::PromiseState::Fulfilled(value) => Ok(value.display()),
157 core::PromiseState::Rejected(error) => Err(JsValue::from_str(&error.message())),
158 }
159 }
160}
161
162#[cfg_attr(not(feature = "raw-wasm"), wasm_bindgen)]
163pub struct Runtime {
164 execution: RuntimeExecutionState,
165 test_runner: String,
166 execution_backend: String,
167 protocols: core::ProtocolRegistry,
168 extensions: core::ExtensionRegistry,
169 wasm_extensions: HashMap<String, extension::WasmExtension>,
170 native_wasm_imports: HashMap<String, extension::WasmExtension>,
171 providers: core::ProviderRegistry,
172 package_catalog: core::PackageCatalog,
173 resources: HashMap<String, String>,
174 #[cfg(not(target_arch = "wasm32"))]
175 source_paths: HashMap<String, std::path::PathBuf>,
176 resource_overrides: HashSet<String>,
177 #[cfg(feature = "bytecode-vm")]
178 bytecode_resources: HashMap<String, (String, Vec<u8>)>,
179 product_cache: RefCell<compiled_product::InMemoryProductCache>,
180 loaded_resources: HashSet<String>,
181 halc_schema_definitions: HashMap<String, Form>,
182 halc_function_schemas: HashMap<String, Form>,
183 halc_schema_types: HashMap<String, kernel::SchemaType>,
184 halc_function_types: HashMap<String, kernel::SchemaType>,
185 halc_inferred_function_types: HashMap<String, kernel::SchemaType>,
186 namespace_registry: kernel::NamespaceRegistry<core::Value>,
187 macros: Rc<RefCell<HashMap<(String, String), Rc<core::Function>>>>,
188 generated_configs: HashMap<String, kernel::GeneratedNamespaceConfig>,
189 #[cfg(feature = "evaluation-journal")]
190 next_journal_id: u64,
191 #[cfg(all(target_arch = "wasm32", not(feature = "raw-wasm")))]
192 host_handler: Option<js_sys::Function>,
193 #[cfg(not(target_arch = "wasm32"))]
194 native_host_handler:
195 Option<Rc<dyn Fn(String, String, Vec<core::Value>) -> Result<core::Value, String>>>,
196 #[cfg(not(target_arch = "wasm32"))]
197 native_modules: native_module::Registry,
198 #[cfg(all(feature = "direct-native", not(target_arch = "wasm32")))]
199 direct_native: crate::direct_native::NativeEngine,
200 #[cfg(all(feature = "direct-native", not(target_arch = "wasm32")))]
201 direct_native_multimethods: core::MultiMethodRegistry,
202 #[cfg(all(feature = "direct-native", not(target_arch = "wasm32")))]
203 direct_native_source_cache: Option<SourceBytecodeCache>,
204 #[cfg(not(target_arch = "wasm32"))]
205 extension_roots: Vec<std::path::PathBuf>,
206}
207
208impl Drop for Runtime {
209 fn drop(&mut self) {
210 let namespaces = self.wasm_extensions.keys().cloned().collect::<Vec<_>>();
215 for namespace in self.namespace_registry.all() {
216 for (symbol, var) in namespace.mappings() {
217 if var
218 .symbol()
219 .get_namespace()
220 .is_some_and(|owner| namespaces.iter().any(|extension| extension == owner))
221 {
222 namespace.unmap(&symbol);
223 }
224 }
225 }
226 self.execution.clear();
227 #[cfg(not(target_arch = "wasm32"))]
228 self.native_wasm_imports.clear();
229 self.wasm_extensions.clear();
230 }
231}