mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-10 06:38:22 +00:00
Improved type reflection
This commit is contained in:
@@ -9,18 +9,36 @@ use std::fmt;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use wasm_bindgen::JsCast;
|
use wasm_bindgen::JsCast;
|
||||||
use wasm_bindgen::JsValue;
|
use wasm_bindgen::JsValue;
|
||||||
|
use wasmer_types::{ExternType, FunctionType, MemoryType};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
pub struct VMMemory {
|
||||||
|
pub(crate) memory: Memory,
|
||||||
|
pub(crate) ty: MemoryType,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VMMemory {
|
||||||
|
pub(crate) fn new(memory: Memory, ty: MemoryType) -> Self {
|
||||||
|
Self { memory, ty }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub type VMMemory = Memory;
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct VMFunction {
|
pub struct VMFunction {
|
||||||
pub(crate) function: Function,
|
pub(crate) function: Function,
|
||||||
|
pub(crate) ty: FunctionType,
|
||||||
pub(crate) environment: Option<Arc<RefCell<Box<dyn WasmerEnv>>>>,
|
pub(crate) environment: Option<Arc<RefCell<Box<dyn WasmerEnv>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VMFunction {
|
impl VMFunction {
|
||||||
pub(crate) fn new(function: Function, environment: Option<Box<dyn WasmerEnv>>) -> Self {
|
pub(crate) fn new(
|
||||||
|
function: Function,
|
||||||
|
ty: FunctionType,
|
||||||
|
environment: Option<Box<dyn WasmerEnv>>,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
function,
|
function,
|
||||||
|
ty,
|
||||||
environment: environment.map(|env| Arc::new(RefCell::new(env))),
|
environment: environment.map(|env| Arc::new(RefCell::new(env))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -63,22 +81,38 @@ pub enum Export {
|
|||||||
impl Export {
|
impl Export {
|
||||||
pub fn as_jsvalue(&self) -> &JsValue {
|
pub fn as_jsvalue(&self) -> &JsValue {
|
||||||
match self {
|
match self {
|
||||||
Export::Memory(js_wasm_memory) => js_wasm_memory.as_ref(),
|
Export::Memory(js_wasm_memory) => js_wasm_memory.memory.as_ref(),
|
||||||
Export::Function(js_func) => js_func.function.as_ref(),
|
Export::Function(js_func) => js_func.function.as_ref(),
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<JsValue> for Export {
|
impl From<(JsValue, ExternType)> for Export {
|
||||||
fn from(val: JsValue) -> Export {
|
fn from((val, extern_type): (JsValue, ExternType)) -> Export {
|
||||||
|
match extern_type {
|
||||||
|
ExternType::Memory(memory_type) => {
|
||||||
if val.is_instance_of::<Memory>() {
|
if val.is_instance_of::<Memory>() {
|
||||||
return Export::Memory(val.unchecked_into::<Memory>());
|
return Export::Memory(VMMemory::new(
|
||||||
|
val.unchecked_into::<Memory>(),
|
||||||
|
memory_type,
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
panic!("Extern type doesn't match js value type");
|
||||||
}
|
}
|
||||||
// Leave this last
|
|
||||||
else if val.is_instance_of::<Function>() {
|
|
||||||
return Export::Function(VMFunction::new(val.unchecked_into::<Function>(), None));
|
|
||||||
}
|
}
|
||||||
unimplemented!();
|
ExternType::Function(function_type) => {
|
||||||
|
if val.is_instance_of::<Function>() {
|
||||||
|
return Export::Function(VMFunction::new(
|
||||||
|
val.unchecked_into::<Function>(),
|
||||||
|
function_type,
|
||||||
|
None,
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
panic!("Extern type doesn't match js value type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => unimplemented!(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
37
lib/js-api/src/externals/function.rs
vendored
37
lib/js-api/src/externals/function.rs
vendored
@@ -2,7 +2,7 @@ use crate::exports::{ExportError, Exportable};
|
|||||||
use crate::externals::Extern;
|
use crate::externals::Extern;
|
||||||
use crate::store::Store;
|
use crate::store::Store;
|
||||||
use crate::types::{AsJs /* ValFuncRef */, Val};
|
use crate::types::{AsJs /* ValFuncRef */, Val};
|
||||||
use crate::FunctionType;
|
use crate::{FunctionType, ValType};
|
||||||
use core::any::Any;
|
use core::any::Any;
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
use wasm_bindgen::{JsCast, __rt::WasmRefCell};
|
use wasm_bindgen::{JsCast, __rt::WasmRefCell};
|
||||||
@@ -45,7 +45,6 @@ pub struct VMFunctionBody(u8);
|
|||||||
// #[derive(PartialEq)]
|
// #[derive(PartialEq)]
|
||||||
pub struct Function {
|
pub struct Function {
|
||||||
pub(crate) store: Store,
|
pub(crate) store: Store,
|
||||||
ty: FunctionType,
|
|
||||||
pub(crate) exported: VMFunction,
|
pub(crate) exported: VMFunction,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,8 +174,7 @@ impl Function {
|
|||||||
// let environment: Option<Arc>
|
// let environment: Option<Arc>
|
||||||
Self {
|
Self {
|
||||||
store: store.clone(),
|
store: store.clone(),
|
||||||
ty: ty.into(),
|
exported: VMFunction::new(func, ty.into(), None),
|
||||||
exported: VMFunction::new(func, None),
|
|
||||||
}
|
}
|
||||||
// Function::new
|
// Function::new
|
||||||
// let wrapped_func =
|
// let wrapped_func =
|
||||||
@@ -314,8 +312,7 @@ impl Function {
|
|||||||
let ty = FunctionType::new(Args::wasm_types(), Rets::wasm_types());
|
let ty = FunctionType::new(Args::wasm_types(), Rets::wasm_types());
|
||||||
Self {
|
Self {
|
||||||
store: store.clone(),
|
store: store.clone(),
|
||||||
ty,
|
exported: VMFunction::new(binded_func, ty, None),
|
||||||
exported: VMFunction::new(binded_func, None),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// let vmctx = VMFunctionEnvironment {
|
// let vmctx = VMFunctionEnvironment {
|
||||||
@@ -396,8 +393,7 @@ impl Function {
|
|||||||
// panic!("Function env {:?}", environment.type_id());
|
// panic!("Function env {:?}", environment.type_id());
|
||||||
Self {
|
Self {
|
||||||
store: store.clone(),
|
store: store.clone(),
|
||||||
ty,
|
exported: VMFunction::new(binded_func, ty, Some(environment)),
|
||||||
exported: VMFunction::new(binded_func, Some(environment)),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// let function = inner::Function::<Args, Rets>::new(func);
|
// let function = inner::Function::<Args, Rets>::new(func);
|
||||||
@@ -443,8 +439,7 @@ impl Function {
|
|||||||
/// assert_eq!(f.ty().results(), vec![Type::I32]);
|
/// assert_eq!(f.ty().results(), vec![Type::I32]);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn ty(&self) -> &FunctionType {
|
pub fn ty(&self) -> &FunctionType {
|
||||||
unimplemented!();
|
&self.exported.ty
|
||||||
// &self.exported.vm_function.signature
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the [`Store`] where the `Function` belongs.
|
/// Returns the [`Store`] where the `Function` belongs.
|
||||||
@@ -599,8 +594,25 @@ impl Function {
|
|||||||
}
|
}
|
||||||
let result =
|
let result =
|
||||||
js_sys::Reflect::apply(&self.exported.function, &wasm_bindgen::JsValue::NULL, &arr);
|
js_sys::Reflect::apply(&self.exported.function, &wasm_bindgen::JsValue::NULL, &arr);
|
||||||
// Ok(vec![Val::F64(result.unwrap().as_f64().unwrap())].into_boxed_slice())
|
|
||||||
Ok(Box::new([]))
|
let result_types = self.exported.ty.results();
|
||||||
|
match result_types.len() {
|
||||||
|
0 => Ok(Box::new([])),
|
||||||
|
1 => {
|
||||||
|
let num_value = result.unwrap().as_f64().unwrap();
|
||||||
|
let value = match result_types[0] {
|
||||||
|
ValType::I32 => Val::I32(num_value as _),
|
||||||
|
ValType::I64 => Val::I64(num_value as _),
|
||||||
|
ValType::F32 => Val::F32(num_value as _),
|
||||||
|
ValType::F64 => Val::F64(num_value),
|
||||||
|
_ => unimplemented!(),
|
||||||
|
};
|
||||||
|
Ok(vec![value].into_boxed_slice())
|
||||||
|
}
|
||||||
|
_ => unimplemented!(),
|
||||||
|
}
|
||||||
|
//
|
||||||
|
|
||||||
// if let Some(trampoline) = self.exported.vm_function.call_trampoline {
|
// if let Some(trampoline) = self.exported.vm_function.call_trampoline {
|
||||||
// let mut results = vec![Val::null(); self.result_arity()];
|
// let mut results = vec![Val::null(); self.result_arity()];
|
||||||
// self.call_wasm(trampoline, params, &mut results)?;
|
// self.call_wasm(trampoline, params, &mut results)?;
|
||||||
@@ -613,7 +625,6 @@ impl Function {
|
|||||||
pub(crate) fn from_vm_export(store: &Store, wasmer_export: VMFunction) -> Self {
|
pub(crate) fn from_vm_export(store: &Store, wasmer_export: VMFunction) -> Self {
|
||||||
Self {
|
Self {
|
||||||
store: store.clone(),
|
store: store.clone(),
|
||||||
ty: FunctionType::new(vec![], vec![]),
|
|
||||||
exported: wasmer_export,
|
exported: wasmer_export,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
20
lib/js-api/src/externals/memory.rs
vendored
20
lib/js-api/src/externals/memory.rs
vendored
@@ -49,7 +49,6 @@ extern "C" {
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Memory {
|
pub struct Memory {
|
||||||
store: Store,
|
store: Store,
|
||||||
ty: MemoryType,
|
|
||||||
vm_memory: VMMemory,
|
vm_memory: VMMemory,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,11 +74,11 @@ impl Memory {
|
|||||||
}
|
}
|
||||||
js_sys::Reflect::set(&descriptor, &"shared".into(), &ty.shared.into());
|
js_sys::Reflect::set(&descriptor, &"shared".into(), &ty.shared.into());
|
||||||
|
|
||||||
let memory = VMMemory::new(&descriptor).unwrap();
|
let js_memory = js_sys::WebAssembly::Memory::new(&descriptor).unwrap();
|
||||||
// unimplemented!();
|
|
||||||
|
let memory = VMMemory::new(js_memory, ty);
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
store: store.clone(),
|
store: store.clone(),
|
||||||
ty,
|
|
||||||
vm_memory: memory,
|
vm_memory: memory,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -98,9 +97,7 @@ impl Memory {
|
|||||||
/// assert_eq!(m.ty(), mt);
|
/// assert_eq!(m.ty(), mt);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn ty(&self) -> MemoryType {
|
pub fn ty(&self) -> MemoryType {
|
||||||
self.ty.clone()
|
self.vm_memory.ty.clone()
|
||||||
// unimplemented!();
|
|
||||||
// self.vm_memory.from.ty()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the [`Store`] where the `Memory` belongs.
|
/// Returns the [`Store`] where the `Memory` belongs.
|
||||||
@@ -158,7 +155,7 @@ impl Memory {
|
|||||||
|
|
||||||
/// Returns the size (in bytes) of the `Memory`.
|
/// Returns the size (in bytes) of the `Memory`.
|
||||||
pub fn data_size(&self) -> u64 {
|
pub fn data_size(&self) -> u64 {
|
||||||
let bytes = js_sys::Reflect::get(&self.vm_memory.buffer(), &"byteLength".into())
|
let bytes = js_sys::Reflect::get(&self.vm_memory.memory.buffer(), &"byteLength".into())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.as_f64()
|
.as_f64()
|
||||||
.unwrap() as u64;
|
.unwrap() as u64;
|
||||||
@@ -180,7 +177,7 @@ impl Memory {
|
|||||||
/// assert_eq!(m.size(), Pages(1));
|
/// assert_eq!(m.size(), Pages(1));
|
||||||
/// ```
|
/// ```
|
||||||
pub fn size(&self) -> Pages {
|
pub fn size(&self) -> Pages {
|
||||||
let bytes = js_sys::Reflect::get(&self.vm_memory.buffer(), &"byteLength".into())
|
let bytes = js_sys::Reflect::get(&self.vm_memory.memory.buffer(), &"byteLength".into())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.as_f64()
|
.as_f64()
|
||||||
.unwrap() as u64;
|
.unwrap() as u64;
|
||||||
@@ -225,7 +222,7 @@ impl Memory {
|
|||||||
let pages = delta.into();
|
let pages = delta.into();
|
||||||
// let new_pages = js_memory_grow(&self.vm_memory.unchecked_into::<JSMemory>(), pages.0).unwrap();
|
// let new_pages = js_memory_grow(&self.vm_memory.unchecked_into::<JSMemory>(), pages.0).unwrap();
|
||||||
// let new_pages = self.vm_memory.unchecked_ref::<JSMemory>().grow(pages.0);
|
// let new_pages = self.vm_memory.unchecked_ref::<JSMemory>().grow(pages.0);
|
||||||
let new_pages = self.vm_memory.grow(pages.0);
|
let new_pages = self.vm_memory.memory.grow(pages.0);
|
||||||
Ok(Pages(new_pages))
|
Ok(Pages(new_pages))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,13 +268,12 @@ impl Memory {
|
|||||||
|
|
||||||
/// example view
|
/// example view
|
||||||
pub fn uint8view(&self) -> js_sys::Uint8Array {
|
pub fn uint8view(&self) -> js_sys::Uint8Array {
|
||||||
js_sys::Uint8Array::new(&self.vm_memory.buffer())
|
js_sys::Uint8Array::new(&self.vm_memory.memory.buffer())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn from_vm_export(store: &Store, vm_memory: VMMemory) -> Self {
|
pub(crate) fn from_vm_export(store: &Store, vm_memory: VMMemory) -> Self {
|
||||||
Self {
|
Self {
|
||||||
store: store.clone(),
|
store: store.clone(),
|
||||||
ty: MemoryType::new(Pages(1), None, false),
|
|
||||||
vm_memory,
|
vm_memory,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use crate::export::Export;
|
||||||
use crate::exports::Exports;
|
use crate::exports::Exports;
|
||||||
use crate::externals::Extern;
|
use crate::externals::Extern;
|
||||||
use crate::module::Module;
|
use crate::module::Module;
|
||||||
@@ -117,8 +118,10 @@ impl Instance {
|
|||||||
.exports()
|
.exports()
|
||||||
.map(|export_type| {
|
.map(|export_type| {
|
||||||
let name = export_type.name();
|
let name = export_type.name();
|
||||||
let export = js_sys::Reflect::get(&instance_exports, &name.into()).unwrap();
|
let extern_type = export_type.ty().clone();
|
||||||
let extern_ = Extern::from_vm_export(store, export.into());
|
let js_export = js_sys::Reflect::get(&instance_exports, &name.into()).unwrap();
|
||||||
|
let export: Export = (js_export, extern_type).into();
|
||||||
|
let extern_ = Extern::from_vm_export(store, export);
|
||||||
(name.to_string(), extern_)
|
(name.to_string(), extern_)
|
||||||
})
|
})
|
||||||
.collect::<Exports>();
|
.collect::<Exports>();
|
||||||
|
|||||||
@@ -313,7 +313,7 @@ pub use crate::externals::{
|
|||||||
};
|
};
|
||||||
pub use crate::import_object::{ImportObject, ImportObjectIterator, LikeNamespace};
|
pub use crate::import_object::{ImportObject, ImportObjectIterator, LikeNamespace};
|
||||||
pub use crate::instance::{Instance, InstantiationError};
|
pub use crate::instance::{Instance, InstantiationError};
|
||||||
pub use crate::module::Module;
|
pub use crate::module::{Module, ModuleTypeHints};
|
||||||
pub use wasm_bindgen::JsValue as RuntimeError;
|
pub use wasm_bindgen::JsValue as RuntimeError;
|
||||||
// pub use crate::native::NativeFunc;
|
// pub use crate::native::NativeFunc;
|
||||||
pub use crate::ptr::{Array, Item, WasmPtr};
|
pub use crate::ptr::{Array, Item, WasmPtr};
|
||||||
|
|||||||
@@ -30,6 +30,23 @@ pub enum IoCompileError {
|
|||||||
Compile(#[from] CompileError),
|
Compile(#[from] CompileError),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// WebAssembly in the browser doesn't yet output the descriptor/types
|
||||||
|
/// corresponding to each extern (import and export).
|
||||||
|
///
|
||||||
|
/// This should be fixed once the JS-Types Wasm proposal is adopted
|
||||||
|
/// by the browsers:
|
||||||
|
/// https://github.com/WebAssembly/js-types/blob/master/proposals/js-types/Overview.md
|
||||||
|
///
|
||||||
|
/// Until that happens, we annotate the module with the expected
|
||||||
|
/// types so we can built on top of them at runtime.
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct ModuleTypeHints {
|
||||||
|
/// The type hints for the imported types
|
||||||
|
pub imports: Vec<ExternType>,
|
||||||
|
/// The type hints for the exported types
|
||||||
|
pub exports: Vec<ExternType>,
|
||||||
|
}
|
||||||
|
|
||||||
/// A WebAssembly Module contains stateless WebAssembly
|
/// A WebAssembly Module contains stateless WebAssembly
|
||||||
/// code that has already been compiled and can be instantiated
|
/// code that has already been compiled and can be instantiated
|
||||||
/// multiple times.
|
/// multiple times.
|
||||||
@@ -43,6 +60,8 @@ pub struct Module {
|
|||||||
store: Store,
|
store: Store,
|
||||||
module: WebAssembly::Module,
|
module: WebAssembly::Module,
|
||||||
name: Option<String>,
|
name: Option<String>,
|
||||||
|
// WebAssembly type hints
|
||||||
|
type_hints: Option<ModuleTypeHints>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Module {
|
impl Module {
|
||||||
@@ -148,6 +167,7 @@ impl Module {
|
|||||||
Ok(Self {
|
Ok(Self {
|
||||||
store: store.clone(),
|
store: store.clone(),
|
||||||
module,
|
module,
|
||||||
|
type_hints: None,
|
||||||
name: None,
|
name: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -352,6 +372,37 @@ impl Module {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the type hints for this module.
|
||||||
|
///
|
||||||
|
/// Returns an error if the hints doesn't match the shape of
|
||||||
|
/// import or export types of the module.
|
||||||
|
pub fn set_type_hints(&mut self, type_hints: ModuleTypeHints) -> Result<(), String> {
|
||||||
|
let exports = WebAssembly::Module::exports(&self.module);
|
||||||
|
// Check exports
|
||||||
|
if exports.length() as usize != type_hints.exports.len() {
|
||||||
|
return Err("The exports length must match the type hints lenght".to_owned());
|
||||||
|
}
|
||||||
|
for (i, val) in exports.iter().enumerate() {
|
||||||
|
let kind = Reflect::get(val.as_ref(), &"kind".into())
|
||||||
|
.unwrap()
|
||||||
|
.as_string()
|
||||||
|
.unwrap();
|
||||||
|
// It is safe to unwrap as we have already checked for the exports length
|
||||||
|
let type_hint = type_hints.exports.get(i).unwrap();
|
||||||
|
let expected_kind = match type_hint {
|
||||||
|
ExternType::Function(_) => "function",
|
||||||
|
ExternType::Global(_) => "global",
|
||||||
|
ExternType::Memory(_) => "memory",
|
||||||
|
ExternType::Table(_) => "table",
|
||||||
|
};
|
||||||
|
if expected_kind != kind.as_str() {
|
||||||
|
return Err(format!("The provided type hint for the export {} is {} which doesn't match the expected kind: {}", i, kind.as_str(), expected_kind));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.type_hints = Some(type_hints);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
// /// Get the custom sections of the module given a `name`.
|
// /// Get the custom sections of the module given a `name`.
|
||||||
// pub fn custom_sections<'a>(&'a self, name: &'a str) -> impl Iterator<Item = Arc<[u8]>> + 'a {
|
// pub fn custom_sections<'a>(&'a self, name: &'a str) -> impl Iterator<Item = Arc<[u8]>> + 'a {
|
||||||
// self.custom_sections
|
// self.custom_sections
|
||||||
@@ -391,7 +442,8 @@ impl Module {
|
|||||||
let exports = WebAssembly::Module::exports(&self.module);
|
let exports = WebAssembly::Module::exports(&self.module);
|
||||||
let iter = exports
|
let iter = exports
|
||||||
.iter()
|
.iter()
|
||||||
.map(move |val| {
|
.enumerate()
|
||||||
|
.map(move |(i, val)| {
|
||||||
let field = Reflect::get(val.as_ref(), &"name".into())
|
let field = Reflect::get(val.as_ref(), &"name".into())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.as_string()
|
.as_string()
|
||||||
@@ -400,7 +452,15 @@ impl Module {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.as_string()
|
.as_string()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let extern_type = match kind.as_str() {
|
let type_hint = self
|
||||||
|
.type_hints
|
||||||
|
.as_ref()
|
||||||
|
.map(|hints| hints.exports.get(i).unwrap().clone());
|
||||||
|
let extern_type = if let Some(hint) = type_hint {
|
||||||
|
hint
|
||||||
|
} else {
|
||||||
|
// The default types
|
||||||
|
match kind.as_str() {
|
||||||
"function" => {
|
"function" => {
|
||||||
let func_type = FunctionType::new(vec![], vec![]);
|
let func_type = FunctionType::new(vec![], vec![]);
|
||||||
ExternType::Function(func_type)
|
ExternType::Function(func_type)
|
||||||
@@ -418,6 +478,7 @@ impl Module {
|
|||||||
ExternType::Table(table_type)
|
ExternType::Table(table_type)
|
||||||
}
|
}
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
|
}
|
||||||
};
|
};
|
||||||
ExportType::new(&field, extern_type)
|
ExportType::new(&field, extern_type)
|
||||||
})
|
})
|
||||||
@@ -454,3 +515,472 @@ impl fmt::Debug for Module {
|
|||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// use anyhow::{bail, Result};
|
||||||
|
// use std::fmt::Write;
|
||||||
|
// use wasmparser::*;
|
||||||
|
|
||||||
|
// pub fn wasm_types(bytes: &[u8]) -> Result<ModuleTypes> {
|
||||||
|
// let mut d = ModuleTypes::new(bytes);
|
||||||
|
// d.parse()?;
|
||||||
|
// Ok(d.dst)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// struct ModuleTypes<'a> {
|
||||||
|
// bytes: &'a [u8],
|
||||||
|
// cur: usize,
|
||||||
|
// }
|
||||||
|
|
||||||
|
// #[derive(Default)]
|
||||||
|
// struct ModuleTypesIndices {
|
||||||
|
// funcs: u32,
|
||||||
|
// globals: u32,
|
||||||
|
// tables: u32,
|
||||||
|
// memories: u32,
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const NBYTES: usize = 4;
|
||||||
|
|
||||||
|
// impl<'a> ModuleTypes<'a> {
|
||||||
|
// fn new(bytes: &'a [u8]) -> Dump<'a> {
|
||||||
|
// Dump {
|
||||||
|
// bytes,
|
||||||
|
// cur: 0,
|
||||||
|
// nesting: 0,
|
||||||
|
// state: String::new(),
|
||||||
|
// dst: String::new(),
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn run(&mut self) -> Result<()> {
|
||||||
|
// self.print_module()?;
|
||||||
|
// assert_eq!(self.cur, self.bytes.len());
|
||||||
|
// Ok(())
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn print_module(&mut self) -> Result<()> {
|
||||||
|
// let mut stack = Vec::new();
|
||||||
|
// let mut i = ModuleTypesIndices::default();
|
||||||
|
// self.nesting += 1;
|
||||||
|
|
||||||
|
// for item in Parser::new(0).parse_all(self.bytes) {
|
||||||
|
// match item? {
|
||||||
|
// Payload::Version { num, range } => {
|
||||||
|
// write!(self.state, "version {}", num)?;
|
||||||
|
// self.print(range.end)?;
|
||||||
|
// }
|
||||||
|
// Payload::TypeSection(s) => self.section(s, "type", |me, end, t| {
|
||||||
|
// write!(me.state, "[type {}] {:?}", i.types, t)?;
|
||||||
|
// i.types += 1;
|
||||||
|
// me.print(end)
|
||||||
|
// })?,
|
||||||
|
// Payload::ImportSection(s) => self.section(s, "import", |me, end, imp| {
|
||||||
|
// write!(me.state, "import ")?;
|
||||||
|
// match imp.ty {
|
||||||
|
// ImportSectionEntryType::Function(_) => {
|
||||||
|
// write!(me.state, "[func {}]", i.funcs)?;
|
||||||
|
// i.funcs += 1;
|
||||||
|
// }
|
||||||
|
// ImportSectionEntryType::Memory(_) => {
|
||||||
|
// write!(me.state, "[memory {}]", i.memories)?;
|
||||||
|
// i.memories += 1;
|
||||||
|
// }
|
||||||
|
// ImportSectionEntryType::Tag(_) => {
|
||||||
|
// write!(me.state, "[tag {}]", i.tags)?;
|
||||||
|
// i.tags += 1;
|
||||||
|
// }
|
||||||
|
// ImportSectionEntryType::Table(_) => {
|
||||||
|
// write!(me.state, "[table {}]", i.tables)?;
|
||||||
|
// i.tables += 1;
|
||||||
|
// }
|
||||||
|
// ImportSectionEntryType::Global(_) => {
|
||||||
|
// write!(me.state, "[global {}]", i.globals)?;
|
||||||
|
// i.globals += 1;
|
||||||
|
// }
|
||||||
|
// ImportSectionEntryType::Instance(_) => {
|
||||||
|
// write!(me.state, "[instance {}]", i.instances)?;
|
||||||
|
// i.instances += 1;
|
||||||
|
// }
|
||||||
|
// ImportSectionEntryType::Module(_) => {
|
||||||
|
// write!(me.state, "[module {}]", i.modules)?;
|
||||||
|
// i.modules += 1;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// write!(me.state, " {:?}", imp)?;
|
||||||
|
// me.print(end)
|
||||||
|
// })?,
|
||||||
|
// Payload::FunctionSection(s) => {
|
||||||
|
// let mut cnt = 0;
|
||||||
|
// self.section(s, "func", |me, end, f| {
|
||||||
|
// write!(me.state, "[func {}] type {:?}", cnt + i.funcs, f)?;
|
||||||
|
// cnt += 1;
|
||||||
|
// me.print(end)
|
||||||
|
// })?
|
||||||
|
// }
|
||||||
|
// Payload::TableSection(s) => self.section(s, "table", |me, end, t| {
|
||||||
|
// write!(me.state, "[table {}] {:?}", i.tables, t)?;
|
||||||
|
// i.tables += 1;
|
||||||
|
// me.print(end)
|
||||||
|
// })?,
|
||||||
|
// Payload::MemorySection(s) => self.section(s, "memory", |me, end, m| {
|
||||||
|
// write!(me.state, "[memory {}] {:?}", i.memories, m)?;
|
||||||
|
// i.memories += 1;
|
||||||
|
// me.print(end)
|
||||||
|
// })?,
|
||||||
|
// Payload::TagSection(s) => self.section(s, "tag", |me, end, m| {
|
||||||
|
// write!(me.state, "[tag {}] {:?}", i.tags, m)?;
|
||||||
|
// i.tags += 1;
|
||||||
|
// me.print(end)
|
||||||
|
// })?,
|
||||||
|
// Payload::ExportSection(s) => self.section(s, "export", |me, end, e| {
|
||||||
|
// write!(me.state, "export {:?}", e)?;
|
||||||
|
// me.print(end)
|
||||||
|
// })?,
|
||||||
|
// Payload::GlobalSection(s) => self.section(s, "global", |me, _end, g| {
|
||||||
|
// write!(me.state, "[global {}] {:?}", i.globals, g.ty)?;
|
||||||
|
// i.globals += 1;
|
||||||
|
// me.print(g.init_expr.get_binary_reader().original_position())?;
|
||||||
|
// me.print_ops(g.init_expr.get_operators_reader())
|
||||||
|
// })?,
|
||||||
|
// Payload::AliasSection(s) => self.section(s, "alias", |me, end, a| {
|
||||||
|
// write!(me.state, "[alias] {:?}", a)?;
|
||||||
|
// match a {
|
||||||
|
// Alias::InstanceExport { kind, .. } => match kind {
|
||||||
|
// ExternalKind::Function => i.funcs += 1,
|
||||||
|
// ExternalKind::Global => i.globals += 1,
|
||||||
|
// ExternalKind::Module => i.modules += 1,
|
||||||
|
// ExternalKind::Table => i.tables += 1,
|
||||||
|
// ExternalKind::Instance => i.instances += 1,
|
||||||
|
// ExternalKind::Memory => i.memories += 1,
|
||||||
|
// ExternalKind::Tag => i.tags += 1,
|
||||||
|
// ExternalKind::Type => i.types += 1,
|
||||||
|
// },
|
||||||
|
// Alias::OuterType { .. } => i.types += 1,
|
||||||
|
// Alias::OuterModule { .. } => i.modules += 1,
|
||||||
|
// }
|
||||||
|
// me.print(end)
|
||||||
|
// })?,
|
||||||
|
// Payload::InstanceSection(s) => {
|
||||||
|
// self.section(s, "instance", |me, _end, instance| {
|
||||||
|
// write!(
|
||||||
|
// me.state,
|
||||||
|
// "[instance {}] instantiate module:{}",
|
||||||
|
// i.instances,
|
||||||
|
// instance.module()
|
||||||
|
// )?;
|
||||||
|
// me.print(instance.original_position())?;
|
||||||
|
// i.instances += 1;
|
||||||
|
// me.print_iter(instance.args()?, |me, end, arg| {
|
||||||
|
// write!(me.state, "[instantiate arg] {:?}", arg)?;
|
||||||
|
// me.print(end)
|
||||||
|
// })
|
||||||
|
// })?
|
||||||
|
// }
|
||||||
|
// Payload::StartSection { func, range } => {
|
||||||
|
// write!(self.state, "start section")?;
|
||||||
|
// self.print(range.start)?;
|
||||||
|
// write!(self.state, "start function {}", func)?;
|
||||||
|
// self.print(range.end)?;
|
||||||
|
// }
|
||||||
|
// Payload::DataCountSection { count, range } => {
|
||||||
|
// write!(self.state, "data count section")?;
|
||||||
|
// self.print(range.start)?;
|
||||||
|
// write!(self.state, "data count {}", count)?;
|
||||||
|
// self.print(range.end)?;
|
||||||
|
// }
|
||||||
|
// Payload::ElementSection(s) => self.section(s, "element", |me, _end, i| {
|
||||||
|
// write!(me.state, "element {:?}", i.ty)?;
|
||||||
|
// let mut items = i.items.get_items_reader()?;
|
||||||
|
// match i.kind {
|
||||||
|
// ElementKind::Passive => {
|
||||||
|
// write!(me.state, " passive, {} items", items.get_count())?;
|
||||||
|
// }
|
||||||
|
// ElementKind::Active {
|
||||||
|
// table_index,
|
||||||
|
// init_expr,
|
||||||
|
// } => {
|
||||||
|
// write!(me.state, " table[{}]", table_index)?;
|
||||||
|
// me.print(init_expr.get_binary_reader().original_position())?;
|
||||||
|
// me.print_ops(init_expr.get_operators_reader())?;
|
||||||
|
// write!(me.state, "{} items", items.get_count())?;
|
||||||
|
// }
|
||||||
|
// ElementKind::Declared => {
|
||||||
|
// write!(me.state, " declared {} items", items.get_count())?;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// me.print(items.original_position())?;
|
||||||
|
// for _ in 0..items.get_count() {
|
||||||
|
// let item = items.read()?;
|
||||||
|
// write!(me.state, "item {:?}", item)?;
|
||||||
|
// me.print(items.original_position())?;
|
||||||
|
// }
|
||||||
|
// Ok(())
|
||||||
|
// })?,
|
||||||
|
|
||||||
|
// Payload::DataSection(s) => self.section(s, "data", |me, end, i| {
|
||||||
|
// match i.kind {
|
||||||
|
// DataKind::Passive => {
|
||||||
|
// write!(me.state, "data passive")?;
|
||||||
|
// me.print(end - i.data.len())?;
|
||||||
|
// }
|
||||||
|
// DataKind::Active {
|
||||||
|
// memory_index,
|
||||||
|
// init_expr,
|
||||||
|
// } => {
|
||||||
|
// write!(me.state, "data memory[{}]", memory_index)?;
|
||||||
|
// me.print(init_expr.get_binary_reader().original_position())?;
|
||||||
|
// me.print_ops(init_expr.get_operators_reader())?;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// write!(me.dst, "0x{:04x} |", me.cur)?;
|
||||||
|
// for _ in 0..NBYTES {
|
||||||
|
// write!(me.dst, "---")?;
|
||||||
|
// }
|
||||||
|
// write!(me.dst, "-| ... {} bytes of data\n", i.data.len())?;
|
||||||
|
// me.cur = end;
|
||||||
|
// Ok(())
|
||||||
|
// })?,
|
||||||
|
|
||||||
|
// Payload::CodeSectionStart { count, range, size } => {
|
||||||
|
// write!(self.state, "code section")?;
|
||||||
|
// self.print(range.start)?;
|
||||||
|
// write!(self.state, "{} count", count)?;
|
||||||
|
// self.print(range.end - size as usize)?;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Payload::CodeSectionEntry(body) => {
|
||||||
|
// write!(
|
||||||
|
// self.dst,
|
||||||
|
// "============== func {} ====================\n",
|
||||||
|
// i.funcs
|
||||||
|
// )?;
|
||||||
|
// i.funcs += 1;
|
||||||
|
// write!(self.state, "size of function")?;
|
||||||
|
// self.print(body.get_binary_reader().original_position())?;
|
||||||
|
// let mut locals = body.get_locals_reader()?;
|
||||||
|
// write!(self.state, "{} local blocks", locals.get_count())?;
|
||||||
|
// self.print(locals.original_position())?;
|
||||||
|
// for _ in 0..locals.get_count() {
|
||||||
|
// let (amt, ty) = locals.read()?;
|
||||||
|
// write!(self.state, "{} locals of type {:?}", amt, ty)?;
|
||||||
|
// self.print(locals.original_position())?;
|
||||||
|
// }
|
||||||
|
// self.print_ops(body.get_operators_reader()?)?;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Payload::ModuleSectionStart { count, range, size } => {
|
||||||
|
// write!(self.state, "module section")?;
|
||||||
|
// self.print(range.start)?;
|
||||||
|
// write!(self.state, "{} count", count)?;
|
||||||
|
// self.print(range.end - size as usize)?;
|
||||||
|
// }
|
||||||
|
// Payload::ModuleSectionEntry { parser: _, range } => {
|
||||||
|
// write!(self.state, "inline module size")?;
|
||||||
|
// self.print(range.start)?;
|
||||||
|
// self.nesting += 1;
|
||||||
|
// stack.push(i);
|
||||||
|
// i = Indices::default();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Payload::CustomSection {
|
||||||
|
// name,
|
||||||
|
// data_offset,
|
||||||
|
// data,
|
||||||
|
// range,
|
||||||
|
// } => {
|
||||||
|
// write!(self.state, "custom section")?;
|
||||||
|
// self.print(range.start)?;
|
||||||
|
// write!(self.state, "name: {:?}", name)?;
|
||||||
|
// self.print(data_offset)?;
|
||||||
|
// if name == "name" {
|
||||||
|
// let mut iter = NameSectionReader::new(data, data_offset)?;
|
||||||
|
// while !iter.eof() {
|
||||||
|
// self.print_custom_name_section(iter.read()?, iter.original_position())?;
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// write!(self.dst, "0x{:04x} |", self.cur)?;
|
||||||
|
// for _ in 0..NBYTES {
|
||||||
|
// write!(self.dst, "---")?;
|
||||||
|
// }
|
||||||
|
// write!(self.dst, "-| ... {} bytes of data\n", data.len())?;
|
||||||
|
// self.cur += data.len();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// Payload::UnknownSection {
|
||||||
|
// id,
|
||||||
|
// range,
|
||||||
|
// contents,
|
||||||
|
// } => {
|
||||||
|
// write!(self.state, "unknown section: {}", id)?;
|
||||||
|
// self.print(range.start)?;
|
||||||
|
// write!(self.dst, "0x{:04x} |", self.cur)?;
|
||||||
|
// for _ in 0..NBYTES {
|
||||||
|
// write!(self.dst, "---")?;
|
||||||
|
// }
|
||||||
|
// write!(self.dst, "-| ... {} bytes of data\n", contents.len())?;
|
||||||
|
// self.cur += contents.len();
|
||||||
|
// }
|
||||||
|
// Payload::End => {
|
||||||
|
// self.nesting -= 1;
|
||||||
|
// if self.nesting > 0 {
|
||||||
|
// i = stack.pop().unwrap();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Ok(())
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn print_name_map(&mut self, thing: &str, n: NameMap<'_>) -> Result<()> {
|
||||||
|
// write!(self.state, "{} names", thing)?;
|
||||||
|
// self.print(n.original_position())?;
|
||||||
|
// let mut map = n.get_map()?;
|
||||||
|
// write!(self.state, "{} count", map.get_count())?;
|
||||||
|
// self.print(map.original_position())?;
|
||||||
|
// for _ in 0..map.get_count() {
|
||||||
|
// write!(self.state, "{:?}", map.read()?)?;
|
||||||
|
// self.print(map.original_position())?;
|
||||||
|
// }
|
||||||
|
// Ok(())
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn print_indirect_name_map(
|
||||||
|
// &mut self,
|
||||||
|
// thing_a: &str,
|
||||||
|
// thing_b: &str,
|
||||||
|
// n: IndirectNameMap<'_>,
|
||||||
|
// ) -> Result<()> {
|
||||||
|
// write!(self.state, "{} names", thing_b)?;
|
||||||
|
// self.print(n.original_position())?;
|
||||||
|
// let mut outer_map = n.get_indirect_map()?;
|
||||||
|
// write!(self.state, "{} count", outer_map.get_indirect_count())?;
|
||||||
|
// self.print(outer_map.original_position())?;
|
||||||
|
// for _ in 0..outer_map.get_indirect_count() {
|
||||||
|
// let inner = outer_map.read()?;
|
||||||
|
// write!(
|
||||||
|
// self.state,
|
||||||
|
// "{} {} {}s",
|
||||||
|
// thing_a, inner.indirect_index, thing_b,
|
||||||
|
// )?;
|
||||||
|
// self.print(inner.original_position())?;
|
||||||
|
// let mut map = inner.get_map()?;
|
||||||
|
// write!(self.state, "{} count", map.get_count())?;
|
||||||
|
// self.print(map.original_position())?;
|
||||||
|
// for _ in 0..map.get_count() {
|
||||||
|
// write!(self.state, "{:?}", map.read()?)?;
|
||||||
|
// self.print(map.original_position())?;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// Ok(())
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn print_custom_name_section(&mut self, name: Name<'_>, end: usize) -> Result<()> {
|
||||||
|
// match name {
|
||||||
|
// Name::Module(n) => {
|
||||||
|
// write!(self.state, "module name")?;
|
||||||
|
// self.print(n.original_position())?;
|
||||||
|
// write!(self.state, "{:?}", n.get_name()?)?;
|
||||||
|
// self.print(end)?;
|
||||||
|
// }
|
||||||
|
// Name::Function(n) => self.print_name_map("function", n)?,
|
||||||
|
// Name::Local(n) => self.print_indirect_name_map("function", "local", n)?,
|
||||||
|
// Name::Label(n) => self.print_indirect_name_map("function", "label", n)?,
|
||||||
|
// Name::Type(n) => self.print_name_map("type", n)?,
|
||||||
|
// Name::Table(n) => self.print_name_map("table", n)?,
|
||||||
|
// Name::Memory(n) => self.print_name_map("memory", n)?,
|
||||||
|
// Name::Global(n) => self.print_name_map("global", n)?,
|
||||||
|
// Name::Element(n) => self.print_name_map("element", n)?,
|
||||||
|
// Name::Data(n) => self.print_name_map("data", n)?,
|
||||||
|
// Name::Unknown { ty, range, .. } => {
|
||||||
|
// write!(self.state, "unknown names: {}", ty)?;
|
||||||
|
// self.print(range.start)?;
|
||||||
|
// self.print(end)?;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// Ok(())
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn section<T>(
|
||||||
|
// &mut self,
|
||||||
|
// iter: T,
|
||||||
|
// name: &str,
|
||||||
|
// print: impl FnMut(&mut Self, usize, T::Item) -> Result<()>,
|
||||||
|
// ) -> Result<()>
|
||||||
|
// where
|
||||||
|
// T: SectionReader + SectionWithLimitedItems,
|
||||||
|
// {
|
||||||
|
// write!(self.state, "{} section", name)?;
|
||||||
|
// self.print(iter.range().start)?;
|
||||||
|
// self.print_iter(iter, print)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn print_iter<T>(
|
||||||
|
// &mut self,
|
||||||
|
// mut iter: T,
|
||||||
|
// mut print: impl FnMut(&mut Self, usize, T::Item) -> Result<()>,
|
||||||
|
// ) -> Result<()>
|
||||||
|
// where
|
||||||
|
// T: SectionReader + SectionWithLimitedItems,
|
||||||
|
// {
|
||||||
|
// write!(self.state, "{} count", iter.get_count())?;
|
||||||
|
// self.print(iter.original_position())?;
|
||||||
|
// for _ in 0..iter.get_count() {
|
||||||
|
// let item = iter.read()?;
|
||||||
|
// print(self, iter.original_position(), item)?;
|
||||||
|
// }
|
||||||
|
// if !iter.eof() {
|
||||||
|
// bail!("too many bytes in section");
|
||||||
|
// }
|
||||||
|
// Ok(())
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn print_ops(&mut self, mut i: OperatorsReader) -> Result<()> {
|
||||||
|
// while !i.eof() {
|
||||||
|
// match i.read() {
|
||||||
|
// Ok(op) => write!(self.state, "{:?}", op)?,
|
||||||
|
// Err(_) => write!(self.state, "??")?,
|
||||||
|
// }
|
||||||
|
// self.print(i.original_position())?;
|
||||||
|
// }
|
||||||
|
// Ok(())
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn print(&mut self, end: usize) -> Result<()> {
|
||||||
|
// assert!(
|
||||||
|
// self.cur < end,
|
||||||
|
// "{:#x} >= {:#x}\ntrying to print: {}\n{}",
|
||||||
|
// self.cur,
|
||||||
|
// end,
|
||||||
|
// self.state,
|
||||||
|
// self.dst
|
||||||
|
// );
|
||||||
|
// let bytes = &self.bytes[self.cur..end];
|
||||||
|
// for _ in 0..self.nesting - 1 {
|
||||||
|
// write!(self.dst, " ")?;
|
||||||
|
// }
|
||||||
|
// write!(self.dst, "0x{:04x} |", self.cur)?;
|
||||||
|
// for (i, chunk) in bytes.chunks(NBYTES).enumerate() {
|
||||||
|
// if i > 0 {
|
||||||
|
// for _ in 0..self.nesting - 1 {
|
||||||
|
// write!(self.dst, " ")?;
|
||||||
|
// }
|
||||||
|
// self.dst.push_str(" |");
|
||||||
|
// }
|
||||||
|
// for j in 0..NBYTES {
|
||||||
|
// match chunk.get(j) {
|
||||||
|
// Some(b) => write!(self.dst, " {:02x}", b)?,
|
||||||
|
// None => write!(self.dst, " ")?,
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// if i == 0 {
|
||||||
|
// self.dst.push_str(" | ");
|
||||||
|
// self.dst.push_str(&self.state);
|
||||||
|
// self.state.truncate(0);
|
||||||
|
// }
|
||||||
|
// self.dst.push_str("\n");
|
||||||
|
// }
|
||||||
|
// self.cur = end;
|
||||||
|
// Ok(())
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ fn test_exported_memory() {
|
|||||||
#[wasm_bindgen_test]
|
#[wasm_bindgen_test]
|
||||||
fn test_exported_function() {
|
fn test_exported_function() {
|
||||||
let store = Store::default();
|
let store = Store::default();
|
||||||
let module = Module::new(
|
let mut module = Module::new(
|
||||||
&store,
|
&store,
|
||||||
br#"
|
br#"
|
||||||
(module
|
(module
|
||||||
@@ -78,6 +78,13 @@ fn test_exported_function() {
|
|||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
module.set_type_hints(ModuleTypeHints {
|
||||||
|
imports: vec![],
|
||||||
|
exports: vec![ExternType::Function(FunctionType::new(
|
||||||
|
vec![],
|
||||||
|
vec![Type::I32],
|
||||||
|
))],
|
||||||
|
});
|
||||||
|
|
||||||
let import_object = imports! {};
|
let import_object = imports! {};
|
||||||
let instance = Instance::new(&module, &import_object).unwrap();
|
let instance = Instance::new(&module, &import_object).unwrap();
|
||||||
@@ -87,8 +94,12 @@ fn test_exported_function() {
|
|||||||
// assert_eq!(memory.data_size(), 65536);
|
// assert_eq!(memory.data_size(), 65536);
|
||||||
|
|
||||||
let get_magic = instance.exports.get_function("get_magic").unwrap();
|
let get_magic = instance.exports.get_function("get_magic").unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
get_magic.ty().clone(),
|
||||||
|
FunctionType::new(vec![], vec![Type::I32])
|
||||||
|
);
|
||||||
|
|
||||||
let expected = vec![Val::F64(42.0)].into_boxed_slice();
|
let expected = vec![Val::I32(42)].into_boxed_slice();
|
||||||
assert_eq!(get_magic.call(&[]), Ok(expected));
|
assert_eq!(get_magic.call(&[]), Ok(expected));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,7 +133,7 @@ fn test_exported_function() {
|
|||||||
#[wasm_bindgen_test]
|
#[wasm_bindgen_test]
|
||||||
fn test_imported_function_dynamic() {
|
fn test_imported_function_dynamic() {
|
||||||
let store = Store::default();
|
let store = Store::default();
|
||||||
let module = Module::new(
|
let mut module = Module::new(
|
||||||
&store,
|
&store,
|
||||||
br#"
|
br#"
|
||||||
(module
|
(module
|
||||||
@@ -134,6 +145,16 @@ fn test_imported_function_dynamic() {
|
|||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
module.set_type_hints(ModuleTypeHints {
|
||||||
|
imports: vec![ExternType::Function(FunctionType::new(
|
||||||
|
vec![Type::I32],
|
||||||
|
vec![Type::I32],
|
||||||
|
))],
|
||||||
|
exports: vec![ExternType::Function(FunctionType::new(
|
||||||
|
vec![Type::I32],
|
||||||
|
vec![Type::I32],
|
||||||
|
))],
|
||||||
|
});
|
||||||
|
|
||||||
let imported_signature = FunctionType::new(vec![Type::I32], vec![Type::I32]);
|
let imported_signature = FunctionType::new(vec![Type::I32], vec![Type::I32]);
|
||||||
let imported = Function::new(&store, &imported_signature, |args| {
|
let imported = Function::new(&store, &imported_signature, |args| {
|
||||||
@@ -156,14 +177,14 @@ fn test_imported_function_dynamic() {
|
|||||||
|
|
||||||
let exported = instance.exports.get_function("exported").unwrap();
|
let exported = instance.exports.get_function("exported").unwrap();
|
||||||
|
|
||||||
let expected = vec![Val::F64(5.0)].into_boxed_slice();
|
let expected = vec![Val::I32(5)].into_boxed_slice();
|
||||||
assert_eq!(exported.call(&[Val::I32(4)]), Ok(expected));
|
assert_eq!(exported.call(&[Val::I32(4)]), Ok(expected));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[wasm_bindgen_test]
|
#[wasm_bindgen_test]
|
||||||
fn test_imported_function_native() {
|
fn test_imported_function_native() {
|
||||||
let store = Store::default();
|
let store = Store::default();
|
||||||
let module = Module::new(
|
let mut module = Module::new(
|
||||||
&store,
|
&store,
|
||||||
br#"
|
br#"
|
||||||
(module
|
(module
|
||||||
@@ -175,6 +196,16 @@ fn test_imported_function_native() {
|
|||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
module.set_type_hints(ModuleTypeHints {
|
||||||
|
imports: vec![ExternType::Function(FunctionType::new(
|
||||||
|
vec![Type::I32],
|
||||||
|
vec![Type::I32],
|
||||||
|
))],
|
||||||
|
exports: vec![ExternType::Function(FunctionType::new(
|
||||||
|
vec![Type::I32],
|
||||||
|
vec![Type::I32],
|
||||||
|
))],
|
||||||
|
});
|
||||||
|
|
||||||
fn imported_fn(arg: u32) -> u32 {
|
fn imported_fn(arg: u32) -> u32 {
|
||||||
return arg + 1;
|
return arg + 1;
|
||||||
@@ -195,14 +226,14 @@ fn test_imported_function_native() {
|
|||||||
|
|
||||||
let exported = instance.exports.get_function("exported").unwrap();
|
let exported = instance.exports.get_function("exported").unwrap();
|
||||||
|
|
||||||
let expected = vec![Val::F64(5.0)].into_boxed_slice();
|
let expected = vec![Val::I32(5)].into_boxed_slice();
|
||||||
assert_eq!(exported.call(&[Val::I32(4)]), Ok(expected));
|
assert_eq!(exported.call(&[Val::I32(4)]), Ok(expected));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[wasm_bindgen_test]
|
#[wasm_bindgen_test]
|
||||||
fn test_imported_function_native_with_env() {
|
fn test_imported_function_native_with_env() {
|
||||||
let store = Store::default();
|
let store = Store::default();
|
||||||
let module = Module::new(
|
let mut module = Module::new(
|
||||||
&store,
|
&store,
|
||||||
br#"
|
br#"
|
||||||
(module
|
(module
|
||||||
@@ -214,6 +245,16 @@ fn test_imported_function_native_with_env() {
|
|||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
module.set_type_hints(ModuleTypeHints {
|
||||||
|
imports: vec![ExternType::Function(FunctionType::new(
|
||||||
|
vec![Type::I32],
|
||||||
|
vec![Type::I32],
|
||||||
|
))],
|
||||||
|
exports: vec![ExternType::Function(FunctionType::new(
|
||||||
|
vec![Type::I32],
|
||||||
|
vec![Type::I32],
|
||||||
|
))],
|
||||||
|
});
|
||||||
|
|
||||||
#[derive(WasmerEnv, Clone)]
|
#[derive(WasmerEnv, Clone)]
|
||||||
struct Env {
|
struct Env {
|
||||||
@@ -239,14 +280,14 @@ fn test_imported_function_native_with_env() {
|
|||||||
|
|
||||||
let exported = instance.exports.get_function("exported").unwrap();
|
let exported = instance.exports.get_function("exported").unwrap();
|
||||||
|
|
||||||
let expected = vec![Val::F64(12.0)].into_boxed_slice();
|
let expected = vec![Val::I32(12)].into_boxed_slice();
|
||||||
assert_eq!(exported.call(&[Val::I32(4)]), Ok(expected));
|
assert_eq!(exported.call(&[Val::I32(4)]), Ok(expected));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[wasm_bindgen_test]
|
#[wasm_bindgen_test]
|
||||||
fn test_imported_function_native_with_wasmer_env() {
|
fn test_imported_function_native_with_wasmer_env() {
|
||||||
let store = Store::default();
|
let store = Store::default();
|
||||||
let module = Module::new(
|
let mut module = Module::new(
|
||||||
&store,
|
&store,
|
||||||
br#"
|
br#"
|
||||||
(module
|
(module
|
||||||
@@ -259,6 +300,16 @@ fn test_imported_function_native_with_wasmer_env() {
|
|||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
module.set_type_hints(ModuleTypeHints {
|
||||||
|
imports: vec![ExternType::Function(FunctionType::new(
|
||||||
|
vec![Type::I32],
|
||||||
|
vec![Type::I32],
|
||||||
|
))],
|
||||||
|
exports: vec![
|
||||||
|
ExternType::Function(FunctionType::new(vec![Type::I32], vec![Type::I32])),
|
||||||
|
ExternType::Memory(MemoryType::new(Pages(1), None, false)),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
#[derive(WasmerEnv, Clone)]
|
#[derive(WasmerEnv, Clone)]
|
||||||
struct Env {
|
struct Env {
|
||||||
@@ -301,11 +352,11 @@ fn test_imported_function_native_with_wasmer_env() {
|
|||||||
let exported = instance.exports.get_function("exported").unwrap();
|
let exported = instance.exports.get_function("exported").unwrap();
|
||||||
|
|
||||||
/// It with the provided memory
|
/// It with the provided memory
|
||||||
let expected = vec![Val::F64(24.0)].into_boxed_slice();
|
let expected = vec![Val::I32(24)].into_boxed_slice();
|
||||||
assert_eq!(exported.call(&[Val::I32(4)]), Ok(expected));
|
assert_eq!(exported.call(&[Val::I32(4)]), Ok(expected));
|
||||||
|
|
||||||
/// It works if we update the memory
|
/// It works if we update the memory
|
||||||
memory.uint8view().set_index(0, 3);
|
memory.uint8view().set_index(0, 3);
|
||||||
let expected = vec![Val::F64(36.0)].into_boxed_slice();
|
let expected = vec![Val::I32(36)].into_boxed_slice();
|
||||||
assert_eq!(exported.call(&[Val::I32(4)]), Ok(expected));
|
assert_eq!(exported.call(&[Val::I32(4)]), Ok(expected));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,11 +101,20 @@ fn exports() {
|
|||||||
let store = Store::default();
|
let store = Store::default();
|
||||||
let wat = r#"(module
|
let wat = r#"(module
|
||||||
(func (export "func") nop)
|
(func (export "func") nop)
|
||||||
(memory (export "memory") 1)
|
(memory (export "memory") 2)
|
||||||
(table (export "table") 1 funcref)
|
(table (export "table") 2 funcref)
|
||||||
(global (export "global") i32 (i32.const 0))
|
(global (export "global") i32 (i32.const 0))
|
||||||
)"#;
|
)"#;
|
||||||
let module = Module::new(&store, wat).unwrap();
|
let mut module = Module::new(&store, wat).unwrap();
|
||||||
|
module.set_type_hints(ModuleTypeHints {
|
||||||
|
exports: vec![
|
||||||
|
ExternType::Function(FunctionType::new(vec![], vec![])),
|
||||||
|
ExternType::Memory(MemoryType::new(Pages(2), None, false)),
|
||||||
|
ExternType::Table(TableType::new(Type::FuncRef, 2, None)),
|
||||||
|
ExternType::Global(GlobalType::new(Type::I32, Mutability::Const)),
|
||||||
|
],
|
||||||
|
imports: vec![],
|
||||||
|
});
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
module.exports().collect::<Vec<_>>(),
|
module.exports().collect::<Vec<_>>(),
|
||||||
vec![
|
vec![
|
||||||
@@ -115,11 +124,11 @@ fn exports() {
|
|||||||
),
|
),
|
||||||
ExportType::new(
|
ExportType::new(
|
||||||
"memory",
|
"memory",
|
||||||
ExternType::Memory(MemoryType::new(Pages(1), None, false))
|
ExternType::Memory(MemoryType::new(Pages(2), None, false))
|
||||||
),
|
),
|
||||||
ExportType::new(
|
ExportType::new(
|
||||||
"table",
|
"table",
|
||||||
ExternType::Table(TableType::new(Type::FuncRef, 1, None))
|
ExternType::Table(TableType::new(Type::FuncRef, 2, None))
|
||||||
),
|
),
|
||||||
ExportType::new(
|
ExportType::new(
|
||||||
"global",
|
"global",
|
||||||
@@ -137,14 +146,14 @@ fn exports() {
|
|||||||
module.exports().memories().collect::<Vec<_>>(),
|
module.exports().memories().collect::<Vec<_>>(),
|
||||||
vec![ExportType::new(
|
vec![ExportType::new(
|
||||||
"memory",
|
"memory",
|
||||||
MemoryType::new(Pages(1), None, false)
|
MemoryType::new(Pages(2), None, false)
|
||||||
),]
|
),]
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
module.exports().tables().collect::<Vec<_>>(),
|
module.exports().tables().collect::<Vec<_>>(),
|
||||||
vec![ExportType::new(
|
vec![ExportType::new(
|
||||||
"table",
|
"table",
|
||||||
TableType::new(Type::FuncRef, 1, None)
|
TableType::new(Type::FuncRef, 2, None)
|
||||||
),]
|
),]
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|||||||
Reference in New Issue
Block a user