-
Notifications
You must be signed in to change notification settings - Fork 824
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
Add types and methods to provide updated API #1313
Merged
Merged
Changes from 17 commits
Commits
Show all changes
22 commits
Select commit
Hold shift + click to select a range
f4dc419
Add types and methods to provide updated API
f864765
Make trailing commas in `imports!` macro optional
71be2c6
Add getter to table and other misc changes
2dc3ea5
Implement table getting and setting
da949f4
Improve Table implementation for API
844a572
Rename new type fields from `type_` to `ty`
59bd6f6
Merge branch 'master' into feature/update-api
MarkMcCaskey 9829d97
Update `Module::custom_sections` to properly return multiples
d8bd258
Add skeleton of exported api
cc13e45
Add skeleton of external API and tests
c14c88f
Improve high level API test
a18371e
Implement `instance.exports` field syntax
2fb8f81
Deprecate `Instance::func` and `Instance::dyn_func`
3eff8c1
Convert usages of `Instance::{func,dyn_func}` to exports.get
a0dca15
Add misc. fixes and updates from feedback
7cd9e82
Simplify `ImportType`
7ca721b
Update from feedback
403d4b4
Merge branch 'master' into feature/update-api
MarkMcCaskey 50fcd57
Improve consistency and add misc clean ups
836711f
Implement `Instance::call` in terms of the exports API
bde319d
Fix bug and un-deprecate `Instance::call`
0527b50
Improve consistency of names, reuse more code, and reorganize a bit
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
[package] | ||
name = "wasmer" | ||
name = "wasmer-bin" | ||
version = "0.16.2" | ||
authors = ["The Wasmer Engineering Team <[email protected]>"] | ||
edition = "2018" | ||
|
@@ -27,6 +27,7 @@ fern = { version = "0.5", features = ["colored"], optional = true } | |
log = "0.4" | ||
structopt = "0.3" | ||
wabt = { version = "0.9.1", optional = true } | ||
wasmer = { path = "lib/api" } | ||
wasmer-clif-backend = { path = "lib/clif-backend", optional = true } | ||
wasmer-singlepass-backend = { path = "lib/singlepass-backend", optional = true } | ||
wasmer-middleware-common = { path = "lib/middleware-common" } | ||
|
@@ -44,6 +45,8 @@ wasmer-wasi-experimental-io-devices = { path = "lib/wasi-experimental-io-devices | |
|
||
[workspace] | ||
members = [ | ||
"lib/api", | ||
"lib/api-tests", | ||
"lib/clif-backend", | ||
"lib/singlepass-backend", | ||
"lib/runtime", | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
[package] | ||
name = "api-tests" | ||
version = "0.16.2" | ||
authors = ["The Wasmer Engineering Team <[email protected]>"] | ||
edition = "2018" | ||
license = "MIT" | ||
publish = false | ||
|
||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[dependencies] | ||
wasmer = { version = "0.16.2", path = "../api" } | ||
|
||
[dev-dependencies] | ||
wabt = "0.9.1" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,211 @@ | ||
static TEST_WAT: &str = r#" | ||
(module | ||
(import "env" "outside-global" (global $outside-global (mut i32))) | ||
(import "env" "update-func" (func $update-func (param i32) (result i32))) | ||
(table $test-table (export "test-table") 2 anyfunc) | ||
(global $test-global (export "test-global") (mut i32) (i32.const 3)) | ||
(elem (;0;) (i32.const 0) $ret_2) | ||
(func $ret_2 (export "ret_2") (result i32) | ||
i32.const 2) | ||
(func $ret_4 (export "ret_4") (result i32) | ||
i32.const 4) | ||
(func $set_test_global (export "set_test_global") (param i32) | ||
(global.set $test-global | ||
(local.get 0))) | ||
(func $update-outside-global (export "update_outside_global") | ||
(global.set $outside-global | ||
(call $update-func (global.get $outside-global)))) | ||
) | ||
"#; | ||
|
||
fn append_custom_section( | ||
wasm: &mut Vec<u8>, | ||
custom_section_name: &str, | ||
custom_section_contents: &[u8], | ||
) { | ||
wasm.reserve( | ||
// 1 for custom section id, 5 for max length of custom section, 5 for max length of name | ||
custom_section_name.len() + custom_section_contents.len() + 1 + 5 + 5, | ||
); | ||
|
||
wasm.push(0); | ||
|
||
let name_length = custom_section_name.as_bytes().len() as u32; | ||
let mut name_length_as_leb128 = vec![]; | ||
write_u32_leb128(&mut name_length_as_leb128, name_length); | ||
|
||
let custom_section_length = (custom_section_contents.len() | ||
+ custom_section_name.as_bytes().len() | ||
+ name_length_as_leb128.len()) as u32; | ||
|
||
let mut custom_section_length_as_leb128 = vec![]; | ||
write_u32_leb128(&mut custom_section_length_as_leb128, custom_section_length); | ||
|
||
wasm.extend(&custom_section_length_as_leb128); | ||
wasm.extend(&name_length_as_leb128); | ||
wasm.extend(custom_section_name.as_bytes()); | ||
wasm.extend(custom_section_contents); | ||
} | ||
|
||
#[test] | ||
fn custom_section_parsing_works() { | ||
use wasmer::{CompiledModule, Module}; | ||
let wasm = { | ||
let mut wasm = wabt::wat2wasm(TEST_WAT).unwrap(); | ||
append_custom_section(&mut wasm, "test_custom_section", b"hello, world!"); | ||
append_custom_section(&mut wasm, "test_custom_section", b"goodbye, world!"); | ||
append_custom_section(&mut wasm, "different_name", b"different value"); | ||
wasm | ||
}; | ||
|
||
let module = Module::new(wasm).unwrap(); | ||
|
||
assert_eq!( | ||
module.custom_sections("test_custom_section"), | ||
Some(&[b"hello, world!".to_vec(), b"goodbye, world!".to_vec()][..]) | ||
); | ||
} | ||
|
||
#[test] | ||
fn module_exports_are_ordered() { | ||
use wasmer::{export, CompiledModule, Module}; | ||
|
||
let wasm = wabt::wat2wasm(TEST_WAT).unwrap(); | ||
// TODO: review error messages when `CompiledModule` is not in scope. My hypothesis is that they'll be | ||
// misleading, if so we may want to do something about it. | ||
let module = Module::new(wasm).unwrap(); | ||
let exports = module.exports().collect::<Vec<_>>(); | ||
assert_eq!( | ||
exports, | ||
vec![ | ||
export::ExportDescriptor { | ||
name: "test-table", | ||
kind: export::ExportKind::Table, | ||
}, | ||
export::ExportDescriptor { | ||
name: "test-global", | ||
kind: export::ExportKind::Global, | ||
}, | ||
export::ExportDescriptor { | ||
name: "ret_2", | ||
kind: export::ExportKind::Function, | ||
}, | ||
export::ExportDescriptor { | ||
name: "ret_4", | ||
kind: export::ExportKind::Function, | ||
}, | ||
export::ExportDescriptor { | ||
name: "set_test_global", | ||
kind: export::ExportKind::Function, | ||
}, | ||
export::ExportDescriptor { | ||
name: "update_outside_global", | ||
kind: export::ExportKind::Function, | ||
}, | ||
] | ||
); | ||
} | ||
|
||
#[test] | ||
fn module_imports_are_correct() { | ||
use wasmer::{CompiledModule, Module}; | ||
|
||
let wasm = wabt::wat2wasm(TEST_WAT).unwrap(); | ||
// TODO: review error messages when `CompiledModule` is not in scope. My hypothesis is that they'll be | ||
// misleading, if so we may want to do something about it. | ||
let module = Module::new(wasm).unwrap(); | ||
|
||
// TODO: test this more later | ||
let imports = module.imports(); | ||
assert_eq!(imports.len(), 2); | ||
} | ||
|
||
#[test] | ||
fn module_can_be_instantiated() { | ||
use wasmer::wasm::{Global, Value}; | ||
use wasmer::{func, imports, CompiledModule, Module}; | ||
|
||
let wasm = wabt::wat2wasm(TEST_WAT).unwrap(); | ||
// TODO: review error messages when `CompiledModule` is not in scope. My hypothesis is that they'll be | ||
// misleading, if so we may want to do something about it. | ||
let module = Module::new(wasm).unwrap(); | ||
|
||
let outside_global = Global::new_mutable(Value::I32(15)); | ||
let import_object = imports! { | ||
"env" => { | ||
"update-func" => func!(|x: i32| x * 2), | ||
"outside-global" => outside_global.clone(), | ||
} | ||
}; | ||
let instance = module.instantiate(&import_object); | ||
|
||
assert!(instance.is_ok()); | ||
} | ||
|
||
#[test] | ||
fn exports_work() { | ||
use wasmer::wasm::{Global, Value}; | ||
use wasmer::{func, imports, CompiledModule, Func, Module, Table}; | ||
|
||
let wasm = wabt::wat2wasm(TEST_WAT).unwrap(); | ||
// TODO: review error messages when `CompiledModule` is not in scope. My hypothesis is that they'll be | ||
// misleading, if so we may want to do something about it. | ||
let module = Module::new(wasm).unwrap(); | ||
|
||
let outside_global = Global::new_mutable(Value::I32(15)); | ||
|
||
let import_object = imports! { | ||
"env" => { | ||
"update-func" => func!(|x: i32| x * 2), | ||
"outside-global" => outside_global.clone(), | ||
} | ||
}; | ||
let instance = module.instantiate(&import_object).unwrap(); | ||
|
||
let ret_2: Func<(), i32> = instance.exports.get("ret_2").unwrap(); | ||
let ret_4: Func<(), i32> = instance.exports.get("ret_4").unwrap(); | ||
let set_test_global: Func<i32> = instance.exports.get("set_test_global").unwrap(); | ||
let update_outside_global: Func = instance.exports.get("update_outside_global").unwrap(); | ||
|
||
assert_eq!(ret_2.call(), Ok(2)); | ||
assert_eq!(ret_4.call(), Ok(4)); | ||
|
||
let _test_table: Table = instance.exports.get("test-table").unwrap(); | ||
// TODO: when table get is stablized test this | ||
|
||
let test_global: Global = instance.exports.get("test-global").unwrap(); | ||
// TODO: do we want to make global.get act like exports.get()? | ||
assert_eq!(test_global.get(), Value::I32(3)); | ||
set_test_global.call(17).unwrap(); | ||
assert_eq!(test_global.get(), Value::I32(17)); | ||
|
||
assert_eq!(outside_global.get(), Value::I32(15)); | ||
update_outside_global.call().unwrap(); | ||
assert_eq!(outside_global.get(), Value::I32(15 * 2)); | ||
update_outside_global.call().unwrap(); | ||
assert_eq!(outside_global.get(), Value::I32(15 * 2 * 2)); | ||
} | ||
|
||
// copied from Rust stdlib: https://doc.rust-lang.org/nightly/nightly-rustc/src/serialize/leb128.rs.html#4-14 | ||
macro_rules! impl_write_unsigned_leb128 { | ||
($fn_name:ident, $int_ty:ident) => { | ||
#[inline] | ||
pub fn $fn_name(out: &mut Vec<u8>, mut value: $int_ty) { | ||
loop { | ||
if value < 0x80 { | ||
out.push(value as u8); | ||
break; | ||
} else { | ||
out.push(((value & 0x7f) | 0x80) as u8); | ||
value >>= 7; | ||
} | ||
} | ||
} | ||
}; | ||
} | ||
|
||
impl_write_unsigned_leb128!(write_u16_leb128, u16); | ||
impl_write_unsigned_leb128!(write_u32_leb128, u32); | ||
impl_write_unsigned_leb128!(write_u64_leb128, u64); | ||
impl_write_unsigned_leb128!(write_u128_leb128, u128); | ||
impl_write_unsigned_leb128!(write_usize_leb128, usize); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why this is needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not strictly needed, but in case we needed the other functions, I figured it might be good to have around. I can macro-expand/inline the one function I need for the custom section writing if you'd prefer that!