Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Conformance

perry-conformance tests Perry-WIT differentially against Node.js. A contract names one capability, such as ecma.string.operations, and supplies directed cases plus a property-based generator (proptest) of TypeScript programs and inputs. Executable cases and their metamorphic variants run as compiled components in a Wasmtime host with WASI 0.3, fuel metering and memory limits, and under Node.js, except aggregate cases with exact integers beyond 2^53, which use an expected-value model. The runner checks that each variant matches its oracle and that transformations preserve return values, evaluation traces and standard streams. Rejection cases and their variants must report the required diagnostic.

Expected Outcomes

Each case declares what must happen:

OutcomeMeaning
EquivalentExecutionThe component produces the same observable result as Node.js.
CompilerRejectionThe compiler rejects the program with a diagnostic, for constructs outside the subset.
InjectedFaultDetectionThe harness detects a deliberately broken export adapter: a wrong value, a dropped effect or a leaked host resource. These cases test the harness itself.
BoundedGrowthFuel for an input of size 4n is at most 6 times the fuel for size n. This admits O(n log n) work and rejects quadratic growth (16 times).

Expected-Pass List

passing.txt in perry-conformance lists the contracts that must pass. A listed contract that fails is a regression, and an unlisted contract that passes fails the run until it is added, so the list only grows. deferred.txt records contracts outside the supported domain with their exclusion rationale.

cargo run -p perry-conformance -- check
cargo run -p perry-conformance -- check --select node.fs
cargo run -p perry-conformance -- list
cargo run -p perry-conformance -- doc

--select filters by contract ID prefix. doc prints the catalog table below.

Catalog

The registry holds 63 capability contracts: 63 passing, 0 deferred, 0 pending.

ECMAScript

