Skip to content

Fix wasm32 build without the wasm feature#337

Open
dmoose wants to merge 1 commit into
eclipse-biscuit:mainfrom
dmoose:fix/wasm32-build-without-wasm-feature
Open

Fix wasm32 build without the wasm feature#337
dmoose wants to merge 1 commit into
eclipse-biscuit:mainfrom
dmoose:fix/wasm32-build-without-wasm-feature

Conversation

@dmoose

@dmoose dmoose commented Jul 14, 2026

Copy link
Copy Markdown

biscuit-auth fails to compile for wasm32 targets unless the wasm
feature is enabled. Building for wasm32-wasip1 (or
wasm32-unknown-unknown without the feature) fails with:

error[E0425]: cannot find function `performance_now` in this scope
error[E0599]: no method named `try_into` found for type `u128`

The cause is an inconsistent set of cfg predicates in
biscuit-auth/src/time.rs. The custom Instant(u64) struct and its
impl are gated on target_arch = "wasm32" alone, while the
performance_now extern and the TryInto import they depend on are
additionally gated on the wasm feature. A wasm32 build without
wasm therefore selects the browser Instant but not the code it
needs.

performance_now is performance.now() bound through wasm-bindgen — a
browser API — so the JS-backed Instant only makes sense under the
wasm feature. Every other wasm32 target, notably WASI (which has a
real monotonic clock), can use the existing std::time::Instant
wrapper. This change gates the JS Instant on
all(target_arch = "wasm32", feature = "wasm") and lets all other
targets fall through to the std implementation. Only the cfg
predicates move; no runtime behavior changes for existing
configurations, and there is no effect on the token format or datalog
semantics.

One judgment call worth surfacing: wasm32-unknown-unknown without the
wasm feature now compiles and relies on std::time::Instant, which
panics at runtime if no clock is available. That configuration
previously failed to compile, so this is not a regression, and browser
builds should keep enabling wasm — but if you would rather keep that
target a hard compile error, I am happy to gate it that way instead.

Verified with cargo build -p biscuit-auth --target wasm32-wasip1, and
by running a full keygen/mint/attenuate/authorize cycle under a WASI
host (wazero).

The wasm32 `Instant(u64)` struct and impl were gated on
`target_arch = "wasm32"` alone, but the `performance_now` extern and
the `TryInto` import they depend on were gated on the `wasm` feature.
A wasm32 build without `wasm` therefore selected the browser `Instant`
without the code it needs, failing to compile with:

    error[E0425]: cannot find function `performance_now` in this scope
    error[E0599]: no method named `try_into` found for type `u128`

`performance_now` is a browser API (`performance.now()` via
wasm-bindgen), so gate the JS `Instant` on
`all(target_arch = "wasm32", feature = "wasm")` and let every other
wasm32 target (e.g. WASI, which has a monotonic clock) fall through to
the `std::time::Instant` wrapper. Only the cfg predicates change.

Signed-off-by: Jeff Shumate <jeff@catapulsion.net>
@divarvel

divarvel commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Hi, the PR description really looks AI-generated.

We don't have an explicit policy for AI contributions yet, but please avoid directly pasting LLM output in places specifically made for human interaction. For this PR, now that I have made this explicit, I may close it if you directly paste LLM output again. As for AI-generated code, please disclose your use of AI, and we will review it as we would any other contribution (perhaps more thoroughly to account for the plausibility-correctness gap)

As for the actual change, ideally not using any feature and just using target-dependent deps would avoid this kind of drift. Maybe @Geal has more context on why a feature was introduced instead on relying only on the target

With that said, compiling only to panic at runtime is not acceptable and is a regression. If the feature is only there to conditionally load dependencies for this target, then the feature should be required for the target.

@dmoose

dmoose commented Jul 14, 2026

Copy link
Copy Markdown
Author

I’m sorry if I tripped over policy with this. Once I found the issue with my code and had created a patch I did delegate pushing the PR to Claude code since it was such a small fix. I will keep this in mind for any future things I find.

@divarvel

Copy link
Copy Markdown
Contributor

Thanks.

Here I think the cleanest fix would be dispensing with the feature altogether and using target-dependent dependencies

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants