diff --git a/crates/cli-support/src/js/mod.rs b/crates/cli-support/src/js/mod.rs index 9b8f1f60b..d5e7a7829 100644 --- a/crates/cli-support/src/js/mod.rs +++ b/crates/cli-support/src/js/mod.rs @@ -29,7 +29,7 @@ pub struct Context<'a> { pub imported_names: HashSet, pub exported_classes: HashMap, pub function_table_needed: bool, - pub run_descriptor: &'a Fn(&str) -> Vec, + pub run_descriptor: &'a Fn(&str) -> Option>, pub module_versions: Vec<(String, String)>, } @@ -474,7 +474,10 @@ impl<'a> Context<'a> { for field in class.fields.iter() { let wasm_getter = shared::struct_field_get(name, &field.name); let wasm_setter = shared::struct_field_set(name, &field.name); - let descriptor = self.describe(&wasm_getter); + let descriptor = match self.describe(&wasm_getter) { + None => continue, + Some(d) => d, + }; let set = { let mut cx = Js2Rust::new(&field.name, self); @@ -1393,10 +1396,9 @@ impl<'a> Context<'a> { Ok(()) } - fn describe(&self, name: &str) -> Descriptor { + fn describe(&self, name: &str) -> Option { let name = format!("__wbindgen_describe_{}", name); - let ret = (self.run_descriptor)(&name); - Descriptor::decode(&ret) + (self.run_descriptor)(&name).map(|d| Descriptor::decode(&d)) } fn global(&mut self, s: &str) { @@ -1474,7 +1476,12 @@ impl<'a, 'b> SubContext<'a, 'b> { if let Some(ref class) = export.class { return self.generate_export_for_class(class, export); } - let descriptor = self.cx.describe(&export.function.name); + + let descriptor = match self.cx.describe(&export.function.name) { + None => return Ok(()), + Some(d) => d, + }; + let (js, ts) = Js2Rust::new(&export.function.name, self.cx) .process(descriptor.unwrap_function())? .finish("function", &format!("wasm.{}", export.function.name)); @@ -1492,7 +1499,12 @@ impl<'a, 'b> SubContext<'a, 'b> { export: &shared::Export, ) -> Result<(), Error> { let wasm_name = shared::struct_function_export_name(class_name, &export.function.name); - let descriptor = self.cx.describe(&wasm_name); + + let descriptor = match self.cx.describe(&wasm_name) { + None => return Ok(()), + Some(d) => d, + }; + let (js, ts) = Js2Rust::new(&export.function.name, self.cx) .method(export.method) .process(descriptor.unwrap_function())? @@ -1603,7 +1615,10 @@ impl<'a, 'b> SubContext<'a, 'b> { import: &shared::ImportFunction) -> Result<(), Error> { - let descriptor = self.cx.describe(&import.shim); + let descriptor = match self.cx.describe(&import.shim) { + None => return Ok(()), + Some(d) => d, + }; let target = match import.class { Some(ref class) if import.js_new => { diff --git a/crates/cli-support/src/lib.rs b/crates/cli-support/src/lib.rs index 8f80a0870..092f8f2ce 100644 --- a/crates/cli-support/src/lib.rs +++ b/crates/cli-support/src/lib.rs @@ -140,11 +140,19 @@ impl Bindgen { module_versions: Default::default(), run_descriptor: &|name| { let mut v = MyExternals(Vec::new()); - let ret = instance - .invoke_export(name, &[], &mut v) - .expect("failed to run export"); - assert!(ret.is_none()); - v.0 + match instance.invoke_export(name, &[], &mut v) { + Ok(None) => Some(v.0), + Ok(Some(_)) => { + unreachable!( + "there is only one export, and we only return None from it" + ) + }, + // Allow missing exported describe functions. This can + // happen when a nested dependency crate exports things + // but the root crate doesn't use them. + Err(wasmi::Error::Function(_)) => None, + Err(e) => panic!("unexpected error running descriptor: {}", e), + } }, }; for program in programs.iter() { @@ -342,6 +350,7 @@ impl wasmi::ImportResolver for MyResolver { } struct MyExternals(Vec); + #[derive(Debug)] struct MyError(String);