ContractCapabilityOutcomePartitionsDomain
ecma.number.arithmeticIEEE arithmetic and evaluation orderEquivalent executionsigned-zero, division, trace, call, record-field-update, byte-alias, checked-json, handled-throwBounded typed functions, control flow, closed aggregates, byte aliases, JSON conversion and exceptions over the IEEE-754 boundary corpus; BMP strings; direct/local/branch/loop/loop-carried/inert-exception forms and overlapping timer completion schedules
ecma.number.bitwiseNumber bitwise operators, shifts and Math.imulEquivalent executionand, or, xor, not, left, right, unsigned-right, imul, trace, counts-and-compound-assignmentsNumber operands over the IEEE-754 boundary corpus; ToInt32/ToUint32 wrapping, non-finite inputs, masked shift counts, signed and unsigned results, evaluation order, compound assignments and loop-carried checksums; direct/local/branch/loop/loop-carried/inert-exception forms
ecma.math.roundingNumeric Math operationsEquivalent executionfloor, ceil, trunc, abs, round, abs-widened-loopBounded typed functions, control flow, closed aggregates, byte aliases, JSON conversion and exceptions over the IEEE-754 boundary corpus; BMP strings; direct/local/branch/loop/loop-carried/inert-exception forms and overlapping timer completion schedules
ecma.string.operationsString search, casing, slicing and lengthEquivalent executionunicode-and-nul, search, lower, upper, slice, char-atBounded typed functions, control flow, closed aggregates, byte aliases, JSON conversion and exceptions over the IEEE-754 boundary corpus; BMP strings; direct/local/branch/loop/loop-carried/inert-exception forms and overlapping timer completion schedules
ecma.array.denseDense numeric arrays preserve values and effectsEquivalent executionindex, branch-true, branch-false, first-index, array-effectsBounded typed functions, control flow, closed aggregates, byte aliases, JSON conversion and exceptions over the IEEE-754 boundary corpus; BMP strings; direct/local/branch/loop/loop-carried/inert-exception forms and overlapping timer completion schedules
ecma.object.recordsRecord fields preserve values and effectsEquivalent executionfield-orderBounded typed functions, control flow, closed aggregates, byte aliases, JSON conversion and exceptions over the IEEE-754 boundary corpus; BMP strings; direct/local/branch/loop/loop-carried/inert-exception forms and overlapping timer completion schedules
ecma.date.epochDate TimeClip and epoch readsEquivalent executiontimeclip, nested-codecsBounded typed functions, control flow, closed aggregates, byte aliases, JSON conversion and exceptions over the IEEE-754 boundary corpus; BMP strings; direct/local/branch/loop/loop-carried/inert-exception forms and overlapping timer completion schedules
ecma.uint8array.conversionByte conversion and indexed accessEquivalent executionwrapping, byte-input, byte-effectsBounded typed functions, control flow, closed aggregates, byte aliases, JSON conversion and exceptions over the IEEE-754 boundary corpus; BMP strings; direct/local/branch/loop/loop-carried/inert-exception forms and overlapping timer completion schedules
ecma.json.roundtripJSON text survives direct and stored decodingEquivalent executiondirect, stored, stored-unicode, direct-unicodeBounded typed functions, control flow, closed aggregates, byte aliases, JSON conversion and exceptions over the IEEE-754 boundary corpus; BMP strings; direct/local/branch/loop/loop-carried/inert-exception forms and overlapping timer completion schedules
ecma.json.commandCLI JSON serialization and schema-guided parsingEquivalent executionstandard-sourceStandard CLI source; exact output bytes and successful exit
ecma.command.arraysCLI dense array manipulation and iterationEquivalent executionstandard-sourceStandard CLI source; exact output bytes and successful exit
ecma.command.textCLI UTF-8 string formatting, UTF-16 code units and regular expressionsEquivalent executionstandard-sourceStandard CLI source; charCodeAt over ASCII/NUL, BMP and supplementary text with omitted, undefined and IEEE-754 boundary positions; exact output bytes and successful exit
ecma.command.recordsCLI closed record layouts and nested objectsEquivalent executionstandard-sourceStandard CLI source; exact output bytes and successful exit
ecma.command.numbersCLI numeric formatting and boundary arithmeticEquivalent executionstandard-sourceStandard CLI source; exact output bytes and successful exit
ecma.command.webCLI Web API codecs and byte viewsEquivalent executionstandard-sourceStandard CLI source; exact output bytes and successful exit
ecma.command.temporalCLI ISO Temporal calendar and instant operationsEquivalent executionstandard-sourceStandard CLI source; exact output bytes and successful exit
ecma.promise.allConcurrent Promise.all settlement orderingEquivalent executionstandard-sourceStandard CLI source; exact output bytes and successful exit
ecma.date.clockPlatform wall-clock reads and ISO Date formattingEquivalent executionstandard-sourceStandard CLI source; exact output bytes and successful exit
ecma.uint8array.setOverlapping byte copies and atomic range rejectionEquivalent executionempty, binary-subviewUint8Array sources of 0..256 bytes; each source evaluated over every IEEE-754 boundary input; byte reads checked explicitly
ecma.module.unawaited_initializationExplicit compiler rejection of module initialization that entry points cannot awaitCompiler rejectionunawaited-async-callSynchronous top-level statements of a module with exported functions that start asynchronous work without awaiting it
ecma.temporal.isoTyped ISO Instant, PlainDate and PlainDateTime valuesEquivalent executionnegative-millisecond, epoch, lower-limit, upper-limitIntegral epoch milliseconds in +/-8640000000000000, ISO formatting, leap-day addition and the ISO 8601 calendarId
ecma.promise.all_settledFulfilled and rejected results retain their status and payloadEquivalent executionzero, negativeTwo numeric tasks; one fulfillment and one rejection for allSettled, two already-completed contenders for race; repeated component calls and IEEE-754 inputs
ecma.promise.raceAlready-settled contenders retain input order and repeated outcomesEquivalent executionzero, negativeTwo numeric tasks; one fulfillment and one rejection for allSettled, two already-completed contenders for race; repeated component calls and IEEE-754 inputs
ecma.error.valuesError messages, causes and identity across promise rejection and rethrowEquivalent executionempty-message, nul-and-unicodeTypeError with a string message and cause; repeated awaits, all/allSettled/race, rethrow and finally; hidden built-in fields; Unicode messages of 0..32 scalar values
ecma.array.inferred_storageFresh empty arrays infer uniform or finite mixed elements from visible writesEquivalent execution, Compiler rejectionuniform-records-and-aliases, dependent-arrays, mixed-index-writes, mixed-alias, mixed-branch, returned-alias, mixed-function-write, string-key-write, conflicting-conditional-field, conflicting-nested-array, unknown-call, closure-capture, reassigned-alias, stored-alias, mutable-element-alias, no-writes, conditional-temporary, number-writes, string-writes, boolean-writes, record-writes, nested-array-writesUp to seven writes and four aliases over numbers, strings, booleans, records and nested arrays; annotations versus alias chains, branches, loops, temporaries, helper-return chains and indexed appends; three calls compare exact serialized contents and evaluation traces; finite mixed writes and returned arrays preserve values; unresolved writes remain rejected through temporaries and control flow; conservative escape boundaries
ecma.object.inferred_storageFresh empty dictionaries share array inference for visible writes and aliasesEquivalent execution, Compiler rejectioncomputed-keys-and-json-residue, conflicting-alias, conflicting-branch, numeric-key, unknown-call, reassigned-alias, stored-alias, returned-alias, mutable-element-alias, open-json-source, number-writes, string-writes, boolean-writes, record-writes, nested-array-writesUniform string-keyed writes over numbers, strings, booleans, records and arrays; annotation versus alias, branch, loop and temporary forms; computed keys, assignment values, absent reads, reserved array property names, nested typed JSON residue; unknown sources and escaping mutations remain rejected
ecma.aggregate.specializationOrthogonal aggregate layout specialization across recursive shapes, exact 64-bit parseInt, origin scaling, and WIT boundariesEquivalent executionself-recursive-wide-parseint-and-float, nested-record-option-boundary-special-values-and-overflowProduct of flat/nested/self-recursive/mutually-recursive/array-bearing records, multi-field/list/option WIT exports, float/NaN/-0.0/int-arith/wide-parseInt value sources, branch joins, shared helpers, array concat/spread, and >32-origin summarization
ecma.collection.iteratorsLive Set and Map iterators across active, paused, and abandoned lifetimes under delete compaction and clearEquivalent executionset-paused-clear-foreach-and-reinsert, map-entries-compaction-and-abandoned-cursor-churnOrthogonal state-machine sequences of NewIter, partial Step and ForEach with in-body mutations, Insert/InsertBatch, Delete/DeleteBatch across the 32-tombstone compaction threshold, Clear, and abandoned cursor churn over Set.values, Set.entries, Map.keys, Map.values, and Map.entries; Node is the oracle

