Expand description
Runtime-agnostic host platform APIs: fetch, and per-origin storage.
The third crate on the same split that produced blitz-dom-api. The DOM
facade took DOM operations and removed the runtime; this takes the platform
APIs and removes both the runtime and the transport, so what is left is
the part every binding would otherwise write again.
blitz-traits FetchProvider, StorageProvider, OriginKey
| the embedder implements these
blitz-platform-api this crate: origin scoping, the in-flight table,
| the completion queue, the counters
blitz-wasm binds it for a WebAssembly guest
blitz-script can bind the same thing for JavaScript§Why this is not inside blitz-wasm
Because JavaScript has no fetch() either. blitz-script’s fetch
module is synchronous <script src> loading and nothing
else, and chuzz’s WEB_API_SHIM supplies an in-memory localStorage and a
deliberately non-conformant URL. Written inside the wasm binding, all of
this would have to be written a second time for Boa. Written here, Boa’s
binding is argument coercion over the same host.
§What is not here
No HTTP. This crate never opens a socket, parses a header off the wire, or
names a client. blitz-net already ships reqwest with HTTP/2, cookies,
compression and a cacache disk cache, and it implements
FetchProvider over that same
client. Anything here that looked like HTTP logic would be a second, worse
implementation of it.
No runtime. Nothing here is async, nothing spawns, and nothing blocks.
PlatformHost::start_fetch hands the request to the provider and returns
an id; the provider answers on whatever thread it likes; the answer waits in
a queue until an embedder drains it.
tests/no_client_or_engine.rs asserts both against the resolved dependency
graph, in the manner of blitz-dom-api’s no_boa.rs.
§Borrow discipline, and why fetch completes the way a click dispatches
A completed fetch is delivered by draining a queue, never by a callback that reaches into a document.
blitz-wasm already learned this on the event path: calling a guest from
inside EventHandler::handle_event would run guest code while the
EventDriver holds the document, and the guest’s first act is to mutate the
DOM. Its answer was to queue listener ids during propagation and call the
guest afterwards, with the borrow gone.
Fetch has the identical hazard from the other direction: a response arrives
on a network thread at a moment nothing knows about. So it takes the
identical answer, and this crate is built so the wrong version does not
compile. Nothing here can reach a document, because nothing here has ever
been given one: PlatformHost holds an origin, two providers and a table.
The completion handler holds a Weak reference to that
table and nothing else.
§Origin scoping
A PlatformHost is built for one origin and holds it for life. Every
storage call on it is scoped to that origin, and there is no method that
takes an origin as an argument. A binding therefore cannot pass the wrong
one, in the same way blitz-wasm’s event handler cannot reach the guest.
See OriginKey for why file: and
data: documents each get their own opaque origin rather than sharing one
bucket.
Re-exports§
pub use counters::PlatformCounters;pub use fetch::FetchState;pub use fetch::RequestId;pub use storage::MemoryStorage;
Modules§
- counters
- What the platform APIs moved, counted where this crate can see it.
- fetch
- The in-flight table: what a request id names, and what states it passes through.
- storage
- The storage provider this crate can supply without depending on anything: an in-memory one.
Structs§
- Platform
Host - The platform APIs available to one document, at one origin.
Type Aliases§
- Ready
Waker - Called when a fetch completes, so an embedder knows to drain the queue.