Skip to content

Commit 060db59

Browse files
authored
Merge pull request RustPython#5390 from youknowone/wasmbind
recreating wasmbind patch
2 parents 2919df1 + 42bba69 commit 060db59

File tree

11 files changed

+105
-29
lines changed

11 files changed

+105
-29
lines changed

.github/workflows/ci.yaml

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -216,13 +216,6 @@ jobs:
216216
- name: Check compilation for freebsd
217217
run: cargo check --target x86_64-unknown-freebsd
218218

219-
- uses: dtolnay/rust-toolchain@stable
220-
with:
221-
target: wasm32-unknown-unknown
222-
223-
- name: Check compilation for wasm32
224-
run: cargo check --target wasm32-unknown-unknown --no-default-features
225-
226219
- uses: dtolnay/rust-toolchain@stable
227220
with:
228221
target: x86_64-unknown-freebsd
@@ -380,6 +373,14 @@ jobs:
380373
env:
381374
NODE_OPTIONS: "--openssl-legacy-provider"
382375
working-directory: ./wasm/demo
376+
- uses: mwilliamson/setup-wabt-action@v1
377+
with: { wabt-version: "1.0.30" }
378+
- name: check wasm32-unknown without js
379+
run: |
380+
cargo build --release --manifest-path wasm/wasm-unknown-test/Cargo.toml --target wasm32-unknown-unknown --verbose
381+
if wasm-objdump -xj Import target/wasm32-unknown-unknown/release/wasm_unknown_test.wasm; then
382+
echo "ERROR: wasm32-unknown module expects imports from the host environment" >2
383+
fi
383384
- name: build notebook demo
384385
if: github.ref == 'refs/heads/release'
385386
run: |

Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,8 @@ x86_64-pc-windows-msvc = { triplet = "x64-windows-static-md", dev-dependencies =
9696
resolver = "2"
9797
members = [
9898
"compiler", "compiler/core", "compiler/codegen",
99-
".", "common", "derive", "jit", "vm", "vm/sre_engine", "pylib", "stdlib", "wasm/lib", "derive-impl",
99+
".", "common", "derive", "jit", "vm", "vm/sre_engine", "pylib", "stdlib", "derive-impl",
100+
"wasm/lib",
100101
]
101102

102103
[workspace.package]
@@ -146,6 +147,7 @@ cfg-if = "1.0"
146147
chrono = "0.4.37"
147148
crossbeam-utils = "0.8.19"
148149
flame = "0.2.2"
150+
getrandom = "0.2.12"
149151
glob = "0.3"
150152
hex = "0.4.3"
151153
indexmap = { version = "2.2.6", features = ["std"] }
@@ -178,6 +180,7 @@ thread_local = "1.1.4"
178180
unicode_names2 = "1.2.0"
179181
widestring = "1.1.0"
180182
windows-sys = "0.52.0"
183+
wasm-bindgen = "0.2.92"
181184

182185
# Lints
183186

stdlib/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ ssl-vendor = ["ssl", "openssl/vendored", "openssl-probe"]
2222
[dependencies]
2323
# rustpython crates
2424
rustpython-derive = { workspace = true }
25-
rustpython-vm = { workspace = true }
25+
rustpython-vm = { workspace = true, default-features = false }
2626
rustpython-common = { workspace = true }
2727

2828
ahash = { workspace = true }

stdlib/src/dis.rs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,23 @@ mod decl {
1313
let co = if let Ok(co) = obj.get_attr("__code__", vm) {
1414
// Method or function:
1515
PyRef::try_from_object(vm, co)?
16-
} else if let Ok(_co_str) = PyStrRef::try_from_object(vm, obj.clone()) {
16+
} else if let Ok(co_str) = PyStrRef::try_from_object(vm, obj.clone()) {
1717
#[cfg(not(feature = "compiler"))]
18-
return Err(vm.new_runtime_error(
19-
"dis.dis() with str argument requires `compiler` feature".to_owned(),
20-
));
18+
{
19+
let _ = co_str;
20+
return Err(vm.new_runtime_error(
21+
"dis.dis() with str argument requires `compiler` feature".to_owned(),
22+
));
23+
}
2124
#[cfg(feature = "compiler")]
22-
vm.compile(
23-
_co_str.as_str(),
24-
crate::vm::compiler::Mode::Exec,
25-
"<dis>".to_owned(),
26-
)
27-
.map_err(|err| vm.new_syntax_error(&err, Some(_co_str.as_str())))?
25+
{
26+
vm.compile(
27+
co_str.as_str(),
28+
crate::vm::compiler::Mode::Exec,
29+
"<dis>".to_owned(),
30+
)
31+
.map_err(|err| vm.new_syntax_error(&err, Some(co_str.as_str())))?
32+
}
2833
} else {
2934
PyRef::try_from_object(vm, obj)?
3035
};

vm/Cargo.toml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ repository.workspace = true
1010
license.workspace = true
1111

1212
[features]
13-
default = ["compiler"]
13+
default = ["compiler", "wasmbind"]
1414
importlib = []
1515
encodings = ["importlib"]
1616
vm-tracing-logging = []
@@ -23,6 +23,7 @@ ast = ["rustpython-ast"]
2323
codegen = ["rustpython-codegen", "ast"]
2424
parser = ["rustpython-parser", "ast"]
2525
serde = ["dep:serde"]
26+
wasmbind = ["chrono/wasmbind", "getrandom/js", "wasm-bindgen"]
2627

2728
[dependencies]
2829
rustpython-compiler = { workspace = true, optional = true }
@@ -48,6 +49,7 @@ cfg-if = { workspace = true }
4849
crossbeam-utils = { workspace = true }
4950
chrono = { workspace = true, features = ["wasmbind"] }
5051
flame = { workspace = true, optional = true }
52+
getrandom = { workspace = true }
5153
hex = { workspace = true }
5254
indexmap = { workspace = true }
5355
itertools = { workspace = true }
@@ -71,7 +73,6 @@ thread_local = { workspace = true }
7173
memchr = { workspace = true }
7274

7375
caseless = "0.2.1"
74-
getrandom = { version = "0.2.12", features = ["js"] }
7576
flamer = { version = "0.4", optional = true }
7677
half = "1.8.2"
7778
memoffset = "0.9.1"
@@ -140,8 +141,9 @@ features = [
140141
"Win32_UI_WindowsAndMessaging",
141142
]
142143

143-
[target.'cfg(target_arch = "wasm32")'.dependencies]
144-
wasm-bindgen = "0.2.92"
144+
[target.'cfg(all(target_arch = "wasm32", target_os = "unknown"))'.dependencies]
145+
wasm-bindgen = { workspace = true, optional = true }
146+
getrandom = { workspace = true, features = ["custom"] }
145147

146148
[build-dependencies]
147149
glob = { workspace = true }

vm/src/stdlib/time.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,12 +97,19 @@ mod decl {
9797
_time(vm)
9898
}
9999

100-
#[cfg(any(not(target_arch = "wasm32"), target_os = "wasi"))]
100+
#[cfg(not(all(
101+
target_arch = "wasm32",
102+
not(any(target_os = "emscripten", target_os = "wasi")),
103+
)))]
101104
fn _time(vm: &VirtualMachine) -> PyResult<f64> {
102105
Ok(duration_since_system_now(vm)?.as_secs_f64())
103106
}
104107

