Skip to content

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.

  • 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 under crypto.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’s Tree; document.evaluate runs it over the DOM.
  • crates/niso-xml: XML 1.0 parsing and DOM Parsing’s XML serialization over its Builder and Tree traits; DOMParser, XMLSerializer and responseXML use 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 by crates/niso-compose from bindings/js/glue and the crates’ glue sections) and the generated host functions are shared by every engine; an engine implements niso_engine.h.
  • bindings/js/quickjs, crates/niso-quickjs: the binding on QuickJS-ng, and niso-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 in dev.niso.dom, generated from the WebIDL with the JNI functions behind them, and the hand-written runtime (Dom, handles, callbacks, exceptions). libniso_jvm is 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, and niso-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, and niso-node, niso-run on it. See docs/engines/napi.md.
  • crates/niso-wpt: the web-platform-tests runner. See docs/wpt.md, which also explains the Baseline score in tests/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 in niso_runtime.h.
  • crates/niso-app: what a native host links: the C API plus QuickJS as one static library, and niso_app.h, the niso_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’s data-niso-surface elements as boxes with text as strings, and <time data-timer-start> as the platform’s self-updating timer. The format is in niso_runtime.h, next to niso_render_surfaces.
  • hosts/apple: the SwiftUI host for iOS, iPadOS, macOS, visionOS, tvOS and watchOS, linking crates/niso-app, its platform differences in hosts/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’s carplay.* surfaces. See docs/hosts/apple.md.
  • hosts/android: the Compose host, calling crates/niso-android over JNI, with a Glance widget and an ongoing notification drawn from the page’s surfaces. hosts/android/niso is 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 in test) 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 the niso-platform cascade layer (see niso_runtime.h; examples/platform and examples/radio use it).
  • examples/lang/: the same timer app in Rust, C, Zig and Go, each binding niso.h directly, 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.

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.

Terminal window
git submodule update --init # QuickJS-ng
cargo test --workspace # C API test (in C against niso.h), JS binding tests, the Rust timer app
examples/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 JVM
tests/svelte/run.sh # mounts a Svelte 5 component headless and drives it
tests/wpt/fetch.sh # pinned WPT checkout in third_party/wpt
cargo run --release -p niso-wpt # WPT's tests of Baseline features; fails on any regression
cargo 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/acid
node tests/acid/run.mjs # Acid1/Acid2 boxes against Chrome, Acid3 score; needs Chrome

node 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.