# Vendored dependency patches

## fastrand-2.5.0

### The problem

`yrs` (pinned exact in `core/Cargo.toml`) depends on `fastrand` with its
`js` feature enabled unconditionally, and fastrand's own manifest ties that
feature, on `wasm32`/`wasm64`-`unknown`, to `getrandom` with the `wasm_js`
feature forced on. That feature makes `getrandom` default to a
`wasm-bindgen`-based backend which imports host JS functions
(`crypto.getRandomValues`, etc.) — an import the Go/wazero host cannot
satisfy, and the thing `core/tests/no_host_imports.rs` gates against.

`yrs::Doc` calls into this path unconditionally on construction (even via
`Doc::with_client_id`, which still generates a random document GUID via
`fastrand::Rng::new()` -> `getrandom`). Worse: merely *referencing*
`yrs::Doc` anywhere in `docs-core`'s public API — required for
`apply_update`/`text_content`, since the test suite calls them from a
separate compilation unit against the `rlib` — is enough for those
`wasm-bindgen` exports to end up linked into the final `.wasm` module, even
along code paths that are never reached at runtime. Reproduced in
isolation (a scratch crate depending on nothing but `yrs = "=0.23.5"`, with
a single `pub fn unused(_doc: &yrs::Doc) {}` and no method calls at all);
see `task-3-report.md` in the plan directory for the full trace.

### The fix, and why it needs vendoring

`getrandom` supports exactly this scenario: selecting its `custom` backend
via `--cfg getrandom_backend="custom"` (set in `docs-wt-core/.cargo/
config.toml`, scoped to the `wasm32-unknown-unknown` target only) routes
entropy requests to a symbol we provide ourselves
(`__getrandom_v03_custom` in `core/src/lib.rs`, which — deliberately —
fails rather than fabricating bytes; see the doc comment above it), with
no JS dependency.

That override alone doesn't compile, though. `getrandom-0.4.3`'s
`src/error.rs:181-185` has a `Display`/`Debug` match arm:

```rust
#[cfg(all(
    feature = "wasm_js",
    target_arch = "wasm32",
    any(target_os = "unknown", target_os = "none")
))]
Error::WEB_CRYPTO => "Web Crypto API is unavailable",
```

gated only on the `wasm_js` Cargo *feature* — not on which backend is
actually *selected* via `--cfg getrandom_backend`. `Error::WEB_CRYPTO`
itself is defined inside `src/backends/wasm_js.rs:71`, inside the `mod
wasm_js;` declaration that a `getrandom_backend="custom"` override skips
compiling entirely (`src/backends.rs`'s `cfg_if!` chain is mutually
exclusive; `custom` is checked first and short-circuits the rest). Result,
reproduced directly against the pinned version with nothing changed except
adding the cfg override:

```
error[E0599]: no associated function or constant named `WEB_CRYPTO` found for struct `error::Error` in the current scope
   --> .../getrandom-0.4.3/src/error.rs:185:20
```

As long as *anything* in the dependency graph requests fastrand's `js`
feature on a wasm32/wasm64-unknown target — which `yrs` does,
unconditionally, and which we cannot override, since Cargo features are
additive across the whole graph and `docs-core` has no way to un-request a
feature another crate requires — this is a hard compile error, regardless
of which non-`wasm_js` backend `--cfg getrandom_backend` selects (`custom`,
`unsupported`, etc. all hit the same match arm). This looks like a real
gap in `getrandom` 0.4.3's own cfg-gating (the match arm's cfg should also
require `not(getrandom_backend = "custom")` or equivalent, matching what
the backend-selection `cfg_if!` already does) rather than anything specific
to this project; `getrandom`'s own issue tracker has at least one adjacent,
still-open report of the same problem area — a `custom`-backend override
not fully insulating a build from a `wasm_js` feature forced on by another
dependency in the graph — closed "not planned":
<https://github.com/rust-random/getrandom/issues/633>. We did not find an
issue number for this exact `E0599`/`WEB_CRYPTO` symptom; if one turns up,
add it here.

### What was changed

This vendored copy of `fastrand-2.5.0` is the unmodified upstream Rust
source (`src/`, `benches/`, `tests/`, licenses — byte-identical to the
crates.io tarball); only `Cargo.toml` differs, by exactly one edit: the
`wasm32`/`wasm64`-`unknown`-scoped `getrandom` dependency drops
`features = ["wasm_js"]` (kept `optional = true`). Nothing in fastrand's
actual logic changes — the `js` feature still exists, `fastrand::Rng::new()`
still calls into `getrandom` the same way — only *which* `getrandom`
backend ends up linked changes, and that's exactly what the
`--cfg getrandom_backend="custom"` override in `.cargo/config.toml` is
choosing on purpose. Wired in via `[patch.crates-io]` in `core/Cargo.toml`.

### When this can be deleted

Try removing the `[patch.crates-io]` block from `core/Cargo.toml` (and
`vendor/fastrand-2.5.0/`) and running:

```
cargo build --release --manifest-path core/Cargo.toml --target wasm32-unknown-unknown
```

If that compiles cleanly (no `E0599`), delete the patch and this
directory — that's the goal state. Concretely, that becomes true once any
one of:

1. A `getrandom` release fixes `error.rs`'s `WEB_CRYPTO` match arm to also
   respect `getrandom_backend` (e.g. adds `not(getrandom_backend =
   "custom")`), and `core/Cargo.toml`'s `getrandom = "=0.4.3"` pin is
   bumped to that version.
2. A `fastrand` release stops forcing `wasm_js` onto its optional
   `getrandom` dependency (making it opt-in instead, which is what
   getrandom issue #633 above is effectively asking for), and `yrs`'s pin
   on it moves to that version.
3. `yrs` stops requiring `fastrand`'s `js` feature at all for the
   wasm32-unknown-unknown target — unlikely while it still generates
   random document GUIDs internally, but would remove the whole problem.

Verified as of this writing (2026-08-30) that the patch is still required:
removing it and rebuilding reproduces the exact `E0599` above.
