Merge pull request #2446 from alexcrichton/option-name

Propagate optional import names to the wasmtime/C API
This commit is contained in:
Nick Fitzgerald
2020-11-24 08:28:35 -08:00
committed by GitHub
18 changed files with 134 additions and 95 deletions

View File

@@ -581,7 +581,7 @@ impl<'data> ModuleEnvironment<'data> for DummyEnvironment {
&mut self, &mut self,
index: TypeIndex, index: TypeIndex,
module: &'data str, module: &'data str,
field: &'data str, field: Option<&'data str>,
) -> WasmResult<()> { ) -> WasmResult<()> {
assert_eq!( assert_eq!(
self.info.functions.len(), self.info.functions.len(),
@@ -591,7 +591,7 @@ impl<'data> ModuleEnvironment<'data> for DummyEnvironment {
self.info.functions.push(Exportable::new(index)); self.info.functions.push(Exportable::new(index));
self.info self.info
.imported_funcs .imported_funcs
.push((String::from(module), String::from(field))); .push((String::from(module), String::from(field.unwrap())));
Ok(()) Ok(())
} }
@@ -609,12 +609,12 @@ impl<'data> ModuleEnvironment<'data> for DummyEnvironment {
&mut self, &mut self,
global: Global, global: Global,
module: &'data str, module: &'data str,
field: &'data str, field: Option<&'data str>,
) -> WasmResult<()> { ) -> WasmResult<()> {
self.info.globals.push(Exportable::new(global)); self.info.globals.push(Exportable::new(global));
self.info self.info
.imported_globals .imported_globals
.push((String::from(module), String::from(field))); .push((String::from(module), String::from(field.unwrap())));
Ok(()) Ok(())
} }
@@ -627,12 +627,12 @@ impl<'data> ModuleEnvironment<'data> for DummyEnvironment {
&mut self, &mut self,
table: Table, table: Table,
module: &'data str, module: &'data str,
field: &'data str, field: Option<&'data str>,
) -> WasmResult<()> { ) -> WasmResult<()> {
self.info.tables.push(Exportable::new(table)); self.info.tables.push(Exportable::new(table));
self.info self.info
.imported_tables .imported_tables
.push((String::from(module), String::from(field))); .push((String::from(module), String::from(field.unwrap())));
Ok(()) Ok(())
} }
@@ -672,12 +672,12 @@ impl<'data> ModuleEnvironment<'data> for DummyEnvironment {
&mut self, &mut self,
memory: Memory, memory: Memory,
module: &'data str, module: &'data str,
field: &'data str, field: Option<&'data str>,
) -> WasmResult<()> { ) -> WasmResult<()> {
self.info.memories.push(Exportable::new(memory)); self.info.memories.push(Exportable::new(memory));
self.info self.info
.imported_memories .imported_memories
.push((String::from(module), String::from(field))); .push((String::from(module), String::from(field.unwrap())));
Ok(()) Ok(())
} }

View File

