The repository
Generated from README.md when the site was built at 7aa23e2.
The DOM as a universal UI API: any language drives it through a C API over node ids, and each platform renders it with its current native toolkit. See DECISIONS.md for the architecture.
Layout
Section titled “Layout”idl/: the WebIDL subset niso implements. The C API and the JS binding are generated from it.crates/niso-idl: the WebIDL model and code generators.crates/niso-core: the DOM core, on blitz-dom.crates/niso-crypto: the cryptography undercrypto.subtle, on AWS-LC through aws-lc-rs.crates/niso-xpath: XPath 1.0 and DOM’s XPath interfaces over the trees a host lends through niso-host’sTree;document.evaluateruns it over the DOM.crates/niso-xml: XML 1.0 parsing and DOM Parsing’s XML serialization over itsBuilderandTreetraits; DOMParser, XMLSerializer andresponseXMLuse it.crates/niso-capi: the C API (niso.h), as a static and dynamic library. Timers and animation frames are part of it: the DOM runs the event loop for every language.bindings/js: the JS binding. The glue (composed bycrates/niso-composefrombindings/js/glueand the crates’gluesections) and the generated host functions are shared by every engine; an engine implementsniso_engine.h.bindings/js/quickjs,crates/niso-quickjs: the binding on QuickJS-ng, andniso-run, which runs scripts against a headless DOM.bindings/jvm,crates/niso-jvm: the JVM binding, for Java and Kotlin: a class per DOM interface indev.niso.dom, generated from the WebIDL with the JNI functions behind them, and the hand-written runtime (Dom, handles, callbacks, exceptions).libniso_jvmis the C API with those JNI functions; the Android host links them into its own library.bindings/js/porffor,crates/niso-porffor: the binding on Porffor, compiled ahead of time with the scripts it runs, andniso-run-porffor. See docs/engines/porffor.md.bindings/js/napi,crates/niso-napi: the binding as a Node-API addon, V8 under Node (JavaScriptCore under Bun), with each page in a realm of its own and Node’s event loop driving it, andniso-node,niso-runon it. See docs/engines/napi.md.crates/niso-wpt: the web-platform-tests runner. See docs/wpt.md, which also explains the Baseline score intests/wpt/baseline.json.crates/niso-core/src/render.rs: the render stream, the laid-out box tree as per-frame changes with shaped glyph runs. Its format is inniso_runtime.h.crates/niso-app: what a native host links: the C API plus QuickJS as one static library, andniso_app.h, theniso_app_main(dom)entry point an app library in any language exports.crates/niso-core/src/template.rs: templates, for targets that take only native views (widgets, Live Activities, notifications): a page’sdata-niso-surfaceelements as boxes with text as strings, and<time data-timer-start>as the platform’s self-updating timer. The format is inniso_runtime.h, next toniso_render_surfaces.hosts/apple: the SwiftUI host for iOS, iPadOS, macOS, visionOS, tvOS and watchOS, linkingcrates/niso-app, its platform differences inhosts/apple/Sources/Platform, with a widget extension (hosts/apple/Widgets) that draws the page’s surfaces as home screen widgets and its Live Activity, from templates the app shares through an App Group, and CarPlay’s templates from the page’scarplay.*surfaces. See docs/hosts/apple.md.hosts/android: the Compose host, callingcrates/niso-androidover JNI, with a Glance widget and an ongoing notification drawn from the page’s surfaces.hosts/android/nisois the page host as an Android library, which the host app (app) and other apps build on.examples/ihatemyphone: an Android volume and screenshot panel, opened as the digital assistant, whose panel and setup screen are niso pages built in Java (pages, tested headless intest) on the host library, with the assistant, volume and screenshots in plain Android code (android).examples/: Svelte pages the hosts run.crates/niso-core/ua/: niso’s platform sheet, which a page asks for with<meta name="niso-platform-style" content="auto">to look native: the platform’s colors, type and corners as--niso-*tokens (niso.css) and a base sheet for iOS, Android or the web, in theniso-platformcascade layer (seeniso_runtime.h;examples/platformandexamples/radiouse it).examples/lang/: the same timer app in Rust, C, Zig and Go, each bindingniso.hdirectly, with a build script that builds it as an app library and runs its headless test, and in Java on the JVM binding.tests/screens: renders an example on a host and in Chrome and compares them, checks every line of text stays in its box, and compares the platform’s text styles with its own text.docs/compat: how far real web apps get on niso headless, and what blocks them.crates/niso-core/src/net: fetch and the network. See docs/security.md for what niso guarantees about cross-origin reads.crates/niso-core/src/storage: where IndexedDB and localStorage keep their data, behind a driver a host can replace. See docs/storage.md.tests/acid: Acid1 and Acid2 laid out by niso and by headless Chrome, box by box, and Acid3 run headless.repros/: minimal standalone repros of the upstream bugs niso works around or that the Acid tests found, each with its issue text.
Checks
Section titled “Checks”tests/check.sh runs all of the below; tests/check.sh --devices also renders
every page in tests/screens/cases.txt on the iOS Simulator and the Android
emulator (macOS with Xcode and the Android SDK). Layout is compared with Chrome:
every element’s box within 1px, and box-only screenshots nearly identical. Text
is checked for consistency, its ink inside its box at the default and a large
text size, and tests/screens/text.mjs compares each text style’s look with
SwiftUI’s and Compose’s own text, loosely, in each text setting. Labelled side-by-side screenshots and
reports land in target/screens/; the simulator is the newest iOS runtime’s
iPhone 17 unless NISO_SIMULATOR names another.
To run a host by hand: hosts/apple/build.sh counter (--platform macos, tvos-sim, visionos-sim or watchos-sim for the other Apple platforms, --page DIR for an HTML page) or hosts/android/build.sh counter;
--app LIB instead of a page name runs an app library (see niso_app.h), and on
Android --jvm DIR CLASS a JVM app: the Java sources in DIR built in, CLASS a
Consumer<dev.niso.dom.Dom> (hosts/android/build.sh --jvm examples/lang/java Timer).
examples/ihatemyphone/build.sh builds ihatemyphone’s APK.
git submodule update --init # QuickJS-ngcargo test --workspace # C API test (in C against niso.h), JS binding tests, the Rust timer appexamples/lang/c/build.sh # the timer app in C (also zig/, go/, java/; rust/ runs in cargo test)examples/ihatemyphone/test/run.sh # ihatemyphone's panel and setup pages, headless on the JVMtests/svelte/run.sh # mounts a Svelte 5 component headless and drives ittests/wpt/fetch.sh # pinned WPT checkout in third_party/wptcargo run --release -p niso-wpt # WPT's tests of Baseline features; fails on any regressioncargo run --release -p niso-wpt -- --engine node # the same tests under niso-node, into target/wpt-napi/ (diff.md against the expectations)tests/acid/fetch.sh # pinned Acid1, Acid2 and Acid3 in third_party/acidnode tests/acid/run.mjs # Acid1/Acid2 boxes against Chrome, Acid3 score; needs Chromenode tests/porffor/run.mjs builds every example and the Svelte fixture with
Porffor, compares each with QuickJS, and runs the JS binding tests on Porffor
(it needs porf; results in target/porffor/results.md).
On Linux, see docs/linux.md for the toolchains and the platform differences.
tests/wpt/expectations.json records which subtests pass, and
tests/wpt/expectations.<os>.json what differs on one system. After a change
that makes more pass, record them with cargo run --release -p niso-wpt -- --update
on each system.
A full run scores its results against the web’s Baseline features in
target/wpt/baseline.json, and --update records the score of the new
expectations in tests/wpt/baseline.json; see docs/wpt.md.
tests/acid/expectations.json lists every Acid difference from Chrome and every
failing Acid3 test with its reason; the run fails on a new one and on one that
stopped happening.