mirror of
https://github.com/rustwasm/wasm-bindgen.git
synced 2024-12-26 11:34:22 +03:00
Add support for modules importing memory
The default of Rust wasm binaries is to export the memory that they contain, but LLD also supports an `--import-memory` option where memory is imported into a module instead. It's looking like importing memory is along the lines of how shared memory wasm modules will work (they'll all import the same memory). This commit adds support to wasm-bindgen to support modules which import memory. Memory accessors are tweaked to no longer always assume that the wasm module exports its memory. Additionally JS bindings will create a `memory` option automatically because LLD always imports memory from an `env` module which won't actually exist.
This commit is contained in:
parent
8ce7465bba
commit
335c0b1ab6
@ -43,6 +43,7 @@ pub struct Context<'a> {
|
||||
pub exported_classes: HashMap<String, ExportedClass>,
|
||||
pub function_table_needed: bool,
|
||||
pub interpreter: &'a mut Interpreter,
|
||||
pub memory_init: Option<ResizableLimits>,
|
||||
}
|
||||
|
||||
#[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> {
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user