Skip to content

recreating wasmbind patch #5390

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

Merged
merged 13 commits into from
Aug 9, 2024
15 changes: 8 additions & 7 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -216,13 +216,6 @@ jobs:
- name: Check compilation for freebsd
run: cargo check --target x86_64-unknown-freebsd

- uses: dtolnay/rust-toolchain@stable
with:
target: wasm32-unknown-unknown

- name: Check compilation for wasm32
run: cargo check --target wasm32-unknown-unknown --no-default-features

- uses: dtolnay/rust-toolchain@stable
with:
target: x86_64-unknown-freebsd
Expand Down Expand Up @@ -380,6 +373,14 @@ jobs:
env:
NODE_OPTIONS: "--openssl-legacy-provider"
working-directory: ./wasm/demo
- uses: mwilliamson/setup-wabt-action@v1
with: { wabt-version: "1.0.30" }
- name: check wasm32-unknown without js
run: |
cargo build --release --manifest-path wasm/wasm-unknown-test/Cargo.toml --target wasm32-unknown-unknown --verbose
if wasm-objdump -xj Import target/wasm32-unknown-unknown/release/wasm_unknown_test.wasm; then
echo "ERROR: wasm32-unknown module expects imports from the host environment" >2
fi
- name: build notebook demo
if: github.ref == 'refs/heads/release'
run: |
Expand Down
5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,8 @@ x86_64-pc-windows-msvc = { triplet = "x64-windows-static-md", dev-dependencies =
resolver = "2"
members = [
"compiler", "compiler/core", "compiler/codegen",
".", "common", "derive", "jit", "vm", "vm/sre_engine", "pylib", "stdlib", "wasm/lib", "derive-impl",
".", "common", "derive", "jit", "vm", "vm/sre_engine", "pylib", "stdlib", "derive-impl",
"wasm/lib",
]

[workspace.package]
Expand Down Expand Up @@ -146,6 +147,7 @@ cfg-if = "1.0"
chrono = "0.4.37"
crossbeam-utils = "0.8.19"
flame = "0.2.2"
getrandom = "0.2.12"
glob = "0.3"
hex = "0.4.3"
indexmap = { version = "2.2.6", features = ["std"] }
Expand Down Expand Up @@ -178,6 +180,7 @@ thread_local = "1.1.4"
unicode_names2 = "1.2.0"
widestring = "1.1.0"
windows-sys = "0.52.0"
wasm-bindgen = "0.2.92"

# Lints

Expand Down
2 changes: 1 addition & 1 deletion stdlib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ ssl-vendor = ["ssl", "openssl/vendored", "openssl-probe"]
[dependencies]
# rustpython crates
rustpython-derive = { workspace = true }
rustpython-vm = { workspace = true }
rustpython-vm = { workspace = true, default-features = false }
rustpython-common = { workspace = true }

ahash = { workspace = true }
Expand Down
25 changes: 15 additions & 10 deletions stdlib/src/dis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,23 @@ mod decl {
let co = if let Ok(co) = obj.get_attr("__code__", vm) {
// Method or function:
PyRef::try_from_object(vm, co)?
} else if let Ok(_co_str) = PyStrRef::try_from_object(vm, obj.clone()) {
} else if let Ok(co_str) = PyStrRef::try_from_object(vm, obj.clone()) {
#[cfg(not(feature = "compiler"))]
return Err(vm.new_runtime_error(
"dis.dis() with str argument requires `compiler` feature".to_owned(),
));
{
let _ = co_str;
return Err(vm.new_runtime_error(
"dis.dis() with str argument requires `compiler` feature".to_owned(),
));
}
#[cfg(feature = "compiler")]
vm.compile(
_co_str.as_str(),
crate::vm::compiler::Mode::Exec,
"<dis>".to_owned(),
)
.map_err(|err| vm.new_syntax_error(&err, Some(_co_str.as_str())))?
{
vm.compile(
co_str.as_str(),
crate::vm::compiler::Mode::Exec,
"<dis>".to_owned(),
)
.map_err(|err| vm.new_syntax_error(&err, Some(co_str.as_str())))?
}
} else {
PyRef::try_from_object(vm, obj)?
};
Expand Down
10 changes: 6 additions & 4 deletions vm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ repository.workspace = true
license.workspace = true

[features]
default = ["compiler"]
default = ["compiler", "wasmbind"]
importlib = []
encodings = ["importlib"]
vm-tracing-logging = []
Expand All @@ -23,6 +23,7 @@ ast = ["rustpython-ast"]
codegen = ["rustpython-codegen", "ast"]
parser = ["rustpython-parser", "ast"]
serde = ["dep:serde"]
wasmbind = ["chrono/wasmbind", "getrandom/js", "wasm-bindgen"]

[dependencies]
rustpython-compiler = { workspace = true, optional = true }
Expand All @@ -48,6 +49,7 @@ cfg-if = { workspace = true }
crossbeam-utils = { workspace = true }
chrono = { workspace = true, features = ["wasmbind"] }
flame = { workspace = true, optional = true }
getrandom = { workspace = true }
hex = { workspace = true }
indexmap = { workspace = true }
itertools = { workspace = true }
Expand All @@ -71,7 +73,6 @@ thread_local = { workspace = true }
memchr = { workspace = true }

caseless = "0.2.1"
getrandom = { version = "0.2.12", features = ["js"] }
flamer = { version = "0.4", optional = true }
half = "1.8.2"
memoffset = "0.9.1"
Expand Down Expand Up @@ -140,8 +141,9 @@ features = [
"Win32_UI_WindowsAndMessaging",
]

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

[build-dependencies]
glob = { workspace = true }
Expand Down
20 changes: 18 additions & 2 deletions vm/src/stdlib/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,12 +97,19 @@ mod decl {
_time(vm)
}

#[cfg(any(not(target_arch = "wasm32"), target_os = "wasi"))]
#[cfg(not(all(
target_arch = "wasm32",
not(any(target_os = "emscripten", target_os = "wasi")),
)))]
fn _time(vm: &VirtualMachine) -> PyResult<f64> {
Ok(duration_since_system_now(vm)?.as_secs_f64())
}

