Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1168,6 +1168,47 @@ jobs:
RUSTFLAGS: --cfg tokio_unstable
CARGO_TARGET_WASM32_WASIP2_RUNNER: wasmtime run -Sinherit-network

wasm32-unknown-emscripten:
name: test tokio for wasm32-unknown-emscripten
needs: basics
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Install Rust ${{ env.rust_stable }}
uses: dtolnay/rust-toolchain@stable
with:
toolchain: ${{ env.rust_stable }}
targets: wasm32-unknown-emscripten

- name: Install Emscripten
uses: mymindstorm/setup-emsdk@v14
with:
version: 'latest'

- uses: actions/setup-node@v4
with:
node-version: 26

- uses: Swatinem/rust-cache@v2

- name: Install cargo-hack
uses: taiki-e/install-action@v2
with:
tool: cargo-hack

- name: Check tokio feature matrix for emscripten
run: cargo hack check -p tokio --each-feature --exclude-features full,net,process,signal,rt-multi-thread,io-uring,taskdump,schedule-latency --target wasm32-unknown-emscripten
working-directory: tokio
env:
RUSTFLAGS: ""

- name: Test tokio for emscripten
run: cargo test -p tokio --target wasm32-unknown-emscripten --features "rt,time,sync,macros,io-util,test-util" --tests
working-directory: tokio
env:
CARGO_TARGET_WASM32_UNKNOWN_EMSCRIPTEN_RUNNER: node
RUSTFLAGS: "-C link-args=-sALLOW_MEMORY_GROWTH=1 -C link-args=-sEXIT_RUNTIME=1 -C link-args=-sSTACK_SIZE=1048576"

check-external-types:
name: check-external-types (${{ matrix.os }})
needs: basics
Expand Down
5 changes: 4 additions & 1 deletion spellcheck.dic
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
324
327
&
+
<
Expand Down Expand Up @@ -106,6 +106,8 @@ dns
DNS
DoS
dwOpenMode
Emscripten
Emscripten's
endian
enqueue
enqueued
Expand Down Expand Up @@ -320,6 +322,7 @@ Wakers
wakeup
wakeups
WASI
Wasm
watchOS
workstealing
ZST
11 changes: 10 additions & 1 deletion tokio-macros/src/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,7 @@ fn parse_knobs(mut input: ItemFn, is_test: bool, config: FinalConfig) -> TokenSt