105-
#[cfg(all(target_arch = "wasm32", not(target_os = "wasi")))]
108+
#[cfg(all(
109+
target_arch = "wasm32",
110+
feature = "wasmbind",
111+
not(any(target_os = "emscripten", target_os = "wasi"))
112+
))]
106113
fn _time(_vm: &VirtualMachine) -> PyResult<f64> {
107114
use wasm_bindgen::prelude::*;
108115
#[wasm_bindgen]
@@ -115,6 +122,15 @@ mod decl {
115122
Ok(Date::now() / 1000.0)
116123
}
117124

125+
#[cfg(all(
126+
target_arch = "wasm32",
127+
not(feature = "wasmbind"),
128+
not(any(target_os = "emscripten", target_os = "wasi"))
129+
))]
130+
fn _time(vm: &VirtualMachine) -> PyResult<f64> {
131+
Err(vm.new_not_implemented_error("time.time".to_owned()))
132+
}
133+
118134
#[pyfunction]
119135
fn monotonic(vm: &VirtualMachine) -> PyResult<f64> {
120136
Ok(get_monotonic_time(vm)?.as_secs_f64())

vm/src/vm/vm_object.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,21 @@ impl VirtualMachine {
1313
#[track_caller]
1414
#[cold]
1515
fn _py_panic_failed(&self, exc: PyBaseExceptionRef, msg: &str) -> ! {
16-
#[cfg(not(all(target_arch = "wasm32", not(target_os = "wasi"))))]
16+
#[cfg(not(all(
17+
target_arch = "wasm32",
18+
not(any(target_os = "emscripten", target_os = "wasi")),
19+
)))]
1720
{
1821
self.print_exception(exc);
1922
self.flush_std();
2023
panic!("{msg}")
2124
}
22-
#[cfg(all(target_arch = "wasm32", not(target_os = "wasi")))]
25+
#[cfg(all(
26+
target_arch = "wasm32",
27+
feature = "wasmbind",
28+
not(any(target_os = "emscripten", target_os = "wasi")),
29+
))]
30+
#[cfg(all(target_arch = "wasm32", not(target_os = "wasi"), feature = "wasmbind"))]
2331
{
2432
use wasm_bindgen::prelude::*;
2533
#[wasm_bindgen]
@@ -32,6 +40,17 @@ impl VirtualMachine {
3240
error(&s);
3341
panic!("{}; exception backtrace above", msg)
3442
}
43+
#[cfg(all(
44+
target_arch = "wasm32",
45+
not(feature = "wasmbind"),
46+
not(any(target_os = "emscripten", target_os = "wasi")),
47+
))]
48+
{
49+
use crate::convert::ToPyObject;
50+
let err_string: String = exc.to_pyobject(self).repr(self).unwrap().to_string();
51+
eprintln!("{err_string}");
52+
panic!("{}; python exception not available", msg)
53+
}
3554
}
3655