@@ -674,7 +674,7 @@ pub trait ModuleEnvironment<'data>: TargetEnvironment {
&mut self, &mut self,
index: TypeIndex, index: TypeIndex,
module: &'data str, module: &'data str,
field: &'data str, field: Option<&'data str>,
) -> WasmResult<()>; ) -> WasmResult<()>;
/// Declares a table import to the environment. /// Declares a table import to the environment.
@@ -682,7 +682,7 @@ pub trait ModuleEnvironment<'data>: TargetEnvironment {
&mut self, &mut self,
table: Table, table: Table,
module: &'data str, module: &'data str,
field: &'data str, field: Option<&'data str>,
) -> WasmResult<()>; ) -> WasmResult<()>;
/// Declares a memory import to the environment. /// Declares a memory import to the environment.
@@ -690,7 +690,7 @@ pub trait ModuleEnvironment<'data>: TargetEnvironment {
&mut self, &mut self,
memory: Memory, memory: Memory,
module: &'data str, module: &'data str,
field: &'data str, field: Option<&'data str>,
) -> WasmResult<()>; ) -> WasmResult<()>;
/// Declares an event import to the environment. /// Declares an event import to the environment.
@@ -698,7 +698,7 @@ pub trait ModuleEnvironment<'data>: TargetEnvironment {
&mut self, &mut self,
event: Event, event: Event,
module: &'data str, module: &'data str,
field: &'data str, field: Option<&'data str>,
) -> WasmResult<()> { ) -> WasmResult<()> {
drop((event, module, field)); drop((event, module, field));
Err(WasmError::Unsupported("wasm events".to_string())) Err(WasmError::Unsupported("wasm events".to_string()))
@@ -709,7 +709,7 @@ pub trait ModuleEnvironment<'data>: TargetEnvironment {
&mut self, &mut self,
global: Global, global: Global,
module: &'data str, module: &'data str,
field: &'data str, field: Option<&'data str>,
) -> WasmResult<()>; ) -> WasmResult<()>;
/// Declares a module import to the environment. /// Declares a module import to the environment.
@@ -717,7 +717,7 @@ pub trait ModuleEnvironment<'data>: TargetEnvironment {
&mut self, &mut self,
ty_index: TypeIndex, ty_index: TypeIndex,
module: &'data str, module: &'data str,
field: &'data str, field: Option<&'data str>,
) -> WasmResult<()> { ) -> WasmResult<()> {
drop((ty_index, module, field)); drop((ty_index, module, field));
Err(WasmError::Unsupported("module linking".to_string())) Err(WasmError::Unsupported("module linking".to_string()))
@@ -728,7 +728,7 @@ pub trait ModuleEnvironment<'data>: TargetEnvironment {
&mut self, &mut self,
ty_index: TypeIndex, ty_index: TypeIndex,
module: &'data str, module: &'data str,
field: &'data str, field: Option<&'data str>,
) -> WasmResult<()> { ) -> WasmResult<()> {
drop((ty_index, module, field)); drop((ty_index, module, field));
Err(WasmError::Unsupported("module linking".to_string())) Err(WasmError::Unsupported("module linking".to_string()))

View File

@@ -156,27 +156,25 @@ pub fn parse_import_section<'data>(
for entry in imports { for entry in imports {
let import = entry?; let import = entry?;
let module_name = import.module;
let field_name = import.field.unwrap(); // TODO Handle error when module linking is implemented.
match entity_type(import.ty, environ)? { match entity_type(import.ty, environ)? {
EntityType::Function(idx) => { EntityType::Function(idx) => {
environ.declare_func_import(idx, module_name, field_name)?; environ.declare_func_import(idx, import.module, import.field)?;
} }
EntityType::Module(idx) => { EntityType::Module(idx) => {
environ.declare_module_import(idx, module_name, field_name)?; environ.declare_module_import(idx, import.module, import.field)?;
} }
EntityType::Instance(idx) => { EntityType::Instance(idx) => {
environ.declare_instance_import(idx, module_name, field_name)?; environ.declare_instance_import(idx, import.module, import.field)?;
} }
EntityType::Memory(ty) => { EntityType::Memory(ty) => {
environ.declare_memory_import(ty, module_name, field_name)?; environ.declare_memory_import(ty, import.module, import.field)?;
} }
EntityType::Event(e) => environ.declare_event_import(e, module_name, field_name)?, EntityType::Event(e) => environ.declare_event_import(e, import.module, import.field)?,
EntityType::Global(ty) => { EntityType::Global(ty) => {
environ.declare_global_import(ty, module_name, field_name)?; environ.declare_global_import(ty, import.module, import.field)?;
} }
EntityType::Table(ty) => { EntityType::Table(ty) => {
environ.declare_table_import(ty, module_name, field_name)?; environ.declare_table_import(ty, import.module, import.field)?;
} }
} }
} }

View File

@@ -960,7 +960,8 @@
* *
* This function takes ownership of the `module`, `name`, and * This function takes ownership of the `module`, `name`, and
* #wasm_externtype_t arguments. The caller is responsible for deleting the * #wasm_externtype_t arguments. The caller is responsible for deleting the
* returned value. * returned value. Note that `name` can be `NULL` where in the module linking
* proposal the import name can be omitted.
* *
* \fn const wasm_name_t* wasm_importtype_module(const wasm_importtype_t *); * \fn const wasm_name_t* wasm_importtype_module(const wasm_importtype_t *);
* \brief Returns the module this import is importing from. * \brief Returns the module this import is importing from.
@@ -972,7 +973,9 @@
* \brief Returns the name this import is importing from. * \brief Returns the name this import is importing from.
* *
* The returned memory is owned by the #wasm_importtype_t argument, the caller * The returned memory is owned by the #wasm_importtype_t argument, the caller
* should not deallocate it. * should not deallocate it. Note that `NULL` can be returned which means
* that the import name is not provided. This is for imports with the module
* linking proposal that only have the module specified.
* *
* \fn const wasm_externtype_t* wasm_importtype_type(const wasm_importtype_t *); * \fn const wasm_externtype_t* wasm_importtype_type(const wasm_importtype_t *);
* \brief Returns the type of item this import is importing. * \brief Returns the type of item this import is importing.

View File

@@ -116,7 +116,7 @@ pub extern "C" fn wasmtime_linker_get_default(
pub extern "C" fn wasmtime_linker_get_one_by_name( pub extern "C" fn wasmtime_linker_get_one_by_name(
linker: &wasmtime_linker_t, linker: &wasmtime_linker_t,
module: &wasm_name_t, module: &wasm_name_t,
name: &wasm_name_t, name: Option<&wasm_name_t>,
item_ptr: &mut *mut wasm_extern_t, item_ptr: &mut *mut wasm_extern_t,
) -> Option<Box<wasmtime_error_t>> { ) -> Option<Box<wasmtime_error_t>> {
let linker = &linker.linker; let linker = &linker.linker;
@@ -124,9 +124,12 @@ pub extern "C" fn wasmtime_linker_get_one_by_name(
Ok(s) => s, Ok(s) => s,
Err(_) => return bad_utf8(), Err(_) => return bad_utf8(),
}; };
let name = match str::from_utf8(name.as_slice()) { let name = match name {
Ok(s) => s, Some(name) => match str::from_utf8(name.as_slice()) {
Err(_) => return bad_utf8(), Ok(s) => Some(s),
Err(_) => return bad_utf8(),
},
None => None,
}; };
handle_result(linker.get_one_by_name(module, name), |which| { handle_result(linker.get_one_by_name(module, name), |which| {
*item_ptr = Box::into_raw(Box::new(wasm_extern_t { which })) *item_ptr = Box::into_raw(Box::new(wasm_extern_t { which }))

View File

@@ -51,7 +51,13 @@ pub extern "C" fn wasmtime_module_new(
handle_result(Module::from_binary(&engine.engine, binary), |module| { handle_result(Module::from_binary(&engine.engine, binary), |module| {
let imports = module let imports = module
.imports() .imports()
.map(|i| wasm_importtype_t::new(i.module().to_owned(), i.name().to_owned(), i.ty())) .map(|i| {
wasm_importtype_t::new(
i.module().to_owned(),
i.name().map(|s| s.to_owned()),
i.ty(),
)
})
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let exports = module let exports = module
.exports() .exports()
@@ -118,7 +124,13 @@ pub extern "C" fn wasm_module_obtain(
} }
let imports = module let imports = module
.imports() .imports()
.map(|i| wasm_importtype_t::new(i.module().to_owned(), i.name().to_owned(), i.ty())) .map(|i| {
wasm_importtype_t::new(
i.module().to_owned(),
i.name().map(|s| s.to_owned()),
i.ty(),
)
})
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let exports = module let exports = module
.exports() .exports()
@@ -175,7 +187,13 @@ pub extern "C" fn wasmtime_module_deserialize(
|module| { |module| {
let imports = module let imports = module
.imports() .imports()
.map(|i| wasm_importtype_t::new(i.module().to_owned(), i.name().to_owned(), i.ty())) .map(|i| {
wasm_importtype_t::new(
i.module().to_owned(),
i.name().map(|s| s.to_owned()),
i.ty(),
)
})
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let exports = module let exports = module
.exports() .exports()

View File

@@ -6,7 +6,7 @@ use wasmtime::ExternType;
#[derive(Clone)] #[derive(Clone)]
pub struct wasm_importtype_t { pub struct wasm_importtype_t {
pub(crate) module: String, pub(crate) module: String,
pub(crate) name: String, pub(crate) name: Option<String>,
pub(crate) ty: ExternType, pub(crate) ty: ExternType,
module_cache: OnceCell<wasm_name_t>, module_cache: OnceCell<wasm_name_t>,
name_cache: OnceCell<wasm_name_t>, name_cache: OnceCell<wasm_name_t>,
@@ -16,7 +16,7 @@ pub struct wasm_importtype_t {
wasmtime_c_api_macros::declare_ty!(wasm_importtype_t); wasmtime_c_api_macros::declare_ty!(wasm_importtype_t);
impl wasm_importtype_t { impl wasm_importtype_t {
pub(crate) fn new(module: String, name: String, ty: ExternType) -> wasm_importtype_t { pub(crate) fn new(module: String, name: Option<String>, ty: ExternType) -> wasm_importtype_t {
wasm_importtype_t { wasm_importtype_t {
module, module,
name, name,
@@ -31,13 +31,16 @@ impl wasm_importtype_t {
#[no_mangle] #[no_mangle]
pub extern "C" fn wasm_importtype_new( pub extern "C" fn wasm_importtype_new(
module: &mut wasm_name_t, module: &mut wasm_name_t,
name: &mut wasm_name_t, name: Option<&mut wasm_name_t>,
ty: Box<wasm_externtype_t>, ty: Box<wasm_externtype_t>,
) -> Option<Box<wasm_importtype_t>> { ) -> Option<Box<wasm_importtype_t>> {
let module = module.take(); let module = module.take();
let name = name.take(); let name = name.map(|n| n.take());
let module = String::from_utf8(module).ok()?; let module = String::from_utf8(module).ok()?;
let name = String::from_utf8(name).ok()?; let name = match name {
Some(name) => Some(String::from_utf8(name).ok()?),
None => None,
};
Some(Box::new(wasm_importtype_t::new(module, name, ty.ty()))) Some(Box::new(wasm_importtype_t::new(module, name, ty.ty())))
} }
@@ -48,9 +51,12 @@ pub extern "C" fn wasm_importtype_module(it: &wasm_importtype_t) -> &wasm_name_t
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn wasm_importtype_name(it: &wasm_importtype_t) -> &wasm_name_t { pub extern "C" fn wasm_importtype_name(it: &wasm_importtype_t) -> Option<&wasm_name_t> {
it.name_cache let name = it.name.as_ref()?;
.get_or_init(|| wasm_name_t::from_name(it.name.clone())) Some(
it.name_cache
.get_or_init(|| wasm_name_t::from_name(name.to_string())),
)
} }
#[no_mangle] #[no_mangle]

View File

@@ -328,7 +328,7 @@ pub extern "C" fn wasi_instance_bind_import<'a>(
import: &wasm_importtype_t, import: &wasm_importtype_t,
) -> Option<&'a wasm_extern_t> { ) -> Option<&'a wasm_extern_t> {
let module = &import.module; let module = &import.module;
let name = str::from_utf8(import.name.as_bytes()).ok()?; let name = str::from_utf8(import.name.as_ref()?.as_bytes()).ok()?;
let export = match &instance.wasi { let export = match &instance.wasi {
WasiInstance::Preview1(wasi) => { WasiInstance::Preview1(wasi) => {

View File

@@ -163,7 +163,7 @@ pub struct Module {
pub name: Option<String>, pub name: Option<String>,
/// All import records, in the order they are declared in the module. /// All import records, in the order they are declared in the module.
pub imports: Vec<(String, String, EntityIndex)>, pub imports: Vec<(String, Option<String>, EntityIndex)>,
/// Exported entities. /// Exported entities.
pub exports: IndexMap<String, EntityIndex>, pub exports: IndexMap<String, EntityIndex>,

View File

@@ -264,7 +264,7 @@ impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data
&mut self, &mut self,
index: TypeIndex, index: TypeIndex,
module: &str, module: &str,
field: &str, field: Option<&str>,
) -> WasmResult<()> { ) -> WasmResult<()> {
debug_assert_eq!( debug_assert_eq!(
self.result.module.functions.len(), self.result.module.functions.len(),
@@ -275,7 +275,7 @@ impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data
let func_index = self.result.module.functions.push(sig_index); let func_index = self.result.module.functions.push(sig_index);
self.result.module.imports.push(( self.result.module.imports.push((
module.to_owned(), module.to_owned(),
field.to_owned(), field.map(|s| s.to_owned()),
EntityIndex::Function(func_index), EntityIndex::Function(func_index),
)); ));
self.result.module.num_imported_funcs += 1; self.result.module.num_imported_funcs += 1;
@@ -283,7 +283,12 @@ impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data
Ok(()) Ok(())
} }
fn declare_table_import(&mut self, table: Table, module: &str, field: &str) -> WasmResult<()> { fn declare_table_import(
&mut self,
table: Table,
module: &str,
field: Option<&str>,
) -> WasmResult<()> {
debug_assert_eq!( debug_assert_eq!(
self.result.module.table_plans.len(), self.result.module.table_plans.len(),
self.result.module.num_imported_tables, self.result.module.num_imported_tables,
@@ -293,7 +298,7 @@ impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data
let table_index = self.result.module.table_plans.push(plan); let table_index = self.result.module.table_plans.push(plan);
self.result.module.imports.push(( self.result.module.imports.push((
module.to_owned(), module.to_owned(),
field.to_owned(), field.map(|s| s.to_owned()),
EntityIndex::Table(table_index), EntityIndex::Table(table_index),
)); ));
self.result.module.num_imported_tables += 1; self.result.module.num_imported_tables += 1;
@@ -304,7 +309,7 @@ impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data
&mut self, &mut self,
memory: Memory, memory: Memory,
module: &str, module: &str,
field: &str, field: Option<&str>,
) -> WasmResult<()> { ) -> WasmResult<()> {
debug_assert_eq!( debug_assert_eq!(
self.result.module.memory_plans.len(), self.result.module.memory_plans.len(),
@@ -318,7 +323,7 @@ impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data
let memory_index = self.result.module.memory_plans.push(plan); let memory_index = self.result.module.memory_plans.push(plan);
self.result.module.imports.push(( self.result.module.imports.push((
module.to_owned(), module.to_owned(),
field.to_owned(), field.map(|s| s.to_owned()),
EntityIndex::Memory(memory_index), EntityIndex::Memory(memory_index),
)); ));
self.result.module.num_imported_memories += 1; self.result.module.num_imported_memories += 1;
@@ -329,7 +334,7 @@ impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data
&mut self, &mut self,
global: Global, global: Global,
module: &str, module: &str,
field: &str, field: Option<&str>,
) -> WasmResult<()> { ) -> WasmResult<()> {
debug_assert_eq!( debug_assert_eq!(
self.result.module.globals.len(), self.result.module.globals.len(),
@@ -339,7 +344,7 @@ impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data
let global_index = self.result.module.globals.push(global); let global_index = self.result.module.globals.push(global);
self.result.module.imports.push(( self.result.module.imports.push((
module.to_owned(), module.to_owned(),
field.to_owned(), field.map(|s| s.to_owned()),
EntityIndex::Global(global_index), EntityIndex::Global(global_index),
)); ));
self.result.module.num_imported_globals += 1; self.result.module.num_imported_globals += 1;

View File

@@ -309,8 +309,9 @@ fn with_imports<R>(
}; };
for (expected, actual) in m.imports.iter().zip(externs) { for (expected, actual) in m.imports.iter().zip(externs) {
process(&expected.2, actual).with_context(|| { process(&expected.2, actual).with_context(|| match &expected.1 {
format!("incompatible import type for {}/{}", expected.0, expected.1) Some(name) => format!("incompatible import type for {}/{}", expected.0, name),
None => format!("incompatible import type for {}", expected.0),
})?; })?;
} }

View File

@@ -371,7 +371,7 @@ impl Linker {
/// "#; /// "#;
/// let module = Module::new(store.engine(), wat)?; /// let module = Module::new(store.engine(), wat)?;
/// linker.module("", &module)?; /// linker.module("", &module)?;
/// let count = linker.get_one_by_name("", "run")?.into_func().unwrap().get0::<i32>()?()?; /// let count = linker.get_one_by_name("", Some("run"))?.into_func().unwrap().get0::<i32>()?()?;
/// assert_eq!(count, 0, "a Command should get a fresh instance on each invocation"); /// assert_eq!(count, 0, "a Command should get a fresh instance on each invocation");
/// ///
/// # Ok(()) /// # Ok(())
@@ -592,28 +592,27 @@ impl Linker {
let mut options = Vec::new(); let mut options = Vec::new();
for i in self.map.keys() { for i in self.map.keys() {
if &*self.strings[i.module] != import.module() if &*self.strings[i.module] != import.module()
|| &*self.strings[i.name] != import.name() || self.strings.get(i.name).map(|s| &**s) != import.name()
{ {
continue; continue;
} }
options.push(format!(" * {:?}\n", i.kind)); options.push(format!(" * {:?}\n", i.kind));
} }
let desc = match import.name() {
Some(name) => format!("{}::{}", import.module(), name),
None => import.module().to_string(),
};
if options.is_empty() { if options.is_empty() {
return anyhow!( return anyhow!("unknown import: `{}` has not been defined", desc);
"unknown import: `{}::{}` has not been defined",
import.module(),
import.name()
);
} }
options.sort(); options.sort();
anyhow!( anyhow!(
"incompatible import type for `{}::{}` specified\n\ "incompatible import type for `{}` specified\n\
desired signature was: {:?}\n\ desired signature was: {:?}\n\
signatures available:\n\n{}", signatures available:\n\n{}",
import.module(), desc,
import.name(),
import.ty(), import.ty(),
options.concat(), options.concat(),
) )
@@ -649,7 +648,10 @@ impl Linker {
pub fn get(&self, import: &ImportType) -> Option<Extern> { pub fn get(&self, import: &ImportType) -> Option<Extern> {
let key = ImportKey { let key = ImportKey {
module: *self.string2idx.get(import.module())?, module: *self.string2idx.get(import.module())?,
name: *self.string2idx.get(import.name())?, name: match import.name() {
Some(name) => *self.string2idx.get(name)?,
None => usize::max_value(),
},
kind: self.import_kind(import.ty()), kind: self.import_kind(import.ty()),
}; };
self.map.get(&key).cloned() self.map.get(&key).cloned()
@@ -662,12 +664,13 @@ impl Linker {
pub fn get_by_name<'a: 'p, 'p>( pub fn get_by_name<'a: 'p, 'p>(
&'a self, &'a self,
module: &'p str, module: &'p str,
name: &'p str, name: Option<&'p str>,
) -> impl Iterator<Item = &'a Extern> + 'p { ) -> impl Iterator<Item = &'a Extern> + 'p {
self.map self.map
.iter() .iter()
.filter(move |(key, _item)| { .filter(move |(key, _item)| {
&*self.strings[key.module] == module && &*self.strings[key.name] == name &*self.strings[key.module] == module
&& self.strings.get(key.name).map(|s| &**s) == name
}) })
.map(|(_, item)| item) .map(|(_, item)| item)
} }
@@ -678,13 +681,17 @@ impl Linker {
/// a single `Extern` item. If the `module` and `name` pair isn't defined /// a single `Extern` item. If the `module` and `name` pair isn't defined
/// in this linker then an error is returned. If more than one value exists /// in this linker then an error is returned. If more than one value exists
/// for the `module` and `name` pairs, then an error is returned as well. /// for the `module` and `name` pairs, then an error is returned as well.
pub fn get_one_by_name(&self, module: &str, name: &str) -> Result<Extern> { pub fn get_one_by_name(&self, module: &str, name: Option<&str>) -> Result<Extern> {
let err_msg = || match name {
Some(name) => format!("named `{}` in `{}`", name, module),
None => format!("named `{}`", module),
};
let mut items = self.get_by_name(module, name); let mut items = self.get_by_name(module, name);
let ret = items let ret = items
.next() .next()
.ok_or_else(|| anyhow!("no item named `{}` in `{}`", name, module))?; .ok_or_else(|| anyhow!("no item {}", err_msg()))?;
if items.next().is_some() { if items.next().is_some() {
bail!("too many items named `{}` in `{}`", name, module); bail!("too many items {}", err_msg());
} }
Ok(ret.clone()) Ok(ret.clone())
} }
@@ -694,7 +701,7 @@ impl Linker {
/// An export with an empty string is considered to be a "default export". /// An export with an empty string is considered to be a "default export".
/// "_start" is also recognized for compatibility. /// "_start" is also recognized for compatibility.
pub fn get_default(&self, module: &str) -> Result<Func> { pub fn get_default(&self, module: &str) -> Result<Func> {
let mut items = self.get_by_name(module, ""); let mut items = self.get_by_name(module, Some(""));
if let Some(external) = items.next() { if let Some(external) = items.next() {
if items.next().is_some() { if items.next().is_some() {
bail!("too many items named `` in `{}`", module); bail!("too many items named `` in `{}`", module);
@@ -706,7 +713,7 @@ impl Linker {
} }
// For compatibility, also recognize "_start". // For compatibility, also recognize "_start".
let mut items = self.get_by_name(module, "_start"); let mut items = self.get_by_name(module, Some("_start"));
if let Some(external) = items.next() { if let Some(external) = items.next() {
if items.next().is_some() { if items.next().is_some() {
bail!("too many items named `_start` in `{}`", module); bail!("too many items named `_start` in `{}`", module);

View File

@@ -406,7 +406,7 @@ impl Module {
/// assert_eq!(module.imports().len(), 1); /// assert_eq!(module.imports().len(), 1);
/// let import = module.imports().next().unwrap(); /// let import = module.imports().next().unwrap();
/// assert_eq!(import.module(), "host"); /// assert_eq!(import.module(), "host");
/// assert_eq!(import.name(), "foo"); /// assert_eq!(import.name(), Some("foo"));
/// match import.ty() { /// match import.ty() {
/// ExternType::Func(_) => { /* ... */ } /// ExternType::Func(_) => { /* ... */ }
/// _ => panic!("unexpected import type!"), /// _ => panic!("unexpected import type!"),
@@ -423,7 +423,7 @@ impl Module {
.iter() .iter()
.map(move |(module_name, name, entity_index)| { .map(move |(module_name, name, entity_index)| {
let r#type = EntityType::new(entity_index, module); let r#type = EntityType::new(entity_index, module);
ImportType::new(module_name, name, r#type) ImportType::new(module_name, name.as_deref(), r#type)
}) })
} }

View File

@@ -43,11 +43,9 @@ pub fn create_global(store: &Store, gt: &GlobalType, val: Val) -> Result<StoreIn
let local_sig_index = module.signatures.push(wasm.clone()); let local_sig_index = module.signatures.push(wasm.clone());
let func_index = module.functions.push(local_sig_index); let func_index = module.functions.push(local_sig_index);
module.num_imported_funcs = 1; module.num_imported_funcs = 1;
module.imports.push(( module
"".into(), .imports
"".into(), .push(("".into(), None, wasm::EntityIndex::Function(func_index)));
wasm::EntityIndex::Function(func_index),
));
let f = f.caller_checked_anyfunc(); let f = f.caller_checked_anyfunc();
let f = unsafe { f.as_ref() }; let f = unsafe { f.as_ref() };

View File

@@ -483,13 +483,10 @@ impl ModuleType {
/// Returns the list of imports associated with this module type. /// Returns the list of imports associated with this module type.
pub fn imports(&self) -> impl ExactSizeIterator<Item = ImportType<'_>> { pub fn imports(&self) -> impl ExactSizeIterator<Item = ImportType<'_>> {
self.imports.iter().map(|(module, name, ty)| { self.imports.iter().map(|(module, name, ty)| ImportType {
ImportType { module,
module, name: name.as_deref(),
// FIXME(#2094) should thread through the `Option` ty: EntityOrExtern::Extern(ty),
name: name.as_ref().unwrap(),
ty: EntityOrExtern::Extern(ty),
}
}) })
} }
@@ -676,7 +673,7 @@ pub struct ImportType<'module> {
module: &'module str, module: &'module str,
/// The field of the import. /// The field of the import.
name: &'module str, name: Option<&'module str>,
/// The type of the import. /// The type of the import.
ty: EntityOrExtern<'module>, ty: EntityOrExtern<'module>,
@@ -693,7 +690,7 @@ impl<'module> ImportType<'module> {
/// is of type `ty`. /// is of type `ty`.
pub(crate) fn new( pub(crate) fn new(
module: &'module str, module: &'module str,
name: &'module str, name: Option<&'module str>,
ty: EntityType<'module>, ty: EntityType<'module>,
) -> ImportType<'module> { ) -> ImportType<'module> {
ImportType { ImportType {
@@ -710,7 +707,10 @@ impl<'module> ImportType<'module> {
/// Returns the field name of the module that this import is expected to /// Returns the field name of the module that this import is expected to
/// come from. /// come from.
pub fn name(&self) -> &'module str { ///
/// Note that the name can be `None` for the module linking proposal. If the
/// module linking proposal is not enabled it's safe to unwrap this.
pub fn name(&self) -> Option<&'module str> {
self.name self.name
} }
@@ -726,8 +726,8 @@ impl<'module> ImportType<'module> {
impl<'module> fmt::Debug for ImportType<'module> { impl<'module> fmt::Debug for ImportType<'module> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ImportType") f.debug_struct("ImportType")
.field("module", &self.module().to_owned()) .field("module", &self.module())
.field("name", &self.name().to_owned()) .field("name", &self.name())
.field("ty", &self.ty()) .field("ty", &self.ty())
.finish() .finish()
} }

View File

@@ -74,7 +74,7 @@ impl WastContext {
fn get_export(&self, module: Option<&str>, name: &str) -> Result<Extern> { fn get_export(&self, module: Option<&str>, name: &str) -> Result<Extern> {
match module { match module {
Some(module) => self.linker.get_one_by_name(module, name), Some(module) => self.linker.get_one_by_name(module, Some(name)),
None => self None => self
.current .current
.as_ref() .as_ref()

View File

@@ -265,7 +265,7 @@ impl RunCommand {
} }
fn invoke_export(&self, linker: &Linker, name: &str) -> Result<()> { fn invoke_export(&self, linker: &Linker, name: &str) -> Result<()> {
let func = match linker.get_one_by_name("", name)?.into_func() { let func = match linker.get_one_by_name("", Some(name))?.into_func() {
Some(func) => func, Some(func) => func,
None => bail!("export of `{}` wasn't a function", name), None => bail!("export of `{}` wasn't a function", name),
}; };

View File

@@ -94,7 +94,7 @@ mod tests {
module module
.imports() .imports()
.map(|import| { .map(|import| {
assert_eq!("hostcall_read", import.name()); assert_eq!(Some("hostcall_read"), import.name());
let func = Func::wrap(&store, { let func = Func::wrap(&store, {
move |caller: Caller<'_>| { move |caller: Caller<'_>| {
let mem = caller.get_export("memory").unwrap().into_memory().unwrap(); let mem = caller.get_export("memory").unwrap().into_memory().unwrap();