wasmtime 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/Cargo.lock +941 -627
  3. data/Cargo.toml +2 -14
  4. data/LICENSE +23 -21
  5. data/README.md +47 -118
  6. data/ext/Cargo.toml +17 -0
  7. data/ext/extconf.rb +6 -0
  8. data/ext/src/helpers/mod.rs +3 -0
  9. data/ext/src/helpers/wrapped_struct.rs +84 -0
  10. data/ext/src/lib.rs +9 -0
  11. data/ext/src/ruby_api/config.rs +68 -0
  12. data/ext/src/ruby_api/convert.rs +92 -0
  13. data/ext/src/ruby_api/engine.rs +66 -0
  14. data/ext/src/ruby_api/errors.rs +56 -0
  15. data/ext/src/ruby_api/externals.rs +113 -0
  16. data/ext/src/ruby_api/func.rs +388 -0
  17. data/ext/src/ruby_api/func_type.rs +139 -0
  18. data/ext/src/ruby_api/instance.rs +174 -0
  19. data/ext/src/ruby_api/linker.rs +296 -0
  20. data/ext/src/ruby_api/macros.rs +12 -0
  21. data/ext/src/ruby_api/memory.rs +142 -0
  22. data/ext/src/ruby_api/memory_type.rs +56 -0
  23. data/ext/src/ruby_api/mod.rs +48 -0
  24. data/ext/src/ruby_api/module.rs +107 -0
  25. data/ext/src/ruby_api/params.rs +42 -0
  26. data/ext/src/ruby_api/static_id.rs +57 -0
  27. data/ext/src/ruby_api/store.rs +182 -0
  28. data/ext/src/ruby_api/trap.rs +135 -0
  29. data/lib/wasmtime/version.rb +1 -1
  30. data/lib/wasmtime.rb +29 -4
  31. metadata +54 -30
  32. data/.cargo/config +0 -4
  33. data/CHANGELOG.md +0 -27
  34. data/ext/wasmtime/Makefile +0 -5
  35. data/ext/wasmtime/Rakefile +0 -3
  36. data/ext/wasmtime/extconf.rb +0 -5
  37. data/lib/tasks/compile.rake +0 -27
  38. data/lib/wasmtime/refinements.rb +0 -20
  39. data/lib/wasmtime/require.rb +0 -72
  40. data/src/export.rs +0 -19
  41. data/src/func.rs +0 -175
  42. data/src/instance.rs +0 -93
  43. data/src/lib.rs +0 -22
  44. data/src/memory.rs +0 -48
  45. data/src/ruby_type.rs +0 -32
  46. 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
+ }