3756
pub(crate) fn flush_std(&self) {

wasm/lib/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,16 @@ rustpython-common = { workspace = true }
2121
rustpython-pylib = { workspace = true, optional = true }
2222
rustpython-stdlib = { workspace = true, default-features = false, optional = true }
2323
# make sure no threading! otherwise wasm build will fail
24-
rustpython-vm = { workspace = true, features = ["compiler", "encodings", "serde"] }
24+
rustpython-vm = { workspace = true, features = ["compiler", "encodings", "serde", "wasmbind"] }
2525

2626
rustpython-parser = { workspace = true }
2727

2828
serde = { workspace = true }
29+
wasm-bindgen = { workspace = true }
2930

3031
console_error_panic_hook = "0.1"
3132
js-sys = "0.3"
3233
serde-wasm-bindgen = "0.3.1"
33-
wasm-bindgen = "0.2.80"
3434
wasm-bindgen-futures = "0.4"
3535
web-sys = { version = "0.3", features = [
3636
"console",

wasm/wasm-unknown-test/Cargo.toml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[package]
2+
name = "wasm-unknown-test"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[lib]
7+
crate-type = ["cdylib"]
8+
9+
[dependencies]
10+
getrandom = { version = "0.2.12", features = ["custom"] }
11+
rustpython-vm = { path = "../../vm", default-features = false, features = ["compiler"] }
12+
13+
[workspace]

wasm/wasm-unknown-test/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
A test crate to ensure that `rustpython-vm` compiles on `wasm32-unknown-unknown` without a JS host.

wasm/wasm-unknown-test/src/lib.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
use rustpython_vm::{eval, Interpreter};
2+
3+
pub unsafe extern "C" fn eval(s: *const u8, l: usize) -> u32 {
4+
let src = std::slice::from_raw_parts(s, l);
5+
let src = std::str::from_utf8(src).unwrap();
6+
Interpreter::without_stdlib(Default::default()).enter(|vm| {
7+
let res = eval::eval(vm, src, vm.new_scope_with_builtins(), "<string>").unwrap();
8+
res.try_into_value(vm).unwrap()
9+
})
10+
}
11+
12+
fn getrandom_always_fail(_buf: &mut [u8]) -> Result<(), getrandom::Error> {
13+
Err(getrandom::Error::UNSUPPORTED)
14+
}
15+
16+
getrandom::register_custom_getrandom!(getrandom_always_fail);

0 commit comments

Comments
 (0)