From fb2b5fd7214aded0cb2054f67a48649ea3a1f5be Mon Sep 17 00:00:00 2001 From: Lann Martin Date: Mon, 10 Aug 2026 15:25:33 -0400 Subject: [PATCH 1/2] Revert "Remove the jco conformance legs; the deltic rows carry both postures" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 677daaca798353720523e5bc2c69cf184d314d0e (PR #40, reverse of 8b16928): the jco legs return until the perf comparison against the deltic legs has been run (operator call, 2026-08-10 — lann/deltic#17 is the tracking issue; the family ruling that jco support ultimately remains only in polymorph-webcrypto stands, lann/deltic#14). The two #39 wiring completions that rode PR #40 (the publish action's deltic-browser results rows, conformance/README's deltic-browser table rows) are re-applied in the follow-up commit rather than lost with the revert. --- .github/workflows/ci.yml | 16 +- .gitignore | 2 + AGENTS.md | 2 +- Cargo.toml | 11 +- README.md | 3 +- conformance/README.md | 26 +- conformance/driver-ct/deltic/README.md | 4 +- conformance/driver-ct/deltic/run-browser.mjs | 5 +- conformance/driver-ct/deltic/run.ts | 6 +- conformance/driver-ct/jco/browser-imports.mjs | 20 + conformance/driver-ct/jco/jco-transpile.mjs | 87 +++ conformance/driver-ct/jco/package-lock.json | 579 ++++++++++++++++++ conformance/driver-ct/jco/package.json | 22 + conformance/driver-ct/jco/run-browser.mjs | 90 +++ conformance/driver-ct/jco/run-node.mjs | 70 +++ conformance/driver-ct/justfile | 65 +- conformance/driver-ct/matrix.md | 18 +- conformance/driver-ct/targets.toml | 34 +- 18 files changed, 1011 insertions(+), 49 deletions(-) create mode 100644 conformance/driver-ct/jco/browser-imports.mjs create mode 100644 conformance/driver-ct/jco/jco-transpile.mjs create mode 100644 conformance/driver-ct/jco/package-lock.json create mode 100644 conformance/driver-ct/jco/package.json create mode 100644 conformance/driver-ct/jco/run-browser.mjs create mode 100644 conformance/driver-ct/jco/run-node.mjs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 977958c..dac8d73 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -98,8 +98,14 @@ jobs: uses: polymorph-components/polymorph-test/actions/setup@b4026866e481ead0738742e3b380601b605e5350 with: js-locks: | - conformance/driver-ct/deltic/package-lock.json - - name: Set up Deno (the deltic-deno and deltic-browser legs; stock, no flags) + conformance/driver-ct/jco/package-lock.json + - name: Set up Node 24 (the jco-node legs; JSPI) + uses: actions/setup-node@v4 + with: + node-version: 24 + cache: npm + cache-dependency-path: conformance/driver-ct/jco/package-lock.json + - name: Set up Deno (the deltic-deno legs; stock, no flags) uses: denoland/setup-deno@v2 with: deno-version: "2.9.5" @@ -123,10 +129,12 @@ jobs: results: | composed=conformance/driver-ct/results/composed.jsonl composed-delegated=conformance/driver-ct/results/composed-delegated.jsonl + jco-node=conformance/driver-ct/results/jco-node.jsonl + jco-node-delegated=conformance/driver-ct/results/jco-node-delegated.jsonl deltic-deno=conformance/driver-ct/results/deltic-deno.jsonl deltic-deno-delegated=conformance/driver-ct/results/deltic-deno-delegated.jsonl - deltic-browser=conformance/driver-ct/results/deltic-browser.jsonl - deltic-browser-delegated=conformance/driver-ct/results/deltic-browser-delegated.jsonl + jco-browser=conformance/driver-ct/results/jco-browser.jsonl + jco-browser-delegated=conformance/driver-ct/results/jco-browser-delegated.jsonl summary-title: Conformance matrix cli: target/ct-tools/bin/component-test # The action fails on a uses: ref that skews from this pin. diff --git a/.gitignore b/.gitignore index 5be3483..d79ed17 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ /target /conformance/driver-ct/results/ +/conformance/driver-ct/jco/node_modules/ +/conformance/driver-ct/jco/generated/ conformance/driver-ct/deltic/node_modules/ diff --git a/AGENTS.md b/AGENTS.md index e742a88..cbb9ad6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -77,7 +77,7 @@ design record. | --- | --- | | `just check` | fmt, clippy (all features), workspace tests (RFC 9001 vectors, profile/provider pinning, class-D key rejection), wasm build | | `just ci` | every gating CI job's body, exactly as CI runs it — each CI job runs one gha:: job recipe (.github/justfile). The timing lab is schedule-only and excluded | -| `just conformance` | the cross-implementation conformance suite (see `conformance/README.md`): the shared guest suite composed with each delivery — the `tls` world's in-guest Ed25519 posture and the `tls-delegated` world with the fixture signer — run under the pinned component-test runner and, runtime-linked under deltic (release-pinned in `conformance/driver-ct/deltic/`), on stock Deno (the deltic-deno targets — no transpile, no engine flag) and in headless Chromium (the deltic-browser targets; CI or CONFORMANCE_BROWSER=1), with import-satisfaction and signer-reachability gates, validated against the committed case inventory (`tests.lock`) and target manifest, and diffed against the committed matrix. `just conformance-ct::run-webcrypto` (on demand: clones the sibling repo) adds the delegated posture over a real `polymorph:webcrypto` provider. jco-based targets (jco-node, transpiled under Node 24 JSPI; jco-browser) were removed — jco coverage is retained family-wide only in `polymorph:webcrypto` | +| `just conformance` | the cross-implementation conformance suite (see `conformance/README.md`): the shared guest suite composed with each delivery — the `tls` world's in-guest Ed25519 posture and the `tls-delegated` world with the fixture signer — run under the pinned component-test runner, transpiled under Node 24 JSPI (the jco-node targets), runtime-linked under deltic on stock Deno (the deltic-deno targets — no transpile, no engine flag; release-pinned in `conformance/driver-ct/deltic/`), and in headless Chromium (the jco-browser targets; CI or CONFORMANCE_BROWSER=1), with import-satisfaction and signer-reachability gates, validated against the committed case inventory (`tests.lock`) and target manifest, and diffed against the committed matrix. `just conformance-ct::run-webcrypto` (on demand: clones the sibling repo) adds the delegated posture over a real `polymorph:webcrypto` provider | | `just smoke-quic` | QUIC over `wasi:sockets` UDP under Wasmtime | | `just smoke-tls-virt` | both tls-virt deliveries against `openssl s_server` over real TCP (needs openssl + python3): the composed guest virtualizer (handle-address and import-satisfaction gates), and the wasmtime host provider on both sockets generations — wasip3 and `std::net`/0.2 guests — with handle-address and profile-cipher-suite gates plus plain-TCP passthrough-delegation legs | | `just interop` | cross-implementation, over real transports, fresh Ed25519 private PKI per run: the composed TLS component against OpenSSL and Go peers over TCP in both directions (including the close_notify-vs-truncation and reset scenarios), and the noq leg against quic-go over UDP in both directions | diff --git a/Cargo.toml b/Cargo.toml index 1fda99e..d0cde70 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,11 +49,12 @@ futures = { version = "0.3", default-features = false, features = ["std", "async # The conformance stack, pinned to one revision everywhere it appears: # this rev, the `component-test`/`ct-runner` installs derived from -# Cargo.lock by `conformance/driver-ct/justfile`, and the -# `polymorph-test/actions/*@` refs in ci.yml (the actions fail on -# skew). To bump: `component-test pins bump --cargo-toml -# Cargo.toml --workflow .github/workflows/ci.yml`, then the follow-ups -# it prints. +# Cargo.lock by `conformance/driver-ct/justfile`, the jco package.json +# pin, and the `polymorph-test/actions/*@` refs in ci.yml (the +# actions fail on skew). To bump: `component-test pins bump +# --cargo-toml Cargo.toml --package-json +# conformance/driver-ct/jco/package.json --workflow +# .github/workflows/ci.yml`, then the follow-ups it prints. component-test-sdk = { git = "https://github.com/polymorph-components/polymorph-test", rev = "b4026866e481ead0738742e3b380601b605e5350" } aead = { version = "0.6", default-features = false, features = ["alloc"] } diff --git a/README.md b/README.md index aed53c7..567ba52 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,7 @@ two deliveries, and the QUIC compatibility layer exist; they pass a cross-implementation [conformance suite](conformance/README.md) on the [`polymorph:test`](https://github.com/polymorph-components/polymorph-test) harness (one shared guest suite against every composed delivery, under -Wasmtime and, runtime-linked via deltic, under stock Deno and in -headless Chromium), +Wasmtime, under Node/jco via JSPI, and in headless Chromium), cross-implementation interop against OpenSSL, Go `crypto/tls`, and quic-go over real transports, and a scheduled dudect-style [timing lab](timing-lab/README.md), with the performance tradeoff diff --git a/conformance/README.md b/conformance/README.md index 98e9730..66dac9c 100644 --- a/conformance/README.md +++ b/conformance/README.md @@ -12,13 +12,13 @@ guest-ct/ the suite: cases on the polymorph:test contract, the polymorph:tls surface imported as a consumer would; tests.lock is the committed case inventory driver-ct/ target manifest (targets.toml), the recipes - (justfile, module `conformance-ct`), the deltic - driver (deltic/), the committed matrix (matrix.md); + (justfile, module `conformance-ct`), the jco-node + driver (jco/), the committed matrix (matrix.md); results/ is generated ``` `just conformance` (from the repository root) runs the standing -matrix: build, inventory check, the wasmtime and deltic targets under +matrix: build, inventory check, the wasmtime and Node targets under the pinned tooling, aggregate, and the committed-matrix diff. ## Targets @@ -26,26 +26,22 @@ the pinned tooling, aggregate, and the committed-matrix diff. A target is a composition, not a runtime configuration: the suite is `wac plug`-ged with one TLS stack, and the resulting artifact imports only wasi and `polymorph:test/test-context`. The wasmtime rows run -under the generic component-test host runner; the deltic rows run the -same artifacts runtime-linked (no transpile step) on stock Deno or -inside headless Chromium — one suite, one composition, multiple -engines. +under the generic component-test host runner; the jco rows transpile +the same artifacts (`-I async`, the lann/jco all-fixes pre-release +pinned in `driver-ct/jco/package.json`) and run them under Node 24 +JSPI — one suite, one composition, two engines. | Target | Composition | | --- | --- | | `composed` | the `tls` world build: in-guest Ed25519 signing only | | `composed-delegated` | the `tls-delegated` world build ⊕ the fixture signer (`examples/test-signer`) | | `composed-delegated-webcrypto` | as above, but the signer is the `examples/webcrypto-signer` shim over a real `polymorph:webcrypto` provider; on demand (`just conformance-ct::run-webcrypto`), declared `optional` | +| `jco-node` | the `composed` artifact, transpiled, under Node 24 JSPI | +| `jco-node-delegated` | the `composed-delegated` artifact, likewise | | `deltic-deno` | the `composed` artifact runtime-linked under deltic on stock Deno (no transpile, no engine flag) | | `deltic-deno-delegated` | the `composed-delegated` artifact, likewise | -| `deltic-browser` | the `composed` artifact runtime-linked inside headless Chromium (gates in CI, locally `CONFORMANCE_BROWSER=1`; declared `optional`) | -| `deltic-browser-delegated` | the `composed-delegated` artifact, likewise | - -jco-node and jco-browser targets ran the same compositions transpiled -under Node 24 JSPI and in headless Chromium via jco; they were removed -as jco support was retired from this repository (retained -family-wide only in `polymorph:webcrypto`), superseded by the deltic -targets above. +| `jco-browser` | the `composed` artifact inside headless Chromium (the upstream page driver; gates in CI, locally `CONFORMANCE_BROWSER=1`; declared `optional`) | +| `jco-browser-delegated` | the `composed-delegated` artifact, likewise | In-suite QUIC cases are [#29](https://github.com/polymorph-components/polymorph-tls/issues/29). diff --git a/conformance/driver-ct/deltic/README.md b/conformance/driver-ct/deltic/README.md index 4db9428..129c738 100644 --- a/conformance/driver-ct/deltic/README.md +++ b/conformance/driver-ct/deltic/README.md @@ -4,8 +4,8 @@ The deltic leg of the conformance matrix: the composed artifacts (`suite-plain`, `suite-delegated`) run **runtime-linked** under [deltic](https://github.com/lann/deltic) on stock Deno — no transpile step, no generated tree, no `--experimental-wasm-jspi` (the WIT -contract's async exports run on the callback ABI). Targets `deltic-deno` -and +contract's async exports run on the callback ABI). The deltic analogue +of `../jco/run-node.mjs`; targets `deltic-deno` and `deltic-deno-delegated` in `../targets.toml`. There is no SUT host module on this leg (the TLS delivery is fused diff --git a/conformance/driver-ct/deltic/run-browser.mjs b/conformance/driver-ct/deltic/run-browser.mjs index de236d6..57b8ed6 100644 --- a/conformance/driver-ct/deltic/run-browser.mjs +++ b/conformance/driver-ct/deltic/run-browser.mjs @@ -5,9 +5,8 @@ // pinned deltic-embedder.mjs release asset and links the suite in the // browser: no transpile step, no generated tree. This file is the frame: // asset URL wiring, target configuration, and results-file writing — -// the browser sibling of ../deltic/run.ts, mirroring the frame the -// former jco-based run-browser.mjs used for its own run-node.mjs -// sibling before the jco legs were removed. +// the browser sibling of ../deltic/run.ts exactly as ../jco/run-browser.mjs +// is the browser sibling of ../jco/run-node.mjs. // // The artifacts import only wasi 0.2 and test-context, so there is no // SUT host module on this leg and the stock upstream worker serves it diff --git a/conformance/driver-ct/deltic/run.ts b/conformance/driver-ct/deltic/run.ts index 92e273d..7b066c5 100644 --- a/conformance/driver-ct/deltic/run.ts +++ b/conformance/driver-ct/deltic/run.ts @@ -1,10 +1,10 @@ // The deltic leg of the conformance harness: runs a composed artifact // (the shared suite fused with one TLS delivery) runtime-linked under // deltic on stock Deno, and writes component-test results JSONL for the -// aggregate. Its frame mirrored the former jco-based run-node.mjs -// (removed with the jco legs) exactly: +// aggregate — the deltic analogue of ../jco/run-node.mjs, mirroring its +// frame exactly: // -// run-node.mjs (removed) | this runner +// run-node.mjs | this runner // --------------------------------------+--------------------------- // jco transpile + loadCoreModules | translator.translate(bytes) // bindImports (preview2-shim, both | wasiShims() (track-keyed: diff --git a/conformance/driver-ct/jco/browser-imports.mjs b/conformance/driver-ct/jco/browser-imports.mjs new file mode 100644 index 0000000..83fbd9d --- /dev/null +++ b/conformance/driver-ct/jco/browser-imports.mjs @@ -0,0 +1,20 @@ +// The browser worker's import-object module: loaded by the upstream +// browser-worker via URL (module workers cannot see import maps), so +// every specifier here is a server path — the harness core through the +// driver's self-mount, the wasi shims through this tree's +// node_modules, both served over the repository-root server. +import { bindImports } from "/__component-test/js/viewer/imports.mjs"; +import * as cli from "./node_modules/@bytecodealliance/preview2-shim/dist/browser/cli.js"; +import * as clocks from "./node_modules/@bytecodealliance/preview2-shim/dist/browser/clocks.js"; +import * as io from "./node_modules/@bytecodealliance/preview2-shim/dist/browser/io.js"; +import * as random from "./node_modules/@bytecodealliance/preview2-shim/dist/browser/random.js"; +import * as filesystem from "./node_modules/@bytecodealliance/preview2-shim/dist/browser/filesystem.js"; + +/** The composed artifacts import only wasi 0.2 and test-context; wasi + * minors differ across the fused halves, so both spellings bind. */ +export async function suiteImports() { + return bindImports({ + wasi: { cli, clocks, io, random, filesystem }, + wasiVersions: ["0.2.0", "0.2.6"], + }); +} diff --git a/conformance/driver-ct/jco/jco-transpile.mjs b/conformance/driver-ct/jco/jco-transpile.mjs new file mode 100644 index 0000000..ee27fa7 --- /dev/null +++ b/conformance/driver-ct/jco/jco-transpile.mjs @@ -0,0 +1,87 @@ +#!/usr/bin/env node +// Vendored from polymorph-test (js/jco-transpile.mjs at 2436bb9, deleted +// there when that repo went jco-free): a thin CLI over +// @bytecodealliance/jco-transpile, covering the two jco +// commands the conformance consumers use: `transpile` (component to ES +// module) and `types` (host-side type definitions for a WIT world). +// jco-transpile is the transpilation half of jco, published without +// the componentization toolchain (componentize-js, weval) that the +// full jco CLI drags in and nothing here runs. +// +// The library is resolved from the invoking package's node_modules — +// each consumer pins its own toolchain version — so this bin must run +// with the consumer's package directory as the working directory, +// which is how package.json scripts invoke it. +// +// The option spellings match the jco CLI's, and the library applies +// the same defaults the CLI did (name derivation, the wasi-shim map +// entries, output-path prefixing), so the generated trees are +// bit-identical to `jco transpile` / `jco types` output for these +// invocations. + +import { createRequire } from "node:module"; +import { join } from "node:path"; +import { pathToFileURL } from "node:url"; +import { parseArgs } from "node:util"; + +const require = createRequire(join(process.cwd(), "package.json")); +const { transpile, generateHostTypes, writeFiles } = await import( + pathToFileURL(require.resolve("@bytecodealliance/jco-transpile")).href +); + +const [command, path, ...rest] = process.argv.slice(2); +const { values } = parseArgs({ + args: rest, + options: { + name: { type: "string" }, + "async-mode": { type: "string" }, + instantiation: { type: "string", short: "I" }, + map: { type: "string", multiple: true }, + "world-name": { type: "string" }, + "out-dir": { type: "string", short: "o" }, + // Never answer an async-lowered import with a bare RETURNED status; + // required for componentize-js guests, whose lowering does not + // implement the returned-immediately case (see the option's doc in + // jco-transpile). + "no-eager-subtask-return": { type: "boolean" }, + // `types` only: WIT `@unstable` gates to enable, like `jco types + // --feature` (repeatable). + feature: { type: "string", multiple: true }, + }, +}); + +switch (command) { + case "transpile": { + const map = Object.fromEntries( + (values.map ?? []).map((entry) => { + const eq = entry.indexOf("="); + if (eq === -1) { + throw new Error(`--map entry has no '=': ${entry}`); + } + return [entry.slice(0, eq), entry.slice(eq + 1)]; + }), + ); + const { files } = await transpile(path, { + name: values.name, + asyncMode: values["async-mode"], + instantiation: values.instantiation, + map, + outDir: values["out-dir"], + noEagerSubtaskReturn: values["no-eager-subtask-return"], + }); + await writeFiles(files); + break; + } + case "types": { + const files = await generateHostTypes(path, { + worldName: values["world-name"], + asyncMode: values["async-mode"], + outDir: values["out-dir"], + features: values.feature, + }); + await writeFiles(files); + break; + } + default: + throw new Error(`unknown command: ${command} (expected transpile or types)`); +} diff --git a/conformance/driver-ct/jco/package-lock.json b/conformance/driver-ct/jco/package-lock.json new file mode 100644 index 0000000..42950aa --- /dev/null +++ b/conformance/driver-ct/jco/package-lock.json @@ -0,0 +1,579 @@ +{ + "name": "@polymorph/tls-conformance-driver-ct-jco", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@polymorph/tls-conformance-driver-ct-jco", + "version": "0.1.0", + "devDependencies": { + "@bytecodealliance/jco-transpile": "https://github.com/lann/jco/releases/download/all-fixes-dbad4d7/bytecodealliance-jco-transpile-0.6.3-gdbad4d7.tgz", + "@bytecodealliance/preview2-shim": "https://github.com/lann/jco/releases/download/all-fixes-dbad4d7/bytecodealliance-preview2-shim-0.20.1-gdbad4d7.tgz", + "@polymorph/component-test-js": "github:polymorph-components/polymorph-test#b4026866e481ead0738742e3b380601b605e5350", + "playwright-core": "1.62.1" + }, + "engines": { + "node": ">=24" + } + }, + "node_modules/@bytecodealliance/jco-transpile": { + "version": "0.6.3-gdbad4d7", + "resolved": "https://github.com/lann/jco/releases/download/all-fixes-dbad4d7/bytecodealliance-jco-transpile-0.6.3-gdbad4d7.tgz", + "integrity": "sha512-6/I8xS2Xr3ggPVdyl8Rj4QeYv71tYm/KYpiXIUaR9pX+uxMScKT8jSKvCKdWI3IdvMgzz2UgeAn+BhYYLTD3DQ==", + "dev": true, + "license": "(Apache-2.0 WITH LLVM-exception)", + "dependencies": { + "@bytecodealliance/preview2-shim": "^0.20.1", + "@bytecodealliance/preview3-shim": "^0.2.2", + "binaryen": "^130.0.0", + "oxc-minify": "^0.136.0" + } + }, + "node_modules/@bytecodealliance/jco-transpile/node_modules/@bytecodealliance/preview2-shim": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@bytecodealliance/preview2-shim/-/preview2-shim-0.20.1.tgz", + "integrity": "sha512-gvQP6DWfeQIYKHBb+nPykku1DRtfXQjM685+e75YYr8ZF2ZxisE4+nWrpwf84+NaWJRfuL5HvoLKQFbup1iwkQ==", + "dev": true, + "license": "(Apache-2.0 WITH LLVM-exception)" + }, + "node_modules/@bytecodealliance/preview2-shim": { + "version": "0.20.1-gdbad4d7", + "resolved": "https://github.com/lann/jco/releases/download/all-fixes-dbad4d7/bytecodealliance-preview2-shim-0.20.1-gdbad4d7.tgz", + "integrity": "sha512-pCKKbbJrAboirUFOmAryjH/qEDmVB7uLIkzVXziEgwptPxv37GkyvTWZ6UMSZuqP1amExw2wyFEdalo6R2lI+g==", + "dev": true, + "license": "(Apache-2.0 WITH LLVM-exception)" + }, + "node_modules/@bytecodealliance/preview3-shim": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@bytecodealliance/preview3-shim/-/preview3-shim-0.2.2.tgz", + "integrity": "sha512-9z4tjc+qixUhyeYo3ycoT4cZ9yIlUfkowJxGoKeMfbRd8zT3uvIr1YNfXyU0I93GPu+gdaTVsr8iMr55utEJSA==", + "dev": true, + "license": "(Apache-2.0 WITH LLVM-exception)", + "dependencies": { + "@bytecodealliance/preview2-shim": "^0.19.0" + } + }, + "node_modules/@bytecodealliance/preview3-shim/node_modules/@bytecodealliance/preview2-shim": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@bytecodealliance/preview2-shim/-/preview2-shim-0.19.0.tgz", + "integrity": "sha512-OSUlcM62fXLuzYP0DjBn/SwjKMZ/y/2PMXZ8v5cRiiFcroauntlPRl/oCnx0xYjYiqdYvE0PY50VCNutll0xOw==", + "dev": true, + "license": "(Apache-2.0 WITH LLVM-exception)" + }, + "node_modules/@emnapi/core": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.1.tgz", + "integrity": "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.2", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.1.tgz", + "integrity": "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.2.tgz", + "integrity": "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.2.tgz", + "integrity": "sha512-JfB4kuJQjaoHuCTseIINHtHWeJnvgEcxjwA5t/Y00ZgaOO1Crz3fjT/p8kT28zA/Caz7oiUMn3d6H2yOVCVwuw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.3" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=23.5.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1 || ^2.0.0-alpha.3", + "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.3" + } + }, + "node_modules/@oxc-minify/binding-android-arm-eabi": { + "version": "0.136.0", + "resolved": "https://registry.npmjs.org/@oxc-minify/binding-android-arm-eabi/-/binding-android-arm-eabi-0.136.0.tgz", + "integrity": "sha512-gk1jzky1vLeOcK7w9Ib2RT/UooZ7O21s8YSeXCsy4tzsmguKb3Cbsv/Ra2fKhMp4mKeKCzvC1Xa41OfSBWfWdQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-minify/binding-android-arm64": { + "version": "0.136.0", + "resolved": "https://registry.npmjs.org/@oxc-minify/binding-android-arm64/-/binding-android-arm64-0.136.0.tgz", + "integrity": "sha512-5GIYanqud/ohXEcg2dsdn0+eSKXqclw5qlRUkvSM1sKEa4ZQ7hqOk8XPJBNPh3LXXw+Qw85B6jkmOFLKsCHp5w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-minify/binding-darwin-arm64": { + "version": "0.136.0", + "resolved": "https://registry.npmjs.org/@oxc-minify/binding-darwin-arm64/-/binding-darwin-arm64-0.136.0.tgz", + "integrity": "sha512-QAMpHKXWOoMCTenSZjQjVT5YmMooujlCKAf1T3PHFl2LuaA6ukQFXba0bgSLgAxRrAeX/itkwi4lzVQXtYmnRg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-minify/binding-darwin-x64": { + "version": "0.136.0", + "resolved": "https://registry.npmjs.org/@oxc-minify/binding-darwin-x64/-/binding-darwin-x64-0.136.0.tgz", + "integrity": "sha512-rDnoPj8hztiU8C1VNKuzujh7SgTJlgiUvUCiWQjTnVSLsABsLW9ZWd1l1Ji0VN3UW39wGpptgvahIWTrHnGH/A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-minify/binding-freebsd-x64": { + "version": "0.136.0", + "resolved": "https://registry.npmjs.org/@oxc-minify/binding-freebsd-x64/-/binding-freebsd-x64-0.136.0.tgz", + "integrity": "sha512-9fGSgP7uyPLCTjMx9z3AUV4UjnfOVoGTH5JzamLegPwGLJ97Gr1jht1437CRk8ZNabGmxQR6qNn3e+Tox2lswg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-minify/binding-linux-arm-gnueabihf": { + "version": "0.136.0", + "resolved": "https://registry.npmjs.org/@oxc-minify/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.136.0.tgz", + "integrity": "sha512-k0QvZS+x6ROI4O5Ikqn9dDU2dmkEJ46Yh6baZJI/eUk/a1k1GOs9/vyXItLZrKlwYrSgdEx2BFXbKgyd1NyRPw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-minify/binding-linux-arm-musleabihf": { + "version": "0.136.0", + "resolved": "https://registry.npmjs.org/@oxc-minify/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.136.0.tgz", + "integrity": "sha512-iRFxUc8ubotVfuyq3e4LPGbHrjvWd1/B3499a55GueMLc1EDJ0fHzNXJiCx2eMQGfzHtHodjmvrJ2BSvSXBNhQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-minify/binding-linux-arm64-gnu": { + "version": "0.136.0", + "resolved": "https://registry.npmjs.org/@oxc-minify/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.136.0.tgz", + "integrity": "sha512-hbKxNCXJsULrb6EyG5SumzJKuPfP8Y0UQ/TElRgXVUhyyPf6cBPlF8HMq+MAylF98ACBzV8jBp2Mm62lJyTo+w==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-minify/binding-linux-arm64-musl": { + "version": "0.136.0", + "resolved": "https://registry.npmjs.org/@oxc-minify/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.136.0.tgz", + "integrity": "sha512-T+u/CGKW0UXemJeVux4ix6rK+ug3bQCUEbu5hFlX9K61KQNd44rOcrM15mDK99L7USaXwmiwHeIkEDvmmyDMSA==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-minify/binding-linux-ppc64-gnu": { + "version": "0.136.0", + "resolved": "https://registry.npmjs.org/@oxc-minify/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-0.136.0.tgz", + "integrity": "sha512-WNPTN2F448tb49BoqjV9IMRzZWa0WB8GHzrB+bnxKQPOyzz07T6rmDKrr4Hjl81ADGjDYSsr1fgXcjyLQFdMdw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-minify/binding-linux-riscv64-gnu": { + "version": "0.136.0", + "resolved": "https://registry.npmjs.org/@oxc-minify/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.136.0.tgz", + "integrity": "sha512-MvcCfu8OeabrmNN9wqhh8Gqizg68RQ3iOvXBJmlLMy5p1PC6az9bAwqOk98lsCmKI4I5LpULekOlfxRYh3o5Kw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-minify/binding-linux-riscv64-musl": { + "version": "0.136.0", + "resolved": "https://registry.npmjs.org/@oxc-minify/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-0.136.0.tgz", + "integrity": "sha512-rwJXFUFFA0egAULtOOgfW8YhhLhtWrr2qFxftvZ7/U6Xtxiev8i+eCwSNW1RpHiX74QMsJVpRE3ykoefqb1MtQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-minify/binding-linux-s390x-gnu": { + "version": "0.136.0", + "resolved": "https://registry.npmjs.org/@oxc-minify/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.136.0.tgz", + "integrity": "sha512-qizAxHmj7VHm5/D5qiIlvzxAS2tlmadDOJ5XFI7zx/wfnk/+fdk5iVaHOv+C4tDE/4wLQyMoBYVIs6R1LeN91w==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-minify/binding-linux-x64-gnu": { + "version": "0.136.0", + "resolved": "https://registry.npmjs.org/@oxc-minify/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.136.0.tgz", + "integrity": "sha512-gcyLAad0UblkEhGjVfx5Mwq63OSx8r04IbcfwzpZYpHisO/vioMsrs4GkDsQZ2Ejc8cdUk6YMIrf9FwNBzh+Dw==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-minify/binding-linux-x64-musl": { + "version": "0.136.0", + "resolved": "https://registry.npmjs.org/@oxc-minify/binding-linux-x64-musl/-/binding-linux-x64-musl-0.136.0.tgz", + "integrity": "sha512-QAK6kwBjljX6luYzeppVdRP3gTaFNFfp9iS/V0cCvU43wUZay5xFXBgmzBHYrzZV2MhzURNnXfEZRo9poAxyvA==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-minify/binding-openharmony-arm64": { + "version": "0.136.0", + "resolved": "https://registry.npmjs.org/@oxc-minify/binding-openharmony-arm64/-/binding-openharmony-arm64-0.136.0.tgz", + "integrity": "sha512-nIGxkTOnN9GwslmooxbZ3Ti2RgbX9QLHy0X9uO0pslOT+4dsNVUawBU/6r4M5cWM+ZdRD2tOF4V+n0l8tS59nQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-minify/binding-wasm32-wasi": { + "version": "0.136.0", + "resolved": "https://registry.npmjs.org/@oxc-minify/binding-wasm32-wasi/-/binding-wasm32-wasi-0.136.0.tgz", + "integrity": "sha512-YB3G8AHT6PpDS8/DfjlJrQjywj+/6gCkNBcAJdYzcYbQRIZE6SaTNowiGuZPR1m1jOl1WjcjefniKSmVxzhvRA==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "1.11.1", + "@emnapi/runtime": "1.11.1", + "@napi-rs/wasm-runtime": "^1.1.5" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-minify/binding-win32-arm64-msvc": { + "version": "0.136.0", + "resolved": "https://registry.npmjs.org/@oxc-minify/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.136.0.tgz", + "integrity": "sha512-UVRH3BlNc2rmla+sbSd5xTF/u+esCqZS6VSWPolZybcBh3TlVe1Sf5MOuHQWUaFoyv5uFOvee4hOfS/14nPvZw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-minify/binding-win32-ia32-msvc": { + "version": "0.136.0", + "resolved": "https://registry.npmjs.org/@oxc-minify/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-0.136.0.tgz", + "integrity": "sha512-zFGkUd82jci0E+isc2O36lVmmXVUDXyEMN2RYIyez+MBNqhdjPLIGx62FCsrJtLKeuiPf/8XkFv977aUtndUng==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-minify/binding-win32-x64-msvc": { + "version": "0.136.0", + "resolved": "https://registry.npmjs.org/@oxc-minify/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.136.0.tgz", + "integrity": "sha512-VHgPwd5xibC9UYxBeq7nURTjY+wxhdumllij6JaCIUVfD9IRcrA66SVlJ5fPNoUXcRp8ZXhJfoIZwVz9wAEGJw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@polymorph/component-test-js": { + "version": "0.2.0", + "resolved": "git+ssh://git@github.com/polymorph-components/polymorph-test.git#b4026866e481ead0738742e3b380601b605e5350", + "integrity": "sha512-yjekMTYYvlXG1ZI6LGw+ySuCZqhBHz7WXkyjpPsCZQkz+hxIRNF/kiemakwfCGiD7f4xf64Hb6sKV18K7d7MjQ==", + "dev": true, + "license": "Apache-2.0 WITH LLVM-exception" + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz", + "integrity": "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/binaryen": { + "version": "130.0.0", + "resolved": "https://registry.npmjs.org/binaryen/-/binaryen-130.0.0.tgz", + "integrity": "sha512-XDrb+zql0RbFPKgj7MuH9zOc78R3Fa/P/VSGnnpdwYsvNZPWjcMYMdAkKCOQEL2A7yqgjSMTDRFp6gfSDW+/QQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "wasm-as": "bin/wasm-as", + "wasm-ctor-eval": "bin/wasm-ctor-eval", + "wasm-dis": "bin/wasm-dis", + "wasm-merge": "bin/wasm-merge", + "wasm-metadce": "bin/wasm-metadce", + "wasm-opt": "bin/wasm-opt", + "wasm-reduce": "bin/wasm-reduce", + "wasm-shell": "bin/wasm-shell", + "wasm2js": "bin/wasm2js" + } + }, + "node_modules/oxc-minify": { + "version": "0.136.0", + "resolved": "https://registry.npmjs.org/oxc-minify/-/oxc-minify-0.136.0.tgz", + "integrity": "sha512-u9UvPFTYVwQ/i1kpp/c20S/SbvLaLV0Ngzyhgi0YV4B1SlxM7RgnnePl4vY9N3Z9sTRcozL1MRStI3PlUN9RFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/sponsors/Boshen" + }, + "optionalDependencies": { + "@oxc-minify/binding-android-arm-eabi": "0.136.0", + "@oxc-minify/binding-android-arm64": "0.136.0", + "@oxc-minify/binding-darwin-arm64": "0.136.0", + "@oxc-minify/binding-darwin-x64": "0.136.0", + "@oxc-minify/binding-freebsd-x64": "0.136.0", + "@oxc-minify/binding-linux-arm-gnueabihf": "0.136.0", + "@oxc-minify/binding-linux-arm-musleabihf": "0.136.0", + "@oxc-minify/binding-linux-arm64-gnu": "0.136.0", + "@oxc-minify/binding-linux-arm64-musl": "0.136.0", + "@oxc-minify/binding-linux-ppc64-gnu": "0.136.0", + "@oxc-minify/binding-linux-riscv64-gnu": "0.136.0", + "@oxc-minify/binding-linux-riscv64-musl": "0.136.0", + "@oxc-minify/binding-linux-s390x-gnu": "0.136.0", + "@oxc-minify/binding-linux-x64-gnu": "0.136.0", + "@oxc-minify/binding-linux-x64-musl": "0.136.0", + "@oxc-minify/binding-openharmony-arm64": "0.136.0", + "@oxc-minify/binding-wasm32-wasi": "0.136.0", + "@oxc-minify/binding-win32-arm64-msvc": "0.136.0", + "@oxc-minify/binding-win32-ia32-msvc": "0.136.0", + "@oxc-minify/binding-win32-x64-msvc": "0.136.0" + } + }, + "node_modules/playwright-core": { + "version": "1.62.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.62.1.tgz", + "integrity": "sha512-wPYSwEBJY9GHraISXqyqtx0na0LpO3XEX7jNDhntbex7tzUS7kLnZsOlFruFJB4Hi/rhDMjXGqHewDZ68nYZVw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD", + "optional": true + } + } +} diff --git a/conformance/driver-ct/jco/package.json b/conformance/driver-ct/jco/package.json new file mode 100644 index 0000000..6c7188f --- /dev/null +++ b/conformance/driver-ct/jco/package.json @@ -0,0 +1,22 @@ +{ + "name": "@polymorph/tls-conformance-driver-ct-jco", + "version": "0.1.0", + "private": true, + "type": "module", + "description": "jco-node legs for the component-test conformance suite: transpile the composed artifacts (suite + TLS delivery, fused by wac) and run them under Node 24 JSPI against the upstream harness core; the artifacts import only wasi 0.2 and test-context, so there is no SUT host module.", + "scripts": { + "transpile": "node ./jco-transpile.mjs transpile ../../../target/conformance/suite-plain.wasm --name suite-plain -I async -o generated", + "transpile:delegated": "node ./jco-transpile.mjs transpile ../../../target/conformance/suite-delegated.wasm --name suite-delegated -I async -o generated", + "run:node": "node --experimental-wasm-jspi run-node.mjs", + "run:browser": "node run-browser.mjs" + }, + "devDependencies": { + "@bytecodealliance/jco-transpile": "https://github.com/lann/jco/releases/download/all-fixes-dbad4d7/bytecodealliance-jco-transpile-0.6.3-gdbad4d7.tgz", + "@bytecodealliance/preview2-shim": "https://github.com/lann/jco/releases/download/all-fixes-dbad4d7/bytecodealliance-preview2-shim-0.20.1-gdbad4d7.tgz", + "@polymorph/component-test-js": "github:polymorph-components/polymorph-test#b4026866e481ead0738742e3b380601b605e5350", + "playwright-core": "1.62.1" + }, + "engines": { + "node": ">=24" + } +} \ No newline at end of file diff --git a/conformance/driver-ct/jco/run-browser.mjs b/conformance/driver-ct/jco/run-browser.mjs new file mode 100644 index 0000000..b8ba9be --- /dev/null +++ b/conformance/driver-ct/jco/run-browser.mjs @@ -0,0 +1,90 @@ +// The jco-browser leg: both composed artifacts run inside headless +// Chromium through the upstream page driver — the page, worker pool, +// stall watchdog, and Chrome ladder all live in +// @polymorph/component-test-js; this file is the frame: core-URL +// enumeration, target configuration, and results-file writing. +// +// Gates in CI (the Actions runner image ships Chrome); locally it runs +// under CONFORMANCE_BROWSER=1 (`just conformance-ct::all`) or directly +// via `just conformance-ct::run-browser`. +import { readdir } from "node:fs/promises"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; +import { parseArgs } from "node:util"; + +import { + buildHarnessPage, + findChrome, + runPageHarness, +} from "@polymorph/component-test-js/browser-driver"; +import { writeResultsFile } from "@polymorph/component-test-js/node-runner"; + +const JCO_DIR = dirname(fileURLToPath(import.meta.url)); +const REPO_ROOT = join(JCO_DIR, "..", "..", ".."); +const BASE = "/conformance/driver-ct/jco"; +const CASE_TIMEOUT_MS = 60_000; +// The pool heartbeats per suite and per 25 rows; with 7-case suites the +// quiet time is bounded by one suite's slowest handshakes. +const STALL_TIMEOUT_MS = 90_000; + +const { values } = parseArgs({ + options: { + out: { type: "string", default: join(JCO_DIR, "..", "results") }, + }, +}); + +async function coreUrls(transpileName) { + const names = (await readdir(join(JCO_DIR, "generated"))).sort(); + return names + .filter((n) => n.startsWith(`${transpileName}.core`) && n.endsWith(".wasm")) + .map((n) => `${BASE}/generated/${n}`); +} + +const common = { + suite: "conformance-guest-ct", + importsUrl: `${BASE}/browser-imports.mjs`, + caseTimeoutMs: CASE_TIMEOUT_MS, +}; +const SUITES = [ + { + ...common, + target: "jco-browser", + moduleUrl: `${BASE}/generated/suite-plain.js`, + coreUrls: await coreUrls("suite-plain"), + missing: ["delegated-signer"], + }, + { + ...common, + target: "jco-browser-delegated", + moduleUrl: `${BASE}/generated/suite-delegated.js`, + coreUrls: await coreUrls("suite-delegated"), + missing: [], + }, +]; + +const playwright = await import("playwright-core"); +const outcome = await runPageHarness({ + playwright, + engine: "chromium", + executablePath: await findChrome(), + repoRoot: REPO_ROOT, + html: buildHarnessPage({ + title: "polymorph:tls conformance (jco-browser)", + config: { jobs: 1, suites: SUITES }, + }), + stallTimeoutMs: STALL_TIMEOUT_MS, +}); + +let failed = 0; +for (const { target } of SUITES) { + const run = outcome[target]; + if (!run) throw new Error(`the page reported no run for target ${target}`); + const outPath = await writeResultsFile({ dir: values.out, target, lines: run.lines }); + const c = run.counts; + process.stderr.write( + `${target}: ${c.passed} passed, ${c.failed} failed, ${c.skipped} skipped, ` + + `${c.na} not applicable, ${c.total} total (wrote ${outPath})\n`, + ); + failed += c.failed; +} +process.exit(failed === 0 ? 0 : 1); diff --git a/conformance/driver-ct/jco/run-node.mjs b/conformance/driver-ct/jco/run-node.mjs new file mode 100644 index 0000000..ae044b5 --- /dev/null +++ b/conformance/driver-ct/jco/run-node.mjs @@ -0,0 +1,70 @@ +// The jco-node leg of the conformance harness: runs a transpiled +// composed artifact (the shared suite fused with one TLS delivery) +// under Node 24 JSPI and writes component-test results JSONL for the +// aggregate. The artifact imports only wasi 0.2 and test-context, so +// the import object is entirely the upstream builder's — there is no +// SUT host module on this leg. The case loop and driver plumbing are +// the upstream helpers; this file is just the frame: argv and wiring. +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; +import { parseArgs } from "node:util"; + +import { cli, clocks, io, random, filesystem } from "@bytecodealliance/preview2-shim"; +import { runSuiteJsonl } from "@polymorph/component-test-js/harness"; +import { inventoryLookup } from "@polymorph/component-test-js/harness"; +import { bindImports } from "@polymorph/component-test-js/imports"; +import { + loadCoreModules, + resolveTestsExport, + writeResultsFile, +} from "@polymorph/component-test-js/node-runner"; + +const JCO_DIR = dirname(fileURLToPath(import.meta.url)); + +// The single-attempt wall bound per case, matching the wasmtime leg's +// defaults in spirit: a wedged case is reported, never retried, and +// never allowed to hang the leg. +const CASE_TIMEOUT_MS = 60_000; + +const { values } = parseArgs({ + options: { + // Transpile name of the composed artifact (suite-plain | suite-delegated). + suite: { type: "string" }, + // The lockfile suite identity (the un-composed suite's wasm stem); + // the composed artifact's name never appears in results. + "suite-name": { type: "string", default: "conformance-guest-ct" }, + missing: { type: "string", default: "" }, + target: { type: "string" }, + out: { type: "string", default: join(JCO_DIR, "..", "results") }, + }, +}); +if (!values.suite || !values.target) { + throw new Error("usage: run-node.mjs --suite --target [--missing f1,f2] [--out dir]"); +} + +const { modules, coreBytes } = await loadCoreModules(join(JCO_DIR, "generated"), values.suite); +const { instantiate } = await import(join(JCO_DIR, "generated", `${values.suite}.js`)); +// wasi minors differ across the fused halves (the suite's std imports +// and the TLS component's), so bind both spellings the generated core +// asks for. +const imports = bindImports({ + wasi: { cli, clocks, io, random, filesystem }, + wasiVersions: ["0.2.0", "0.2.6"], +}); + +const lines = []; +const counts = await runSuiteJsonl({ + newTests: async () => + resolveTestsExport(await instantiate((name) => modules.get(name), imports)), + tagsOf: inventoryLookup(coreBytes), + target: values.target, + suiteName: values["suite-name"], + missing: values.missing.split(",").filter(Boolean), + caseTimeoutMs: CASE_TIMEOUT_MS, + emit: (line) => lines.push(line), + log: (msg) => process.stderr.write(`[${values.target}] ${msg}\n`), +}); + +const outPath = await writeResultsFile({ dir: values.out, target: values.target, lines }); +process.stderr.write(`wrote ${outPath} (${counts.total} cases, ${counts.failed} failed)\n`); +process.exit(counts.failed === 0 ? 0 : 1); diff --git a/conformance/driver-ct/justfile b/conformance/driver-ct/justfile index ed2e038..1f3d389 100644 --- a/conformance/driver-ct/justfile +++ b/conformance/driver-ct/justfile @@ -48,6 +48,7 @@ _ct-tools: printf '%s' "$rev" > target/ct-tools/.rev fi {{ct}} pins --cargo-lock Cargo.lock \ + --js-lock conformance/driver-ct/jco/package-lock.json \ --js-lock conformance/driver-ct/deltic/package-lock.json \ --expect "$rev" > /dev/null @@ -86,6 +87,43 @@ run-delegated: build _ct-tools --suite-artifact {{guest}} \ --target composed-delegated --jsonl > {{results}}/composed-delegated.jsonl +# Transpile both composed artifacts for the Node legs. The stamp covers +# the artifacts and the package.json: the transpile flags and the +# pinned transpiler live there, and either changing must invalidate the +# generated tree. +_jco-prepared: build + #!/usr/bin/env bash + set -euo pipefail + cd {{root}}/conformance/driver-ct/jco + if [ package-lock.json -nt node_modules/.package-lock.json ]; then + npm ci --no-audit --no-fund + fi + stamp=$(cat ../../../target/conformance/suite-plain.wasm \ + ../../../target/conformance/suite-delegated.wasm \ + package.json | sha256sum | cut -d' ' -f1) + if [ "$(cat generated/.stamp 2>/dev/null || true)" != "$stamp" ]; then + npm run --silent transpile + npm run --silent transpile:delegated + printf '%s' "$stamp" > generated/.stamp + fi + +# The suite over the in-guest Ed25519 posture, under Node 24 JSPI. +run-jco-node: _jco-prepared + #!/usr/bin/env bash + set -euo pipefail + cd {{root}}/conformance/driver-ct/jco + node --experimental-wasm-jspi run-node.mjs --suite suite-plain \ + --missing delegated-signer --target jco-node + +# The suite over the delegated build with the fixture signer, under +# Node 24 JSPI. +run-jco-node-delegated: _jco-prepared + #!/usr/bin/env bash + set -euo pipefail + cd {{root}}/conformance/driver-ct/jco + node --experimental-wasm-jspi run-node.mjs --suite suite-delegated \ + --target jco-node-delegated + # The composed artifact runtime-linked under deltic on stock Deno — # no transpile step, no generated tree, no engine flag (callback ABI). # The pin and the module-graph lock live in deltic/ (see its README). @@ -189,6 +227,8 @@ aggregate: _ct-tools cd {{root}} extra=() [ -f {{results}}/composed-delegated-webcrypto.jsonl ] && extra+=(--results composed-delegated-webcrypto={{results}}/composed-delegated-webcrypto.jsonl) + [ -f {{results}}/jco-browser.jsonl ] && extra+=(--results jco-browser={{results}}/jco-browser.jsonl) + [ -f {{results}}/jco-browser-delegated.jsonl ] && extra+=(--results jco-browser-delegated={{results}}/jco-browser-delegated.jsonl) [ -f {{results}}/deltic-browser.jsonl ] && extra+=(--results deltic-browser={{results}}/deltic-browser.jsonl) [ -f {{results}}/deltic-browser-delegated.jsonl ] && extra+=(--results deltic-browser-delegated={{results}}/deltic-browser-delegated.jsonl) {{ct}} aggregate \ @@ -196,15 +236,38 @@ aggregate: _ct-tools --manifest conformance/driver-ct/targets.toml \ --results composed={{results}}/composed.jsonl \ --results composed-delegated={{results}}/composed-delegated.jsonl \ + --results jco-node={{results}}/jco-node.jsonl \ + --results jco-node-delegated={{results}}/jco-node-delegated.jsonl \ --results deltic-deno={{results}}/deltic-deno.jsonl \ --results deltic-deno-delegated={{results}}/deltic-deno-delegated.jsonl \ ${extra[@]+"${extra[@]}"} \ -o {{results}}/matrix.md +# The browser targets: both composed artifacts inside headless +# Chromium via the upstream page driver. Gates in CI; locally opt-in. +run-browser: _jco-prepared + #!/usr/bin/env bash + set -euo pipefail + cd {{root}}/conformance/driver-ct/jco + node run-browser.mjs + +# Runs the browser leg under CI or CONFORMANCE_BROWSER=1; otherwise +# clears stale browser results so the standing run is deterministic. +_run-browser-if-enabled: + #!/usr/bin/env bash + set -euo pipefail + if [ "${GITHUB_ACTIONS:-}" = "true" ] || [ "${CONFORMANCE_BROWSER:-}" = "1" ]; then + cd {{root}} && just conformance-ct::run-browser + else + cd {{root}} + rm -f {{results}}/jco-browser.jsonl {{results}}/jco-browser-delegated.jsonl + echo "browser leg skipped (set CONFORMANCE_BROWSER=1, needs Chrome/Chromium)" + fi + # The standing matrix: inventory check, all standing targets, # aggregate. Stale on-demand webcrypto results are cleared first so the # standing run is deterministic. -all: lock-check run-composed run-delegated run-deltic run-deltic-delegated _run-deltic-browser-if-enabled _clear-webcrypto aggregate +all: lock-check run-composed run-delegated run-jco-node run-jco-node-delegated run-deltic run-deltic-delegated _run-browser-if-enabled _run-deltic-browser-if-enabled _clear-webcrypto aggregate _clear-webcrypto: rm -f results/composed-delegated-webcrypto.jsonl diff --git a/conformance/driver-ct/matrix.md b/conformance/driver-ct/matrix.md index a8ea725..02cd69c 100644 --- a/conformance/driver-ct/matrix.md +++ b/conformance/driver-ct/matrix.md @@ -4,13 +4,13 @@ - target `composed-delegated-webcrypto`: no results (declared optional) -| Case | composed | composed-delegated | composed-delegated-webcrypto | deltic-browser | deltic-browser-delegated | deltic-deno | deltic-deno-delegated | -| --- | --- | --- | --- | --- | --- | --- | --- | -| data (1 cases) | pass | pass | — | pass | pass | pass | pass | -| delegated (3 cases) | 2 N/A, 1 pass | 1 N/A, 2 pass | — | 2 N/A, 1 pass | 1 N/A, 2 pass | 2 N/A, 1 pass | 1 N/A, 2 pass | -| handshake (1 cases) | pass | pass | — | pass | pass | pass | pass | -| identity (1 cases) | pass | pass | — | pass | pass | pass | pass | -| shutdown (1 cases) | pass | pass | — | pass | pass | pass | pass | +| Case | composed | composed-delegated | composed-delegated-webcrypto | deltic-browser | deltic-browser-delegated | deltic-deno | deltic-deno-delegated | jco-browser | jco-browser-delegated | jco-node | jco-node-delegated | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| data (1 cases) | pass | pass | — | pass | pass | pass | pass | pass | pass | pass | pass | +| delegated (3 cases) | 2 N/A, 1 pass | 1 N/A, 2 pass | — | 2 N/A, 1 pass | 1 N/A, 2 pass | 2 N/A, 1 pass | 1 N/A, 2 pass | 2 N/A, 1 pass | 1 N/A, 2 pass | 2 N/A, 1 pass | 1 N/A, 2 pass | +| handshake (1 cases) | pass | pass | — | pass | pass | pass | pass | pass | pass | pass | pass | +| identity (1 cases) | pass | pass | — | pass | pass | pass | pass | pass | pass | pass | pass | +| shutdown (1 cases) | pass | pass | — | pass | pass | pass | pass | pass | pass | pass | pass | ## Failures @@ -25,3 +25,7 @@ None. - `deltic-browser-delegated`: 1 N/A, 6 pass (7 total) - `deltic-deno`: 2 N/A, 5 pass (7 total) - `deltic-deno-delegated`: 1 N/A, 6 pass (7 total) +- `jco-browser`: 2 N/A, 5 pass (7 total) +- `jco-browser-delegated`: 1 N/A, 6 pass (7 total) +- `jco-node`: 2 N/A, 5 pass (7 total) +- `jco-node-delegated`: 1 N/A, 6 pass (7 total) diff --git a/conformance/driver-ct/targets.toml b/conformance/driver-ct/targets.toml index abf9fd6..e54bfb2 100644 --- a/conformance/driver-ct/targets.toml +++ b/conformance/driver-ct/targets.toml @@ -2,12 +2,16 @@ # A target is a composition of the shared suite with one delivery of # the algorithm profile: the wasmtime rows run under the generic # component-test host runner (the composed artifact imports only wasi -# and test-context); the deltic rows run the same artifacts runtime- -# linked under deltic (driver-ct/deltic/), on stock Deno or inside -# headless Chromium — no transpile step. The browser rows gate in CI -# (the Actions image ships Chrome); locally they run under -# CONFORMANCE_BROWSER=1, so both are declared optional — a missing -# results file is a warning, not an error. +# and test-context), and the jco-node rows run the same artifacts +# transpiled, under Node 24 JSPI (driver-ct/jco/run-node.mjs; the +# transpiler is the lann/jco all-fixes pre-release pinned in +# driver-ct/jco/package.json). +# +# The jco-browser rows run the same transpiles inside headless +# Chromium via the upstream page driver (driver-ct/jco/run-browser.mjs). +# They gate in CI (the Actions image ships Chrome); locally they run +# under CONFORMANCE_BROWSER=1, so both are declared optional — a +# missing results file is a warning, not an error. version = "0.1" # The target's TLS stack has a composed `polymorph:tls/signer`, so @@ -26,6 +30,14 @@ missing-features = ["delegated-signer"] [targets.composed-delegated] missing-features = [] +# The composed artifact, transpiled and run under Node 24 JSPI. +[targets.jco-node] +missing-features = ["delegated-signer"] + +# The composed-delegated artifact under Node 24 JSPI. +[targets.jco-node-delegated] +missing-features = [] + # The composed artifact runtime-linked under deltic on stock Deno # (driver-ct/deltic/run.ts): no transpile step, no engine flag — the # release-pinned runtime links the component at load time. @@ -46,6 +58,16 @@ missing-features = [] missing-features = [] optional = true +# The composed artifact inside headless Chromium. +[targets.jco-browser] +missing-features = ["delegated-signer"] +optional = true + +# The composed-delegated artifact inside headless Chromium. +[targets.jco-browser-delegated] +missing-features = [] +optional = true + # The composed artifact runtime-linked inside headless Chromium (the # upstream deltic worker; no transpile step). [targets.deltic-browser] From a40db0dcebd5b92df1df46c17771e4e3200e592c Mon Sep 17 00:00:00 2001 From: Lann Martin Date: Mon, 10 Aug 2026 15:26:39 -0400 Subject: [PATCH 2/2] CI/docs: keep the #39 completions the revert would lose MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The publish action's results list keeps the deltic-browser rows and the setup action's js-locks gains deltic's lockfile (both missing since #39 — the local justfile wiring already had them), and conformance/README's targets table keeps its deltic-browser rows. Content-identical to what PR #40 carried alongside the removal. --- .github/workflows/ci.yml | 3 +++ conformance/README.md | 2 ++ 2 files changed, 5 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dac8d73..6ddd809 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -99,6 +99,7 @@ jobs: with: js-locks: | conformance/driver-ct/jco/package-lock.json + conformance/driver-ct/deltic/package-lock.json - name: Set up Node 24 (the jco-node legs; JSPI) uses: actions/setup-node@v4 with: @@ -135,6 +136,8 @@ jobs: deltic-deno-delegated=conformance/driver-ct/results/deltic-deno-delegated.jsonl jco-browser=conformance/driver-ct/results/jco-browser.jsonl jco-browser-delegated=conformance/driver-ct/results/jco-browser-delegated.jsonl + deltic-browser=conformance/driver-ct/results/deltic-browser.jsonl + deltic-browser-delegated=conformance/driver-ct/results/deltic-browser-delegated.jsonl summary-title: Conformance matrix cli: target/ct-tools/bin/component-test # The action fails on a uses: ref that skews from this pin. diff --git a/conformance/README.md b/conformance/README.md index 66dac9c..a64d8ce 100644 --- a/conformance/README.md +++ b/conformance/README.md @@ -42,6 +42,8 @@ JSPI — one suite, one composition, two engines. | `deltic-deno-delegated` | the `composed-delegated` artifact, likewise | | `jco-browser` | the `composed` artifact inside headless Chromium (the upstream page driver; gates in CI, locally `CONFORMANCE_BROWSER=1`; declared `optional`) | | `jco-browser-delegated` | the `composed-delegated` artifact, likewise | +| `deltic-browser` | the `composed` artifact runtime-linked inside headless Chromium (gates in CI, locally `CONFORMANCE_BROWSER=1`; declared `optional`) | +| `deltic-browser-delegated` | the `composed-delegated` artifact, likewise | In-suite QUIC cases are [#29](https://github.com/polymorph-components/polymorph-tls/issues/29).