No globals
No package reads globalThis. Each helper asks only for the members it uses, so you can pass
the whole platform or only those members.
A program that calls setTimeout, crypto, fetch or process.env directly is tied to the place
it runs. To test it, you patch globals and hope that nothing else reads them.
With @wtf/platform, your program takes a Platform as a parameter instead: its timers, crypto,
console, locks, channels, workers, fetch, file system, environment, paths, folders, terminal, a
way to open a URL and, where the platform has one, a way to start a process. Your code never reads a
global. A test gives it doubles, and gets the same result every time.
import type { Platform } from '@wtf/platform'import { testPlatform } from '@wtf/platform/test'import { sleep } from '@wtf/platform/timers'
const program = async ({ platform, signal }: { platform: Platform; signal: AbortSignal }) => { platform.console.log('Running on %s', platform.dirs.os) await sleep(1000, platform, signal)}
// In a test, time moves only when you say so.const platform = testPlatform()const running = program({ platform, signal: new AbortController().signal })await platform.timers.advance(1000)await runningplatform.console.records // each line it logged| Where your program runs | Its platform |
|---|---|
| Node | nodePlatform({ fetch, storage }), or runMain(program, { fetch, storage }) |
| A page | browserPlatform({ window }) |
| A test | testPlatform(), with fake timers and a seeded crypto |
| A dry run | memoryPlatform(), with each process answered by your script |
Where a web standard defines a member, the platform uses the standard’s own name and signature:
setTimeout, performance, crypto, console, navigator.locks, navigator.storage,
BroadcastChannel, MessageChannel, Worker and fetch. So a browser’s window and Node’s own
objects fit as they are. Where no standard exists, the platform adds its own members: env, path,
dirs, terminal and open.
The file system is the browser’s own file system API, the
WHATWG File System Standard. Your code takes a folder handle and works
with any handle it gets. A browser gives you one already. The fs packages give you one anywhere
else, and helpers that work on any of them.
No globals
No package reads globalThis. Each helper asks only for the members it uses, so you can pass
the whole platform or only those members.
A double for each member
Fake timers, a seeded crypto, a console that records, a fetch that your handler answers,
and processes that your script answers.
Held to the standards
The Web Platform Tests run against the doubles and against Node’s own objects, so each one behaves as its standard says, errors included.
Errors you can match
A member that no standard defines throws a PlatformError. A member from a web standard throws
what the standard says, a DOMException.