Web Platform

ContractCapabilityOutcomePartitionsDomain
web.textencoder.subviewsUTF-8 encoding and byte subviewsEquivalent executionsubview-boundsBounded typed functions, control flow, closed aggregates, byte aliases, JSON conversion and exceptions over the IEEE-754 boundary corpus; BMP strings; direct/local/branch/loop/loop-carried/inert-exception forms and overlapping timer completion schedules
web.console.routingStandard output and error stream routing via consoleEquivalent executionstandard-sourceStandard CLI source; exact output bytes and successful exit
web.performance.monotonicMonotonic clock reads via performance.nowEquivalent executionstandard-sourceStandard CLI source; exact output bytes and successful exit
web.crypto.randomCryptographic random byte fill via crypto.getRandomValuesEquivalent executionstandard-sourceStandard CLI source; exact output bytes and successful exit
web.streams.byob_readerBYOB readers transfer shared buffers and fill visible views directlyEquivalent executionempty, byte-boundary, transfer-boundary, beyond-guest-memory, cancel-and-reuseUint8Array destinations with offsets, alias detachment, buffer reuse, min:8192, short EOF, locking and cancellation; three calls per instance; exact output bytes within 64 KiB guest memory
web.fetch.bounded_bodyHeaders-first Fetch, bounded byte consumption, completion failure and reuseEquivalent executionempty, binary-exact-limit, non-success-status, overflow-cancellation, completion-errorGET loopback HTTP; 200 and 404; binary bodies, explicit body cap and producer truncation; three calls per instance
web.fetch.bounded_byob_bodyBYOB bounded Fetch consumes directly into its final bufferEquivalent executionempty, binary-exact-limit, non-success-status, overflow-cancellation, completion-errorGET loopback HTTP; 200 and 404; binary bodies, explicit body cap and producer truncation; three calls per instance
web.response.bytesConstructed response snapshot, body use and repeated consumptionEquivalent executionempty, binary-subviewUint8Array sources of 0..256 bytes; each source evaluated over every IEEE-754 boundary input; byte reads checked explicitly
web.request.bytesConstructed request snapshot, body use and repeated consumptionEquivalent executionempty, binary-subviewUint8Array sources of 0..256 bytes; each source evaluated over every IEEE-754 boundary input; byte reads checked explicitly
web.textdecoder.streamingFatal UTF-8 decoding across byte boundariesEquivalent executionempty, bom-and-split-scalar, invalid-sequence, incomplete-sequenceFatal UTF-8, one-byte chunks, final flush; compare successful prefix bytes and normalized decoding failure
web.headers.multimapHeader name folding, joined duplicates and mutationsEquivalent executionempty-value, trim-and-duplicatesASCII values, case-insensitive names, whitespace trimming, append/get/set/has/delete