#[cfg(all(target_arch = "wasm32", not(target_os = "wasi")))]
#[cfg(all(
target_arch = "wasm32",
feature = "wasmbind",
not(any(target_os = "emscripten", target_os = "wasi"))
))]
fn _time(_vm: &VirtualMachine) -> PyResult<f64> {
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
Expand All @@ -115,6 +122,15 @@ mod decl {
Ok(Date::now() / 1000.0)
}

#[cfg(all(
target_arch = "wasm32",
not(feature = "wasmbind"),
not(any(target_os = "emscripten", target_os = "wasi"))
))]
fn _time(vm: &VirtualMachine) -> PyResult<f64> {
Err(vm.new_not_implemented_error("time.time".to_owned()))
}

#[pyfunction]
fn monotonic(vm: &VirtualMachine) -> PyResult<f64> {
Ok(get_monotonic_time(vm)?.as_secs_f64())
Expand Down
23 changes: 21 additions & 2 deletions vm/src/vm/vm_object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,21 @@ impl VirtualMachine {
#[track_caller]
#[cold]
fn _py_panic_failed(&self, exc: PyBaseExceptionRef, msg: &str) -> ! {
#[cfg(not(all(target_arch = "wasm32", not(target_os = "wasi"))))]
#[cfg(not(all(
target_arch = "wasm32",
not(any(target_os = "emscripten", target_os = "wasi")),
)))]
{
self.print_exception(exc);
self.flush_std();
panic!("{msg}")
}
#[cfg(all(target_arch = "wasm32", not(target_os = "wasi")))]
#[cfg(all(
target_arch = "wasm32",
feature = "wasmbind",
not(any(target_os = "emscripten", target_os = "wasi")),
))]
#[cfg(all(target_arch = "wasm32", not(target_os = "wasi"), feature = "wasmbind"))]
{
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
Expand All @@ -32,6 +40,17 @@ impl VirtualMachine {
error(&s);
panic!("{}; exception backtrace above", msg)
}
#[cfg(all(
target_arch = "wasm32",
not(feature = "wasmbind"),
not(any(target_os = "emscripten", target_os = "wasi")),
))]
{
use crate::convert::ToPyObject;
let err_string: String = exc.to_pyobject(self).repr(self).unwrap().to_string();
eprintln!("{err_string}");
panic!("{}; python exception not available", msg)
}
}

pub(crate) fn flush_std(&self) {
Expand Down
4 changes: 2 additions & 2 deletions wasm/lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,16 @@ rustpython-common = { workspace = true }
rustpython-pylib = { workspace = true, optional = true }
rustpython-stdlib = { workspace = true, default-features = false, optional = true }
# make sure no threading! otherwise wasm build will fail
rustpython-vm = { workspace = true, features = ["compiler", "encodings", "serde"] }
rustpython-vm = { workspace = true, features = ["compiler", "encodings", "serde", "wasmbind"] }

rustpython-parser = { workspace = true }

serde = { workspace = true }
wasm-bindgen = { workspace = true }

console_error_panic_hook = "0.1"
js-sys = "0.3"
serde-wasm-bindgen = "0.3.1"
wasm-bindgen = "0.2.80"
wasm-bindgen-futures = "0.4"
web-sys = { version = "0.3", features = [
"console",
Expand Down
13 changes: 13 additions & 0 deletions wasm/wasm-unknown-test/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
name = "wasm-unknown-test"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["cdylib"]

[dependencies]
getrandom = { version = "0.2.12", features = ["custom"] }
rustpython-vm = { path = "../../vm", default-features = false, features = ["compiler"] }

[workspace]
1 change: 1 addition & 0 deletions wasm/wasm-unknown-test/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
A test crate to ensure that `rustpython-vm` compiles on `wasm32-unknown-unknown` without a JS host.
16 changes: 16 additions & 0 deletions wasm/wasm-unknown-test/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use rustpython_vm::{eval, Interpreter};

pub unsafe extern "C" fn eval(s: *const u8, l: usize) -> u32 {
let src = std::slice::from_raw_parts(s, l);
let src = std::str::from_utf8(src).unwrap();
Interpreter::without_stdlib(Default::default()).enter(|vm| {
let res = eval::eval(vm, src, vm.new_scope_with_builtins(), "<string>").unwrap();
res.try_into_value(vm).unwrap()
})
}

fn getrandom_always_fail(_buf: &mut [u8]) -> Result<(), getrandom::Error> {
Err(getrandom::Error::UNSUPPORTED)
}

getrandom::register_custom_getrandom!(getrandom_always_fail);
Loading