wasmtime 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Cargo.lock +941 -627
- data/Cargo.toml +2 -14
- data/LICENSE +23 -21
- data/README.md +47 -118
- data/ext/Cargo.toml +17 -0
- data/ext/extconf.rb +6 -0
- data/ext/src/helpers/mod.rs +3 -0
- data/ext/src/helpers/wrapped_struct.rs +84 -0
- data/ext/src/lib.rs +9 -0
- data/ext/src/ruby_api/config.rs +68 -0
- data/ext/src/ruby_api/convert.rs +92 -0
- data/ext/src/ruby_api/engine.rs +66 -0
- data/ext/src/ruby_api/errors.rs +56 -0
- data/ext/src/ruby_api/externals.rs +113 -0
- data/ext/src/ruby_api/func.rs +388 -0
- data/ext/src/ruby_api/func_type.rs +139 -0
- data/ext/src/ruby_api/instance.rs +174 -0
- data/ext/src/ruby_api/linker.rs +296 -0
- data/ext/src/ruby_api/macros.rs +12 -0
- data/ext/src/ruby_api/memory.rs +142 -0
- data/ext/src/ruby_api/memory_type.rs +56 -0
- data/ext/src/ruby_api/mod.rs +48 -0
- data/ext/src/ruby_api/module.rs +107 -0
- data/ext/src/ruby_api/params.rs +42 -0
- data/ext/src/ruby_api/static_id.rs +57 -0
- data/ext/src/ruby_api/store.rs +182 -0
- data/ext/src/ruby_api/trap.rs +135 -0
- data/lib/wasmtime/version.rb +1 -1
- data/lib/wasmtime.rb +29 -4
- metadata +54 -30
- data/.cargo/config +0 -4
- data/CHANGELOG.md +0 -27
- data/ext/wasmtime/Makefile +0 -5
- data/ext/wasmtime/Rakefile +0 -3
- data/ext/wasmtime/extconf.rb +0 -5
- data/lib/tasks/compile.rake +0 -27
- data/lib/wasmtime/refinements.rb +0 -20
- data/lib/wasmtime/require.rb +0 -72
- data/src/export.rs +0 -19
- data/src/func.rs +0 -175
- data/src/instance.rs +0 -93
- data/src/lib.rs +0 -22
- data/src/memory.rs +0 -48
- data/src/ruby_type.rs +0 -32
- data/src/vm.rs +0 -6
@@ -0,0 +1,139 @@
|
|
1
|
+
use super::root;
|
2
|
+
use crate::{define_rb_intern, err};
|
3
|
+
use magnus::{function, method, Error, Module as _, Object, RArray, Symbol, Value};
|
4
|
+
use wasmtime::{FuncType as FuncTypeImpl, ValType};
|
5
|
+
|
6
|
+
define_rb_intern!(
|
7
|
+
I32 => "i32",
|
8
|
+
I64 => "i64",
|
9
|
+
F32 => "f32",
|
10
|
+
F64 => "f64",
|
11
|
+
V128 => "v128",
|
12
|
+
FUNCREF => "funcref",
|
13
|
+
EXTERNREF => "externref",
|
14
|
+
);
|
15
|
+
|
16
|
+
/// @yard
|
17
|
+
/// Represents a Func's signature.
|
18
|
+
/// @see https://docs.rs/wasmtime/latest/wasmtime/struct.FuncType.html Wasmtime's Rust doc
|
19
|
+
#[derive(Clone, Debug)]
|
20
|
+
#[magnus::wrap(class = "Wasmtime::FuncType")]
|
21
|
+
pub struct FuncType {
|
22
|
+
inner: FuncTypeImpl,
|
23
|
+
}
|
24
|
+
|
25
|
+
impl FuncType {
|
26
|
+
pub fn get(&self) -> &FuncTypeImpl {
|
27
|
+
&self.inner
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
31
|
+
impl FuncType {
|
32
|
+
/// @yard
|
33
|
+
/// A descriptor for a function in a WebAssembly module.
|
34
|
+
/// WebAssembly functions can have 0 or more parameters and results. Each param
|
35
|
+
/// must be a valid WebAssembly type represented as a symbol. The valid symbols are:
|
36
|
+
/// +:i32+, +:i64+, +:f32+, +:f64+, +:v128+, +:funcref+, +:externref+.
|
37
|
+
///
|
38
|
+
/// @def new(params, results)
|
39
|
+
/// @param params [Array<Symbol>] The function's parameter types.
|
40
|
+
/// @param results [Array<Symbol>] The function's result types.
|
41
|
+
/// @return [FuncType]
|
42
|
+
///
|
43
|
+
/// @example +FuncType+ that takes 2 +i32+s and returns 1 +i32+:
|
44
|
+
/// FuncType.new([:i32, :i32], [:i32])
|
45
|
+
pub fn new(params: RArray, results: RArray) -> Result<Self, Error> {
|
46
|
+
let inner = FuncTypeImpl::new(params.to_val_type_vec()?, results.to_val_type_vec()?);
|
47
|
+
Ok(Self { inner })
|
48
|
+
}
|
49
|
+
|
50
|
+
/// @yard
|
51
|
+
/// @return [Array<Symbol>] The function's parameter types.
|
52
|
+
pub fn params(&self) -> Vec<Symbol> {
|
53
|
+
self.get().params().map(ToSym::to_sym).collect()
|
54
|
+
}
|
55
|
+
|
56
|
+
/// @yard
|
57
|
+
/// @return [Array<Symbol>] The function's result types.
|
58
|
+
pub fn results(&self) -> Vec<Symbol> {
|
59
|
+
self.get().results().map(ToSym::to_sym).collect()
|
60
|
+
}
|
61
|
+
}
|
62
|
+
|
63
|
+
trait ToValType {
|
64
|
+
fn to_val_type(&self) -> Result<ValType, Error>;
|
65
|
+
}
|
66
|
+
|
67
|
+
impl ToValType for Value {
|
68
|
+
fn to_val_type(&self) -> Result<ValType, Error> {
|
69
|
+
if let Ok(symbol) = self.try_convert::<Symbol>() {
|
70
|
+
if let Ok(true) = symbol.equal(Symbol::from(*I32)) {
|
71
|
+
return Ok(ValType::I32);
|
72
|
+
}
|
73
|
+
if let Ok(true) = symbol.equal(Symbol::from(*I64)) {
|
74
|
+
return Ok(ValType::I64);
|
75
|
+
}
|
76
|
+
if let Ok(true) = symbol.equal(Symbol::from(*F32)) {
|
77
|
+
return Ok(ValType::F32);
|
78
|
+
}
|
79
|
+
if let Ok(true) = symbol.equal(Symbol::from(*F64)) {
|
80
|
+
return Ok(ValType::F64);
|
81
|
+
}
|
82
|
+
if let Ok(true) = symbol.equal(Symbol::from(*V128)) {
|
83
|
+
return Ok(ValType::V128);
|
84
|
+
}
|
85
|
+
if let Ok(true) = symbol.equal(Symbol::from(*FUNCREF)) {
|
86
|
+
return Ok(ValType::FuncRef);
|
87
|
+
}
|
88
|
+
if let Ok(true) = symbol.equal(Symbol::from(*EXTERNREF)) {
|
89
|
+
return Ok(ValType::ExternRef);
|
90
|
+
}
|
91
|
+
}
|
92
|
+
|
93
|
+
err!(
|
94
|
+
"invalid Webassembly type, expected one of [:i32, :i64, :f32, :f64, :v128, :funcref, :externref], got {:}",
|
95
|
+
self.inspect()
|
96
|
+
)
|
97
|
+
}
|
98
|
+
}
|
99
|
+
|
100
|
+
trait ToValTypeVec {
|
101
|
+
fn to_val_type_vec(&self) -> Result<Vec<ValType>, Error>;
|
102
|
+
}
|
103
|
+
|
104
|
+
impl ToValTypeVec for RArray {
|
105
|
+
fn to_val_type_vec(&self) -> Result<Vec<ValType>, Error> {
|
106
|
+
unsafe { self.as_slice() }
|
107
|
+
.iter()
|
108
|
+
.map(ToValType::to_val_type)
|
109
|
+
.collect::<Result<Vec<ValType>, Error>>()
|
110
|
+
}
|
111
|
+
}
|
112
|
+
|
113
|
+
trait ToSym {
|
114
|
+
fn to_sym(self) -> Symbol;
|
115
|
+
}
|
116
|
+
|
117
|
+
impl ToSym for ValType {
|
118
|
+
fn to_sym(self) -> Symbol {
|
119
|
+
match self {
|
120
|
+
ValType::I32 => Symbol::from(*I32),
|
121
|
+
ValType::I64 => Symbol::from(*I64),
|
122
|
+
ValType::F32 => Symbol::from(*F32),
|
123
|
+
ValType::F64 => Symbol::from(*F64),
|
124
|
+
ValType::V128 => Symbol::from(*V128),
|
125
|
+
ValType::FuncRef => Symbol::from(*FUNCREF),
|
126
|
+
ValType::ExternRef => Symbol::from(*EXTERNREF),
|
127
|
+
}
|
128
|
+
}
|
129
|
+
}
|
130
|
+
|
131
|
+
pub fn init() -> Result<(), Error> {
|
132
|
+
let class = root().define_class("FuncType", Default::default())?;
|
133
|
+
|
134
|
+
class.define_singleton_method("new", function!(FuncType::new, 2))?;
|
135
|
+
class.define_method("params", method!(FuncType::params, 0))?;
|
136
|
+
class.define_method("results", method!(FuncType::results, 0))?;
|
137
|
+
|
138
|
+
Ok(())
|
139
|
+
}
|
@@ -0,0 +1,174 @@
|
|
1
|
+
use super::{
|
2
|
+
convert::{ToExtern, WrapWasmtimeType},
|
3
|
+
func::Func,
|
4
|
+
module::Module,
|
5
|
+
root,
|
6
|
+
store::{Store, StoreContextValue, StoreData},
|
7
|
+
};
|
8
|
+
use crate::{err, helpers::WrappedStruct};
|
9
|
+
use magnus::{
|
10
|
+
function, method, scan_args, DataTypeFunctions, Error, Module as _, Object, RArray, RHash,
|
11
|
+
RString, TypedData, Value,
|
12
|
+
};
|
13
|
+
use wasmtime::{Extern, Instance as InstanceImpl, StoreContextMut};
|
14
|
+
|
15
|
+
/// @yard
|
16
|
+
/// Represents a WebAssembly instance.
|
17
|
+
/// @see https://docs.rs/wasmtime/latest/wasmtime/struct.Instance.html Wasmtime's Rust doc
|
18
|
+
#[derive(Clone, Debug, TypedData)]
|
19
|
+
#[magnus(class = "Wasmtime::Instance", mark, free_immediatly)]
|
20
|
+
pub struct Instance {
|
21
|
+
inner: InstanceImpl,
|
22
|
+
store: WrappedStruct<Store>,
|
23
|
+
}
|
24
|
+
|
25
|
+
unsafe impl Send for Instance {}
|
26
|
+
|
27
|
+
impl DataTypeFunctions for Instance {
|
28
|
+
fn mark(&self) {
|
29
|
+
self.store.mark()
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
impl Instance {
|
34
|
+
/// @yard
|
35
|
+
/// @def new(store, mod, imports = [])
|
36
|
+
/// @param store [Store] The store to instantiate the module in.
|
37
|
+
/// @param mod [Module] The module to instantiate.
|
38
|
+
/// @param imports [Array<Func, Memory>]
|
39
|
+
/// The module's import, in orders that that they show up in the module.
|
40
|
+
/// @return [Instance]
|
41
|
+
pub fn new(args: &[Value]) -> Result<Self, Error> {
|
42
|
+
let args =
|
43
|
+
scan_args::scan_args::<(Value, &Module), (Option<Value>,), (), (), (), ()>(args)?;
|
44
|
+
let (s, module) = args.required;
|
45
|
+
let wrapped_store: WrappedStruct<Store> = s.try_convert()?;
|
46
|
+
let store = wrapped_store.get()?;
|
47
|
+
let context = store.context_mut();
|
48
|
+
let imports = args
|
49
|
+
.optional
|
50
|
+
.0
|
51
|
+
.and_then(|v| if v.is_nil() { None } else { Some(v) });
|
52
|
+
|
53
|
+
let imports: Vec<Extern> = match imports {
|
54
|
+
Some(arr) => {
|
55
|
+
let arr: RArray = arr.try_convert()?;
|
56
|
+
let mut imports = Vec::with_capacity(arr.len());
|
57
|
+
for import in arr.each() {
|
58
|
+
let import = import?;
|
59
|
+
store.retain(import);
|
60
|
+
imports.push(import.to_extern()?);
|
61
|
+
}
|
62
|
+
imports
|
63
|
+
}
|
64
|
+
None => vec![],
|
65
|
+
};
|
66
|
+
|
67
|
+
let module = module.get();
|
68
|
+
let inner = InstanceImpl::new(context, module, &imports)
|
69
|
+
.map_err(|e| StoreContextValue::from(wrapped_store).handle_wasm_error(e))?;
|
70
|
+
|
71
|
+
Ok(Self {
|
72
|
+
inner,
|
73
|
+
store: wrapped_store,
|
74
|
+
})
|
75
|
+
}
|
76
|
+
|
77
|
+
pub fn get(&self) -> InstanceImpl {
|
78
|
+
self.inner
|
79
|
+
}
|
80
|
+
|
81
|
+
pub fn from_inner(store: WrappedStruct<Store>, inner: InstanceImpl) -> Self {
|
82
|
+
Self { inner, store }
|
83
|
+
}
|
84
|
+
|
85
|
+
/// @yard
|
86
|
+
/// Returns a +Hash+ of exports where keys are export names as +String+s
|
87
|
+
/// and values are {Extern}s.
|
88
|
+
///
|
89
|
+
/// @def exports
|
90
|
+
/// @return [Hash{String => Extern}]
|
91
|
+
pub fn exports(&self) -> Result<RHash, Error> {
|
92
|
+
let store = self.store.get()?;
|
93
|
+
let mut ctx = store.context_mut();
|
94
|
+
let hash = RHash::new();
|
95
|
+
|
96
|
+
for export in self.inner.exports(&mut ctx) {
|
97
|
+
let export_name: RString = export.name().into();
|
98
|
+
let wrapped_store = self.store;
|
99
|
+
let wrapped_export = export
|
100
|
+
.into_extern()
|
101
|
+
.wrap_wasmtime_type(wrapped_store.into())?;
|
102
|
+
hash.aset(export_name, wrapped_export)?;
|
103
|
+
}
|
104
|
+
|
105
|
+
Ok(hash)
|
106
|
+
}
|
107
|
+
|
108
|
+
/// @yard
|
109
|
+
/// Get an export by name.
|
110
|
+
///
|
111
|
+
/// @def export(name)
|
112
|
+
/// @param name [String]
|
113
|
+
/// @return [Extern, nil] The export if it exists, nil otherwise.
|
114
|
+
pub fn export(&self, str: RString) -> Result<Option<super::externals::Extern>, Error> {
|
115
|
+
let store = self.store.get()?;
|
116
|
+
let export = self
|
117
|
+
.inner
|
118
|
+
.get_export(store.context_mut(), unsafe { str.as_str()? });
|
119
|
+
match export {
|
120
|
+
Some(export) => export.wrap_wasmtime_type(self.store.into()).map(Some),
|
121
|
+
None => Ok(None),
|
122
|
+
}
|
123
|
+
}
|
124
|
+
|
125
|
+
/// @yard
|
126
|
+
/// Retrieves a Wasm function from the instance and calls it.
|
127
|
+
/// Essentially a shortcut for +instance.export(name).call(...)+.
|
128
|
+
///
|
129
|
+
/// @def invoke(name, *args)
|
130
|
+
/// @param name [String] The name of function to run.
|
131
|
+
/// @param (see Func#call)
|
132
|
+
/// @return (see Func#call)
|
133
|
+
/// @see Func#call
|
134
|
+
pub fn invoke(&self, args: &[Value]) -> Result<Value, Error> {
|
135
|
+
let name: RString = args
|
136
|
+
.get(0)
|
137
|
+
.ok_or_else(|| {
|
138
|
+
Error::new(
|
139
|
+
magnus::exception::type_error(),
|
140
|
+
"wrong number of arguments (given 0, expected 1+)",
|
141
|
+
)
|
142
|
+
})?
|
143
|
+
.try_convert()?;
|
144
|
+
|
145
|
+
let store: &Store = self.store.try_convert()?;
|
146
|
+
let func = self.get_func(store.context_mut(), unsafe { name.as_str()? })?;
|
147
|
+
Func::invoke(&self.store.into(), &func, &args[1..]).map_err(|e| e.into())
|
148
|
+
}
|
149
|
+
|
150
|
+
fn get_func(
|
151
|
+
&self,
|
152
|
+
context: StoreContextMut<'_, StoreData>,
|
153
|
+
name: &str,
|
154
|
+
) -> Result<wasmtime::Func, Error> {
|
155
|
+
let instance = self.inner;
|
156
|
+
|
157
|
+
if let Some(func) = instance.get_func(context, name) {
|
158
|
+
Ok(func)
|
159
|
+
} else {
|
160
|
+
err!("function \"{}\" not found", name)
|
161
|
+
}
|
162
|
+
}
|
163
|
+
}
|
164
|
+
|
165
|
+
pub fn init() -> Result<(), Error> {
|
166
|
+
let class = root().define_class("Instance", Default::default())?;
|
167
|
+
|
168
|
+
class.define_singleton_method("new", function!(Instance::new, -1))?;
|
169
|
+
class.define_method("invoke", method!(Instance::invoke, -1))?;
|
170
|
+
class.define_method("exports", method!(Instance::exports, 0))?;
|
171
|
+
class.define_method("export", method!(Instance::export, 1))?;
|
172
|
+
|
173
|
+
Ok(())
|
174
|
+
}
|
@@ -0,0 +1,296 @@
|
|
1
|
+
use super::{
|
2
|
+
convert::WrapWasmtimeType,
|
3
|
+
engine::Engine,
|
4
|
+
externals::Extern,
|
5
|
+
func::{self, Func},
|
6
|
+
func_type::FuncType,
|
7
|
+
instance::Instance,
|
8
|
+
module::Module,
|
9
|
+
root,
|
10
|
+
store::{Store, StoreContextValue, StoreData},
|
11
|
+
};
|
12
|
+
use crate::{error, helpers::WrappedStruct, ruby_api::convert::ToExtern};
|
13
|
+
use magnus::{
|
14
|
+
block::Proc, function, gc, method, scan_args::scan_args, DataTypeFunctions, Error, Module as _,
|
15
|
+
Object, RHash, RString, TypedData, Value,
|
16
|
+
};
|
17
|
+
use std::cell::RefCell;
|
18
|
+
use wasmtime::Linker as LinkerImpl;
|
19
|
+
|
20
|
+
/// @yard
|
21
|
+
/// @see https://docs.rs/wasmtime/latest/wasmtime/struct.Linker.html Wasmtime's Rust doc
|
22
|
+
#[derive(TypedData)]
|
23
|
+
#[magnus(class = "Wasmtime::Linker", size, mark, free_immediatly)]
|
24
|
+
pub struct Linker {
|
25
|
+
inner: RefCell<LinkerImpl<StoreData>>,
|
26
|
+
refs: RefCell<Vec<Value>>,
|
27
|
+
}
|
28
|
+
|
29
|
+
unsafe impl Send for Linker {}
|
30
|
+
|
31
|
+
impl DataTypeFunctions for Linker {
|
32
|
+
fn mark(&self) {
|
33
|
+
self.refs.borrow().iter().for_each(gc::mark);
|
34
|
+
}
|
35
|
+
}
|
36
|
+
|
37
|
+
impl Linker {
|
38
|
+
/// @yard
|
39
|
+
/// @def new(engine)
|
40
|
+
/// @param engine [Engine]
|
41
|
+
/// @return [Linker]
|
42
|
+
pub fn new(engine: &Engine) -> Result<Self, Error> {
|
43
|
+
Ok(Self {
|
44
|
+
inner: RefCell::new(LinkerImpl::new(engine.get())),
|
45
|
+
refs: Default::default(),
|
46
|
+
})
|
47
|
+
}
|
48
|
+
|
49
|
+
/// @yard
|
50
|
+
/// Allow shadowing.
|
51
|
+
/// @def allow_shadowing=(val)
|
52
|
+
/// @param val [Boolean]
|
53
|
+
pub fn set_allow_shadowing(&self, val: bool) {
|
54
|
+
self.inner.borrow_mut().allow_shadowing(val);
|
55
|
+
}
|
56
|
+
|
57
|
+
/// @yard
|
58
|
+
/// Allow unknown exports.
|
59
|
+
/// @def allow_unknown_exports=(val)
|
60
|
+
/// @param val [Boolean]
|
61
|
+
pub fn set_allow_unknown_exports(&self, val: bool) {
|
62
|
+
self.inner.borrow_mut().allow_unknown_exports(val);
|
63
|
+
}
|
64
|
+
|
65
|
+
/// @yard
|
66
|
+
/// Define unknown (unresolved) imports as functions which trap.
|
67
|
+
/// @def define_unknown_imports_as_traps(mod)
|
68
|
+
/// @param mod [Module]
|
69
|
+
/// @return [void]
|
70
|
+
pub fn define_unknown_imports_as_traps(&self, module: &Module) -> Result<(), Error> {
|
71
|
+
self.inner
|
72
|
+
.borrow_mut()
|
73
|
+
.define_unknown_imports_as_traps(module.get())
|
74
|
+
.map_err(|e| error!("{}", e))
|
75
|
+
}
|
76
|
+
|
77
|
+
/// @yard
|
78
|
+
/// Define an item in this linker.
|
79
|
+
/// @def define(mod, name, item)
|
80
|
+
/// @param mod [String] Module name
|
81
|
+
/// @param name [String] Import name
|
82
|
+
/// @param item [Func, Memory] The item to define.
|
83
|
+
/// @return [void]
|
84
|
+
pub fn define(&self, module: RString, name: RString, item: Value) -> Result<(), Error> {
|
85
|
+
let item = item.to_extern()?;
|
86
|
+
|
87
|
+
self.inner
|
88
|
+
.borrow_mut()
|
89
|
+
.define(unsafe { module.as_str()? }, unsafe { name.as_str()? }, item)
|
90
|
+
.map(|_| ())
|
91
|
+
.map_err(|e| error!("{}", e))
|
92
|
+
}
|
93
|
+
|
94
|
+
/// @yard
|
95
|
+
/// Define a function in this linker.
|
96
|
+
///
|
97
|
+
/// @def func_new(mod, name, type, &block)
|
98
|
+
///
|
99
|
+
/// @param mod [String] Module name
|
100
|
+
/// @param name [String] Import name
|
101
|
+
/// @param type [FuncType]
|
102
|
+
/// @param block [Block] See {Func.new} for block argument details.
|
103
|
+
/// @return [void]
|
104
|
+
/// @see Func.new
|
105
|
+
pub fn func_new(&self, args: &[Value]) -> Result<(), Error> {
|
106
|
+
let args = scan_args::<(RString, RString, &FuncType), (), (), (), RHash, Proc>(args)?;
|
107
|
+
let (module, name, ty) = args.required;
|
108
|
+
let callable = args.block;
|
109
|
+
let func_closure = func::make_func_closure(ty.get(), callable);
|
110
|
+
|
111
|
+
self.refs.borrow_mut().push(callable.into());
|
112
|
+
|
113
|
+
self.inner
|
114
|
+
.borrow_mut()
|
115
|
+
.func_new(
|
116
|
+
unsafe { module.as_str() }?,
|
117
|
+
unsafe { name.as_str() }?,
|
118
|
+
ty.get().clone(),
|
119
|
+
func_closure,
|
120
|
+
)
|
121
|
+
.map_err(|e| error!("{}", e))
|
122
|
+
.map(|_| ())
|
123
|
+
}
|
124
|
+
|
125
|
+
/// @yard
|
126
|
+
/// Looks up a previously defined item in this linker.
|
127
|
+
///
|
128
|
+
/// @def get(store, mod, name)
|
129
|
+
/// @param store [Store]
|
130
|
+
/// @param mod [String] Module name
|
131
|
+
/// @param name [String] Import name
|
132
|
+
/// @return [Extern, nil] The item if it exists, nil otherwise.
|
133
|
+
pub fn get(
|
134
|
+
&self,
|
135
|
+
s: WrappedStruct<Store>,
|
136
|
+
module: RString,
|
137
|
+
name: RString,
|
138
|
+
) -> Result<Option<Extern>, Error> {
|
139
|
+
let store: &Store = s.try_convert()?;
|
140
|
+
let ext =
|
141
|
+
self.inner
|
142
|
+
.borrow()
|
143
|
+
.get(store.context_mut(), unsafe { module.as_str() }?, unsafe {
|
144
|
+
name.as_str()?
|
145
|
+
});
|
146
|
+
|
147
|
+
match ext {
|
148
|
+
None => Ok(None),
|
149
|
+
Some(ext) => ext.wrap_wasmtime_type(s.into()).map(Some),
|
150
|
+
}
|
151
|
+
}
|
152
|
+
|
153
|
+
/// @yard
|
154
|
+
/// Defines an entire {Instance} in this linker.
|
155
|
+
///
|
156
|
+
/// @def instance(store, mod, instance)
|
157
|
+
/// @param store [Store]
|
158
|
+
/// @param mod [String] Module name
|
159
|
+
/// @param instance [Instance]
|
160
|
+
/// @return [void]
|
161
|
+
pub fn instance(
|
162
|
+
&self,
|
163
|
+
store: &Store,
|
164
|
+
module: RString,
|
165
|
+
instance: &Instance,
|
166
|
+
) -> Result<(), Error> {
|
167
|
+
self.inner
|
168
|
+
.borrow_mut()
|
169
|
+
.instance(
|
170
|
+
store.context_mut(),
|
171
|
+
unsafe { module.as_str() }?,
|
172
|
+
instance.get(),
|
173
|
+
)
|
174
|
+
.map_err(|e| error!("{}", e))
|
175
|
+
.map(|_| ())
|
176
|
+
}
|
177
|
+
|
178
|
+
/// @yard
|
179
|
+
/// Defines automatic instantiation of a {Module} in this linker.
|
180
|
+
///
|
181
|
+
/// @def module(store, name, mod)
|
182
|
+
/// @param store [Store]
|
183
|
+
/// @param name [String] Module name
|
184
|
+
/// @param mod [Module]
|
185
|
+
/// @return [void]
|
186
|
+
pub fn module(&self, store: &Store, name: RString, module: &Module) -> Result<(), Error> {
|
187
|
+
self.inner
|
188
|
+
.borrow_mut()
|
189
|
+
.module(store.context_mut(), unsafe { name.as_str()? }, module.get())
|
190
|
+
.map(|_| ())
|
191
|
+
.map_err(|e| error!("{}", e))
|
192
|
+
}
|
193
|
+
|
194
|
+
/// @yard
|
195
|
+
/// Aliases one item’s name as another.
|
196
|
+
///
|
197
|
+
/// @def alias(mod, name, as_mod, as_name)
|
198
|
+
/// @param mod [String] The source module name.
|
199
|
+
/// @param name [String] The source item name.
|
200
|
+
/// @param as_mod [String] The destination module name.
|
201
|
+
/// @param as_name [String] The destination item name.
|
202
|
+
/// @return [void]
|
203
|
+
pub fn alias(
|
204
|
+
&self,
|
205
|
+
module: RString,
|
206
|
+
name: RString,
|
207
|
+
as_module: RString,
|
208
|
+
as_name: RString,
|
209
|
+
) -> Result<(), Error> {
|
210
|
+
self.inner
|
211
|
+
.borrow_mut()
|
212
|
+
.alias(
|
213
|
+
unsafe { module.as_str() }?,
|
214
|
+
unsafe { name.as_str() }?,
|
215
|
+
unsafe { as_module.as_str() }?,
|
216
|
+
unsafe { as_name.as_str() }?,
|
217
|
+
)
|
218
|
+
.map_err(|e| error!("{}", e))
|
219
|
+
.map(|_| ())
|
220
|
+
}
|
221
|
+
|
222
|
+
/// @yard
|
223
|
+
/// Aliases one module’s name as another.
|
224
|
+
///
|
225
|
+
/// @def alias(mod, as_mod)
|
226
|
+
/// @param mod [String] Source module name
|
227
|
+
/// @param as_mod [String] Destination module name
|
228
|
+
/// @return [void]
|
229
|
+
pub fn alias_module(&self, module: RString, as_module: RString) -> Result<(), Error> {
|
230
|
+
self.inner
|
231
|
+
.borrow_mut()
|
232
|
+
.alias_module(unsafe { module.as_str() }?, unsafe { as_module.as_str() }?)
|
233
|
+
.map_err(|e| error!("{}", e))
|
234
|
+
.map(|_| ())
|
235
|
+
}
|
236
|
+
|
237
|
+
/// @yard
|
238
|
+
/// Instantiates a {Module} in a {Store} using the defined imports in the linker.
|
239
|
+
/// @def instantiate(store, mod)
|
240
|
+
/// @param store [Store]
|
241
|
+
/// @param mod [Module]
|
242
|
+
/// @return [Instance]
|
243
|
+
pub fn instantiate(&self, s: WrappedStruct<Store>, module: &Module) -> Result<Instance, Error> {
|
244
|
+
let wrapped_store: WrappedStruct<Store> = s.try_convert()?;
|
245
|
+
let store = wrapped_store.get()?;
|
246
|
+
self.inner
|
247
|
+
.borrow_mut()
|
248
|
+
.instantiate(store.context_mut(), module.get())
|
249
|
+
.map_err(|e| StoreContextValue::from(wrapped_store).handle_wasm_error(e))
|
250
|
+
.map(|instance| {
|
251
|
+
self.refs.borrow().iter().for_each(|val| store.retain(*val));
|
252
|
+
Instance::from_inner(s, instance)
|
253
|
+
})
|
254
|
+
}
|
255
|
+
|
256
|
+
/// @yard
|
257
|
+
/// Returns the “default export” of a module.
|
258
|
+
/// @def get_default(store, mod)
|
259
|
+
/// @param store [Store]
|
260
|
+
/// @param mod [String] Module name
|
261
|
+
/// @return [Func]
|
262
|
+
pub fn get_default(&self, s: WrappedStruct<Store>, module: RString) -> Result<Func, Error> {
|
263
|
+
let store = s.get()?;
|
264
|
+
|
265
|
+
self.inner
|
266
|
+
.borrow()
|
267
|
+
.get_default(store.context_mut(), unsafe { module.as_str() }?)
|
268
|
+
.map(|func| Func::from_inner(s.into(), func))
|
269
|
+
.map_err(|e| error!("{}", e))
|
270
|
+
}
|
271
|
+
}
|
272
|
+
|
273
|
+
pub fn init() -> Result<(), Error> {
|
274
|
+
let class = root().define_class("Linker", Default::default())?;
|
275
|
+
class.define_singleton_method("new", function!(Linker::new, 1))?;
|
276
|
+
class.define_method("allow_shadowing=", method!(Linker::set_allow_shadowing, 1))?;
|
277
|
+
class.define_method(
|
278
|
+
"allow_unknown_exports=",
|
279
|
+
method!(Linker::set_allow_unknown_exports, 1),
|
280
|
+
)?;
|
281
|
+
class.define_method(
|
282
|
+
"define_unknown_imports_as_traps",
|
283
|
+
method!(Linker::define_unknown_imports_as_traps, 1),
|
284
|
+
)?;
|
285
|
+
class.define_method("define", method!(Linker::define, 3))?;
|
286
|
+
class.define_method("func_new", method!(Linker::func_new, -1))?;
|
287
|
+
class.define_method("get", method!(Linker::get, 3))?;
|
288
|
+
class.define_method("instance", method!(Linker::instance, 3))?;
|
289
|
+
class.define_method("module", method!(Linker::module, 3))?;
|
290
|
+
class.define_method("alias", method!(Linker::alias, 4))?;
|
291
|
+
class.define_method("alias_module", method!(Linker::alias_module, 2))?;
|
292
|
+
class.define_method("instantiate", method!(Linker::instantiate, 2))?;
|
293
|
+
class.define_method("get_default", method!(Linker::get_default, 2))?;
|
294
|
+
|
295
|
+
Ok(())
|
296
|
+
}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
/// A macro to define a new `Id` const for a given string.
|
2
|
+
#[macro_export]
|
3
|
+
macro_rules! define_rb_intern {
|
4
|
+
($($name:ident => $id:expr,)*) => {
|
5
|
+
$(
|
6
|
+
lazy_static::lazy_static! {
|
7
|
+
/// Define a Ruby internal `Id`. Equivalent to `rb_intern("$name")`
|
8
|
+
pub static ref $name: $crate::ruby_api::static_id::StaticId = $crate::ruby_api::static_id::StaticId::intern_str($id);
|
9
|
+
}
|
10
|
+
)*
|
11
|
+
};
|
12
|
+
}
|