Node.js

ContractCapabilityOutcomePartitionsDomain
node.timers.promises.valueTimer resultEquivalent executionretained-operationRetained async operation interleaved with typed numeric evaluation; instance reused across boundary inputs
node.timers.promises.observersRepeated timer observationEquivalent executionretained-operationRetained async operation interleaved with typed numeric evaluation; instance reused across boundary inputs
node.fs.readFile.utf8UTF-8 file read across retained and dynamic Unicode payloadsEquivalent executionretained-operation, unicode-and-concurrent-readRetained async UTF-8 read interleaved with numeric evaluation, plus dynamic Unicode/NUL payloads of 0..48 scalar values and concurrent reads
node.fs.writeFile.textText file round trip, overwrite and truncationEquivalent executionretained-operation, overwrite-and-truncateRetained JSON text round trip plus sequential UTF-8 writes testing file truncation and growth across arbitrary Unicode strings
node.fs.metadataFile stat and directory listing across dynamic files and cleanupEquivalent executionretained-operation, multi-file-stat-and-unlinkRetained stat/readdir on fixture plus multi-file creation, exact byte-length stat verification, directory entry count and unlink cleanup
node.fs.readFile.bytesBinary file read, buffer isolation and UTF-8 decodingEquivalent executionretained-operation, binary-buffer-isolationRetained binary read plus arbitrary 0..256-byte payloads, returned Uint8Array mutation isolation across repeated reads and TextDecoder verification
node.fs.writeFile.subviewsByte view and empty file round trip across arbitrary subarray slicesEquivalent executionretained-operation, arbitrary-subview-sliceRetained subarray write plus arbitrary 0..128-byte buffers and subarray(start, end) slices, post-write view mutation isolation and empty subview truncation
node.fs.readFile.recoveryRepeated rejection across missing UTF-8, binary and stat calls followed by recoveryEquivalent executionretained-operation, multi-op-rejection-recoveryRetained rejected readFile plus repeated rejection observation across UTF-8 readFile, binary readFile and stat, followed by successful write/read recovery
node.process.environmentEnvironment variable reads via process.envEquivalent executionstandard-sourceStandard CLI source; exact output bytes and successful exit
node.timers.promises.lifecycleStart, host release, completion, cancellation, observation and reuseEquivalent executionsettlement-and-reobserve, cancel-and-reuseComplete sequential lifecycle traces with controlled Node/WASI clocks; no claim of exhaustive async scheduling
node.stream.writable_to_webQueued acknowledged writes, writer locks and closed-writer rejectionEquivalent executionempty, binary-and-closestdout/stderr Uint8Array writes and subviews; two queued writes, repeat observation, close, rejected released-writer use and a new stdio wrapper; exact output bytes
node.timers.callbacks.unsupportedExplicit compiler rejection of callback timersCompiler rejectioncallback-timerCallback timers are outside the supported source domain
node.fs.directoriesDirectory creation, listing, metadata and deletionEquivalent executionempty-file, binary-fileOne directory and binary file; exact size, one listed entry, cleanup and reuse across the numeric boundary corpus
node.process.exit_statusExplicit failure status and immediate process exitEquivalent executionexit-code, immediate-exitExit status 1 via process.exitCode or process.exit; exact preceding output and unreachable following output