let body_ident = quote! { body };
// This explicit `return` is intentional. See tokio-rs/tokio#4636
let last_block = quote_spanned! {last_stmt_end_span=>
let native_last_block = quote_spanned! {last_stmt_end_span=>

#[allow(clippy::expect_used, clippy::diverging_sub_expression, clippy::needless_return, clippy::unwrap_in_result)]
{
Expand All @@ -521,6 +521,15 @@ fn parse_knobs(mut input: ItemFn, is_test: bool, config: FinalConfig) -> TokenSt

};

let last_block = match config.flavor {
RuntimeFlavor::Threaded => quote! {
#crate_path::__tokio_unsupported_multi_thread_on_emscripten! {
#native_last_block
}
},
_ => native_last_block,
};

let body = input.body();

// For test functions pin the body to the stack and use `Pin<&mut dyn
Expand Down
14 changes: 10 additions & 4 deletions tokio/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ bytes = { version = "1.2.1", optional = true }
mio = { version = "1.2.0", optional = true, default-features = false }
parking_lot = { version = "0.12.0", optional = true }

[target.'cfg(any(not(target_family = "wasm"), all(target_os = "wasi", not(target_env = "p1"))))'.dependencies]
[target.'cfg(any(not(target_family = "wasm"), target_os = "emscripten", all(target_os = "wasi", not(target_env = "p1"))))'.dependencies]
socket2 = { version = "0.6.3", optional = true, features = ["all"] }

# Currently unstable. The API exposed by these features may be broken at any time.
Expand Down Expand Up @@ -130,6 +130,8 @@ libc = { version = "0.2.168", optional = true }

[target.'cfg(unix)'.dev-dependencies]
libc = { version = "0.2.168" }

[target.'cfg(all(unix, not(target_os = "emscripten")))'.dev-dependencies]
nix = { version = "0.31.0", default-features = false, features = ["aio", "fs", "socket"] }

[target.'cfg(windows)'.dependencies.windows-sys]
Expand All @@ -146,22 +148,26 @@ features = [
[dev-dependencies]
tokio-test = "0.4.0"
tokio-stream = "0.1"
tokio-util = { version = "0.7", features = ["rt"] }
futures = { version = "0.3.0", features = ["async-await"] }
futures-test = "0.3.31"
mockall = "0.13.0"
async-stream = "0.3"
futures-concurrency = "7.6.3"

[target.'cfg(not(target_os = "emscripten"))'.dev-dependencies]
tokio-util = { version = "0.7", features = ["rt"] }

[target.'cfg(not(target_family = "wasm"))'.dev-dependencies]
socket2 = "0.6.0"
tempfile = "3.1.0"
proptest = "1"

[target.'cfg(any(not(target_family = "wasm"), target_os = "emscripten"))'.dev-dependencies]
tempfile = "3.1.0"

[target.'cfg(not(all(target_family = "wasm", target_os = "unknown")))'.dev-dependencies]
rand = "0.9"

[target.'cfg(all(target_family = "wasm", not(target_os = "wasi")))'.dev-dependencies]
[target.'cfg(all(target_family = "wasm", target_os = "unknown"))'.dev-dependencies]
wasm-bindgen-test = "0.3.0"

[target.'cfg(target_os = "freebsd")'.dev-dependencies]
Expand Down
11 changes: 11 additions & 0 deletions tokio/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,13 @@
//! immediately instead of blocking forever. On platforms that don't support
//! time, this means that the runtime can never be idle in any way.
//!
//! ### Emscripten support
//!
//! The `wasm32-unknown-emscripten` target supports the single-threaded runtime
//! with the `rt`, `time`, `sync`, `macros`, `fs`, `io-util`, `io-std`, and
//! `test-util` features. The `net`, `process`, `signal`, and `rt-multi-thread`
//! features are not supported.
//!
//! ## Unstable `WASM` support
//!
//! Tokio also has unstable support for some additional `WASM` features. This
Expand All @@ -467,6 +474,7 @@ compile_error! {
#[cfg(all(
not(tokio_unstable),
target_family = "wasm",
not(target_os = "emscripten"),
any(
feature = "fs",
feature = "io-std",
Expand All @@ -478,6 +486,9 @@ compile_error! {
))]
compile_error!("Only features sync,macros,io-util,rt,time are supported on wasm.");

#[cfg(all(target_os = "emscripten", feature = "process"))]
compile_error!("The `process` feature is not supported on wasm32-unknown-emscripten.");

#[cfg(all(not(tokio_unstable), feature = "io-uring"))]
compile_error!("The `io-uring` feature requires `--cfg tokio_unstable`.");

Expand Down
13 changes: 10 additions & 3 deletions tokio/src/macros/cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ macro_rules! cfg_process {
#[cfg_attr(docsrs, doc(cfg(feature = "process")))]
#[cfg(not(loom))]
#[cfg(not(target_os = "wasi"))]
#[cfg(not(target_os = "emscripten"))]
$item
)*
}
Expand All @@ -414,7 +415,10 @@ macro_rules! cfg_process_driver {
macro_rules! cfg_not_process_driver {
($($item:item)*) => {
$(
#[cfg(not(all(unix, not(loom), feature = "process")))]
#[cfg(any(
target_os = "emscripten",
not(all(unix, not(loom), feature = "process")),
))]
$item
)*
}
Expand All @@ -427,6 +431,8 @@ macro_rules! cfg_signal {
#[cfg_attr(docsrs, doc(cfg(feature = "signal")))]
#[cfg(not(loom))]
#[cfg(not(target_os = "wasi"))]
// No kernel signal delivery on Emscripten; inert there.
#[cfg(not(target_os = "emscripten"))]
$item
)*
}
Expand All @@ -437,6 +443,7 @@ macro_rules! cfg_signal_internal {
$(
#[cfg(any(feature = "signal", all(unix, feature = "process")))]
#[cfg(not(loom))]
#[cfg(not(target_os = "emscripten"))]
$item
)*
}
Expand All @@ -452,7 +459,7 @@ macro_rules! cfg_signal_internal_and_unix {
macro_rules! cfg_not_signal_internal {
($($item:item)*) => {
$(
#[cfg(any(loom, not(unix), not(any(feature = "signal", all(unix, feature = "process")))))]
#[cfg(any(loom, not(unix), target_os = "emscripten", not(any(feature = "signal", all(unix, feature = "process")))))]
$item
)*
}
Expand Down Expand Up @@ -715,7 +722,7 @@ macro_rules! cfg_not_wasip1 {
macro_rules! cfg_is_wasm_not_wasi {
($($item:item)*) => {
$(
#[cfg(all(target_family = "wasm", not(target_os = "wasi")))]
#[cfg(all(target_family = "wasm", target_os = "unknown"))]
$item
)*
}
Expand Down
20 changes: 20 additions & 0 deletions tokio/src/macros/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,23 @@ cfg_macros! {
// Includes re-exports needed to implement macros
#[doc(hidden)]
pub mod support;

#[doc(hidden)]
#[macro_export]
#[cfg(not(target_os = "emscripten"))]
macro_rules! __tokio_unsupported_multi_thread_on_emscripten {
($($body:tt)*) => { $($body)* };
}

#[doc(hidden)]
#[macro_export]
#[cfg(target_os = "emscripten")]
macro_rules! __tokio_unsupported_multi_thread_on_emscripten {
($($body:tt)*) => {
::core::compile_error!(
"the `multi_thread` runtime flavor is not available on \
wasm32-unknown-emscripten (no native threads); use \
`flavor = \"current_thread\"`"
);
};
}
2 changes: 1 addition & 1 deletion tokio/src/runtime/time/tests/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#![cfg(not(target_os = "wasi"))]
#![cfg(all(not(target_os = "wasi"), not(target_os = "emscripten")))]

use std::{task::Context, time::Duration};

Expand Down
2 changes: 1 addition & 1 deletion tokio/src/sync/tests/atomic_waker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ impl AssertSync for AtomicWaker {}
impl AssertSend for Waker {}
impl AssertSync for Waker {}

#[cfg(all(target_family = "wasm", not(target_os = "wasi")))]
#[cfg(all(target_family = "wasm", target_os = "unknown"))]
use wasm_bindgen_test::wasm_bindgen_test as test;

#[test]
Expand Down
2 changes: 1 addition & 1 deletion tokio/src/sync/tests/notify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::future::Future;
use std::sync::Arc;
use std::task::{Context, RawWaker, RawWakerVTable, Waker};

#[cfg(all(target_family = "wasm", not(target_os = "wasi")))]
#[cfg(all(target_family = "wasm", target_os = "unknown"))]
use wasm_bindgen_test::wasm_bindgen_test as test;

#[test]
Expand Down
2 changes: 1 addition & 1 deletion tokio/src/sync/tests/semaphore_batch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use tokio_test::*;

const MAX_PERMITS: usize = crate::sync::Semaphore::MAX_PERMITS;

#[cfg(all(target_family = "wasm", not(target_os = "wasi")))]
#[cfg(all(target_family = "wasm", target_os = "unknown"))]
use wasm_bindgen_test::wasm_bindgen_test as test;

#[test]
Expand Down
2 changes: 1 addition & 1 deletion tokio/src/task/coop/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,7 @@ cfg_coop! {
mod test {
use super::*;

#[cfg(all(target_family = "wasm", not(target_os = "wasi")))]
#[cfg(all(target_family = "wasm", target_os = "unknown"))]
use wasm_bindgen_test::wasm_bindgen_test as test;

fn get() -> Budget {
Expand Down
2 changes: 1 addition & 1 deletion tokio/src/task/local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1278,7 +1278,7 @@ impl LocalState {
// ensure they are on the same thread that owns the `LocalSet`.
unsafe impl Send for LocalState {}

#[cfg(all(test, not(loom)))]
#[cfg(all(test, not(loom), not(target_os = "emscripten")))]
mod tests {
use super::*;

Expand Down
2 changes: 1 addition & 1 deletion tokio/src/util/idle_notified_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -492,7 +492,7 @@ unsafe impl<T> linked_list::Link for ListEntry<T> {
}
}

#[cfg(all(test, not(loom)))]
#[cfg(all(test, not(loom), not(target_os = "emscripten")))]
mod tests {
use crate::runtime::Builder;
use crate::task::JoinSet;
Expand Down
6 changes: 3 additions & 3 deletions tokio/tests/macros_join.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
#![allow(clippy::disallowed_names)]
use std::sync::Arc;

#[cfg(all(target_family = "wasm", not(target_os = "wasi")))]
#[cfg(all(target_family = "wasm", target_os = "unknown"))]
#[cfg(target_pointer_width = "64")]
use wasm_bindgen_test::wasm_bindgen_test as test;
#[cfg(all(target_family = "wasm", not(target_os = "wasi")))]
#[cfg(all(target_family = "wasm", target_os = "unknown"))]
use wasm_bindgen_test::wasm_bindgen_test as maybe_tokio_test;

#[cfg(not(all(target_family = "wasm", not(target_os = "wasi"))))]
#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
use tokio::test as maybe_tokio_test;

use tokio::sync::{oneshot, Semaphore};
Expand Down
4 changes: 2 additions & 2 deletions tokio/tests/macros_pin.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#![cfg(feature = "macros")]

#[cfg(all(target_family = "wasm", not(target_os = "wasi")))]
#[cfg(all(target_family = "wasm", target_os = "unknown"))]
use wasm_bindgen_test::wasm_bindgen_test as maybe_tokio_test;

#[cfg(not(all(target_family = "wasm", not(target_os = "wasi"))))]
#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
use tokio::test as maybe_tokio_test;

async fn one() {}
Expand Down
4 changes: 2 additions & 2 deletions tokio/tests/macros_select.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#![cfg(feature = "macros")]
#![allow(clippy::disallowed_names)]

#[cfg(all(target_family = "wasm", not(target_os = "wasi")))]
#[cfg(all(target_family = "wasm", target_os = "unknown"))]
use wasm_bindgen_test::wasm_bindgen_test as maybe_tokio_test;

#[cfg(not(all(target_family = "wasm", not(target_os = "wasi"))))]
#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
use tokio::test as maybe_tokio_test;

use tokio::sync::oneshot;
Expand Down
4 changes: 2 additions & 2 deletions tokio/tests/macros_try_join.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ use std::{convert::Infallible, sync::Arc};
use tokio::sync::{oneshot, Semaphore};
use tokio_test::{assert_pending, assert_ready, task};

#[cfg(all(target_family = "wasm", not(target_os = "wasi")))]
#[cfg(all(target_family = "wasm", target_os = "unknown"))]
use wasm_bindgen_test::wasm_bindgen_test as maybe_tokio_test;

#[cfg(not(all(target_family = "wasm", not(target_os = "wasi"))))]
#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
use tokio::test as maybe_tokio_test;

#[maybe_tokio_test]
Expand Down
2 changes: 1 addition & 1 deletion tokio/tests/sync_barrier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#![warn(rust_2018_idioms)]
#![cfg(feature = "sync")]

#[cfg(all(target_family = "wasm", not(target_os = "wasi")))]
#[cfg(all(target_family = "wasm", target_os = "unknown"))]
use wasm_bindgen_test::wasm_bindgen_test as test;

use tokio::sync::Barrier;
Expand Down
4 changes: 2 additions & 2 deletions tokio/tests/sync_broadcast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#![warn(rust_2018_idioms)]
#![cfg(feature = "sync")]

#[cfg(all(target_family = "wasm", not(target_os = "wasi")))]
#[cfg(all(target_family = "wasm", target_os = "unknown"))]
use wasm_bindgen_test::wasm_bindgen_test as test;

use tokio::sync::broadcast;
Expand Down Expand Up @@ -563,7 +563,7 @@ fn sender_len() {
}

#[test]
#[cfg(not(all(target_family = "wasm", not(target_os = "wasi"))))]
#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
fn sender_len_random() {
let (tx, mut rx1) = broadcast::channel(16);
let mut rx2 = tx.subscribe();
Expand Down
Loading
Loading