diff --git a/crates/cli-support/src/js/mod.rs b/crates/cli-support/src/js/mod.rs index a1986c35b..efedf96e1 100644 --- a/crates/cli-support/src/js/mod.rs +++ b/crates/cli-support/src/js/mod.rs @@ -43,6 +43,7 @@ pub struct Context<'a> { pub exported_classes: HashMap, pub function_table_needed: bool, pub interpreter: &'a mut Interpreter, + pub memory_init: Option, } #[derive(Default)] @@ -377,6 +378,7 @@ impl<'a> Context<'a> { )) })?; + self.create_memory_export(); self.unexport_unused_internal_exports(); self.gc()?; @@ -685,6 +687,20 @@ impl<'a> Context<'a> { } } + fn create_memory_export(&mut self) { + let limits = match self.memory_init.clone() { + Some(limits) => limits, + None => return, + }; + let mut initializer = String::from("new WebAssembly.Memory({"); + initializer.push_str(&format!("initial:{}", limits.initial())); + if let Some(max) = limits.maximum() { + initializer.push_str(&format!(",maximum:{}", max)); + } + initializer.push_str("})"); + self.export("memory", &initializer, None); + } + fn rewrite_imports(&mut self, module_name: &str) { for (name, contents) in self._rewrite_imports(module_name) { self.export(&name, &contents, None); @@ -715,6 +731,15 @@ impl<'a> Context<'a> { continue; } + // If memory is imported we'll have exported it from the shim module + // so let's import it from there. + if import.field() == "memory" { + import.module_mut().truncate(0); + import.module_mut().push_str("./"); + import.module_mut().push_str(module_name); + continue + } + let renamed_import = format!("__wbindgen_{}", import.field()); let mut bind_math = |expr: &str| { math_imports.push((renamed_import.clone(), format!("function{}", expr))); @@ -1333,18 +1358,20 @@ impl<'a> Context<'a> { if !self.exposed_globals.insert(name) { return; } + let mem = self.memory(); self.global(&format!( " let cache{name} = null; function {name}() {{ - if (cache{name} === null || cache{name}.buffer !== wasm.memory.buffer) {{ - cache{name} = new {js}(wasm.memory.buffer); + if (cache{name} === null || cache{name}.buffer !== {mem}.buffer) {{ + cache{name} = new {js}({mem}.buffer); }} return cache{name}; }} ", name = name, js = js, + mem = mem, )); } @@ -1690,6 +1717,29 @@ impl<'a> Context<'a> { fn use_node_require(&self) -> bool { self.config.nodejs && !self.config.nodejs_experimental_modules } + + fn memory(&mut self) -> &'static str { + if self.module.memory_section().is_some() { + return "wasm.memory"; + } + + let (entry, mem) = self.module.import_section() + .expect("must import memory") + .entries() + .iter() + .filter_map(|i| { + match i.external() { + External::Memory(m) => Some((i, m)), + _ => None, + } + }) + .next() + .expect("must import memory"); + assert_eq!(entry.module(), "env"); + assert_eq!(entry.field(), "memory"); + self.memory_init = Some(mem.limits().clone()); + "memory" + } } impl<'a, 'b> SubContext<'a, 'b> { diff --git a/crates/cli-support/src/lib.rs b/crates/cli-support/src/lib.rs index fdb09dc68..372803549 100644 --- a/crates/cli-support/src/lib.rs +++ b/crates/cli-support/src/lib.rs @@ -200,6 +200,7 @@ impl Bindgen { module: &mut module, function_table_needed: false, interpreter: &mut instance, + memory_init: None, }; for program in programs.iter() { js::SubContext { diff --git a/crates/cli-support/src/wasm2es6js.rs b/crates/cli-support/src/wasm2es6js.rs index 9d7cda53a..517ee6358 100644 --- a/crates/cli-support/src/wasm2es6js.rs +++ b/crates/cli-support/src/wasm2es6js.rs @@ -150,19 +150,6 @@ impl Output { if let Some(i) = self.module.import_section() { let mut set = HashSet::new(); for entry in i.entries() { - match *entry.external() { - External::Function(_) => {} - External::Table(_) => { - bail!("wasm imports a table which isn't supported yet"); - } - External::Memory(_) => { - bail!("wasm imports memory which isn't supported yet"); - } - External::Global(_) => { - bail!("wasm imports globals which aren't supported yet"); - } - } - if !set.insert(entry.module()) { continue; }