Skip to content

Preserve the function table explicitly #1970

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/cli-support/src/js/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2889,7 +2889,7 @@ impl<'a> Context<'a> {
}

fn export_function_table(&mut self) -> Result<String, Error> {
match self.module.tables.main_function_table()? {
match self.aux.function_table {
Some(id) => Ok(self.export_name_of(id)),
None => bail!("no function table found in module"),
}
Expand Down
9 changes: 9 additions & 0 deletions crates/cli-support/src/wit/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,12 @@ impl<'a> Context<'a> {
// access to them while processing programs.
self.descriptors.extend(descriptors);

// If any closures exist we need to prevent the function table from
// getting gc'd
if closure_imports.len() > 0 {
self.aux.function_table = self.module.tables.main_function_table()?;
}

// Register all the injected closure imports as that they're expected
// to manufacture a particular type of closure.
//
Expand Down Expand Up @@ -310,6 +316,9 @@ impl<'a> Context<'a> {
}

fn bind_intrinsic(&mut self, id: ImportId, intrinsic: Intrinsic) -> Result<(), Error> {
if let Intrinsic::FunctionTable = intrinsic {
self.aux.function_table = self.module.tables.main_function_table()?;
}
let id = self.import_adapter(id, intrinsic.signature(), AdapterJsImportKind::Normal)?;
self.aux
.import_map
Expand Down
4 changes: 4 additions & 0 deletions crates/cli-support/src/wit/nonstandard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ pub struct WasmBindgenAux {
/// Information about various internal functions used to manage the `anyref`
/// table, later used to process JS bindings.
pub anyref_table: Option<walrus::TableId>,
pub function_table: Option<walrus::TableId>,
pub anyref_alloc: Option<walrus::FunctionId>,
pub anyref_drop_slice: Option<walrus::FunctionId>,

Expand Down Expand Up @@ -366,6 +367,9 @@ impl walrus::CustomSection for WasmBindgenAux {
if let Some(id) = self.anyref_table {
roots.push_table(id);
}
if let Some(id) = self.function_table {
roots.push_table(id);
}
if let Some(id) = self.anyref_alloc {
roots.push_func(id);
}
Expand Down
1 change: 1 addition & 0 deletions crates/cli-support/src/wit/section.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ pub fn add(module: &mut Module) -> Result<(), Error> {
anyref_drop_slice: _,
exn_store: _,
shadow_stack_pointer: _,
function_table: _,
} = *aux;

let adapter_context = |id: AdapterId| {
Expand Down
18 changes: 18 additions & 0 deletions crates/cli/tests/wasm-bindgen/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -334,3 +334,21 @@ $",
)?);
Ok(())
}

#[test]
fn function_table_preserved() {
let (mut cmd, _out_dir) = Project::new("function_table_preserved")
.file(
"src/lib.rs",
r#"
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn bar() {
Closure::wrap(Box::new(|| {}) as Box<dyn Fn()>);
}
"#,
)
.wasm_bindgen("");
cmd.assert().success();
}