> ## Documentation Index
> Fetch the complete documentation index at: https://docs.spurdoverse.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Web APIs

> The standard web globals scripts get, and where they differ from a browser.

Scripts run in a context shaped like a Web Worker. The APIs below are globals and follow the specs, so
[MDN](https://developer.mozilla.org/en-US/docs/Web/API) is the reference.

<Note>
  There's no `window`, `document`, `sessionStorage`, `indexedDB`, `Worker`, `alert`/`prompt` or
  `onmessage`, even though TypeScript's DOM types declare them. `using` works; `DisposableStack` doesn't exist.
</Note>

## What's there

| Area | Globals |
| :- | :- |
| Networking | `fetch`, `Headers`, `Request`, `Response`, `FormData`, `XMLHttpRequest`, `WebSocket`, `EventSource`: see [Networking](/api/networking) |
| Events | `EventTarget`, `Event`, `CustomEvent`, `ErrorEvent`, `MessageEvent`, `PromiseRejectionEvent`, `KeyboardEvent`, `MouseEvent`, `WheelEvent`, `AbortController`, `AbortSignal`, `DOMException` |
| Text | `TextEncoder`, `TextDecoder`, `btoa`, `atob`, `URL`, `URLSearchParams` |
| Binary | `Blob`, `File`, `FileReader`, `URL.createObjectURL`, `structuredClone` |
| Streams | `ReadableStream`, `WritableStream`, `TransformStream`, queuing strategies, `TextEncoderStream`, `TextDecoderStream`, `CompressionStream`, `DecompressionStream` |
| Crypto | `crypto.getRandomValues`, `crypto.randomUUID`, `crypto.subtle` |
| Scheduling | `queueMicrotask`, `requestAnimationFrame`, `requestIdleCallback`, `MessageChannel`, `performance`, `reportError` |
| Other | `navigator`, `origin`, `WebAssembly` (with [WASI](/api/wasi)) |

Timers, `console` and the game events are on [Globals](/api/globals), storage on
[localStorage](/api/localStorage).

***

## Differences

| API | Here |
| :- | :- |
| `TextDecoder` | only `utf-8`, `utf-16le`, `utf-16be`, `windows-1251`, `windows-1252` and `koi8-r`; other labels throw `RangeError` |
| `CompressionStream` | `gzip`, `deflate`, `deflate-raw` |
| `DecompressionStream` | the same plus `br` |
| `requestAnimationFrame`, `requestIdleCallback` | run once per overlay frame, like `render` |
| `performance` | only `now`, `timeOrigin`, `mark`, `measure` |

***

## crypto.subtle

| Kind | Algorithms |
| :- | :- |
| Digest | SHA-1, SHA-256, SHA-384, SHA-512 |
| MAC | HMAC |
| Ciphers | AES-GCM, AES-CBC, AES-CTR, RSA-OAEP |
| Signatures | RSASSA-PKCS1-v1\_5, RSA-PSS, ECDSA |
| Derivation | PBKDF2, HKDF, ECDH |
| Curves | P-256, P-384, P-521 |
| Key formats | `raw`, `jwk`, `spki`, `pkcs8` |

Other algorithms (Ed25519, X25519, SHA-3, …) reject with `NotSupportedError`.

<Warning>
  RSA `generateKey` blocks the script for tens of milliseconds (4096-bit far more). Generate keys once
  and keep them.
</Warning>

```ts theme={null}
const key = await crypto.subtle.importKey(
    "raw", new TextEncoder().encode("secret"),
    { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);

const mac = await crypto.subtle.sign("HMAC", key, new TextEncoder().encode("payload"));
const hex = [...new Uint8Array(mac)].map((b) => b.toString(16).padStart(2, "0")).join("");
```
