wasmer 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +100 -0
- data/.gitignore +3 -1
- data/CHANGELOG.md +147 -0
- data/Cargo.lock +302 -840
- data/Cargo.toml +4 -5
- data/LICENSE +21 -0
- data/README.md +30 -3
- data/bors.toml +3 -1
- data/lib/wasmer/version.rb +1 -1
- data/src/{instance.rs → instance/exports.rs} +16 -112
- data/src/instance/globals.rs +234 -0
- data/src/instance/mod.rs +141 -0
- data/src/lib.rs +40 -2
- data/src/memory/mod.rs +1 -2
- data/wasmer.gemspec +4 -4
- metadata +16 -12
- data/.circleci/config.yml +0 -72
data/Cargo.toml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
[package]
|
2
2
|
publish = false
|
3
3
|
name = "ruby-ext-wasm"
|
4
|
-
version = "0.
|
4
|
+
version = "0.4.0"
|
5
5
|
authors = ["Ivan Enderlin <ivan.enderlin@hoa-project.net>"]
|
6
6
|
edition = "2018"
|
7
7
|
description = "Ruby extension to run WebAssembly binaries"
|
@@ -15,7 +15,6 @@ name = "wasmer"
|
|
15
15
|
crate-type = ["dylib"]
|
16
16
|
|
17
17
|
[dependencies]
|
18
|
-
wasmer-runtime = "0.
|
19
|
-
|
20
|
-
|
21
|
-
lazy_static = "1.3.0"
|
18
|
+
wasmer-runtime = "0.14"
|
19
|
+
rutie = "0.7"
|
20
|
+
lazy_static = "1.4"
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2019-present Wasmer, Inc. and its affiliates.
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
<p align="center">
|
2
|
-
<a href="https://wasmer.io" target="_blank" rel="noopener
|
3
|
-
<img width="
|
2
|
+
<a href="https://wasmer.io" target="_blank" rel="noopener">
|
3
|
+
<img width="300" src="https://raw.githubusercontent.com/wasmerio/wasmer/master/assets/logo.png" alt="Wasmer logo">
|
4
4
|
</a>
|
5
5
|
</p>
|
6
6
|
|
@@ -76,7 +76,8 @@ $ ruby simple.rb
|
|
76
76
|
|
77
77
|
## The `Instance` class
|
78
78
|
|
79
|
-
Instantiates a WebAssembly module represented by bytes, and calls
|
79
|
+
Instantiates a WebAssembly module represented by bytes, and calls
|
80
|
+
exported functions on it:
|
80
81
|
|
81
82
|
```ruby
|
82
83
|
require "wasmer"
|
@@ -93,10 +94,14 @@ result = instance.exports.sum 1, 2
|
|
93
94
|
puts result # 3
|
94
95
|
```
|
95
96
|
|
97
|
+
### Exported functions
|
98
|
+
|
96
99
|
All exported functions are accessible on the `exports`
|
97
100
|
getter. Arguments of these functions are automatically casted to
|
98
101
|
WebAssembly values.
|
99
102
|
|
103
|
+
### Exported memory
|
104
|
+
|
100
105
|
The `memory` getter exposes the `Memory` class representing the memory
|
101
106
|
of that particular instance, e.g.:
|
102
107
|
|
@@ -104,8 +109,30 @@ of that particular instance, e.g.:
|
|
104
109
|
view = instance.memory.uint8_view
|
105
110
|
```
|
106
111
|
|
112
|
+
`Instance.memory` throws an exception if no memory is exported.
|
113
|
+
|
107
114
|
See below for more information.
|
108
115
|
|
116
|
+
### Exported globals
|
117
|
+
|
118
|
+
The `globals` getter exposes the `ExportedGlobal` class represented an
|
119
|
+
exported global variable, e.g.:
|
120
|
+
|
121
|
+
```ruby
|
122
|
+
# Get the `x` global.
|
123
|
+
x = instance.globals.x
|
124
|
+
|
125
|
+
# Check whether the global is mutable.
|
126
|
+
assert x.mutable
|
127
|
+
assert_equal x.value, 7
|
128
|
+
|
129
|
+
# Update its value.
|
130
|
+
x.value = 42
|
131
|
+
|
132
|
+
# Tada!
|
133
|
+
assert_equal x.value, 42
|
134
|
+
```
|
135
|
+
|
109
136
|
## The `Memory` class
|
110
137
|
|
111
138
|
A WebAssembly instance has its own memory, represented by the `Memory`
|
data/bors.toml
CHANGED
data/lib/wasmer/version.rb
CHANGED
@@ -1,21 +1,17 @@
|
|
1
|
-
//! The `
|
1
|
+
//! The `ExportedFunctions` WebAssembly class.
|
2
2
|
|
3
|
-
use crate::
|
4
|
-
error::unwrap_or_raise,
|
5
|
-
memory::{Memory, RubyMemory, MEMORY_WRAPPER},
|
6
|
-
};
|
3
|
+
use crate::error::unwrap_or_raise;
|
7
4
|
use lazy_static::lazy_static;
|
8
5
|
use rutie::{
|
9
6
|
class, methods,
|
10
7
|
rubysys::{class, value::ValueType},
|
11
8
|
types::{Argc, Value},
|
12
9
|
util::str_to_cstring,
|
13
|
-
wrappable_struct, AnyException, AnyObject, Array, Boolean, Exception, Fixnum, Float,
|
14
|
-
|
10
|
+
wrappable_struct, AnyException, AnyObject, Array, Boolean, Exception, Fixnum, Float, NilClass,
|
11
|
+
Object, Symbol,
|
15
12
|
};
|
16
|
-
use std::
|
17
|
-
use wasmer_runtime::{self as runtime,
|
18
|
-
use wasmer_runtime_core::types::Type;
|
13
|
+
use std::rc::Rc;
|
14
|
+
use wasmer_runtime::{self as runtime, types::Type};
|
19
15
|
|
20
16
|
/// The `ExportedFunctions` Ruby class.
|
21
17
|
pub struct ExportedFunctions {
|
@@ -150,12 +146,18 @@ impl ExportedFunctions {
|
|
150
146
|
.call(function_arguments.as_slice())
|
151
147
|
.map_err(|e| AnyException::new("RuntimeError", Some(&format!("{}", e))))?;
|
152
148
|
|
153
|
-
if results.
|
149
|
+
if !results.is_empty() {
|
154
150
|
Ok(match results[0] {
|
155
151
|
runtime::Value::I32(result) => Fixnum::new(result as i64).into(),
|
156
152
|
runtime::Value::I64(result) => Fixnum::new(result).into(),
|
157
153
|
runtime::Value::F32(result) => Float::new(result as f64).into(),
|
158
154
|
runtime::Value::F64(result) => Float::new(result).into(),
|
155
|
+
runtime::Value::V128(_result) => {
|
156
|
+
return Err(AnyException::new(
|
157
|
+
"RuntimeError",
|
158
|
+
Some("Type `V128` isn't supported yet."),
|
159
|
+
))
|
160
|
+
}
|
159
161
|
})
|
160
162
|
} else {
|
161
163
|
Ok(NilClass::new().into())
|
@@ -180,9 +182,9 @@ methods!(
|
|
180
182
|
fn ruby_exported_functions_method_exists(symbol: Symbol, _include_private: Boolean) -> Boolean {
|
181
183
|
unwrap_or_raise(|| {
|
182
184
|
let symbol = symbol?;
|
183
|
-
let
|
185
|
+
let exported_functions = itself.get_data(&*EXPORTED_FUNCTIONS_WRAPPER);
|
184
186
|
|
185
|
-
Ok(Boolean::new(
|
187
|
+
Ok(Boolean::new(exported_functions.respond_to_missing(symbol.to_str())))
|
186
188
|
})
|
187
189
|
}
|
188
190
|
);
|
@@ -197,7 +199,7 @@ pub extern "C" fn ruby_exported_functions_method_missing(
|
|
197
199
|
let arguments = Value::from(0);
|
198
200
|
|
199
201
|
unsafe {
|
200
|
-
let argv_pointer
|
202
|
+
let argv_pointer = argv as *const Value;
|
201
203
|
|
202
204
|
class::rb_scan_args(argc, argv_pointer, str_to_cstring("*").as_ptr(), &arguments)
|
203
205
|
};
|
@@ -211,101 +213,3 @@ pub extern "C" fn ruby_exported_functions_method_missing(
|
|
211
213
|
.method_missing(method_name, arguments)
|
212
214
|
})
|
213
215
|
}
|
214
|
-
|
215
|
-
/// The `Instance` Ruby class.
|
216
|
-
pub struct Instance {
|
217
|
-
/// The WebAssembly instance.
|
218
|
-
instance: Rc<runtime::Instance>,
|
219
|
-
}
|
220
|
-
|
221
|
-
impl Instance {
|
222
|
-
/// Create a new instance of the `Instance` Ruby class.
|
223
|
-
/// The constructor receives bytes from a string.
|
224
|
-
pub fn new(bytes: &[u8]) -> Result<Self, AnyException> {
|
225
|
-
let import_object = imports! {};
|
226
|
-
|
227
|
-
Ok(Self {
|
228
|
-
instance: Rc::new(runtime::instantiate(bytes, &import_object).map_err(|e| {
|
229
|
-
AnyException::new(
|
230
|
-
"RuntimeError",
|
231
|
-
Some(&format!("Failed to instantiate the module:\n {}", e)),
|
232
|
-
)
|
233
|
-
})?),
|
234
|
-
})
|
235
|
-
}
|
236
|
-
}
|
237
|
-
|
238
|
-
wrappable_struct!(Instance, InstanceWrapper, INSTANCE_WRAPPER);
|
239
|
-
|
240
|
-
class!(RubyInstance);
|
241
|
-
|
242
|
-
#[rustfmt::skip]
|
243
|
-
methods!(
|
244
|
-
RubyInstance,
|
245
|
-
_itself,
|
246
|
-
|
247
|
-
// Glue code to call the `Instance.new` method.
|
248
|
-
fn ruby_instance_new(bytes: RString) -> AnyObject {
|
249
|
-
unwrap_or_raise(|| {
|
250
|
-
let instance = Instance::new(
|
251
|
-
bytes
|
252
|
-
.map_err(|_| {
|
253
|
-
AnyException::new(
|
254
|
-
"ArgumentError",
|
255
|
-
Some("WebAssembly module must be represented by Ruby bytes only."),
|
256
|
-
)
|
257
|
-
})?
|
258
|
-
.to_bytes_unchecked(),
|
259
|
-
)?;
|
260
|
-
let exported_functions = ExportedFunctions::new(instance.instance.clone());
|
261
|
-
|
262
|
-
let memory = instance
|
263
|
-
.instance
|
264
|
-
.exports()
|
265
|
-
.find_map(|(_, export)| match export {
|
266
|
-
Export::Memory(memory) => Some(Memory::new(Rc::new(memory))),
|
267
|
-
_ => None,
|
268
|
-
})
|
269
|
-
.ok_or_else(|| {
|
270
|
-
AnyException::new(
|
271
|
-
"RuntimeError",
|
272
|
-
Some("The WebAssembly module has no exported memory."),
|
273
|
-
)
|
274
|
-
})?;
|
275
|
-
|
276
|
-
let wasmer_module = Module::from_existing("Wasmer");
|
277
|
-
|
278
|
-
let mut ruby_instance: AnyObject = wasmer_module
|
279
|
-
.get_nested_class("Instance")
|
280
|
-
.wrap_data(instance, &*INSTANCE_WRAPPER);
|
281
|
-
|
282
|
-
let ruby_exported_functions: RubyExportedFunctions = wasmer_module
|
283
|
-
.get_nested_class("ExportedFunctions")
|
284
|
-
.wrap_data(exported_functions, &*EXPORTED_FUNCTIONS_WRAPPER);
|
285
|
-
|
286
|
-
ruby_instance.instance_variable_set("@exports", ruby_exported_functions);
|
287
|
-
|
288
|
-
let ruby_memory: RubyMemory = wasmer_module
|
289
|
-
.get_nested_class("Memory")
|
290
|
-
.wrap_data(memory, &*MEMORY_WRAPPER);
|
291
|
-
|
292
|
-
ruby_instance.instance_variable_set("@memory", ruby_memory);
|
293
|
-
|
294
|
-
Ok(ruby_instance)
|
295
|
-
})
|
296
|
-
}
|
297
|
-
|
298
|
-
// Glue code to call the `Instance.exports` getter method.
|
299
|
-
fn ruby_instance_exported_functions() -> RubyExportedFunctions {
|
300
|
-
unsafe {
|
301
|
-
_itself
|
302
|
-
.instance_variable_get("@exports")
|
303
|
-
.to::<RubyExportedFunctions>()
|
304
|
-
}
|
305
|
-
}
|
306
|
-
|
307
|
-
// Glue code to call the `Instance.memory` getter method.
|
308
|
-
fn ruby_instance_memory() -> RubyMemory {
|
309
|
-
unsafe { _itself.instance_variable_get("@memory").to::<RubyMemory>() }
|
310
|
-
}
|
311
|
-
);
|
@@ -0,0 +1,234 @@
|
|
1
|
+
//! The `ExportedGlobals` WebAssembly class.
|
2
|
+
|
3
|
+
use crate::error::unwrap_or_raise;
|
4
|
+
use lazy_static::lazy_static;
|
5
|
+
use rutie::{
|
6
|
+
class, methods,
|
7
|
+
rubysys::class,
|
8
|
+
types::{Argc, Value},
|
9
|
+
util::str_to_cstring,
|
10
|
+
wrappable_struct, AnyException, AnyObject, Array, Boolean, Exception, Fixnum, Float, Module,
|
11
|
+
NilClass, Object, Symbol,
|
12
|
+
};
|
13
|
+
use std::rc::Rc;
|
14
|
+
use wasmer_runtime::{
|
15
|
+
self as runtime, types::Type as WasmType, Export, Global, Value as WasmValue,
|
16
|
+
};
|
17
|
+
|
18
|
+
/// The `ExportedGlobals` Ruby class.
|
19
|
+
pub struct ExportedGlobals {
|
20
|
+
/// The WebAssembly runtime.
|
21
|
+
instance: Rc<runtime::Instance>,
|
22
|
+
}
|
23
|
+
|
24
|
+
impl ExportedGlobals {
|
25
|
+
/// Create a new instance of the `ExportedGlobals` Ruby class.
|
26
|
+
pub fn new(instance: Rc<runtime::Instance>) -> Self {
|
27
|
+
Self { instance }
|
28
|
+
}
|
29
|
+
|
30
|
+
/// Check that an exported function exists.
|
31
|
+
pub fn respond_to_missing(&self, method_name: &str) -> bool {
|
32
|
+
self.instance
|
33
|
+
.exports()
|
34
|
+
.any(|(export_name, export)| match export {
|
35
|
+
Export::Global(_) if export_name == method_name => true,
|
36
|
+
_ => false,
|
37
|
+
})
|
38
|
+
}
|
39
|
+
|
40
|
+
/// Call an exported function on the given WebAssembly instance.
|
41
|
+
pub fn method_missing(
|
42
|
+
&self,
|
43
|
+
method_name: &str,
|
44
|
+
_arguments: Array,
|
45
|
+
) -> Result<ExportedGlobal, AnyException> {
|
46
|
+
let global = self
|
47
|
+
.instance
|
48
|
+
.exports()
|
49
|
+
.find_map(|(export_name, export)| match export {
|
50
|
+
Export::Global(global) if export_name == method_name => Some(global),
|
51
|
+
_ => None,
|
52
|
+
})
|
53
|
+
.ok_or_else(|| {
|
54
|
+
AnyException::new(
|
55
|
+
"RuntimeError",
|
56
|
+
Some(&format!("Global `{}` does not exist.", method_name)),
|
57
|
+
)
|
58
|
+
})?;
|
59
|
+
|
60
|
+
Ok(ExportedGlobal {
|
61
|
+
global_name: method_name.to_string(),
|
62
|
+
global: Rc::new(global),
|
63
|
+
})
|
64
|
+
}
|
65
|
+
}
|
66
|
+
|
67
|
+
wrappable_struct!(
|
68
|
+
ExportedGlobals,
|
69
|
+
ExportedGlobalsWrapper,
|
70
|
+
EXPORTED_GLOBALS_WRAPPER
|
71
|
+
);
|
72
|
+
|
73
|
+
class!(RubyExportedGlobals);
|
74
|
+
|
75
|
+
#[rustfmt::skip]
|
76
|
+
methods!(
|
77
|
+
RubyExportedGlobals,
|
78
|
+
itself,
|
79
|
+
|
80
|
+
// Glue code to call the `Exportedglobals.respond_to` method.
|
81
|
+
fn ruby_exported_globals_method_exists(symbol: Symbol, _include_private: Boolean) -> Boolean {
|
82
|
+
unwrap_or_raise(|| {
|
83
|
+
let symbol = symbol?;
|
84
|
+
let exported_globals = itself.get_data(&*EXPORTED_GLOBALS_WRAPPER);
|
85
|
+
|
86
|
+
Ok(Boolean::new(exported_globals.respond_to_missing(symbol.to_str())))
|
87
|
+
})
|
88
|
+
}
|
89
|
+
);
|
90
|
+
|
91
|
+
/// Glue code to call the `ExportedGlobals.method_missing` method.
|
92
|
+
pub extern "C" fn ruby_exported_globals_method_missing(
|
93
|
+
argc: Argc,
|
94
|
+
argv: *const AnyObject,
|
95
|
+
itself: RubyExportedGlobals,
|
96
|
+
) -> RubyExportedGlobal {
|
97
|
+
unwrap_or_raise(|| {
|
98
|
+
let arguments = Value::from(0);
|
99
|
+
|
100
|
+
unsafe {
|
101
|
+
let argv_pointer = argv as *const Value;
|
102
|
+
|
103
|
+
class::rb_scan_args(argc, argv_pointer, str_to_cstring("*").as_ptr(), &arguments)
|
104
|
+
};
|
105
|
+
|
106
|
+
let mut arguments = Array::from(arguments);
|
107
|
+
let method_name = unsafe { arguments.shift().to::<Symbol>() };
|
108
|
+
let method_name = method_name.to_str();
|
109
|
+
|
110
|
+
Ok(Module::from_existing("Wasmer")
|
111
|
+
.get_nested_class("ExportedGlobal")
|
112
|
+
.wrap_data(
|
113
|
+
itself
|
114
|
+
.get_data(&*EXPORTED_GLOBALS_WRAPPER)
|
115
|
+
.method_missing(method_name, arguments)?,
|
116
|
+
&*EXPORTED_GLOBAL_WRAPPER,
|
117
|
+
))
|
118
|
+
})
|
119
|
+
}
|
120
|
+
|
121
|
+
#[allow(unused)]
|
122
|
+
/// The `ExportedGlobal` Ruby class.
|
123
|
+
pub struct ExportedGlobal {
|
124
|
+
/// The exported global name from the WebAssembly instance.
|
125
|
+
global_name: String,
|
126
|
+
|
127
|
+
/// The exported global from the WebAssembly instance.
|
128
|
+
global: Rc<Global>,
|
129
|
+
}
|
130
|
+
|
131
|
+
impl ExportedGlobal {
|
132
|
+
pub fn get_value(&self) -> WasmValue {
|
133
|
+
self.global.get()
|
134
|
+
}
|
135
|
+
|
136
|
+
pub fn set_value(&self, value: WasmValue) {
|
137
|
+
self.global.set(value);
|
138
|
+
}
|
139
|
+
|
140
|
+
pub fn mutable(&self) -> bool {
|
141
|
+
self.global.descriptor().mutable
|
142
|
+
}
|
143
|
+
|
144
|
+
fn ty(&self) -> WasmType {
|
145
|
+
self.global.descriptor().ty
|
146
|
+
}
|
147
|
+
}
|
148
|
+
|
149
|
+
wrappable_struct!(
|
150
|
+
ExportedGlobal,
|
151
|
+
ExportedGlobalWrapper,
|
152
|
+
EXPORTED_GLOBAL_WRAPPER
|
153
|
+
);
|
154
|
+
|
155
|
+
class!(RubyExportedGlobal);
|
156
|
+
|
157
|
+
#[rustfmt::skip]
|
158
|
+
methods!(
|
159
|
+
RubyExportedGlobal,
|
160
|
+
itself,
|
161
|
+
|
162
|
+
// Glue code to call the `ExportedGlobal.get_value` method.
|
163
|
+
fn ruby_exported_global_get_value() -> AnyObject {
|
164
|
+
unwrap_or_raise(|| {
|
165
|
+
let exported_global = itself.get_data(&*EXPORTED_GLOBAL_WRAPPER);
|
166
|
+
|
167
|
+
Ok(match exported_global.get_value() {
|
168
|
+
WasmValue::I32(result) => Fixnum::new(result as i64).to_any_object(),
|
169
|
+
WasmValue::I64(result) => Fixnum::new(result).to_any_object(),
|
170
|
+
WasmValue::F32(result) => Float::new(result as f64).to_any_object(),
|
171
|
+
WasmValue::F64(result) => Float::new(result).to_any_object(),
|
172
|
+
WasmValue::V128(_result) => {
|
173
|
+
return Err(AnyException::new(
|
174
|
+
"RuntimeError",
|
175
|
+
Some("Type `V128` isn't supported yet."),
|
176
|
+
))
|
177
|
+
}
|
178
|
+
})
|
179
|
+
})
|
180
|
+
}
|
181
|
+
|
182
|
+
// Glue code to call the `ExportedGlobal.set_value` method.
|
183
|
+
fn ruby_exported_global_set_value(value: AnyObject) -> NilClass {
|
184
|
+
unwrap_or_raise(|| {
|
185
|
+
let exported_global = itself.get_data(&*EXPORTED_GLOBAL_WRAPPER);
|
186
|
+
|
187
|
+
if !exported_global.mutable() {
|
188
|
+
return Err(AnyException::new(
|
189
|
+
"RuntimeError",
|
190
|
+
Some(&format!(
|
191
|
+
"The global variable `{}` is not mutable, cannot set a new value.",
|
192
|
+
exported_global.global_name
|
193
|
+
)),
|
194
|
+
));
|
195
|
+
}
|
196
|
+
|
197
|
+
let value = value?;
|
198
|
+
|
199
|
+
let wasm_type = exported_global.ty();
|
200
|
+
let wasm_value = match wasm_type {
|
201
|
+
WasmType::I32 if value.is_fixnum() => {
|
202
|
+
WasmValue::I32(unsafe { value.to::<Fixnum>().to_i32() })
|
203
|
+
}
|
204
|
+
WasmType::I64 if value.is_fixnum() => {
|
205
|
+
WasmValue::I64(unsafe { value.to::<Fixnum>().to_i64() })
|
206
|
+
}
|
207
|
+
WasmType::F32 if value.is_flonum() => {
|
208
|
+
WasmValue::F32(unsafe { value.to::<Float>().to_f64() as f32 })
|
209
|
+
}
|
210
|
+
WasmType::F64 if value.is_flonum() => {
|
211
|
+
WasmValue::F64(unsafe { value.to::<Float>().to_f64() })
|
212
|
+
}
|
213
|
+
_ => {
|
214
|
+
return Err(AnyException::new(
|
215
|
+
"TypeError",
|
216
|
+
Some(&format!(
|
217
|
+
"Failed to set `{:?}` to the global `{}` (with type `{}`).",
|
218
|
+
value, exported_global.global_name, wasm_type
|
219
|
+
)),
|
220
|
+
))
|
221
|
+
}
|
222
|
+
};
|
223
|
+
|
224
|
+
exported_global.set_value(wasm_value);
|
225
|
+
|
226
|
+
Ok(NilClass::new())
|
227
|
+
})
|
228
|
+
}
|
229
|
+
|
230
|
+
// Glue code to call the `ExportedGlobal.mutable` getter.
|
231
|
+
fn ruby_exported_global_mutable() -> Boolean {
|
232
|
+
Boolean::new(itself.get_data(&*EXPORTED_GLOBAL_WRAPPER).mutable())
|
233
|
+
}
|
234
|
+
);
|