Repository navigation
fix: exclude emscripten from the browser-wasm cfg branches - #857
Merged
Merged
Conversation
`wasm32-unknown-emscripten` is `target_arch = "wasm32"`, but it is also unix with a full libc, so it wants the native code paths: `std::process::Command`, `percent_encoding` and a Rust closure for the markdown highlighter all work there, while `js_sys`/`wasm-bindgen` do not (there is no JS host reaching into the module that way). Today deno_doc keys those branches on `target_arch = "wasm32"` alone, so an emscripten build takes the browser path and fails to compile — e.g. `src/html/usage.rs` hands the highlighter a `js_sys::Function` where the native signature wants `Fn(&str, Option<&str>)`. Gate them on the os as well: every `cfg(target_arch = "wasm32")` browser branch becomes `all(target_arch = "wasm32", not(target_os = "emscripten"))`, and its `not(target_arch = "wasm32")` counterpart becomes `any(not(target_arch = "wasm32"), target_os = "emscripten")`. The same gate goes on the wasm-only dependency table, so emscripten builds do not pull js-sys, serde-wasm-bindgen or wasm-bindgen at all. No behaviour change for any existing target. Verified: `cargo check --all-features` (native) and `cargo check --target wasm32-unknown-unknown --no-default-features` for both deno_doc and deno_doc_wasm pass before and after.
crowlKats
enabled auto-merge (squash)
October 1, 2026 02:18
magurotuna
approved these changes
Oct 1, 2026
crowlKats
added a commit
to jsr-io/jsr
that referenced
this pull request
Oct 10, 2026
Moves the branch off every local checkout and onto published toolchains:
* [patch.crates-io] now carries the workers-rs emscripten tokio patchset
verbatim from cloudflare/workers-rs examples/emscripten-tokio (guybedford
tokio/mio tags + rust-lang/libc), and the whole wasm-bindgen family comes
from crates.io 0.2.129 — the sibling ../workers-rs forks are gone, as are
the 3 tokio methods that fork needed.
* `worker-build --emscripten --release` (workers-rs 0.8.7) is the build
driver, via api/build-worker.sh and wrangler's [build] command. It
provisions emsdk 6.0.10 and applies the emscripten frontend patches itself,
so the hand-patched emscripten checkout and the import-source workaround
are no longer needed. It also requires the `worker` SDK crate in the graph,
which is what makes it pass the tokio/wasm-bindgen unstable cfgs.
* The fetch export is `#[wasm_bindgen(experimental_tokio = "isolated")]`
(upstream's name) and drops `js_namespace = ["default"]`: worker-build's
generated shim provides the default export as a WorkerEntrypoint subclass.
* tokio can no longer use `features = ["full"]` on wasm — the patched tokio
hard-errors on process/signal/rt-multi-thread for emscripten — so the
shared dep lists a wasm-buildable set and native re-adds `full`.
* Release profile for the worker: opt-level = "s" + fat LTO, 36.6MB -> 24.2MB
wasm. opt-level = "z" reaches 22.0MB but triples latency and starves the
per-request pool under load; opt-level = 3 + LTO does not link (wasm-bindgen
cannot parse the exnref output). See EMSCRIPTEN_EXPERIMENT.md#size.
* Four patches retired by upgrading instead of patching (libc from the git
patchset, and socket2 0.6 / deno_doc / tar from the vendored set), leaving the
tokio+mio git patchset and six vendored cfg fixes:
- libc: the emscripten declarations shipped in 0.2.190, so it comes from
crates.io now. The release alone was not enough - the mio fork hardcodes
`libc = { git = "rust-lang/libc", branch = "libc-0.2" }`, so a
[patch."https://github.com/rust-lang/libc"] entry redirects that source at the
published crate, otherwise the graph carries two libc copies.
- socket2 0.6: 0.6.5 has the emscripten cfg upstream (tokio uses it unpatched);
socket2 0.5 refreshed 0.5.7 -> 0.5.10.
- deno_doc: 0.208.0 ships denoland/deno_doc#857. Needs deno_graph =0.109.0 ->
=0.111.0 (two deno_graph versions in one graph are different types), and with
it: BuildOptions::unstable_text_imports is gone (0.111 allows
`with { type: "text" }` unconditionally - jsr had it false, and there is no
flag left to keep it off), BuildOptions gained unstable_config_imports and
prefer_cached_jsr_versions (both false = previous behaviour), GenerateOptions
gained symbol_listing_limit (None = render everything, as before).
- tar: 0.4.46 builds for emscripten unpatched. The blocker was jsr's own
fixture - big_file/big.txt is 21MB of zeros stored sparsely, and tar >= 0.4.46
writes a sparse file as a GNUSparse entry, which the reader rejects as
invalidEntryType before the size check the test is about. tar.sparse(false) in
the test helpers fixes it and stops the fixture depending on the checkout's
filesystem.
The six fixes that remain are deliberately NOT in this commit. jsr does not
carry local patches of third-party crates, so the committed [patch] table is
just the git tags above, and as a consequence the wasm32-unknown-emscripten
link does not succeed from a clean checkout until those six land upstream.
Native builds are unaffected: `cargo test` is 173/173 with no patch directory
present at all, and Cargo.lock resolves those crates from crates.io at main's
versions (reqwest 0.12.12 and astral-tokio-tar 0.6.3 pinned back so re-resolving
does not drag in unrelated drift).
EMSCRIPTEN_EXPERIMENT.md records what each fix is - 2 lines for ring, 3 for
slug, 4 for socket2, ~10 for astral-tokio-tar, 110 mechanical ones for reqwest -
and the blocker for each: ring
needs the tree-sitter grammar bump (tree-sitter-javascript 0.21.4 is the last
crate pinning cc ~1.0.90) before briansmith/ring#2877 can be used; socket2 0.5
is pulled only by routerify's hyper "tcp" feature; reqwest is stuck in two
different ways (below); slug is a mandatory comrak 0.29 dependency that
deno_doc pins; astral-tokio-tar has no upstream fix in 0.7.0.
* .gitignore picks up .wrangler/, api/build/ and .emscripten-patches/, and
.licenserc.json / deno.json exclude .emscripten-patches/ as well, so a locally
reconstructed copy of those crates cannot be committed by accident and does not
trip the license-header check (it globs **/*.rs and flagged 418 files).
Also fixes a regression from the first experiment commit: the native-only
rust-s3 dep had lost `default-features = false`, which re-enabled rust-s3's
`fail-on-err` and turned every missing-object 404 into a 500 (3 failing tests).
Upstream re-checked 2026-10-08: mio#1969 is merged but unreleased (mio 1.2.4
predates it), tokio#8484 and ring#2877 are still open, rust-s3 0.38.0 is still on
reqwest 0.12, and comrak 0.56 drops slug to a dev-dependency but deno_doc still
pins comrak 0.29.
reqwest specifically (2026-10-10): the emscripten gate only ever landed in 0.13 -
0.12.28, the latest 0.12, still has the bare cfg(target_arch = "wasm32") - and
neither copy can reach it from jsr's side. The 0.12 copy belongs to rust-s3 and
opentelemetry (opentelemetry-http is still ^0.12 even at 0.31), and 0.13 cannot
satisfy ^0.12. The 0.11 copy is capped at 0.12 by oauth2 5.0.0, so the only
reachable step is consolidating 0.11 -> 0.12: it retires one of the two patches
and costs oauth2 4->5 plus postmark 0.10->2.0 in the auth/email path.
Verified: 173/173 + 8 native tests pass; the worker serves on stock
`wrangler dev` (no forked workerd) with 64/64 concurrent requests returning
200 and no cross-request-I/O errors.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
wasm32-unknown-emscriptenistarget_arch = "wasm32", but unlikewasm32-unknown-unknownit is also unix with a full libc — it wants the native code paths.std::process::Command,percent_encodingand a Rust closure for the markdown highlighter all work there;js_sys/wasm-bindgendo not, since nothing is reaching into the module from a JS host that way.deno_doc currently keys those branches on
target_arch = "wasm32"alone, so an emscripten build takes the browser path and fails to compile. For examplesrc/html/usage.rspasses ajs_sys::Functionwhere the native signature wantsFn(&str, Option<&str>):This PR gates each of those cfgs on the OS as well:
cfg(target_arch = "wasm32")→cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))cfg(not(target_arch = "wasm32"))→cfg(any(not(target_arch = "wasm32"), target_os = "emscripten"))including the
[target.'cfg(target_arch = "wasm32")'.dependencies]table, so emscripten builds don't pull js-sys, serde-wasm-bindgen or wasm-bindgen at all.No behaviour change for any existing target — emscripten is the only cfg that moves. Verified:
cargo check --all-features(native): passescargo check --target wasm32-unknown-unknown --no-default-features, for bothdeno_docanddeno_doc_wasm: passes, before and afterContext: this came out of running the whole jsr registry API as a
wasm32-unknown-emscriptenCloudflare Worker, where deno_doc is currently the one dependency that has to be vendored with a local patch.