WASI 0.3 Host

ContractCapabilityOutcomePartitionsDomain
wasi.execution.detect_value_faultInjected faults must be distinguished from the unchanged programFault detectioninjected-faultValue corruption, omitted effects, and retained host resources; only the component adapter is faulted
wasi.execution.detect_trace_faultInjected faults must be distinguished from the unchanged programFault detectioninjected-faultValue corruption, omitted effects, and retained host resources; only the component adapter is faulted
wasi.execution.detect_resource_faultInjected faults must be distinguished from the unchanged programFault detectioninjected-faultValue corruption, omitted effects, and retained host resources; only the component adapter is faulted
wasi.streams.incoming_bytesOwned WIT byte streams use Web readers and acknowledged Web writesEquivalent executionempty, byte-boundary, transfer-boundary, beyond-guest-memory, cancel-and-reuseThree calls per instance; input chunks of 8192 bytes; 64 KiB guest memory; exact output bytes, locking, cancellation and completion
wasi.http.handlerNative HTTP ABI with WIT-generated request and response declarationsEquivalent executionempty, binary-and-duplicates, request-response-limitPUT requests with binary bodies up to 64 KiB, duplicate headers, statuses 200/201/404; three exchanges reuse one component instance
wasi.execution.scaling.retained_recordsPushing n records into a local array and reading them back costs O(n) guest fuelBounded fuel growthn-128Warm-up n, n, and 4n calls on one instance; n in 32..=128 generated, 128 directed; values equal Node, fuel ratio of the last two calls at most 6
wasi.execution.scaling.number_pushPushing n numbers into a dense array and summing them costs O(n) guest fuelBounded fuel growthn-128Warm-up n, n, and 4n calls on one instance; n in 32..=128 generated, 128 directed; values equal Node, fuel ratio of the last two calls at most 6
wasi.execution.scaling.temporary_recordsOne temporary record per loop iteration costs O(n) guest fuel in totalBounded fuel growthn-128Warm-up n, n, and 4n calls on one instance; n in 32..=128 generated, 128 directed; values equal Node, fuel ratio of the last two calls at most 6
wasi.execution.scaling.string_appendAppending one character n times costs at most n·log n guest fuelBounded fuel growthn-128Warm-up n, n, and 4n calls on one instance; n in 32..=128 generated, 128 directed; values equal Node, fuel ratio of the last two calls at most 6
wasi.execution.scaling.collection_churnAbandoned Set/Map iterators and insert-delete churn cost O(n) guest fuelBounded fuel growthn-128Warm-up n, n, and 4n calls on one instance; n in 32..=128 generated, 128 directed; values equal Node, fuel ratio of the last two calls at most 6