Standards conformance
Generated by zinc compat (tests/compat/run.mjs) on 2026-09-28 from Zinc ea4ef8c (with uncommitted compiler / runtime changes), darwin-arm64, in 924 s. Do not edit: rerun zinc compat. The raw per-test results are in tests/compat/results/2026-09-28.json.
Zinc runs every test four ways: the sim oracle (JavaScript on Node) and the native host build, each in the gradual profile (any is Dyn) and the strict one (any refused). Node, Deno, Bun and QuickJS run the same tests as reference engines, with the real harnesses (test262 assert.js, WPT testharness.js). Status letters: ✓ pass, ✗ fail (wrong result or crash), R rejected at compile time (a Z or TypeScript diagnostic: the program is outside Zinc’s subset or uses a missing API), U unsupported by the harness for Zinc (reflection helpers, the asynchronous testharness API, sloppy mode), T timeout. Rates are passes over every selected test, so R and U count as losses.
Engines: Zinc sim, Zinc sim strict, Zinc native, Zinc native strict, Node (v24.14.0), Deno (deno 2.9.6 (stable, release, aarch64-apple-darwin)), Bun (1.3.11), QuickJS (QuickJS version 2026-06-04). Suites: test262 7ab7fafa00 (BSD-3-Clause), wpt 375cf2548a (BSD-3-Clause), quickjs 2f0aa72a6b (MIT), plus 19 curated Node API tests (tests/compat/node).
Summary
| Suite | Tests | Zinc sim | Zinc sim strict | Zinc native | Zinc native strict | Node | Deno | Bun | QuickJS |
|---|---|---|---|---|---|---|---|---|---|
| WinterTC APIs exposed as globals | 78 | 54/78 | 54/78 | 54/78 | 54/78 | 71/78 | 77/78 | 75/78 | 3/78 |
| WinterTC WPT files | 222 | 8/222 (4%) | 8/222 (4%) | 4/222 (2%) | 4/222 (2%) | 174/222 (78%) | 191/222 (86%) | 128/222 (58%) | 4/222 (2%) |
| WinterTC WPT subtests | 39/39 (100%) | 39/39 (100%) | 20/20 (100%) | 20/20 (100%) | 17368/17758 (97.8%) | 17445/17916 (97.4%) | 12751/17673 (72.1%) | 39/16137 (0.2%) | |
| ECMAScript (test262) | 2113 | 434/2113 (20.5%) | 426/2113 (20.2%) | 401/2113 (19.0%) | 396/2113 (18.7%) | 2030/2113 (96.1%) | 2038/2113 (96.5%) | 1867/2113 (88.4%) | 2077/2113 (98.3%) |
| Node API (curated) | 19 | 0/19 (0%) | 0/19 (0%) | 0/19 (0%) | 0/19 (0%) | 19/19 (100%) | 19/19 (100%) | 18/19 (95%) | 0/19 (0%) |
| QuickJS’s own tests | 90 | 5/90 (6%) | 5/90 (6%) | 5/90 (6%) | 5/90 (6%) | 70/90 (78%) | 69/90 (77%) | 65/90 (72%) | 63/90 (70%) |
305 selected test262 tests use features outside Zinc’s design (skipped on every engine, below).
1. WinterTC Minimum Common Web API
The primary axis: the 78 interfaces and globals of Ecma TC55’s Minimum Common Web API (2025 snapshot, ECMA-429), each with the WPT files that test it. Exposed is how the API reaches a Zinc program (a global declared in lib/zinc.d.ts, an import from a zinc: module, or nothing); the reference columns say whether globalThis has it (✓ / ✗) and the share of WPT subtests passed. Zinc cells count WPT files passed per profile (gradual · strict).
| API | Spec | Zinc exposed | WPT files | Zinc sim | Zinc native | Node | Deno | Bun | QuickJS |
|---|---|---|---|---|---|---|---|---|---|
AbortController | DOM | global | 2 | 0/2 · 0/2 | 0/2 · 0/2 | ✓ 100% | ✓ 100% | ✓ 100% | ✗ 0% |
AbortSignal | DOM | global | 2 | 0/2 · 0/2 | 0/2 · 0/2 | ✓ 100% | ✓ 100% | ✓ 100% | ✗ 0% |
Event | DOM | global | 2 | 0/2 · 0/2 | 0/2 · 0/2 | ✓ 93% | ✓ 80% | ✓ 87% | ✗ 0% |
EventTarget | DOM | global | 7 | 2/7 · 2/7 | 0/7 · 0/7 | ✓ 96% | ✓ 100% | ✓ 96% | ✗ 0% |
CustomEvent | HTML | global | — | — | — | ✓ | ✓ | ✓ | ✗ |
ErrorEvent | HTML | global | — | — | — | ✗ | ✓ | ✓ | ✗ |
MessageChannel | HTML | global | 4 | 0/4 · 0/4 | 0/4 · 0/4 | ✓ 89% | ✓ 100% | ✓ 89% | ✗ 0% |
MessageEvent | HTML | global | 2 | 0/2 · 0/2 | 0/2 · 0/2 | ✓ 100% | ✓ 100% | ✓ 100% | ✗ 0% |
MessagePort | HTML | global | 2 | 0/2 · 0/2 | 0/2 · 0/2 | ✓ 50% | ✓ 100% | ✓ 50% | ✗ 0% |
PromiseRejectionEvent | HTML | global | — | — | — | ✗ | ✓ | ✗ | ✗ |
DOMException | WebIDL | global | 4 | 0/4 · 0/4 | 0/4 · 0/4 | ✓ 100% | ✓ 100% | ✓ 98% | ✗ 2% |
Headers | Fetch | global | 10 | 0/10 · 0/10 | 0/10 · 0/10 | ✓ 60% | ✓ 60% | ✓ 56% | ✗ 0% |
Request | Fetch | global | 8 | 1/8 · 1/8 | 1/8 · 1/8 | ✓ 19% | ✓ 76% | ✓ 12% | ✗ 0% |
Response | Fetch | global | 9 | 2/9 · 2/9 | 1/9 · 1/9 | ✓ 81% | ✓ 96% | ✓ 75% | ✗ 0% |
FormData | XHR | global | 9 | 0/9 · 0/9 | 0/9 · 0/9 | ✓ 100% | ✓ 100% | ✓ 70% | ✗ 0% |
Blob | File API | global | 8 | 1/8 · 1/8 | 0/8 · 0/8 | ✓ 95% | ✓ 100% | ✓ 84% | ✗ 0% |
File | File API | global | 2 | 0/2 · 0/2 | 0/2 · 0/2 | ✓ 100% | ✓ 100% | ✓ 62% | ✗ 0% |
CompressionStream | Compression | — | 6 | 0/6 · 0/6 | 0/6 · 0/6 | ✓ 95% | ✓ 100% | ✓ 93% | ✗ 0% |
DecompressionStream | Compression | — | 9 | 0/9 · 0/9 | 0/9 · 0/9 | ✓ 99% | ✓ 97% | ✓ 97% | ✗ 0% |
ByteLengthQueuingStrategy | Streams | — | 1 | 0/1 · 0/1 | 0/1 · 0/1 | ✓ 100% | ✓ 100% | ✓ 90% | ✗ 0% |
CountQueuingStrategy | Streams | — | 1 | 0/1 · 0/1 | 0/1 · 0/1 | ✓ 100% | ✓ 100% | ✓ 100% | ✗ 0% |
ReadableByteStreamController | Streams | — | 3 | 0/3 · 0/3 | 0/3 · 0/3 | ✓ 100% | ✓ 100% | ✓ 46% | ✗ 1% |
ReadableStream | Streams | — | 13 | 0/13 · 0/13 | 0/13 · 0/13 | ✓ 99% | ✓ 100% | ✓ 84% | ✗ 5% |
ReadableStreamBYOBReader | Streams | — | 1 | 0/1 · 0/1 | 0/1 · 0/1 | ✓ 100% | ✓ 100% | ✓ 22% | ✗ 0% |
ReadableStreamBYOBRequest | Streams | — | 1 | 0/1 · 0/1 | 0/1 · 0/1 | ✓ 100% | ✓ 100% | ✓ 100% | ✗ 0% |
ReadableStreamDefaultController | Streams | — | — | — | — | ✓ | ✓ | ✓ | ✗ |
ReadableStreamDefaultReader | Streams | — | 1 | 0/1 · 0/1 | 0/1 · 0/1 | ✓ 100% | ✓ 100% | ✓ 86% | ✗ 0% |
TransformStream | Streams | — | 8 | 0/8 · 0/8 | 0/8 · 0/8 | ✓ 100% | ✓ 99% | ✓ 87% | ✗ 0% |
TransformStreamDefaultController | Streams | — | — | — | — | ✓ | ✓ | ✓ | ✗ |
WritableStream | Streams | — | 10 | 0/10 · 0/10 | 0/10 · 0/10 | ✓ 99% | ✓ 99% | ✓ 92% | ✗ 0% |
WritableStreamDefaultController | Streams | — | — | — | — | ✓ | ✓ | ✓ | ✗ |
WritableStreamDefaultWriter | Streams | — | — | — | — | ✓ | ✓ | ✓ | ✗ |
TextDecoder | Encoding | global | 16 | 0/16 · 0/16 | 0/16 · 0/16 | ✓ 99.7% | ✓ 99.8% | ✓ 61.4% | ✗ 0.0% |
TextDecoderStream | Encoding | — | 7 | 0/7 · 0/7 | 0/7 · 0/7 | ✓ 100% | ✓ 100% | ✓ 92% | ✗ 0% |
TextEncoder | Encoding | global | 4 | 0/4 · 0/4 | 0/4 · 0/4 | ✓ 100% | ✓ 100% | ✓ 74% | ✗ 0% |
TextEncoderStream | Encoding | — | 3 | 0/3 · 0/3 | 0/3 · 0/3 | ✓ 100% | ✓ 100% | ✓ 100% | ✗ 0% |
URL | URL | global | 8 | 1/8 · 1/8 | 1/8 · 1/8 | ✓ 99.1% | ✓ 94.1% | ✓ 98.3% | ✗ 0.2% |
URLSearchParams | URL | global | 13 | 1/13 · 1/13 | 1/13 · 1/13 | ✓ 100% | ✓ 99% | ✓ 98% | ✗ 0% |
URLPattern | URL Pattern | — | 3 | 0/3 · 0/3 | 0/3 · 0/3 | ✓ 99% | ✓ 98% | ✓ 99% | ✗ 0% |
Crypto | WebCrypto | global | 2 | 0/2 · 0/2 | 0/2 · 0/2 | ✓ 79% | ✓ 100% | ✓ 71% | ✗ 0% |
CryptoKey | WebCrypto | global | — | — | — | ✓ | ✓ | ✓ | ✗ |
SubtleCrypto | WebCrypto | global | 4 | 0/4 · 0/4 | 0/4 · 0/4 | ✓ 91% | ✓ 80% | ✓ 91% | ✗ 0% |
Performance | HR-Time | — | 2 | 0/2 · 0/2 | 0/2 · 0/2 | ✓ 100% | ✓ 100% | ✓ 100% | ✗ 86% |
WebAssembly.Global | Wasm JS API | global | 2 | 0/2 · 0/2 | 0/2 · 0/2 | ✓ 99% | ✓ 100% | ✓ 99% | ✗ 0% |
WebAssembly.Instance | Wasm JS API | global | 2 | 0/2 · 0/2 | 0/2 · 0/2 | ✓ 100% | ✓ 100% | ✓ 97% | ✗ 0% |
WebAssembly.Memory | Wasm JS API | global | 2 | 0/2 · 0/2 | 0/2 · 0/2 | ✓ 100% | ✓ 100% | ✓ 100% | ✗ 0% |
WebAssembly.Module | Wasm JS API | global | 2 | 0/2 · 0/2 | 0/2 · 0/2 | ✓ 100% | ✓ 100% | ✓ 100% | ✗ 0% |
WebAssembly.Table | Wasm JS API | global | 2 | 0/2 · 0/2 | 0/2 · 0/2 | ✓ 100% | ✓ 100% | ✓ 100% | ✗ 0% |
WebAssembly.Tag | Wasm JS API | global | 1 | 0/1 · 0/1 | 0/1 · 0/1 | ✓ 100% | ✓ 100% | ✓ 100% | ✗ 0% |
WebAssembly.Exception | Wasm JS API | global | 1 | 0/1 · 0/1 | 0/1 · 0/1 | ✓ 83% | ✓ 100% | ✓ 83% | ✗ 0% |
WebAssembly.CompileError | Wasm JS API | global | — | — | — | ✓ | ✓ | ✓ | ✗ |
WebAssembly.LinkError | Wasm JS API | global | — | — | — | ✓ | ✓ | ✓ | ✗ |
WebAssembly.RuntimeError | Wasm JS API | global | — | — | — | ✓ | ✓ | ✓ | ✗ |
WebAssembly.compile() | Wasm JS API | global | 1 | 0/1 · 0/1 | 0/1 · 0/1 | ✓ 100% | ✓ 100% | ✓ 100% | ✗ 0% |
WebAssembly.compileStreaming() | Wasm JS API | global | — | — | — | ✓ | ✓ | ✓ | ✗ |
WebAssembly.instantiate() | Wasm JS API | global | 1 | 0/1 · 0/1 | 0/1 · 0/1 | ✓ 100% | ✓ 100% | ✓ 100% | ✗ 0% |
WebAssembly.instantiateStreaming() | Wasm JS API | global | — | — | — | ✓ | ✓ | ✓ | ✗ |
WebAssembly.JSTag | Wasm JS API | global | — | — | — | ✓ | ✓ | ✓ | ✗ |
WebAssembly.validate() | Wasm JS API | global | 1 | 0/1 · 0/1 | 0/1 · 0/1 | ✓ 100% | ✓ 100% | ✓ 100% | ✗ 0% |
globalThis | ECMA-262 | rejected (Z1015) | — | — | — | ✓ | ✓ | ✓ | ✓ |
atob() | HTML | global | 1 | 0/1 · 0/1 | 0/1 · 0/1 | ✓ 100% | ✓ 100% | ✓ 100% | ✗ 0% |
btoa() | HTML | global | — | — | — | ✓ | ✓ | ✓ | ✗ |
setTimeout() | HTML | global | 3 | 0/3 · 0/3 | 0/3 · 0/3 | ✓ 100% | ✓ 100% | ✓ 100% | ✗ 0% |
clearTimeout() | HTML | global | 1 | 0/1 · 0/1 | 0/1 · 0/1 | ✓ 100% | ✓ 100% | ✓ 100% | ✗ 0% |
setInterval() | HTML | global | 4 | 0/4 · 0/4 | 0/4 · 0/4 | ✓ 100% | ✓ 100% | ✓ 100% | ✗ 0% |
clearInterval() | HTML | global | 1 | 0/1 · 0/1 | 0/1 · 0/1 | ✓ 100% | ✓ 100% | ✓ 100% | ✗ 0% |
queueMicrotask() | HTML | global | 2 | 0/2 · 0/2 | 0/2 · 0/2 | ✓ 83% | ✓ 100% | ✓ 100% | ✗ 0% |
structuredClone() | HTML | global | 1 | 0/1 · 0/1 | 0/1 · 0/1 | ✓ 98% | ✓ 97% | ✓ 91% | ✗ 0% |
reportError() | HTML | global | 1 | 0/1 · 0/1 | 0/1 · 0/1 | ✗ 20% | ✓ 0% | ✓ 0% | ✗ 20% |
navigator.userAgent | HTML | global | — | — | — | ✓ | ✓ | ✓ | ✗ |
self | HTML | — | — | — | — | ✗ | ✓ | ✓ | ✗ |
onerror | HTML | — | — | — | — | ✗ | ✓ | ✓ | ✗ |
onunhandledrejection | HTML | — | — | — | — | ✗ | ✓ | ✗ | ✗ |
onrejectionhandled | HTML | — | — | — | — | ✗ | ✗ | ✗ | ✗ |
fetch() | Fetch | global | — | — | — | ✓ | ✓ | ✓ | ✗ |
console | Console | global | 6 | 0/6 · 0/6 | 0/6 · 0/6 | ✓ 100% | ✓ 100% | ✓ 100% | ✓ 30% |
crypto | WebCrypto | global | — | — | — | ✓ | ✓ | ✓ | ✗ |
performance | HR-Time | global | — | — | — | ✓ | ✓ | ✓ | ✓ |
Why the WPT files do not pass on Zinc (sim, gradual):
| Files | Reason |
|---|---|
| 82 | R TS2304 Cannot find name ’…’. |
| 20 | U harness async_test (asynchronous testharness API) |
| 16 | R TS2339 Property ’…’ does not exist on type ’…’. |
| 11 | R TS2693 ’…’ only refers to a type, but is being used as a value here. |
| 11 | U harness step_func (asynchronous testharness API) |
| 9 | R TS2554 Expected N arguments, but got N. |
| 8 | R TS2345 Argument of type ’…’ is not assignable to parameter of type ’…’. |
| 5 | R TS2488 Type ’…’ must have a ’…’ method that returns an iterator. |
| 4 | R TS7023 ’…’ implicitly has return type ’…’ because it does not have a return type annotation and is referenced |
| 4 | R TS7034 Variable ’…’ implicitly has type ’…’ in some locations where its type cannot be determined. |
| 4 | R TS2552 Cannot find name ’…’. Did you mean ’…’? |
| 3 | R TS1345 An expression of type ’…’ cannot be tested for truthiness. |
| 3 | R Z9042 calling ’…’ through a Dyn value is not supported; narrow it first (typeof/instanceof) or convert it (as |
| 3 | R Z9002 structural conversion from ’…’ to ’…’ is not supported; declare ’…’ or ’…’ |
| 3 | R TS2318 Cannot find global type ’…’. |
2. ECMAScript (test262)
A deterministic sample of 2113 tests (every n-th file, tests/compat/manifest.json) from the built-ins Zinc implements and from the language directories. Zinc inputs get the mechanical rewrites zinc check --fix would make (var → let) and the harness passes error constructors by name; test262’s propertyHelper.js and friends need property descriptors and are U on Zinc.
| Area | Tests | Zinc sim | Zinc sim strict | Zinc native | Zinc native strict | Node | Deno | Bun | QuickJS |
|---|---|---|---|---|---|---|---|---|---|
| built-ins/Array | 269 | 8/269 (3%) | 7/269 (3%) | 6/269 (2%) | 6/269 (2%) | 260/269 (97%) | 261/269 (97%) | 268/269 (100%) | 269/269 (100%) |
| built-ins/JSON | 128 | 22/128 (17%) | 22/128 (17%) | 19/128 (15%) | 19/128 (15%) | 127/128 (99%) | 127/128 (99%) | 127/128 (99%) | 128/128 (100%) |
| built-ins/Map | 75 | 1/75 (1%) | 1/75 (1%) | 1/75 (1%) | 1/75 (1%) | 65/75 (87%) | 73/75 (97%) | 72/75 (96%) | 75/75 (100%) |
| built-ins/Math | 132 | 38/132 (29%) | 38/132 (29%) | 38/132 (29%) | 38/132 (29%) | 127/132 (96%) | 132/132 (100%) | 132/132 (100%) | 132/132 (100%) |
| built-ins/Number | 138 | 45/138 (33%) | 45/138 (33%) | 44/138 (32%) | 44/138 (32%) | 137/138 (99%) | 137/138 (99%) | 137/138 (99%) | 138/138 (100%) |
| built-ins/Promise | 140 | 0/140 (0%) | 0/140 (0%) | 0/140 (0%) | 0/140 (0%) | 121/140 (86%) | 121/140 (86%) | 121/140 (86%) | 121/140 (86%) |
| built-ins/Set | 133 | 6/133 (5%) | 6/133 (5%) | 5/133 (4%) | 5/133 (4%) | 133/133 (100%) | 133/133 (100%) | 132/133 (99%) | 133/133 (100%) |
| built-ins/String | 209 | 37/209 (18%) | 37/209 (18%) | 33/209 (16%) | 33/209 (16%) | 209/209 (100%) | 209/209 (100%) | 209/209 (100%) | 209/209 (100%) |
| language/expressions | 469 | 97/469 (21%) | 97/469 (21%) | 91/469 (19%) | 91/469 (19%) | 458/469 (98%) | 456/469 (97%) | 403/469 (86%) | 469/469 (100%) |
| language/literals | 50 | 37/50 (74%) | 37/50 (74%) | 37/50 (74%) | 37/50 (74%) | 50/50 (100%) | 50/50 (100%) | 28/50 (56%) | 50/50 (100%) |
| language/statements | 313 | 119/313 (38%) | 117/313 (37%) | 103/313 (33%) | 103/313 (33%) | 288/313 (92%) | 284/313 (91%) | 188/313 (60%) | 296/313 (95%) |
| language/types | 57 | 24/57 (42%) | 19/57 (33%) | 24/57 (42%) | 19/57 (33%) | 55/57 (96%) | 55/57 (96%) | 50/57 (88%) | 57/57 (100%) |
| all | 2113 | 434/2113 (20.5%) | 426/2113 (20.2%) | 401/2113 (19.0%) | 396/2113 (18.7%) | 2030/2113 (96.1%) | 2038/2113 (96.5%) | 1867/2113 (88.4%) | 2077/2113 (98.3%) |
Zinc outcomes:
| Engine | Pass | Fail | Rejected | Unsupported | Timeout |
|---|---|---|---|---|---|
| Zinc sim | 434 | 3 | 1404 | 272 | 0 |
| Zinc sim strict | 426 | 2 | 1413 | 272 | 0 |
| Zinc native | 401 | 36 | 1404 | 272 | 0 |
| Zinc native strict | 396 | 32 | 1413 | 272 | 0 |
Language, by directory
| Directory | Tests | Zinc sim | Zinc sim strict | Zinc native | Zinc native strict | Node | Deno | Bun | QuickJS |
|---|---|---|---|---|---|---|---|---|---|
| expressions/addition | 6 | 1/6 | 1/6 | 1/6 | 1/6 | 6/6 | 6/6 | 6/6 | 6/6 |
| expressions/array | 8 | 1/8 | 1/8 | 0/8 | 0/8 | 8/8 | 8/8 | 8/8 | 8/8 |
| expressions/arrow-function | 8 | 2/8 | 2/8 | 1/8 | 1/8 | 8/8 | 8/8 | 7/8 | 8/8 |
| expressions/assignment | 8 | 0/8 | 0/8 | 0/8 | 0/8 | 8/8 | 7/8 | 8/8 | 8/8 |
| expressions/assignmenttargettype | 8 | 8/8 | 8/8 | 8/8 | 8/8 | 8/8 | 8/8 | 0/8 | 8/8 |
| expressions/async-arrow-function | 8 | 4/8 | 4/8 | 4/8 | 4/8 | 8/8 | 8/8 | 4/8 | 8/8 |
| expressions/async-function | 7 | 5/7 | 5/7 | 5/7 | 5/7 | 7/7 | 7/7 | 2/7 | 7/7 |
| expressions/async-generator | 8 | 4/8 | 4/8 | 4/8 | 4/8 | 8/8 | 8/8 | 4/8 | 8/8 |
| expressions/await | 8 | 2/8 | 2/8 | 2/8 | 2/8 | 6/8 | 5/8 | 3/8 | 8/8 |
| expressions/bitwise-and | 7 | 0/7 | 0/7 | 0/7 | 0/7 | 7/7 | 7/7 | 7/7 | 7/7 |
| expressions/bitwise-not | 7 | 1/7 | 1/7 | 1/7 | 1/7 | 7/7 | 7/7 | 7/7 | 7/7 |
| expressions/bitwise-or | 7 | 0/7 | 0/7 | 0/7 | 0/7 | 7/7 | 7/7 | 7/7 | 7/7 |
| expressions/bitwise-xor | 7 | 0/7 | 0/7 | 0/7 | 0/7 | 7/7 | 7/7 | 7/7 | 7/7 |
| expressions/call | 8 | 0/8 | 0/8 | 0/8 | 0/8 | 8/8 | 8/8 | 8/8 | 8/8 |
| expressions/class | 8 | 2/8 | 2/8 | 2/8 | 2/8 | 8/8 | 8/8 | 6/8 | 8/8 |
| expressions/coalesce | 8 | 1/8 | 1/8 | 1/8 | 1/8 | 8/8 | 8/8 | 7/8 | 8/8 |
| expressions/comma | 5 | 0/5 | 0/5 | 0/5 | 0/5 | 5/5 | 5/5 | 5/5 | 5/5 |
| expressions/compound-assignment | 8 | 2/8 | 2/8 | 2/8 | 2/8 | 7/8 | 7/8 | 7/8 | 8/8 |
| expressions/concatenation | 5 | 3/5 | 3/5 | 2/5 | 2/5 | 5/5 | 5/5 | 5/5 | 5/5 |
| expressions/conditional | 7 | 0/7 | 0/7 | 0/7 | 0/7 | 7/7 | 7/7 | 7/7 | 7/7 |
| expressions/delete | 8 | 0/8 | 0/8 | 0/8 | 0/8 | 7/8 | 7/8 | 7/8 | 8/8 |
| expressions/division | 7 | 2/7 | 2/7 | 2/7 | 2/7 | 7/7 | 7/7 | 7/7 | 7/7 |
| expressions/does-not-equals | 7 | 0/7 | 0/7 | 0/7 | 0/7 | 7/7 | 7/7 | 7/7 | 7/7 |
| expressions/equals | 6 | 0/6 | 0/6 | 0/6 | 0/6 | 6/6 | 6/6 | 6/6 | 6/6 |
| expressions/exponentiation | 7 | 2/7 | 2/7 | 2/7 | 2/7 | 7/7 | 7/7 | 6/7 | 7/7 |
| expressions/function | 8 | 3/8 | 3/8 | 3/8 | 3/8 | 8/8 | 8/8 | 6/8 | 8/8 |
| expressions/generators | 8 | 0/8 | 0/8 | 0/8 | 0/8 | 8/8 | 8/8 | 8/8 | 8/8 |
| expressions/greater-than | 7 | 3/7 | 3/7 | 2/7 | 2/7 | 7/7 | 7/7 | 7/7 | 7/7 |
| expressions/greater-than-or-equal | 7 | 2/7 | 2/7 | 2/7 | 2/7 | 7/7 | 7/7 | 7/7 | 7/7 |
| expressions/grouping | 8 | 0/8 | 0/8 | 0/8 | 0/8 | 8/8 | 8/8 | 8/8 | 8/8 |
| expressions/in | 8 | 2/8 | 2/8 | 2/8 | 2/8 | 8/8 | 8/8 | 6/8 | 8/8 |
| expressions/instanceof | 8 | 0/8 | 0/8 | 0/8 | 0/8 | 8/8 | 8/8 | 8/8 | 8/8 |
| expressions/left-shift | 7 | 2/7 | 2/7 | 2/7 | 2/7 | 7/7 | 7/7 | 7/7 | 7/7 |
| expressions/less-than | 7 | 2/7 | 2/7 | 2/7 | 2/7 | 7/7 | 7/7 | 7/7 | 7/7 |
| expressions/less-than-or-equal | 7 | 3/7 | 3/7 | 2/7 | 2/7 | 7/7 | 7/7 | 7/7 | 7/7 |
| expressions/logical-and | 8 | 0/8 | 0/8 | 0/8 | 0/8 | 8/8 | 8/8 | 8/8 | 8/8 |
| expressions/logical-assignment | 8 | 2/8 | 2/8 | 2/8 | 2/8 | 8/8 | 8/8 | 7/8 | 8/8 |
| expressions/logical-not | 8 | 1/8 | 1/8 | 1/8 | 1/8 | 8/8 | 8/8 | 8/8 | 8/8 |
| expressions/logical-or | 8 | 1/8 | 1/8 | 0/8 | 0/8 | 8/8 | 8/8 | 8/8 | 8/8 |
| expressions/member-expression | 1 | 0/1 | 0/1 | 0/1 | 0/1 | 1/1 | 1/1 | 1/1 | 1/1 |
| expressions/modulus | 7 | 2/7 | 2/7 | 2/7 | 2/7 | 7/7 | 7/7 | 7/7 | 7/7 |
| expressions/multiplication | 7 | 2/7 | 2/7 | 2/7 | 2/7 | 7/7 | 7/7 | 7/7 | 7/7 |
| expressions/new | 7 | 0/7 | 0/7 | 0/7 | 0/7 | 7/7 | 7/7 | 7/7 | 7/7 |
| expressions/new.target | 7 | 1/7 | 1/7 | 1/7 | 1/7 | 6/7 | 6/7 | 5/7 | 7/7 |
| expressions/object | 6 | 1/6 | 1/6 | 1/6 | 1/6 | 6/6 | 6/6 | 4/6 | 6/6 |
| expressions/optional-chaining | 8 | 3/8 | 3/8 | 3/8 | 3/8 | 7/8 | 7/8 | 4/8 | 8/8 |
| expressions/postfix-decrement | 8 | 2/8 | 2/8 | 2/8 | 2/8 | 8/8 | 8/8 | 5/8 | 8/8 |
| expressions/postfix-increment | 7 | 3/7 | 3/7 | 3/7 | 3/7 | 7/7 | 7/7 | 4/7 | 7/7 |
| expressions/prefix-decrement | 8 | 3/8 | 3/8 | 3/8 | 3/8 | 7/8 | 7/8 | 4/8 | 8/8 |
| expressions/prefix-increment | 8 | 2/8 | 2/8 | 2/8 | 2/8 | 7/8 | 7/8 | 5/8 | 8/8 |
| expressions/property-accessors | 8 | 0/8 | 0/8 | 0/8 | 0/8 | 8/8 | 8/8 | 8/8 | 8/8 |
| expressions/relational | 1 | 0/1 | 0/1 | 0/1 | 0/1 | 1/1 | 1/1 | 1/1 | 1/1 |
| expressions/right-shift | 7 | 1/7 | 1/7 | 1/7 | 1/7 | 7/7 | 7/7 | 7/7 | 7/7 |
| expressions/strict-does-not-equals | 6 | 2/6 | 2/6 | 2/6 | 2/6 | 6/6 | 6/6 | 6/6 | 6/6 |
| expressions/strict-equals | 6 | 2/6 | 2/6 | 2/6 | 2/6 | 6/6 | 6/6 | 6/6 | 6/6 |
| expressions/subtraction | 7 | 1/7 | 1/7 | 1/7 | 1/7 | 7/7 | 7/7 | 7/7 | 7/7 |
| expressions/super | 8 | 0/8 | 0/8 | 0/8 | 0/8 | 8/8 | 8/8 | 8/8 | 8/8 |
| expressions/tagged-template | 7 | 0/7 | 0/7 | 0/7 | 0/7 | 7/7 | 7/7 | 7/7 | 7/7 |
| expressions/template-literal | 8 | 4/8 | 4/8 | 4/8 | 4/8 | 8/8 | 8/8 | 6/8 | 8/8 |
| expressions/this | 6 | 1/6 | 1/6 | 1/6 | 1/6 | 4/6 | 4/6 | 3/6 | 6/6 |
| expressions/typeof | 5 | 0/5 | 0/5 | 0/5 | 0/5 | 4/5 | 4/5 | 4/5 | 5/5 |
| expressions/unary-minus | 7 | 2/7 | 2/7 | 2/7 | 2/7 | 7/7 | 7/7 | 7/7 | 7/7 |
| expressions/unary-plus | 8 | 3/8 | 3/8 | 3/8 | 3/8 | 8/8 | 8/8 | 8/8 | 8/8 |
| expressions/unsigned-right-shift | 7 | 1/7 | 1/7 | 1/7 | 1/7 | 7/7 | 7/7 | 7/7 | 7/7 |
| expressions/void | 8 | 0/8 | 0/8 | 0/8 | 0/8 | 8/8 | 8/8 | 8/8 | 8/8 |
| expressions/yield | 8 | 0/8 | 0/8 | 0/8 | 0/8 | 8/8 | 8/8 | 7/8 | 8/8 |
| literals/boolean | 1 | 1/1 | 1/1 | 1/1 | 1/1 | 1/1 | 1/1 | 1/1 | 1/1 |
| literals/numeric | 24 | 23/24 | 23/24 | 23/24 | 23/24 | 24/24 | 24/24 | 13/24 | 24/24 |
| literals/regexp | 15 | 6/15 | 6/15 | 6/15 | 6/15 | 15/15 | 15/15 | 9/15 | 15/15 |
| literals/string | 10 | 7/10 | 7/10 | 7/10 | 7/10 | 10/10 | 10/10 | 5/10 | 10/10 |
| statements/async-function | 12 | 7/12 | 7/12 | 7/12 | 7/12 | 11/12 | 11/12 | 4/12 | 11/12 |
| statements/async-generator | 9 | 1/9 | 1/9 | 1/9 | 1/9 | 9/9 | 9/9 | 7/9 | 9/9 |
| statements/await-using | 12 | 3/12 | 3/12 | 3/12 | 3/12 | 3/12 | 3/12 | 0/12 | 4/12 |
| statements/block | 11 | 9/11 | 9/11 | 9/11 | 9/11 | 11/11 | 11/11 | 3/11 | 11/11 |
| statements/break | 12 | 6/12 | 6/12 | 6/12 | 6/12 | 12/12 | 12/12 | 7/12 | 12/12 |
| statements/class | 12 | 1/12 | 1/12 | 1/12 | 1/12 | 12/12 | 12/12 | 11/12 | 12/12 |
| statements/const | 12 | 8/12 | 8/12 | 5/12 | 5/12 | 12/12 | 12/12 | 9/12 | 12/12 |
| statements/continue | 12 | 10/12 | 10/12 | 10/12 | 10/12 | 12/12 | 12/12 | 6/12 | 12/12 |
| statements/debugger | 2 | 1/2 | 1/2 | 1/2 | 1/2 | 2/2 | 2/2 | 1/2 | 2/2 |
| statements/do-while | 12 | 7/12 | 7/12 | 6/12 | 6/12 | 12/12 | 12/12 | 5/12 | 12/12 |
| statements/empty | 2 | 1/2 | 1/2 | 1/2 | 1/2 | 2/2 | 2/2 | 2/2 | 2/2 |
| statements/expression | 3 | 1/3 | 1/3 | 1/3 | 1/3 | 3/3 | 3/3 | 2/3 | 3/3 |
| statements/for | 12 | 6/12 | 6/12 | 5/12 | 5/12 | 12/12 | 12/12 | 8/12 | 12/12 |
| statements/for-await-of | 12 | 0/12 | 0/12 | 0/12 | 0/12 | 12/12 | 12/12 | 12/12 | 12/12 |
| statements/for-in | 12 | 4/12 | 4/12 | 4/12 | 4/12 | 12/12 | 12/12 | 6/12 | 12/12 |
| statements/for-of | 12 | 1/12 | 1/12 | 0/12 | 0/12 | 12/12 | 12/12 | 12/12 | 12/12 |
| statements/function | 12 | 2/12 | 2/12 | 0/12 | 0/12 | 12/12 | 12/12 | 12/12 | 12/12 |
| statements/generators | 12 | 0/12 | 0/12 | 0/12 | 0/12 | 12/12 | 12/12 | 12/12 | 12/12 |
| statements/if | 12 | 8/12 | 8/12 | 7/12 | 7/12 | 12/12 | 12/12 | 5/12 | 12/12 |
| statements/labeled | 11 | 6/11 | 6/11 | 6/11 | 6/11 | 11/11 | 10/11 | 4/11 | 11/11 |
| statements/let | 12 | 6/12 | 5/12 | 2/12 | 2/12 | 12/12 | 12/12 | 10/12 | 12/12 |
| statements/return | 12 | 10/12 | 10/12 | 9/12 | 9/12 | 4/12 | 4/12 | 4/12 | 12/12 |
| statements/switch | 12 | 8/12 | 8/12 | 8/12 | 8/12 | 12/12 | 12/12 | 4/12 | 12/12 |
| statements/throw | 12 | 0/12 | 0/12 | 0/12 | 0/12 | 12/12 | 12/12 | 12/12 | 12/12 |
| statements/try | 12 | 2/12 | 1/12 | 1/12 | 1/12 | 12/12 | 12/12 | 10/12 | 12/12 |
| statements/using | 12 | 2/12 | 2/12 | 3/12 | 3/12 | 12/12 | 9/12 | 3/12 | 4/12 |
| statements/variable | 12 | 5/12 | 5/12 | 4/12 | 4/12 | 12/12 | 12/12 | 8/12 | 12/12 |
| statements/while | 12 | 3/12 | 3/12 | 2/12 | 2/12 | 12/12 | 12/12 | 7/12 | 12/12 |
| statements/with | 11 | 1/11 | 1/11 | 1/11 | 1/11 | 4/11 | 4/11 | 2/11 | 11/11 |
| types/boolean | 3 | 1/3 | 1/3 | 1/3 | 1/3 | 3/3 | 3/3 | 2/3 | 3/3 |
| types/list | 2 | 0/2 | 0/2 | 0/2 | 0/2 | 2/2 | 2/2 | 2/2 | 2/2 |
| types/null | 2 | 2/2 | 1/2 | 2/2 | 1/2 | 2/2 | 2/2 | 2/2 | 2/2 |
| types/number | 11 | 8/11 | 7/11 | 8/11 | 7/11 | 11/11 | 11/11 | 11/11 | 11/11 |
| types/object | 10 | 0/10 | 0/10 | 0/10 | 0/10 | 8/10 | 8/10 | 8/10 | 10/10 |
| types/reference | 13 | 5/13 | 4/13 | 5/13 | 4/13 | 13/13 | 13/13 | 12/13 | 13/13 |
| types/string | 12 | 6/12 | 6/12 | 6/12 | 6/12 | 12/12 | 12/12 | 9/12 | 12/12 |
| types/undefined | 4 | 2/4 | 0/4 | 2/4 | 0/4 | 4/4 | 4/4 | 4/4 | 4/4 |
Skipped test262 features
Outside Zinc by design (docs/guide/02-language.md: no reflection, no regex engine, no symbols beyond Symbol.iterator / Symbol.dispose, no typed arrays yet) or host-specific; skipped on every engine so the rates compare the same tests. Tests carrying several features count once per feature.
Reflect.construct 62 · Symbol 57 · BigInt 45 · Proxy 24 · Symbol.toPrimitive 20 · Symbol.species 17 · regexp-modifiers 13 · Array.fromAsync 10 · WeakMap 10 · cross-realm 9 · import.meta 8 · regexp-named-groups 8 · dynamic-import 7 · Reflect 6 · Symbol.matchAll 6 · Symbol.replace 5 · resizable-arraybuffer 4 · Symbol.match 4 · String.prototype.matchAll 4 · Symbol.unscopables 3 · Symbol.isConcatSpreadable 3 · WeakSet 3 · tail-call-optimization 3 · import-defer 3 · Symbol.asyncIterator 3 · Symbol.toStringTag 2 · Float16Array 2 · Symbol.search 2 · regexp-duplicate-named-groups 1 · Symbol.split 1 · source-phase-imports 1 · top-level-await 1 · module flag (harness runs scripts) 1
3. Node API (curated)
Self-contained tests after Node’s test/parallel for the Node-like APIs (fs, path, os, process, buffer, timers, events, util, crypto), with a trimmed common (mustCall). Zinc has its own modules (zinc:fs, zinc:sys, zinc:events…) but no node:* specifiers, so these measure source compatibility with Node programs.
| Test | Zinc sim | Zinc sim strict | Zinc native | Zinc native strict | Node | Deno | Bun | QuickJS |
|---|---|---|---|---|---|---|---|---|
| test-buffer-concat-compare.js | R | R | R | R | ✓ | ✓ | ✓ | ✗ |
| test-buffer-from-tostring.js | R | R | R | R | ✓ | ✓ | ✓ | ✗ |
| test-crypto-hash.js | R | R | R | R | ✓ | ✓ | ✓ | ✗ |
| test-events-emitter.js | R | R | R | R | ✓ | ✓ | ✓ | ✗ |
| test-events-once-promise.js | R | R | R | R | ✓ | ✓ | ✓ | ✗ |
| test-fs-mkdir-stat.js | R | R | R | R | ✓ | ✓ | ✓ | ✗ |
| test-fs-promises.js | R | R | R | R | ✓ | ✓ | ✓ | ✗ |
| test-fs-write-read.js | R | R | R | R | ✓ | ✓ | ✓ | ✗ |
| test-os.js | R | R | R | R | ✓ | ✓ | ✓ | ✗ |
| test-path-basename-dirname-extname.js | R | R | R | R | ✓ | ✓ | ✓ | ✗ |
| test-path-join-normalize.js | R | R | R | R | ✓ | ✓ | ✓ | ✗ |
| test-path-parse-format.js | R | R | R | R | ✓ | ✓ | ✓ | ✗ |
| test-path-resolve-relative.js | R | R | R | R | ✓ | ✓ | ✓ | ✗ |
| test-process-env-argv.js | R | R | R | R | ✓ | ✓ | ✗ | ✗ |
| test-process-hrtime.js | R | R | R | R | ✓ | ✓ | ✓ | ✗ |
| test-process-next-tick.js | R | R | R | R | ✓ | ✓ | ✓ | ✗ |
| test-timers-interval-immediate.js | R | R | R | R | ✓ | ✓ | ✓ | ✗ |
| test-timers-ordering.js | R | R | R | R | ✓ | ✓ | ✓ | ✗ |
| test-util-text-encoding.js | R | R | R | R | ✓ | ✓ | ✓ | ✗ |
4. QuickJS’s own tests
quickjs-ng’s tests/, one test per test_*() call (the function plus the declarations it reaches; qjs:os / qjs:std imports removed). The qjs binary here is Bellard’s QuickJS, so its misses on quickjs-ng-only features are expected.
| File | Tests | Zinc sim | Zinc sim strict | Zinc native | Zinc native strict | Node | Deno | Bun | QuickJS |
|---|---|---|---|---|---|---|---|---|---|
| test_bigint.js | 4 | 0/4 | 0/4 | 0/4 | 0/4 | 4/4 | 4/4 | 3/4 | 3/4 |
| test_builtin.js | 30 | 0/30 | 0/30 | 0/30 | 0/30 | 11/30 | 12/30 | 14/30 | 13/30 |
| test_closure.js | 7 | 0/7 | 0/7 | 0/7 | 0/7 | 7/7 | 6/7 | 6/7 | 7/7 |
| test_language.js | 28 | 0/28 | 0/28 | 0/28 | 0/28 | 27/28 | 27/28 | 21/28 | 23/28 |
| test_loop.js | 17 | 4/17 | 4/17 | 4/17 | 4/17 | 17/17 | 16/17 | 17/17 | 17/17 |
| test_queue_microtask.js | 4 | 1/4 | 1/4 | 1/4 | 1/4 | 4/4 | 4/4 | 4/4 | 0/4 |
5. Zinc failure clusters
Programs Zinc compiled but ran wrongly, grouped by the first error (all suites, all four Zinc runs). Each cluster names one test to reproduce with zinc compat --filter <id>.
| Runs | Engines | Error | Example |
|---|---|---|---|
| 14 | Zinc native, Zinc native strict | fail: C++ build failed: field has incomplete type ’…’ | test262/language/expressions/array/spread-err-sngl-err-expr-throws.js |
| 9 | Zinc native, Zinc native strict | fail: C++ build failed: no matching function for call to ’…’ | test262/built-ins/Array/prototype/findIndex/return-abrupt-from-predicate-call.js |
| 6 | Zinc native, Zinc native strict | fail: panic: Uncaught Test262Error: Test262: This statement should not be evaluated. | test262/language/statements/do-while/decl-fun.js |
| 5 | Zinc native, Zinc native strict | fail: C++ build failed: use of undeclared identifier ’…’ | test262/language/statements/const/block-local-closure-get-before-initialization.js |
| 4 | Zinc native, Zinc native strict | fail: panic: Uncaught Test262Error: Expected SameValue(«…», «…») to be true | test262/built-ins/JSON/stringify/value-primitive-top-level.js |
| 4 | Zinc native, Zinc native strict | fail: C++ build failed: variable has incomplete type ’…’ | test262/built-ins/Set/prototype/clear/clears-an-empty-set.js |
| 4 | Zinc native, Zinc native strict | fail: C++ build failed: expected ’…’ for function-style cast or type construction | test262/language/expressions/arrow-function/dstr/ary-ptrn-elem-id-init-undef.js |
| 4 | Zinc native, Zinc native strict | fail: C++ build failed: declaration of reference variable ’…’ requires an initializer | wpt/FileAPI/blob/Blob-slice-overflow.any.js |
| 2 | Zinc native, Zinc native strict | fail: panic: Uncaught Test262Error: JSON.stringify(”…”) Expected SameValue(«…», «…») to be true | test262/built-ins/JSON/stringify/value-string-escape-unicode.js |
| 2 | Zinc native, Zinc native strict | fail: panic: RangeError: toFixed() digits argument must be between N and N | test262/built-ins/Number/prototype/toFixed/range.js |
| 2 | Zinc native, Zinc native strict | fail: panic: RangeError: invalid count | test262/built-ins/String/prototype/repeat/count-less-than-zero-throws.js |
| 2 | Zinc native, Zinc native strict | fail: panic: Uncaught Test262Error: Sigma preceded by LATIN CAPITAL LETTER A Expected SameValue(«…», «…») to be true | test262/built-ins/String/prototype/toLowerCase/special_casing_conditional.js |
| 2 | Zinc native, Zinc native strict | fail: panic: Uncaught Error | test262/language/expressions/concatenation/S9.8_A2_T2.js |
| 2 | Zinc native, Zinc native strict | fail: C++ build failed: invalid operands to binary expression (’…’ and ‘zrt::Ref<m_z_test262_language_e | test262/language/expressions/greater-than/11.8.2-1.js |
| 2 | Zinc native, Zinc native strict | fail: C++ build failed: invalid operands to binary expression (’…’ and ‘zrt::Ref<m_z_test262_lang | test262/language/expressions/less-than-or-equal/11.8.3-1.js |
| 2 | Zinc native, Zinc native strict | fail: C++ build failed: non-pointer operand type ’…’ incompatible with nullptr | test262/language/expressions/logical-or/S11.11.2_A4_T4.js |
| 2 | Zinc sim, Zinc native | fail: RangeError: Maximum call stack size exceeded | test262/language/expressions/tagged-template/chained-application.js |
| 2 | Zinc sim, Zinc sim strict | fail: panic: Uncaught Test262Error: Expected SameValue(«…», «…») to be false | test262/language/expressions/this/11.1.1-1.js |
| 2 | Zinc native, Zinc native strict | fail: C++ build failed: invalid use of ’…’ outside of a non-static member function | test262/language/expressions/this/11.1.1-1.js |
| 2 | Zinc native, Zinc native strict | fail: panic: Uncaught Test262Error: Expected a ReferenceError to be thrown but no exception was thrown at all | test262/language/statements/let/global-closure-set-before-initialization.js |
| 2 | Zinc sim, Zinc sim strict | fail: panic: Uncaught SyntaxError: Unexpected reserved word | test262/language/statements/using/static-init-await-binding-valid.js |
| 2 | Zinc native, Zinc native strict | fail: C++ build failed: no viable conversion from ’…’ to ’…’ | wpt/dom/events/EventTarget-addEventListener.any.js |
| 2 | Zinc native, Zinc native strict | fail: C++ build failed: expected unqualified-id | wpt/fetch/api/response/response-error.any.js |
| 1 | Zinc native | fail: C++ build failed: redefinition of ’…’ with a different type: ’…’ vs ’…’ | test262/language/statements/try/early-catch-lex.js |
Compile-time rejections (Zinc sim, gradual), by diagnostic:
| Tests | Diagnostic | Example |
|---|---|---|
| 321 | TS2339 Property ’…’ does not exist on type ’…’. | quickjs/test_builtin.js#test_exception_capture_stack_trace |
| 195 | TS2304 Cannot find name ’…’. | quickjs/test_builtin.js#test_proxy_is_array |
| 175 | TS2693 ’…’ only refers to a type, but is being used as a value here. | quickjs/test_builtin.js#test_enum |
| 132 | TS2554 Expected N arguments, but got N. | quickjs/test_builtin.js#test_set |
| 106 | TS2345 Argument of type ’…’ is not assignable to parameter of type ’…’. | node/test-buffer-concat-compare.js |
| 96 | TS7009 ’…’ expression, whose target lacks a construct signature, implicitly has an ’…’ type. | quickjs/test_language.js#test_constructor |
| 59 | TS2550 Property ’…’ does not exist on type ’…’. Do you need to change your target library? Try changing the ’… | test262/built-ins/Array/from/source-object-iterator-1.js |
| 51 | TS2351 This expression is not constructable. | test262/built-ins/Array/length/S15.4.2.2_A2.2_T3.js |
| 39 | TS7034 Variable ’…’ implicitly has type ’…’ in some locations where its type cannot be determined. | quickjs/test_builtin.js#test_cur_pc |
| 36 | TS2451 Cannot redeclare block-scoped variable ’…’. | test262/built-ins/Promise/race/capability-executor-not-callable.js |
| 35 | TS2362 The left-hand side of an arithmetic operation must be of type ’…’, ’…’, ’…’ or an enum type. | test262/language/expressions/bitwise-and/S11.10.1_A3_T1.3.js |
| 33 | TS2318 Cannot find global type ’…’. | quickjs/test_builtin.js#test_eval |
| 24 | Z1014 only Error instances (or subclasses) can be thrown (LNG-N) | test262/language/expressions/bitwise-and/S11.10.1_A2.4_T2.js |
| 23 | TS2367 This comparison appears to be unintentional because the types ’…’ and ’…’ have no overlap. | quickjs/test_builtin.js#test_function_source_pos |
| 21 | TS7053 Element implicitly has an ’…’ type because expression of type ’…’ can’…’{}’. | quickjs/test_builtin.js#test_symbol |
| 17 | TS2683 ’…’ implicitly has type ’…’ because it does not have a type annotation. | quickjs/test_builtin.js#test_function |
| 16 | Z9041 a Dyn value cannot be converted to this type (tp); only primitives, arrays, classes and plain interfaces | test262/built-ins/JSON/parse/15.12.1.1-g1-1.js |
| 16 | TS2322 Type ’…’ is not assignable to type ’…’. | test262/built-ins/Promise/all/invoke-resolve-error-reject.js |
| 12 | Z9004 anonymous object type ’…’ is not supported; declare a named interface or type | test262/built-ins/Array/prototype/indexOf/15.4.4.14-5-10.js |
| 11 | TS2348 Value of type ’…’ is not callable. Did you mean to include ’…’? | quickjs/test_builtin.js#test |
| 11 | TS2552 Cannot find name ’…’. Did you mean ’…’? | quickjs/test_builtin.js#test_finalization_registry |
| 11 | TS2508 No base constructor has the specified number of type arguments. | test262/built-ins/Promise/all/ctx-ctor.js |
| 11 | TS18050 The value ’…’ cannot be used here. | test262/language/expressions/addition/S11.6.1_A3.1_T2.4.js |
| 10 | TS2794 Expected N arguments, but got N. Did you forget to include ’…’ in your type argument to ’…’? | test262/built-ins/Promise/all/resolve-ignores-late-rejection-deferred.js |
| 9 | Z9001 type ’…’ is not supported yet | test262/built-ins/Array/isArray/15.4.3.2-1-11.js |
Sim / native divergences
The sim is the oracle: a program must behave the same natively. 39 test(s) differ:
| Test | Sim (gradual · strict) | Native (gradual · strict) |
|---|---|---|
test262/built-ins/Array/prototype/findIndex/return-abrupt-from-predicate-call.js | ✓ · ✓ | ✗ C++ build failed: no matching function for call to ’…’ · ✗ C++ build failed: no matching function for call to ’…’ |
test262/built-ins/Array/prototype/some/15.4.4.17-7-c-ii-10.js | ✓ · R Z1006 ’…’ is not allowed in the strict typing profile (DYN-N) | ✗ C++ build failed: no matching function for call to ’…’ · R Z1006 ’…’ is not allowed in the strict typing profile (DYN-N) |
test262/built-ins/JSON/stringify/value-function.js | ✓ · ✓ | ✗ C++ build failed: no matching function for call to ’…’ · ✗ C++ build failed: no matching function for call to ’…’ |
test262/built-ins/JSON/stringify/value-primitive-top-level.js | ✓ · ✓ | ✗ panic: Uncaught Test262Error: Expected SameValue(«…», «…») to be true · ✗ panic: Uncaught Test262Error: Expected SameValue(«…», «…») to be true |
test262/built-ins/JSON/stringify/value-string-escape-unicode.js | ✓ · ✓ | ✗ panic: Uncaught Test262Error: JSON.stringify(”…”) Expected SameValue(« · ✗ panic: Uncaught Test262Error: JSON.stringify(”…”) Expected SameValue(« |
test262/built-ins/Number/prototype/toFixed/range.js | ✓ · ✓ | ✗ panic: RangeError: toFixed() digits argument must be between N and N · ✗ panic: RangeError: toFixed() digits argument must be between N and N |
test262/built-ins/Set/prototype/clear/clears-an-empty-set.js | ✓ · ✓ | ✗ C++ build failed: variable has incomplete type ’…’ · ✗ C++ build failed: variable has incomplete type ’…’ |
test262/built-ins/String/S15.5.1.1_A1_T1.js | ✓ · ✓ | ✗ C++ build failed: no matching function for call to ’…’ · ✗ C++ build failed: no matching function for call to ’…’ |
test262/built-ins/String/prototype/padEnd/normal-operation.js | ✓ · ✓ | ✗ panic: Uncaught Test262Error: Expected SameValue(«…», «…») to be true · ✗ panic: Uncaught Test262Error: Expected SameValue(«…», «…») to be true |
test262/built-ins/String/prototype/repeat/count-less-than-zero-throws.js | ✓ · ✓ | ✗ panic: RangeError: invalid count · ✗ panic: RangeError: invalid count |
test262/built-ins/String/prototype/toLowerCase/special_casing_conditional.js | ✓ · ✓ | ✗ panic: Uncaught Test262Error: Sigma preceded by LATIN CAPITAL LETTER A · ✗ panic: Uncaught Test262Error: Sigma preceded by LATIN CAPITAL LETTER A |
test262/language/expressions/array/spread-err-sngl-err-expr-throws.js | ✓ · ✓ | ✗ C++ build failed: field has incomplete type ’…’ · ✗ C++ build failed: field has incomplete type ’…’ |
test262/language/expressions/arrow-function/dstr/ary-ptrn-elem-id-init-undef.js | ✓ · ✓ | ✗ C++ build failed: expected ’…’ for function-style cast or type constru · ✗ C++ build failed: expected ’…’ for function-style cast or type constru |
test262/language/expressions/concatenation/S9.8_A2_T2.js | ✓ · ✓ | ✗ panic: Uncaught Error · ✗ panic: Uncaught Error |
test262/language/expressions/greater-than/11.8.2-1.js | ✓ · ✓ | ✗ C++ build failed: invalid operands to binary expression (’…’ and ‘zrt: · ✗ C++ build failed: invalid operands to binary expression (’…’ and ‘zrt: |
test262/language/expressions/less-than-or-equal/11.8.3-1.js | ✓ · ✓ | ✗ C++ build failed: invalid operands to binary expression (’…’ and ‘zrt: · ✗ C++ build failed: invalid operands to binary expression (’…’ and ‘zrt: |
test262/language/expressions/logical-or/S11.11.2_A4_T4.js | ✓ · ✓ | ✗ C++ build failed: non-pointer operand type ’…’ incompatible with nullp · ✗ C++ build failed: non-pointer operand type ’…’ incompatible with nullp |
test262/language/statements/const/block-local-closure-get-before-initialization.js | ✓ · ✓ | ✗ C++ build failed: use of undeclared identifier ’…’ · ✗ C++ build failed: use of undeclared identifier ’…’ |
test262/language/statements/const/dstr/ary-ptrn-elem-ary-elision-init.js | ✓ · ✓ | ✗ C++ build failed: field has incomplete type ’…’ · ✗ C++ build failed: field has incomplete type ’…’ |
test262/language/statements/const/function-local-closure-get-before-initialization.js | ✓ · ✓ | ✗ C++ build failed: use of undeclared identifier ’…’ · ✗ C++ build failed: use of undeclared identifier ’…’ |
test262/language/statements/do-while/decl-fun.js | ✓ · ✓ | ✗ panic: Uncaught Test262Error: Test262: This statement should not be ev · ✗ panic: Uncaught Test262Error: Test262: This statement should not be ev |
test262/language/statements/for-of/generator-next-error.js | ✓ · ✓ | ✗ C++ build failed: field has incomplete type ’…’ · ✗ C++ build failed: field has incomplete type ’…’ |
test262/language/statements/for/decl-async-fun.js | ✓ · ✓ | ✗ panic: Uncaught Test262Error: Test262: This statement should not be ev · ✗ panic: Uncaught Test262Error: Test262: This statement should not be ev |
test262/language/statements/function/dstr/ary-ptrn-elem-obj-id-init.js | ✓ · ✓ | ✗ C++ build failed: variable has incomplete type ’…’ · ✗ C++ build failed: variable has incomplete type ’…’ |
test262/language/statements/function/dstr/dflt-ary-ptrn-elem-ary-empty-init.js | ✓ · ✓ | ✗ C++ build failed: field has incomplete type ’…’ · ✗ C++ build failed: field has incomplete type ’…’ |
test262/language/statements/if/if-fun-no-else-strict.js | ✓ · ✓ | ✗ panic: Uncaught Test262Error: Test262: This statement should not be ev · ✗ panic: Uncaught Test262Error: Test262: This statement should not be ev |
test262/language/statements/let/block-local-closure-get-before-initialization.js | ✓ · R Z1006 ’…’ is not allowed in the strict typing profile (DYN-N) | ✗ C++ build failed: use of undeclared identifier ’…’ · R Z1006 ’…’ is not allowed in the strict typing profile (DYN-N) |
test262/language/statements/let/dstr/ary-ptrn-elem-ary-elision-init.js | ✓ · ✓ | ✗ C++ build failed: field has incomplete type ’…’ · ✗ C++ build failed: field has incomplete type ’…’ |
test262/language/statements/let/dstr/ary-ptrn-elem-obj-id-init.js | ✓ · ✓ | ✗ C++ build failed: expected ’…’ for function-style cast or type constru · ✗ C++ build failed: expected ’…’ for function-style cast or type constru |
test262/language/statements/let/global-closure-set-before-initialization.js | ✓ · ✓ | ✗ panic: Uncaught Test262Error: Expected a ReferenceError to be thrown b · ✗ panic: Uncaught Test262Error: Expected a ReferenceError to be thrown b |
test262/language/statements/return/line-terminators.js | ✓ · ✓ | ✗ C++ build failed: no matching function for call to ’…’ · ✗ C++ build failed: no matching function for call to ’…’ |
test262/language/statements/try/early-catch-lex.js | ✓ · R Z1006 ’…’ is not allowed in the strict typing profile (DYN-N) | ✗ C++ build failed: redefinition of ’…’ with a different type: ’…’ vs ’… · R Z1006 ’…’ is not allowed in the strict typing profile (DYN-N) |
test262/language/statements/using/static-init-await-binding-valid.js | ✗ panic: Uncaught SyntaxError: Unexpected reserved word · ✗ panic: Uncaught SyntaxError: Unexpected reserved word | ✓ · ✓ |
test262/language/statements/variable/dstr/ary-ptrn-elision.js | ✓ · ✓ | ✗ C++ build failed: field has incomplete type ’…’ · ✗ C++ build failed: field has incomplete type ’…’ |
test262/language/statements/while/decl-gen.js | ✓ · ✓ | ✗ C++ build failed: field has incomplete type ’…’ · ✗ C++ build failed: field has incomplete type ’…’ |
wpt/FileAPI/blob/Blob-slice-overflow.any.js | ✓ · ✓ | ✗ C++ build failed: declaration of reference variable ’…’ requires an in · ✗ C++ build failed: declaration of reference variable ’…’ requires an in |
wpt/dom/events/AddEventListenerOptions-once.any.js | ✓ · ✓ | ✗ C++ build failed: declaration of reference variable ’…’ requires an in · ✗ C++ build failed: declaration of reference variable ’…’ requires an in |
wpt/dom/events/EventTarget-addEventListener.any.js | ✓ · ✓ | ✗ C++ build failed: no viable conversion from ’…’ to ’…’ · ✗ C++ build failed: no viable conversion from ’…’ to ’…’ |
wpt/fetch/api/response/response-error.any.js | ✓ · ✓ | ✗ C++ build failed: expected unqualified-id · ✗ C++ build failed: expected unqualified-id |
6. WinterTC compliance
What a claim needs (ECMA-429 §Conformance): every interface and global of section 1 exposed on globalThis with
the behaviour of its W3C / WHATWG definition, conformance to ECMA-262, the global error / unhandledrejection /
rejectionhandled events (on an EventTarget global or an equivalent mechanism), a navigator.userAgent token, and
written documentation of every deviation with its impact.
Where Zinc stands. Zinc cannot claim WinterTC conformance, and running WPT verbatim is not how it could get there:
- Programs are typed ahead of time. WPT (and test262) files are dynamic JavaScript: untyped callbacks, mixed-type
arrays,
instanceofon constructors passed as values, property enumeration. Zinc’s strict subset rejects nearly all of them at compile time (the R column), whatever the API behind them does. A WinterTC profile for Zinc would be measured with typed ports of the WPT files, one per API, kept next to these runs. - Web APIs are modules, not globals.
globalThisis refused by design (Z1015) and there is noself; the Web APIs being written for Zinc (zinc:web: TextEncoder / TextDecoder, atob / btoa, URL / URLSearchParams, Event / EventTarget / CustomEvent, AbortController / AbortSignal, crypto) are imports. A conformance claim needs them as ambient globals (alib/web.d.tsplus auto-import in the compiler). - Typed arrays and
ArrayBufferare missing (Zinc usesu8[]). Almost every binary API depends on them: TextEncoder,crypto.getRandomValues, Blob / File, streams chunks, fetch bodies, compression, WebAssembly. - No reflection. WebIDL behaviour (property descriptors,
length/nameof methods, prototype chains,Symbol.toStringTag) is checked by most WPT files and by test262’spropertyHelper.js.
Gaps, by effort (S: days, M: 1-3 weeks, L: a quarter or more, one engineer):
| Gap | APIs it unlocks | Effort |
|---|---|---|
Web APIs as ambient globals (lib/web.d.ts, compiler auto-import) and self | everything in zinc:web | S |
| Typed ports of the WPT files for each API Zinc implements, run on sim and native | a measured WinterTC profile | M |
Uint8Array / ArrayBuffer / DataView backed by the runtime’s byte arrays | TextEncoder, crypto, Blob, streams, fetch bodies | M |
DOMException with its legacy codes; ErrorEvent, PromiseRejectionEvent, global error events | HTML error reporting, reportError | S |
Headers / Request / Response with WHATWG shapes (today zinc:net has its own) and fetch as a global | Fetch | M |
structuredClone for plain data (objects, arrays, Map / Set, Date) | HTML | S |
Blob / File / FormData over byte arrays | File API, XHR FormData | M |
| WHATWG Streams (readable, writable, transform, byte streams, queuing strategies) | Streams, TextEncoderStream, CompressionStream, fetch bodies | L |
CompressionStream / DecompressionStream (deflate / gzip; brotli optional) | Compression | M (after streams) |
MessageChannel / MessagePort / MessageEvent on the event loop | HTML messaging | M |
URLPattern (needs a regex engine, refused by design today: Z1008) | URL Pattern | L |
crypto.subtle beyond SHA digests (HMAC, AES-GCM, ECDSA / Ed25519…) | WebCrypto | L |
WebAssembly (an interpreter or AOT of wasm modules) | Wasm JS API | L, likely out of scope |
7. Fixes made with this harness
The first run of this harness found these; each has a regression program in tests/conformance (sim and native print the same bytes, checked against Node too). Together they move the test262 sample from 16.7% to 20.5% on the sim and from 14.4% to 19.0% natively, and cut the sim / native divergences from 51 tests to 35.
| Fix | Before | Program |
|---|---|---|
Generic static methods infer their type arguments; a type parameter bound to two number kinds is number | C++ build failure (Check.same(xs.length, 2.5)) | generic_static.ts |
| Array literals inside unannotated object literals (fixed on main at the same time; regression program added) | compiler crash (stack overflow in Sema.contextual) | literal_member_arrays.ts |
| The sim runs the native backend’s checks | programs refused natively (Z9042, Z1013, Z9001) ran on the sim | (compat divergence table) |
-0 literals keep their sign natively | 1 / -0 was Infinity | string_number_edges.ts |
toFixed: exact ties round up, abs(x) >= 1e21 / NaN / Infinity print like ToString, (-0).toFixed(), digits outside 0-100 | (2.5).toFixed(0) “2”, (1e21).toFixed(2) 22 digits, “nan” | string_number_edges.ts |
parseInt reads 0x without a radix, radix outside 2-36 is NaN; parseFloat is decimal only | parseInt('0x1F') 0, parseFloat('0x10') 16, parseFloat('inf') Infinity | string_number_edges.ts, conversions.ts |
trim / trimStart / trimEnd remove JS white space (U+00A0, U+FEFF, U+2000-U+200A, U+2028, U+3000…) | ASCII only natively | string_number_edges.ts |
String(x), Number(x), Boolean(x); Number.MAX_VALUE, MIN_VALUE, NaN, POSITIVE_INFINITY, NEGATIVE_INFINITY, MIN_SAFE_INTEGER, isSafeInteger, parseFloat, parseInt | Z9019 / TS2339 | conversions.ts |
charAt, concat, trimStart, trimEnd, the position argument of includes / startsWith / endsWith | TS2339 / TS2554 | string_number_edges.ts |
replace / replaceAll substitutions ($$ $& $\ $‘), replaceAll` with an empty pattern | literal $&, ''.replaceAll('', 'x') "" | conversions.ts |
undefined for an optional library parameter means absent | 'abc'.padEnd(5, undefined) “abc”, s.slice(1, undefined) "" | conversions.ts |
Arrays: indexOf / includes from an index, lastIndexOf, findLast, findLastIndex, reduceRight, fill(v, start, end); includes is SameValueZero | TS errors; [NaN].includes(NaN) false natively | array_search.ts |
Math.min / Math.max take any number of values | TS2554 | string_number_edges.ts |
JSON.parse of invalid text throws a SyntaxError | a plain Error (sim and native) | conversions.ts |
Unary + / - on a string or a boolean is ToNumber | +'0x1F' stayed a string natively (C++ build failure) | conversions.ts |
An unannotated const a = [] whose elements nothing types is Z9001 on every target | ran on the sim, Array<void> C++ build failure natively (5 test262 exponentiation tests move from a sim-only pass to a rejection) | (compat) |
8. Larger gaps found (ECMAScript)
Ordered by the number of selected tests they cost (see the clusters above). Effort as in section 6.
| Gap | Where it shows | Effort |
|---|---|---|
No reflection: X.prototype, property descriptors, Function.prototype.call / length / name, Object.getPrototypeOf | test262 propertyHelper.js (U), String.prototype.x.call(...) (TS2339 on prototype) | design (no) |
No Object global: Object.keys / entries / assign / freeze / is / defineProperty | ~140 test262 files (TS2693) | M for the non-reflective part (keys, values, entries, assign, is) |
eval, with, arguments, sloppy mode, new String() wrappers | TS2304 eval, U sloppy tests, TS2351 | design (no) |
Promise beyond then(onFulfilled): catch, finally, then(_, onRejected), race, any, allSettled | built-ins/Promise 0% | M (sim and native event loops) |
Library errors are catchable on the sim but panic natively ('x'.repeat(-1), toFixed(101), invalid array length) | sim / native divergences | M (throw a RangeError / TypeError through the status-return path, ADR 0006) |
Accepted programs whose C++ does not build: void results stored in variables or fields, this at top level, < on objects, unary - on a string, JSON.stringify of a function | “C++ build failed” clusters | S-M (refuse them with a Z code, or give them their JS meaning) |
| UTF-8 strings cannot hold lone surrogates | 'abc'.padEnd(6, '💩'), JSON.stringify('\uD834') | L (design: WTF-8 storage) |
string | null stores null like '': JSON.stringify(['x', null]) prints "" natively | JSON | M (a null tag for strings) |
Math: asin, acos, atan, sinh…, cbrt, log2, log10, expm1, log1p, sumPrecise | built-ins/Math | M (an fdlibm port, so sim and native stay bit-identical) |
Number.prototype.toString(radix), toPrecision, toExponential | built-ins/Number | S-M |
String.fromCodePoint, codePointAt, normalize, localeCompare, String.raw, split(sep, limit) | built-ins/String | S-M each |
Arrays: Array.from / of, keys / values / entries, flat / flatMap, toSorted / toReversed / with, copyWithin, holes | built-ins/Array | M |
Unicode case mapping outside Latin / Greek / Cyrillic, final sigma, İ | toLowerCase special casing | S-M (tables) |
typeof narrowing on a type parameter is refused natively (Z1013) | generic helpers | S-M |
| Labeled statements (Z9011), rest elements in destructuring (Z9016), destructured parameters of async functions (Z9007) | language/statements | S each |
Node API: no node:* modules (fs, path, os, process, buffer, events, timers, util, crypto) | section 3 | L (a node: layer over zinc:fs / zinc:sys / zinc:os / zinc:events / zinc:web) |
The Web API branch. zinc compat --zinc <checkout> measured a snapshot of the parity branch (zinc:web, commit
e0f0e8c): 2 of the 222 WPT files pass on the sim (url-tojson, urlsearchparams-stringifier); the others are
rejected for the reasons of section 6 (globals, typed arrays, dynamic test code), and two crashed the compiler with
the stack overflow fixed here.
How to run
zinc compat # all suites, 4 jobs; writes tests/compat/results/<date>.json and this page
zinc compat --suite wpt --engines zinc-sim,node
zinc compat --filter built-ins/String/prototype/trim # a slice (recorded in tests/compat/cache/last.json only)
zinc compat --zinc path/to/other/checkout # measure another Zinc tree (a branch), same tests
zinc compat --check # exit 1 if a Zinc pass recorded in tests/compat/baseline.json regressed
zinc compat --update-baseline # after an intended change
zinc compat --report tests/compat/results/<date>.json # regenerate this page
The harness is tests/compat/run.mjs (selection, engines, classification) and report.mjs (this page); the pins
and the WinterTC API list are in tests/compat/manifest.json, the Zinc harness shims in tests/compat/shims, the
Node API tests in tests/compat/node, and these notes in tests/compat/notes.md.