diff --git a/.github/justfile b/.github/justfile index 34fb986..21cf6bb 100644 --- a/.github/justfile +++ b/.github/justfile @@ -31,6 +31,7 @@ rust-checks: @just gha::_step test conformance-checks: + @just gha::_step exam-deltic @just gha::_step conformance-ct::all @just gha::_step deltic-module-check @just gha::_step wpt::parity diff --git a/AGENTS.md b/AGENTS.md index 5ac1f40..aed500f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -36,14 +36,15 @@ Layout (each directory's justfile module in parentheses): Its knobs are exported functions (`configure`, `setMaxInboundBufferBytes`, `setConnectTimeoutMs`, `setCloseTimeoutMs`); the module reads no ambient configuration. The - deltic release is pinned in `conformance/driver-ct/deltic/fetch-translator.ts` - (TAG + translator-shim sha256) and in TWO import maps — - `js/deltic/deno.json` and `conformance/driver-ct/deltic/deno.json` — - which must agree byte-for-byte on the `@deltic/runtime/embedder` URL - (deltic's `wasi-shims` imports it by bare specifier internally, so a - drift would load the embedder module twice and break `instanceof - WitError` across the boundary). Bump procedure: - `conformance/driver-ct/deltic/README.md`. + deltic release is pinned in TWO import maps — `js/deltic/deno.json` and + `conformance/driver-ct/deltic/deno.json` — as exact-pinned JSR + prereleases (`jsr:@deltic/@0.1.0-pre.g`; a version names one + upstream commit) which must agree on the `@deltic/runtime` version + (deltic's `wasi-shims` imports `@deltic/runtime/embedder` by bare + specifier internally, so a drift would load the embedder module twice + and break `instanceof WitError` across the boundary); the root + justfile's `exam-deltic` recipe (CI-wired) asserts one version + repo-wide. Bump procedure: `conformance/driver-ct/deltic/README.md`. - `js/componentize/` (`just wpt::…`) — `websocket.js`, the WHATWG-API shim for componentize-js guests (deviations registry in its header), and the WPT parity gate (`wpt/README.md` is the vendoring policy; losses @@ -64,8 +65,8 @@ Layout (each directory's justfile module in parentheses): records (`conformance-ct::_ct-tools`). One rev everywhere; the root `Cargo.toml` comment is the bump checklist. There is no transpiler dependency anywhere: the JS host legs are runtime-linked by the pinned - deltic release assets (single pin site: - `driver-ct/deltic/{deno.json,deno.lock,fetch-translator.ts}`). + deltic JSR prereleases (single pin site: `driver-ct/deltic/{deno.json, + deno.lock}`). - `examples/` (`just demo::…`) — the echo-demo guest and its host runners. Checks to run before committing, by what changed: WIT or `wit/README.md` → diff --git a/conformance/driver-ct/deltic/README.md b/conformance/driver-ct/deltic/README.md index 78d9512..fe7ffe2 100644 --- a/conformance/driver-ct/deltic/README.md +++ b/conformance/driver-ct/deltic/README.md @@ -14,34 +14,46 @@ exact mirror. just conformance-ct::run-deltic ``` -which builds the suite + echod, fetches (and caches) the pinned -translator-shim release asset, and runs the suite through `ct-runner`, -writing `conformance/driver-ct/results/deltic-deno.jsonl`. +which builds the suite + echod and runs the suite through `ct-runner`, +writing `conformance/driver-ct/results/deltic-deno.jsonl`. The translator +comes from the packaged `@deltic/translator` JSR prerelease through the +module graph — no fetch step, no net grant. ## The pin -deltic is pinned to a release tag in **three** places, cross-checked at -run time by `fetch-translator.ts`: - -- `deno.json` (this directory) — import-map URLs - (`raw.githubusercontent.com/lann/deltic//…`) for `@deltic/ct-runner`, - `@deltic/runtime/embedder`, `@deltic/runtime/shim`, `@deltic/wasi-shims`. - `deno.lock` carries integrity hashes for that module graph, enforced - with `--frozen`. +deltic publishes `@deltic/{runtime,translator,wasi-shims,ct-runner}` to +JSR as exact-pinned prereleases (`0.1.0-pre.g`, the same short +hash as the corresponding GitHub release — a version names one exact +upstream commit; see deltic's README "Consuming the unstable +prereleases"). It is pinned in **two** places, both required to agree: + +- `deno.json` (this directory) — import-map versions + (`jsr:@deltic/@0.1.0-pre.g`) for `@deltic/ct-runner`, + `@deltic/runtime/embedder`, `@deltic/runtime/shim`, `@deltic/wasi-shims`, + `@deltic/translator`. `deno.lock` carries integrity hashes for that + module graph, enforced with `--frozen`. - [`../../../js/deltic/deno.json`](../../../js/deltic/deno.json) — the - SAME `@deltic/runtime/embedder` URL (the module-identity constraint: - deltic's `wasi-shims` imports that specifier by bare name internally, - so every config resolving it must agree, or the embedder module loads - twice and `instanceof WitError` stops holding across the boundary). -- `fetch-translator.ts` — `TAG` + `TRANSLATOR_SHA256` for the - `deltic-translator-shim.wasm` release asset (cached under - `target/deltic//`). - -To bump: update the tag in all three files (this `deno.json`, -`js/deltic/deno.json`, and `fetch-translator.ts`) and the sha256 from the -release's `SHA256SUMS`, delete BOTH `deno.lock` files (this directory and -`js/deltic/`), re-run `deno cache run.ts fetch-translator.ts` here and -`deno cache websocket.ts tests/websocket_test.ts` in `js/deltic/` to -regenerate them, then re-run `just conformance-ct::run-deltic` and commit -the diff (including the regenerated `matrix.md`, via -`just conformance-ct::matrix-update`). + SAME `@deltic/runtime` version (the module-identity constraint: deltic's + `wasi-shims` imports `@deltic/runtime/embedder` by bare specifier + internally, so every config resolving it must agree, or the embedder + module loads twice and `instanceof WitError` stops holding across the + boundary). + +`@deltic/translator` ships the translator wasm asset **for the same +commit** as `@deltic/runtime`, so the plan-format coupling is +self-consistent per graph by construction — there is no separate sha256 +to track. The root justfile's `exam-deltic` recipe (wired into CI) is the +one-version-everywhere gate: it asserts every `jsr:@deltic/*` import +across both `deno.json` files names the identical version. + +Both `deno.json`s carry +`"minimumDependencyAge": { "age": "P1D", "exclude": ["jsr:@deltic/*"] }` +(verbatim from deltic's README): Deno's 24-hour supply-chain gate would +otherwise block resolving a same-day publish. + +To bump: update the version in both `deno.json` import maps, delete +**both** `deno.lock` files (this directory and `js/deltic/`), regenerate +with `deno install` (or `deno check`) in each directory, then re-run +`just conformance-ct::run-deltic` and commit the diff (including the +regenerated `matrix.md`, via `just conformance-ct::matrix-update`). +`exam-deltic` fails loud on any drift between the two configs. diff --git a/conformance/driver-ct/deltic/browser-bundle-entry.ts b/conformance/driver-ct/deltic/browser-bundle-entry.ts new file mode 100644 index 0000000..a182f7e --- /dev/null +++ b/conformance/driver-ct/deltic/browser-bundle-entry.ts @@ -0,0 +1,18 @@ +// The deltic-browser worker's bundle entry for the engine surface: +// upstream's tools/release-bundle/entry.ts public surface, reproduced +// locally now that deltic publishes JSR prereleases instead of a +// pinned raw-URL release bundle (see ../../../README.md's deltic pin +// story and js/deltic/deno.json's MODULE-IDENTITY comment). +// +// Bundled with `deno bundle --platform browser` from THIS directory (so +// every re-export resolves through this directory's deno.json import +// map — the single deltic pin site), the emitted module is what +// browser/worker-entry.ts imports as `@deltic/release-bundle-entry` +// used to. Same export surface: instantiate/Translator/runSuite/ +// wasiShims/WitError/artifactsFromEnvelope and friends (49 exports +// verified against the retired upstream entry). +export * from "@deltic/runtime/embedder"; +export { Translator } from "@deltic/runtime/shim"; +export * from "@deltic/ct-runner"; +export { wasiShims } from "@deltic/wasi-shims"; +export type { WasiShims, WasiShimsOptions } from "@deltic/wasi-shims"; diff --git a/conformance/driver-ct/deltic/browser/worker-entry.ts b/conformance/driver-ct/deltic/browser/worker-entry.ts index e031cc2..9c3573e 100644 --- a/conformance/driver-ct/deltic/browser/worker-entry.ts +++ b/conformance/driver-ct/deltic/browser/worker-entry.ts @@ -1,17 +1,18 @@ // The deltic-browser shard worker's bundle entry: the deltic engine -// surface (the release-bundle entry at the pinned tag), the upstream -// worker message loop, and this repo's deltic host module, resolved -// through ONE import map so the emitted bundle carries exactly one -// embedder module instance — which is what keeps `instanceof WitError` -// true when the host module throws across the component boundary -// (workers resolve no import maps, so bundling is the only sound shape; -// see @polymorph/component-test-js's runner-deltic README). +// surface (the local browser-bundle-entry.ts, re-exporting the pinned +// JSR packages' public surface), the upstream worker message loop, and +// this repo's deltic host module, resolved through ONE import map so the +// emitted bundle carries exactly one embedder module instance — which is +// what keeps `instanceof WitError` true when the host module throws +// across the component boundary (workers resolve no import maps, so +// bundling is the only sound shape; see @polymorph/component-test-js's +// runner-deltic README). // // Built by `just conformance-ct::run-deltic-browser` with // `deno bundle --platform browser` into target/deltic-browser/, and // served to the page from there as runSuitesInPage's workerUrl. -import * as deltic from "@deltic/release-bundle-entry"; +import * as deltic from "../browser-bundle-entry.ts"; import { workerMain } from "@polymorph/component-test-js/deltic-worker-main"; import { configure, websocketImports } from "../../../../js/deltic/websocket.ts"; diff --git a/conformance/driver-ct/deltic/deno.json b/conformance/driver-ct/deltic/deno.json index 5c86210..62d1ea3 100644 --- a/conformance/driver-ct/deltic/deno.json +++ b/conformance/driver-ct/deltic/deno.json @@ -1,14 +1,15 @@ { - "//": "MODULE-IDENTITY CONSTRAINT: deltic's wasi-shims module imports @deltic/runtime/embedder by bare specifier internally. The @deltic/runtime/embedder entry here must map to the IDENTICAL URL as ../../../js/deltic/deno.json's entry, or the embedder module loads twice and `instanceof WitError` stops holding across the module boundary.", + "//": "MODULE-IDENTITY CONSTRAINT: deltic's wasi-shims module imports @deltic/runtime/embedder by bare specifier internally. The @deltic/runtime/embedder entry here must map to the IDENTICAL exact-pinned JSR version as ../../../js/deltic/deno.json's entry, or the embedder module loads twice and `instanceof WitError` stops holding across the module boundary. Pin story: 0.1.0-pre.ga67ee83 names one upstream deltic commit; @deltic/translator ships the translator wasm for that SAME commit; deno.lock carries integrity, --frozen enforced everywhere; one version repo-wide is asserted by the pin gate (justfile: exam-deltic).", "imports": { - "@deltic/ct-runner": "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/ct-runner/src/mod.ts", - "@deltic/runtime/embedder": "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/embedder/mod.ts", - "@deltic/runtime/shim": "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/shim/mod.ts", - "@deltic/wasi-shims": "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/wasi-shims/src/mod.ts", - "@deltic/release-bundle-entry": "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/tools/release-bundle/entry.ts", + "@deltic/ct-runner": "jsr:@deltic/ct-runner@0.1.0-pre.ga67ee83", + "@deltic/runtime/embedder": "jsr:@deltic/runtime@0.1.0-pre.ga67ee83/embedder", + "@deltic/runtime/shim": "jsr:@deltic/runtime@0.1.0-pre.ga67ee83/shim", + "@deltic/wasi-shims": "jsr:@deltic/wasi-shims@0.1.0-pre.ga67ee83", + "@deltic/translator": "jsr:@deltic/translator@0.1.0-pre.ga67ee83", "@polymorph/component-test-js/deltic-worker-main": "./node_modules/@polymorph/component-test-js/js/runner-deltic/worker-main.mjs" }, + "minimumDependencyAge": { "age": "P1D", "exclude": ["jsr:@deltic/*"] }, "tasks": { - "check": "deno check run.ts fetch-translator.ts browser/worker-entry.ts" + "check": "deno check run.ts browser/worker-entry.ts browser-bundle-entry.ts" } } \ No newline at end of file diff --git a/conformance/driver-ct/deltic/deno.lock b/conformance/driver-ct/deltic/deno.lock index fdf4aa2..9cdcc72 100644 --- a/conformance/driver-ct/deltic/deno.lock +++ b/conformance/driver-ct/deltic/deno.lock @@ -1,70 +1,49 @@ { "version": "5", - "remote": { - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/ct-runner/src/context.ts": "366db52e3189260a7fd2fc2fdb90aea9bd6a3055d83c42acad082eb75565c634", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/ct-runner/src/import-analysis.ts": "64971e796ebccd98730ba2a0e78b599db38284f22b7976687fc4cad898703c32", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/ct-runner/src/mod.ts": "24a88cb8dda9c1d346a1809297cc5b2ab1c3a2d39c4914694c2ee5f76e9911db", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/ct-runner/src/run-suite.ts": "1220e6129b17e89b9a7c7ff372bfc86f70b1cbab6cc9645cca90b62ac677c406", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/ct-runner/src/tags.ts": "d64136eb7e21e18e73cc255e052f59377d2be869f4929bf4fc6de026f3b74a0b", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/cabi/async_values.ts": "af1279d4e4db5b756268979aeff5b27c1cf6c0f021213655676ade90472f282b", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/cabi/context.ts": "b4b60891ef9d9e72b208636f6ba37f0b9b6962d307af6156ad3b5ad59a626902", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/cabi/flatten.ts": "6c980fe38d7adce349d5e028b819eb0ffbb92714f958c1d5daae8da3e7ed3889", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/cabi/float.ts": "0483e8c1aa8786eee4c6f6357fee6738555e4310650c474aba6cd811a80d7d36", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/cabi/handles.ts": "30510750261499f48a812bb8c349a8f88a3bb7239175e6f1d4e6d10c38571e5d", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/cabi/layout.ts": "8122141b39f4d8189c13d91fc1b37825ceead86988f879f3fa9351bbef96f8f2", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/cabi/lift.ts": "e4475a44a5618114f288025601b535bc04b97e9a37b3be21f51d3be092d419c8", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/cabi/load.ts": "c1d8ddb1b3b3c59afe30710a97ad6dd7ae1ecd59aa1d427a5eaf4552d3b1ea01", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/cabi/lower.ts": "916ef7476dc583783770f4c42de7a655350531b3763c81a92249cca96f5e4d80", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/cabi/memory.ts": "09728360d6413fb30a5a7bff1ba6abec1ac6474ff150d45f093b8ebe5e65cd51", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/cabi/mod.ts": "b79cf9e2bab2e837fee76fa61dc18bff66d941e08597f1b76de93811bd6d6008", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/cabi/store.ts": "97aaecfeb4dfbf5c3c132fb5eadf1f5677924936eee0c7fa75a266a00cd73634", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/cabi/strings.ts": "9589dda3857725792ae15ef6888449b48e973b9eb0f3058ed64e10bf4d39b793", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/cabi/trap.ts": "307d8b48806eeba30400b3d7db9370cee70a12298851c1c19053dd8ca0013e1c", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/cabi/types.ts": "d0392e8cdf2990a76c8a1f9b85795d3b7c19b8eb006c2b159b671d08c39b9535", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/cabi/values.ts": "9e6ddcc4192d05897b2cbea250db3fef0ad9bf6548ba87aff378ee14b7ab7022", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/embedder/casing.ts": "1e9083becfc08107c09015ce3db79c304b05c40085a3c899ea1c8ebe25fcd45f", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/embedder/errors.ts": "b0cac244526b92c052d165f2aee1d9492e5915a5a4cad114e1ab575ffe1587ba", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/embedder/imports.ts": "98cca003e4a1131c35854c91b458f109d6761a3e8f67c23730f7e9bc28bbad88", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/embedder/instantiate.ts": "ef330d0a8562932e38d3a8a38a155bbd66ddb9c5d1025a1d39b5ce567817f334", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/embedder/mod.ts": "0a4f42b8c569b528b4c3172c3394ad5f9ddafa33bcaf5eccd00e645e111da2b1", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/embedder/resources.ts": "d209e5f13545b9c0c095ac4e188b72370d97c9bd394ba7c8793ddd74f436b1ef", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/embedder/streams.ts": "4ef894a43da94b4cb01ee65798a108a8fb3f6b2dc6013c71881f63e0806df565", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/embedder/values.ts": "ed876f9103f4a4f34e8eb475934091156bee1447f5a029ea300644b8f3ee71eb", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/embedder/version.ts": "b1c589988e5fb88dce3a014846c9253399e286f12afb5fd92509c8d6090ad4bb", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/exec/boundary.ts": "1b4b7d6394a79b4048fb932219ea9420c6461106c30d1bd70b29b09e16cad20d", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/exec/executor.ts": "267a6e5542e0fef3a930a3e2242aa58c3c83aa25b174c7533a07b70960f74e5d", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/exec/host_streams.ts": "63f6b113806c401ae9895df82448da70a7745a97b6e2f04061fb5bc64e7d0acf", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/exec/mod.ts": "a46320977ece14342bcb72c9c9e36d65a1cd09d789591d0909d7d1185264010b", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/intrinsics/async_builtins.ts": "526795358da8908d54a483bb47eebc43e0a1ea59e69ece94d0c6890ad0fa8784", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/intrinsics/context.ts": "be93b23d127ff71d5c372781f89d1c3746c5d32a44e67ebbcd91f2b0f0807e93", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/intrinsics/errors.ts": "9d09fc1818b4dc98b238aa69008a9110d9d305b6a8e806604f3bd48fca1eebcb", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/intrinsics/fact_calls.ts": "aa0b0aef81b59cdcd8dc572c20e1f57a8f5592f75a0d5d666032851df9201229", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/intrinsics/mod.ts": "f9c095e561f5fbb51f70693b21f272f66241f2e8ff2e1a83cd4176bcd0104eb9", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/intrinsics/stream_builtins.ts": "bbc1e1ea0e4616026a46d790a68695aa70589a88b08a6275acdb525f0ab531ec", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/intrinsics/transcode.ts": "e3fcaeb7a60b6cbad999d9389d4bce59e305e6f54e035ba791f909e10d1f82c7", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/jspi/bridge.ts": "7cf3706d3bf34b503aea516a31918a8d930aba3dac7e94ec04caecd23fe6025e", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/jspi/mechanics.ts": "dc0fe4965b3ef8c0aff6674afd8bae2a38942ab934fa07fd2eb7db72b2462f17", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/jspi/mod.ts": "4d047b820b50c410ed946c62dc48286f8abe4787ce6ae5466cd0ae255d98943c", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/jspi/types.ts": "86929224733a764a148ac75a9d6b95d61ab4c8123a48fe956d998e97726a1432", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/plan/format.ts": "90e31bbc7137c2f80c0782e1431afb6f81827aab8d38dba1178b8761f1b3ea0a", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/plan/loader.ts": "107db77e724a7f74f161a5fd20e7110a6e6f182c46f18282eba650bc887dc876", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/shim/mod.ts": "34af2240dfd0be720def487db2db34eaad6ba9178003f20e2193d03a0632779b", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/shim/translator.ts": "7ea1a4101363ee62ddedb9d6c3f798fd6042886ef38ee13046ac3cdb9485bf24", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/task/mod.ts": "5decca8045dfd9743910e83d512258a7be3b0d0917954b8d9cdbac38e03f7dfb", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/task/scheduler.ts": "18a4404f620407bd867876115861ee0cf98f6f1ccd41c5f3c877ef90e429ef9c", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/task/streams.ts": "83b522a6393ba06fbdb87881bc6761f3fce9c03b85e9eda03d3befe7d2605a60", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/task/subtask.ts": "750b13a1318f62836bfd149f1b9144de5b017fd7a84adc8e2fb2151e63130fbc", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/task/thread.ts": "81fe38b37a1ec130803b478a24e428b19ee4e1ef8c0bae741395cd8d52751580", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/task/waitable.ts": "5e1fc092e3d8f1fb4429d6a91d8886b3e474aa9ac6254e7924fd896c4929e1f9", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/tools/release-bundle/entry.ts": "2b6a277d426c5930b79e120bb792506329cc2603e54a8e50a27cb7b76e39e2fa", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/wasi-shims/src/cli.ts": "d1617e12dc2569f4ee107f8b92488797daf431d14b8a86a1ab10750a28757394", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/wasi-shims/src/clocks.ts": "05468a822b635408ce3a671b40fd06fd4448c220019f9449bf029ac1c7e59664", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/wasi-shims/src/filesystem.ts": "6dcead5346d78084c3923410e44875e678f3b58db0c2d59513339b428596ec25", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/wasi-shims/src/io.ts": "dfe270e5ad3388c02696e27a5c69c58a411759fe8c99416361b0ac10177366da", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/wasi-shims/src/mod.ts": "1748985cf851252e1755aafd9ebb9c7ae96003ec41322d9524a952062d2b8570", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/wasi-shims/src/random.ts": "dc04d20de5399cc7fa8685a04ec954618e3994a374ef94535fff408a745425e2" + "specifiers": { + "jsr:@deltic/ct-runner@0.1.0-pre.ga67ee83": "0.1.0-pre.ga67ee83", + "jsr:@deltic/runtime@0.1.0-pre.ga67ee83": "0.1.0-pre.ga67ee83", + "jsr:@deltic/runtime@~0.1.0-pre.ga67ee83": "0.1.0-pre.ga67ee83", + "jsr:@deltic/translator@0.1.0-pre.ga67ee83": "0.1.0-pre.ga67ee83", + "jsr:@deltic/wasi-shims@0.1.0-pre.ga67ee83": "0.1.0-pre.ga67ee83", + "npm:playwright-core@^1.61.1": "1.62.1" + }, + "jsr": { + "@deltic/ct-runner@0.1.0-pre.ga67ee83": { + "integrity": "d78e96eba54e53dabe7c1de5a67782aad755362824d741913ab4d36941ebfbcc", + "dependencies": [ + "jsr:@deltic/runtime@~0.1.0-pre.ga67ee83" + ] + }, + "@deltic/runtime@0.1.0-pre.ga67ee83": { + "integrity": "2a2b0949031747a2340dc186299e654ea9f361ae39ac6bd633019940682db4ed" + }, + "@deltic/translator@0.1.0-pre.ga67ee83": { + "integrity": "e4f1bb219e56b62262b0c9665e3f6646aa13883b2cfbb9d6306f69d19974d412", + "dependencies": [ + "jsr:@deltic/runtime@~0.1.0-pre.ga67ee83" + ] + }, + "@deltic/wasi-shims@0.1.0-pre.ga67ee83": { + "integrity": "a5754e65d50873e675695a51279989e22b3771e31f16a84a09feb15905c574a7", + "dependencies": [ + "jsr:@deltic/runtime@~0.1.0-pre.ga67ee83" + ] + } + }, + "npm": { + "playwright-core@1.62.1": { + "integrity": "sha512-wPYSwEBJY9GHraISXqyqtx0na0LpO3XEX7jNDhntbex7tzUS7kLnZsOlFruFJB4Hi/rhDMjXGqHewDZ68nYZVw==", + "bin": true + } }, "workspace": { + "dependencies": [ + "jsr:@deltic/ct-runner@0.1.0-pre.ga67ee83", + "jsr:@deltic/runtime@0.1.0-pre.ga67ee83", + "jsr:@deltic/translator@0.1.0-pre.ga67ee83", + "jsr:@deltic/wasi-shims@0.1.0-pre.ga67ee83" + ], "packageJson": { "dependencies": [ "npm:playwright-core@^1.61.1" diff --git a/conformance/driver-ct/deltic/fetch-translator.ts b/conformance/driver-ct/deltic/fetch-translator.ts deleted file mode 100644 index c9981c2..0000000 --- a/conformance/driver-ct/deltic/fetch-translator.ts +++ /dev/null @@ -1,121 +0,0 @@ -// Fetch (and cache) pinned deltic release assets. -// -// deltic is a runtime linker: components are translated by a wasm build of -// its translator, shipped as a release asset so consumers need no Rust -// toolchain; the browser leg additionally loads `deltic-embedder.mjs` -// (embedder API + Translator + runner glue + wasi shims in one -// platform-neutral ES module). This script downloads the selected asset -// once into target/deltic/, verifies it against the pinned sha256, and -// prints the cached path on stdout (the `conformance-ct::run-deltic*` -// recipes capture it). -// -// fetch-translator.ts [--asset translator|embedder] (default: translator) -// -// THE PIN lives here (TAG + per-asset sha256) and in TWO import maps: -// this directory's deno.json AND ../../../js/deltic/deno.json (the -// module-identity constraint documented there requires the embedder URL -// to be byte-identical in both). `assertPinConsistency` checks both and -// fails loud if either drifts. -// -// Bumping: update TAG here and in BOTH deno.json files, update the -// shas from the release's SHA256SUMS, delete BOTH deno.lock -// files, and re-run `deno cache run.ts fetch-translator.ts` in this -// directory plus `deno cache websocket.ts tests/websocket_test.ts` in -// js/deltic to regenerate them (commit the diff). - -const TAG = "pre-58b2404"; -const ASSETS: Record = { - translator: { - file: "deltic-translator-shim.wasm", - sha256: "6d02b363785593595a789d083cda0aebb1de790726718ccf543198354fa3870c", - }, - embedder: { - file: "deltic-embedder.mjs", - sha256: "3cf48c6a984864c3cd8b094f9d99669967858e37c4835ee50543e3d04dca44a6", - }, -}; - -const HERE = new URL(".", import.meta.url); -const REPO_ROOT = new URL("../../../", HERE); -const CACHE_DIR = new URL(`target/deltic/${TAG}/`, REPO_ROOT); - -async function sha256Hex(bytes: Uint8Array): Promise { - const digest = await crypto.subtle.digest( - "SHA-256", - bytes as BufferSource, - ); - return Array.from(new Uint8Array(digest)) - .map((b) => b.toString(16).padStart(2, "0")) - .join(""); -} - -/** The one-pin-everywhere gate: every raw.githubusercontent URL in BOTH - * sibling import maps must reference TAG. */ -async function assertPinConsistency(): Promise { - const configs = [ - new URL("deno.json", HERE), - new URL("../../../js/deltic/deno.json", HERE), - ]; - for (const configUrl of configs) { - const denoJson = await Deno.readTextFile(configUrl); - const urls = denoJson.match(/https:\/\/raw\.githubusercontent\.com[^"]+/g) ?? []; - if (urls.length === 0) { - throw new Error(`${configUrl.pathname}: no pinned deltic URLs found`); - } - for (const url of urls) { - if (!url.includes(`/lann/deltic/${TAG}/`)) { - throw new Error( - `pin drift: ${configUrl.pathname} pins ${url}\n` + - `but fetch-translator.ts pins ${TAG}`, - ); - } - } - } -} - -async function main() { - await assertPinConsistency(); - - const flag = Deno.args.indexOf("--asset"); - const name = flag === -1 ? "translator" : Deno.args[flag + 1]; - const asset = ASSETS[name]; - if (!asset) { - throw new Error( - `unknown asset ${JSON.stringify(name)}; expected one of: ${ - Object.keys(ASSETS).join(", ") - }`, - ); - } - const cached = new URL(asset.file, CACHE_DIR); - - try { - const bytes = await Deno.readFile(cached); - if (await sha256Hex(bytes) === asset.sha256) { - console.log(cached.pathname); - return; - } - console.error(`cached ${asset.file} has a stale digest; re-fetching`); - } catch { - // not cached yet - } - - const releaseUrl = - `https://github.com/lann/deltic/releases/download/${TAG}/${asset.file}`; - console.error(`fetching ${releaseUrl} …`); - const resp = await fetch(releaseUrl); - if (!resp.ok) { - throw new Error(`GET ${releaseUrl}: ${resp.status} ${resp.statusText}`); - } - const bytes = new Uint8Array(await resp.arrayBuffer()); - const got = await sha256Hex(bytes); - if (got !== asset.sha256) { - throw new Error( - `sha256 mismatch for ${asset.file}@${TAG}:\n want ${asset.sha256}\n got ${got}`, - ); - } - await Deno.mkdir(CACHE_DIR, { recursive: true }); - await Deno.writeFile(cached, bytes); - console.log(cached.pathname); -} - -await main(); diff --git a/conformance/driver-ct/deltic/run-browser.mjs b/conformance/driver-ct/deltic/run-browser.mjs index cf09c11..474c888 100644 --- a/conformance/driver-ct/deltic/run-browser.mjs +++ b/conformance/driver-ct/deltic/run-browser.mjs @@ -30,10 +30,8 @@ import { spawnEchod, unreachableUrl } from "../../server/echod.mjs"; const DELTIC_DIR = dirname(fileURLToPath(import.meta.url)); const REPO_ROOT = resolve(DELTIC_DIR, "..", "..", ".."); -// Must agree with fetch-translator.ts's TAG (the translator is served -// from its cache directory). -const TAG = "pre-58b2404"; const WORKER_URL = "/target/deltic-browser/websocket-worker.mjs"; +const TRANSLATOR_URL = "/target/deltic-browser/deltic-translator-shim.wasm"; const MAX_INBOUND_BUFFER_BYTES = 256 * 1024; const CASE_TIMEOUT_MS = 60_000; const STALL_TIMEOUT_MS = 90_000; @@ -57,7 +55,7 @@ const { values } = parseArgs({ async function main() { for (const [what, rel] of [ ["bundled worker (run `just conformance-ct::run-deltic-browser`)", WORKER_URL], - [`translator asset (run fetch-translator.ts)`, `/target/deltic/${TAG}/deltic-translator-shim.wasm`], + [`translator asset (run \`just conformance-ct::run-deltic-browser\`)`, TRANSLATOR_URL], ["suite component (run `just conformance-ct::build-suite`)", "/target/wasm32-wasip2/release/conformance_guest_ct.wasm"], ]) { try { @@ -83,7 +81,7 @@ async function main() { { suite: "conformance-guest-ct", target: values.target, - translatorUrl: `/target/deltic/${TAG}/deltic-translator-shim.wasm`, + translatorUrl: TRANSLATOR_URL, suiteUrl: "/target/wasm32-wasip2/release/conformance_guest_ct.wasm", missing: [], caseTimeoutMs: CASE_TIMEOUT_MS, diff --git a/conformance/driver-ct/deltic/run.ts b/conformance/driver-ct/deltic/run.ts index 1b9a3fb..c4e7009 100644 --- a/conformance/driver-ct/deltic/run.ts +++ b/conformance/driver-ct/deltic/run.ts @@ -19,7 +19,7 @@ // exports run on the callback ABI under stock Deno. // // just conformance-ct::run-deltic # the full leg -// … run.ts --translator [--only SUBSTRING] [--jspi] +// … run.ts [--translator ] [--only SUBSTRING] [--jspi] // // `DENO_CERT` must name the suite's committed test CA so the three // `websocket/tls/*` cases can complete their handshake; the @@ -30,8 +30,13 @@ // MODULE-IDENTITY CONSTRAINT: deltic's wasi-shims module imports // `@deltic/runtime/embedder` by bare specifier internally; this leg's // `deno.json` AND `js/deltic/deno.json` must map that specifier to the -// IDENTICAL pinned URL, or the embedder module loads twice and -// `instanceof WitError` stops holding across the module boundary. +// IDENTICAL exact-pinned JSR version, or the embedder module loads twice +// and `instanceof WitError` stops holding across the module boundary. +// +// The translator comes from the packaged `@deltic/translator` JSR +// prerelease (defaultTranslator()) by default — no fetch step, no +// sha256 bookkeeping, no net grant; `--translator ` remains as an +// optional override for a locally-built translator shim. // // The suite artifact is the BARE suite — websocket still imported — so // the run actually exercises the host module; the sibling `composed/` @@ -40,6 +45,7 @@ import { Translator } from "@deltic/runtime/shim"; import type { ComponentArtifacts } from "@deltic/runtime/embedder"; +import { defaultTranslator } from "@deltic/translator"; import { runSuite } from "@deltic/ct-runner"; import { wasiShims } from "@deltic/wasi-shims"; import { configure, websocketImports } from "../../../js/deltic/websocket.ts"; @@ -170,8 +176,10 @@ async function ensureEchod(): Promise { ); } -async function loadArtifacts(translatorPath: string): Promise { - const translator = await Translator.create(await Deno.readFile(translatorPath)); +async function loadArtifacts(translatorPath?: string): Promise { + const translator = translatorPath + ? await Translator.create(await Deno.readFile(translatorPath)) + : await defaultTranslator(); const componentBytes = await Deno.readFile(SUITE_WASM); const { plan, adapters } = translator.translate(componentBytes); return { plan, componentBytes, adapters }; @@ -180,14 +188,6 @@ async function loadArtifacts(translatorPath: string): Promise; fetch the pinned release " + - "asset with `deno run ... conformance/driver-ct/deltic/fetch-translator.ts` " + - "(see that script for exact permissions).", - ); - } - if (Deno.env.get("DENO_CERT") === undefined) { console.error( `warning: DENO_CERT is unset — the suite's committed test PKI is not ` + diff --git a/conformance/driver-ct/justfile b/conformance/driver-ct/justfile index 8ffd166..d6e004f 100644 --- a/conformance/driver-ct/justfile +++ b/conformance/driver-ct/justfile @@ -131,27 +131,21 @@ run-composed: compose-suite build-driver build-echod --jsonl --jobs 4 --target composed > {{results}}/composed.jsonl # The deltic-native leg: runtime-linked under stock Deno, no transpile -# step. fetch-translator.ts owns the release-asset pin (TAG + -# TRANSLATOR_SHA256, cross-checked against both deno.json import maps); -# run.ts owns the suite run. Scoped permissions throughout, EXCEPT -# --allow-run: Deno refuses a *scoped* --allow-run outright whenever -# dynamic-linker vars (LD_LIBRARY_PATH etc.) sit in the ambient -# environment — they could redirect the allowed binary, and no -# --allow-env grant lifts the refusal (verified on Deno 2.9.5). Ambient -# LD_LIBRARY_PATH is common on dev machines and run.ts is in-repo -# trusted code, so --allow-run stays unscoped; the spawn target is -# still just the echod binary. DENO_CERT provisions trust for the +# step. The translator comes from the packaged `@deltic/translator` JSR +# prerelease through the module graph — no fetch step, no sha256 +# bookkeeping, no net grant. run.ts owns the suite run. Scoped +# permissions throughout, EXCEPT --allow-run: Deno refuses a *scoped* +# --allow-run outright whenever dynamic-linker vars (LD_LIBRARY_PATH +# etc.) sit in the ambient environment — they could redirect the allowed +# binary, and no --allow-env grant lifts the refusal (verified on Deno +# 2.9.5). Ambient LD_LIBRARY_PATH is common on dev machines and run.ts is +# in-repo trusted code, so --allow-run stays unscoped; the spawn target +# is still just the echod binary. DENO_CERT provisions trust for the # suite's committed test PKI, the Deno analogue of the NODE_EXTRA_CA_CERTS # the retired jco Node leg carried (see git history). run-deltic: build-suite build-echod #!/usr/bin/env bash set -euo pipefail - shim=$(deno run \ - --config {{root}}/conformance/driver-ct/deltic/deno.json --frozen \ - --allow-read={{root}} \ - --allow-write={{root}}/target/deltic \ - --allow-net=github.com,objects.githubusercontent.com,release-assets.githubusercontent.com \ - {{root}}/conformance/driver-ct/deltic/fetch-translator.ts) mkdir -p {{results}} DENO_CERT={{root}}/conformance/server/tls/ca.pem {{timeout_cmd}} deno run \ --config {{root}}/conformance/driver-ct/deltic/deno.json --frozen \ @@ -161,7 +155,7 @@ run-deltic: build-suite build-echod --allow-run \ --allow-env=DENO_CERT \ {{root}}/conformance/driver-ct/deltic/run.ts \ - --translator "$shim" --out {{results}}/deltic-deno.jsonl --target deltic-deno + --out {{results}}/deltic-deno.jsonl --target deltic-deno # The deltic browser driver's npm tree (the upstream page driver + # worker message loop + playwright-core; no transpiler). @@ -177,16 +171,12 @@ _deltic-browser-prepared: # host module: the worker is one deno-bundled module (engine + host # module + message loop; browser/worker-entry.ts), so no transpile step # and no generated tree. -run-deltic-browser: build-suite build-echod _deltic-browser-prepared +run-deltic-browser: build-suite build-echod _deltic-browser-prepared (extract-deltic-translator root / "target/deltic-browser") #!/usr/bin/env bash set -euo pipefail cd {{root}}/conformance/driver-ct/deltic - deno run --config deno.json --frozen \ - --allow-read={{root}} --allow-write={{root}}/target/deltic \ - --allow-net=github.com,objects.githubusercontent.com,release-assets.githubusercontent.com \ - fetch-translator.ts >/dev/null mkdir -p {{root}}/target/deltic-browser - deno bundle --config deno.json --platform browser \ + deno bundle --config deno.json --frozen --platform browser \ -o {{root}}/target/deltic-browser/websocket-worker.mjs browser/worker-entry.ts mkdir -p {{results}} {{timeout_cmd}} node run-browser.mjs diff --git a/examples/deltic-demo/run.ts b/examples/deltic-demo/run.ts index e789e80..7519c38 100644 --- a/examples/deltic-demo/run.ts +++ b/examples/deltic-demo/run.ts @@ -10,18 +10,20 @@ // component and drove the same `demo.run(url, count)` export. // // just demo::deltic [count] -// … run.ts --translator [count] +// … run.ts [--translator ] [count] // // The deltic pin is SINGLE-SITE: this runner resolves `@deltic/*` through -// conformance/driver-ct/deltic/deno.json and takes the translator asset -// from conformance/driver-ct/deltic/fetch-translator.ts (the justfile -// recipe fetches it and passes the cached path). The same import map is -// what keeps `instanceof WitError` holding across the host-module -// boundary (see that deno.json's MODULE-IDENTITY note). +// conformance/driver-ct/deltic/deno.json. The translator comes from the +// packaged `@deltic/translator` JSR prerelease by default (no fetch +// step); `--translator ` remains as an optional override for a +// locally-built translator shim. The same import map is what keeps +// `instanceof WitError` holding across the host-module boundary (see +// that deno.json's MODULE-IDENTITY note). import { Translator } from "@deltic/runtime/shim"; import type { ComponentArtifacts } from "@deltic/runtime/embedder"; import { instantiate, WitError } from "@deltic/runtime/embedder"; +import { defaultTranslator } from "@deltic/translator"; import { wasiShims } from "@deltic/wasi-shims"; import { websocketImports } from "../../js/deltic/websocket.ts"; @@ -94,8 +96,10 @@ async function spawnEchod(): Promise<{ base: string; shutdown: () => void }> { } } -async function loadArtifacts(translatorPath: string): Promise { - const translator = await Translator.create(await Deno.readFile(translatorPath)); +async function loadArtifacts(translatorPath?: string): Promise { + const translator = translatorPath + ? await Translator.create(await Deno.readFile(translatorPath)) + : await defaultTranslator(); const componentBytes = await Deno.readFile(DEMO_WASM); const { plan, adapters } = translator.translate(componentBytes); return { plan, componentBytes, adapters }; @@ -103,13 +107,6 @@ async function loadArtifacts(translatorPath: string): Promise; fetch the pinned release " + - "asset with `deno run ... conformance/driver-ct/deltic/fetch-translator.ts` " + - "(the `just demo::deltic` recipe does it for you).", - ); - } const artifacts = await loadArtifacts(cli.translator); const echod = await spawnEchod(); diff --git a/examples/justfile b/examples/justfile index ac096c1..7c33503 100644 --- a/examples/justfile +++ b/examples/justfile @@ -20,17 +20,12 @@ wasmtime count="100": component build-echod # Run the JS-host demo by hand: `just demo::deltic [count]` — the same # component runtime-linked under deltic on stock Deno against # js/deltic/websocket.ts, with no transpile step and no engine flag. The -# deltic pin is single-site: the import map and the translator asset both -# come from conformance/driver-ct/deltic/. +# translator comes from the packaged `@deltic/translator` JSR prerelease +# through the module graph — no fetch step. The deltic pin is single-site: +# the import map is conformance/driver-ct/deltic/deno.json. deltic count="100": component build-echod #!/usr/bin/env bash set -euo pipefail - shim=$(deno run \ - --config {{root}}/conformance/driver-ct/deltic/deno.json --frozen \ - --allow-read={{root}} \ - --allow-write={{root}}/target/deltic \ - --allow-net=github.com,objects.githubusercontent.com,release-assets.githubusercontent.com \ - {{root}}/conformance/driver-ct/deltic/fetch-translator.ts) # --allow-run is unscoped for the same reason run-deltic's is: Deno # refuses a scoped --allow-run whenever dynamic-linker vars sit in the # ambient environment (see the conformance-ct::run-deltic comment). @@ -39,7 +34,7 @@ deltic count="100": component build-echod --allow-read={{root}} \ --allow-net=127.0.0.1,localhost \ --allow-run \ - {{root}}/examples/deltic-demo/run.ts --translator "$shim" {{count}} + {{root}}/examples/deltic-demo/run.ts {{count}} [private] build-echod: diff --git a/js/componentize/wpt/justfile b/js/componentize/wpt/justfile index 1ef0160..7327e72 100644 --- a/js/componentize/wpt/justfile +++ b/js/componentize/wpt/justfile @@ -9,8 +9,10 @@ # (this directory) for the vendoring policy and architecture. # # The deltic pin is single-site: the carrier bundle resolves @deltic/* -# through conformance/driver-ct/deltic/deno.json and its translator asset -# comes from that directory's fetch-translator.ts. +# through conformance/driver-ct/deltic/deno.json (exact-pinned JSR +# prereleases; see that deno.json's MODULE-IDENTITY comment) and its +# translator asset is extracted from the packaged `@deltic/translator` +# JSR package's lock-pinned module cache (no fetch step). import '../../../justfile.shared.just' @@ -73,18 +75,14 @@ _artifacts: build-echod _carrier # The round trip's carrier: the pinned deltic translator asset, plus the # one bundle that carries the engine, the host module, and the reporter # instance the runner's import is wired to (deltic-carrier.ts's header -# explains why one bundle is the sound shape). Both the fetch and the +# explains why one bundle is the sound shape). Both the extraction and the # bundle run out of conformance/driver-ct/deltic — the single deltic pin # site — mirroring conformance-ct::run-deltic-browser. [private] -_carrier: +_carrier: (extract-deltic-translator root / "target/deltic-browser") #!/usr/bin/env bash set -euo pipefail cd '{{root}}/conformance/driver-ct/deltic' - deno run --config deno.json --frozen \ - --allow-read={{root}} --allow-write={{root}}/target/deltic \ - --allow-net=github.com,objects.githubusercontent.com,release-assets.githubusercontent.com \ - fetch-translator.ts >/dev/null mkdir -p {{root}}/js/componentize/wpt/parity/build deno bundle --config deno.json --frozen --platform browser \ -o {{root}}/js/componentize/wpt/parity/build/deltic-carrier.mjs \ diff --git a/js/componentize/wpt/parity/deltic-carrier.ts b/js/componentize/wpt/parity/deltic-carrier.ts index 9467141..c330915 100644 --- a/js/componentize/wpt/parity/deltic-carrier.ts +++ b/js/componentize/wpt/parity/deltic-carrier.ts @@ -19,11 +19,13 @@ // legs.mjs must not import `../reporter.js` itself. // // THE DELTIC PIN IS SINGLE-SITE: this module resolves `@deltic/*` through -// conformance/driver-ct/deltic/deno.json (the bundle recipe runs -// `deno bundle` from that directory) and the translator asset comes from -// that directory's fetch-translator.ts. Bundling from there is also what -// keeps `@deltic/runtime/embedder` a single module instance across this -// bundle and js/deltic/websocket.ts, so `instanceof WitError` holds. +// conformance/driver-ct/deltic/deno.json (exact-pinned JSR prereleases; +// the bundle recipe runs `deno bundle` from that directory) and the +// translator asset is extracted from the packaged `@deltic/translator` +// JSR package's lock-pinned module cache (no fetch step). Bundling from +// there is also what keeps `@deltic/runtime/embedder` a single module +// instance across this bundle and js/deltic/websocket.ts, so +// `instanceof WitError` holds. import { Translator } from "@deltic/runtime/shim"; import { instantiate } from "@deltic/runtime/embedder"; diff --git a/js/componentize/wpt/parity/roundtrip.mjs b/js/componentize/wpt/parity/roundtrip.mjs index f95a474..2535267 100644 --- a/js/componentize/wpt/parity/roundtrip.mjs +++ b/js/componentize/wpt/parity/roundtrip.mjs @@ -16,14 +16,9 @@ import { runRoundtrip } from "./legs.mjs"; const HERE = dirname(fileURLToPath(import.meta.url)); const REPO_ROOT = resolve(HERE, "..", "..", "..", ".."); -// Must agree with conformance/driver-ct/deltic/fetch-translator.ts's TAG -// (the single pin site; the asset is served out of its cache directory), -// exactly as conformance/driver-ct/deltic/run-browser.mjs pins it. -const TAG = "pre-58b2404"; - const carrier = { url: pathToFileURL(join(HERE, "build", "deltic-carrier.mjs")).href, - translatorPath: `target/deltic/${TAG}/deltic-translator-shim.wasm`, + translatorPath: "target/deltic-browser/deltic-translator-shim.wasm", componentPath: "js/componentize/wpt/build/parity-runner.component.wasm", async loadBytes(path) { return new Uint8Array(await readFile(join(REPO_ROOT, path))); diff --git a/js/componentize/wpt/parity/run-browser.mjs b/js/componentize/wpt/parity/run-browser.mjs index b5ba4eb..76f09cd 100644 --- a/js/componentize/wpt/parity/run-browser.mjs +++ b/js/componentize/wpt/parity/run-browser.mjs @@ -11,8 +11,8 @@ // vendored group modules) resolve with no bundling and the same URL // identity legs.mjs relies on; the carrier itself is one bundle // (parity/build/deltic-carrier.mjs) and the two wasm artifacts it needs — -// the pinned deltic translator under /target/deltic/ and the parity -// runner component — are fetched from the same server. The page opens +// the pinned deltic translator under /target/deltic-browser/ and the +// parity runner component — are fetched from the same server. The page opens // `ws:` connections to the echo server directly: WebSocket is not subject // to CORS, and a localhost `http:` page may open `ws:` connections. // @@ -38,10 +38,6 @@ import { spawnEchod } from "../../../../conformance/server/echod.mjs"; const HERE = dirname(fileURLToPath(import.meta.url)); const REPO_ROOT = resolve(HERE, "..", "..", "..", ".."); const update = process.argv.includes("--update"); -// Must agree with conformance/driver-ct/deltic/fetch-translator.ts's TAG -// (the single pin site), as roundtrip.mjs does. -const TAG = "pre-58b2404"; - const MIME = { ".js": "text/javascript", ".mjs": "text/javascript", @@ -53,7 +49,7 @@ const MIME = { // The subtrees a page may read: the WPT gate's own tree (harness, groups, // reporter, parity modules, the carrier bundle and the runner component) // and the pinned deltic translator asset the carrier translates with. -const SERVED_PREFIXES = ["/js/componentize/wpt/", "/target/deltic/"]; +const SERVED_PREFIXES = ["/js/componentize/wpt/", "/target/deltic-browser/"]; /** Serve the repository layout, read-only, under SERVED_PREFIXES. */ function startServer() { @@ -95,12 +91,12 @@ function startServer() { * One leg, inside the browser page: import the shared leg bodies over * HTTP and run one of them. Serialized via `page.evaluate`. */ -async function runLegInPage({ base, wsBase, leg, tag }) { +async function runLegInPage({ base, wsBase, leg }) { const legs = await import(`${base}/js/componentize/wpt/parity/legs.mjs`); if (leg === "baseline") return legs.runBaseline(wsBase); const carrier = { url: `${base}/js/componentize/wpt/parity/build/deltic-carrier.mjs`, - translatorPath: `target/deltic/${tag}/deltic-translator-shim.wasm`, + translatorPath: "target/deltic-browser/deltic-translator-shim.wasm", componentPath: "js/componentize/wpt/build/parity-runner.component.wasm", async loadBytes(path) { const resp = await fetch(`${base}/${path}`); @@ -115,7 +111,7 @@ async function main() { for (const [what, rel] of [ ["carrier bundle (run `just wpt::parity-chromium`)", "js/componentize/wpt/parity/build/deltic-carrier.mjs"], ["parity runner component (run `js/componentize/wpt/component.sh build`)", "js/componentize/wpt/build/parity-runner.component.wasm"], - ["translator asset (run conformance/driver-ct/deltic/fetch-translator.ts)", `target/deltic/${TAG}/deltic-translator-shim.wasm`], + ["translator asset (run `just wpt::parity-chromium`)", "target/deltic-browser/deltic-translator-shim.wasm"], ]) { try { await access(join(REPO_ROOT, rel)); @@ -144,7 +140,7 @@ async function main() { page.on("console", (msg) => process.stderr.write(`[browser] ${msg.text()}\n`)); page.on("pageerror", (err) => console.error(`[browser error] ${err.stack ?? err.message}`)); await page.goto(`${base}/`); - records[leg] = await page.evaluate(runLegInPage, { base, wsBase: echod.base, leg, tag: TAG }); + records[leg] = await page.evaluate(runLegInPage, { base, wsBase: echod.base, leg }); await page.close(); } } finally { diff --git a/js/componentize/wpt/parity/smoke-run.mjs b/js/componentize/wpt/parity/smoke-run.mjs index b15be86..ea39c45 100644 --- a/js/componentize/wpt/parity/smoke-run.mjs +++ b/js/componentize/wpt/parity/smoke-run.mjs @@ -11,10 +11,6 @@ import { spawnEchod } from "../../../../conformance/server/echod.mjs"; const HERE = dirname(fileURLToPath(import.meta.url)); const REPO_ROOT = resolve(HERE, "..", "..", "..", ".."); -// Must agree with conformance/driver-ct/deltic/fetch-translator.ts's TAG -// (the single pin site), as roundtrip.mjs does. -const TAG = "pre-58b2404"; - const loadBytes = async (path) => new Uint8Array(await readFile(join(REPO_ROOT, path))); const { setSink, instantiateRunner } = await import( @@ -23,7 +19,7 @@ const { setSink, instantiateRunner } = await import( setSink((record) => console.error("[smoke]", JSON.parse(record).name)); const [translatorBytes, componentBytes] = await Promise.all([ - loadBytes(`target/deltic/${TAG}/deltic-translator-shim.wasm`), + loadBytes("target/deltic-browser/deltic-translator-shim.wasm"), loadBytes("js/componentize/wpt/build/smoke.component.wasm"), ]); const runner = await instantiateRunner(translatorBytes, componentBytes); diff --git a/js/deltic/deno.json b/js/deltic/deno.json index 2faaba8..beebfda 100644 --- a/js/deltic/deno.json +++ b/js/deltic/deno.json @@ -2,10 +2,11 @@ "name": "@polymorph/websocket-deltic", "version": "0.0.0", "exports": "./websocket.ts", - "//": "MODULE-IDENTITY CONSTRAINT: deltic's wasi-shims module imports @deltic/runtime/embedder by bare specifier internally. Every config in this repo (this file AND conformance/driver-ct/deltic/deno.json) must map that specifier to the IDENTICAL URL, or the embedder module loads twice and `instanceof WitError` stops holding across the module boundary.", + "//": "MODULE-IDENTITY CONSTRAINT: deltic's wasi-shims module imports @deltic/runtime/embedder by bare specifier internally. Every config in this repo (this file AND conformance/driver-ct/deltic/deno.json) must map @deltic/runtime to the IDENTICAL exact-pinned JSR version, or the embedder module loads twice and `instanceof WitError` stops holding across the module boundary. Pin story: 0.1.0-pre.ga67ee83 names one upstream deltic commit; @deltic/translator ships the translator wasm for that SAME commit; deno.lock carries integrity, --frozen enforced everywhere; one version repo-wide is asserted by the pin gate (justfile: exam-deltic).", "imports": { - "@deltic/runtime/embedder": "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/embedder/mod.ts" + "@deltic/runtime/embedder": "jsr:@deltic/runtime@0.1.0-pre.ga67ee83/embedder" }, + "minimumDependencyAge": { "age": "P1D", "exclude": ["jsr:@deltic/*"] }, "compilerOptions": { "lib": ["dom", "dom.iterable", "dom.asynciterable", "deno.ns"] }, diff --git a/js/deltic/deno.lock b/js/deltic/deno.lock index c1d8827..f9adb89 100644 --- a/js/deltic/deno.lock +++ b/js/deltic/deno.lock @@ -1,10 +1,14 @@ { "version": "5", "specifiers": { + "jsr:@deltic/runtime@0.1.0-pre.ga67ee83": "0.1.0-pre.ga67ee83", "jsr:@std/assert@1": "1.0.19", "jsr:@std/internal@^1.0.12": "1.0.14" }, "jsr": { + "@deltic/runtime@0.1.0-pre.ga67ee83": { + "integrity": "2a2b0949031747a2340dc186299e654ea9f361ae39ac6bd633019940682db4ed" + }, "@std/assert@1.0.19": { "integrity": "eaada96ee120cb980bc47e040f82814d786fe8162ecc53c91d8df60b8755991e", "dependencies": [ @@ -15,54 +19,9 @@ "integrity": "291516b3d4c35024d6ffbc0a9df5bf4c64116e05b50012cf846710152d2ffdf7" } }, - "remote": { - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/cabi/async_values.ts": "af1279d4e4db5b756268979aeff5b27c1cf6c0f021213655676ade90472f282b", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/cabi/context.ts": "b4b60891ef9d9e72b208636f6ba37f0b9b6962d307af6156ad3b5ad59a626902", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/cabi/flatten.ts": "6c980fe38d7adce349d5e028b819eb0ffbb92714f958c1d5daae8da3e7ed3889", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/cabi/float.ts": "0483e8c1aa8786eee4c6f6357fee6738555e4310650c474aba6cd811a80d7d36", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/cabi/handles.ts": "30510750261499f48a812bb8c349a8f88a3bb7239175e6f1d4e6d10c38571e5d", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/cabi/layout.ts": "8122141b39f4d8189c13d91fc1b37825ceead86988f879f3fa9351bbef96f8f2", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/cabi/lift.ts": "e4475a44a5618114f288025601b535bc04b97e9a37b3be21f51d3be092d419c8", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/cabi/load.ts": "c1d8ddb1b3b3c59afe30710a97ad6dd7ae1ecd59aa1d427a5eaf4552d3b1ea01", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/cabi/lower.ts": "916ef7476dc583783770f4c42de7a655350531b3763c81a92249cca96f5e4d80", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/cabi/memory.ts": "09728360d6413fb30a5a7bff1ba6abec1ac6474ff150d45f093b8ebe5e65cd51", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/cabi/mod.ts": "b79cf9e2bab2e837fee76fa61dc18bff66d941e08597f1b76de93811bd6d6008", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/cabi/store.ts": "97aaecfeb4dfbf5c3c132fb5eadf1f5677924936eee0c7fa75a266a00cd73634", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/cabi/strings.ts": "9589dda3857725792ae15ef6888449b48e973b9eb0f3058ed64e10bf4d39b793", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/cabi/trap.ts": "307d8b48806eeba30400b3d7db9370cee70a12298851c1c19053dd8ca0013e1c", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/cabi/types.ts": "d0392e8cdf2990a76c8a1f9b85795d3b7c19b8eb006c2b159b671d08c39b9535", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/cabi/values.ts": "9e6ddcc4192d05897b2cbea250db3fef0ad9bf6548ba87aff378ee14b7ab7022", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/embedder/casing.ts": "1e9083becfc08107c09015ce3db79c304b05c40085a3c899ea1c8ebe25fcd45f", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/embedder/errors.ts": "b0cac244526b92c052d165f2aee1d9492e5915a5a4cad114e1ab575ffe1587ba", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/embedder/imports.ts": "98cca003e4a1131c35854c91b458f109d6761a3e8f67c23730f7e9bc28bbad88", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/embedder/instantiate.ts": "ef330d0a8562932e38d3a8a38a155bbd66ddb9c5d1025a1d39b5ce567817f334", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/embedder/mod.ts": "0a4f42b8c569b528b4c3172c3394ad5f9ddafa33bcaf5eccd00e645e111da2b1", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/embedder/resources.ts": "d209e5f13545b9c0c095ac4e188b72370d97c9bd394ba7c8793ddd74f436b1ef", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/embedder/streams.ts": "4ef894a43da94b4cb01ee65798a108a8fb3f6b2dc6013c71881f63e0806df565", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/embedder/values.ts": "ed876f9103f4a4f34e8eb475934091156bee1447f5a029ea300644b8f3ee71eb", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/embedder/version.ts": "b1c589988e5fb88dce3a014846c9253399e286f12afb5fd92509c8d6090ad4bb", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/exec/boundary.ts": "1b4b7d6394a79b4048fb932219ea9420c6461106c30d1bd70b29b09e16cad20d", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/exec/executor.ts": "267a6e5542e0fef3a930a3e2242aa58c3c83aa25b174c7533a07b70960f74e5d", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/exec/host_streams.ts": "63f6b113806c401ae9895df82448da70a7745a97b6e2f04061fb5bc64e7d0acf", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/exec/mod.ts": "a46320977ece14342bcb72c9c9e36d65a1cd09d789591d0909d7d1185264010b", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/intrinsics/async_builtins.ts": "526795358da8908d54a483bb47eebc43e0a1ea59e69ece94d0c6890ad0fa8784", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/intrinsics/context.ts": "be93b23d127ff71d5c372781f89d1c3746c5d32a44e67ebbcd91f2b0f0807e93", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/intrinsics/errors.ts": "9d09fc1818b4dc98b238aa69008a9110d9d305b6a8e806604f3bd48fca1eebcb", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/intrinsics/fact_calls.ts": "aa0b0aef81b59cdcd8dc572c20e1f57a8f5592f75a0d5d666032851df9201229", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/intrinsics/mod.ts": "f9c095e561f5fbb51f70693b21f272f66241f2e8ff2e1a83cd4176bcd0104eb9", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/intrinsics/stream_builtins.ts": "bbc1e1ea0e4616026a46d790a68695aa70589a88b08a6275acdb525f0ab531ec", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/intrinsics/transcode.ts": "e3fcaeb7a60b6cbad999d9389d4bce59e305e6f54e035ba791f909e10d1f82c7", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/jspi/bridge.ts": "7cf3706d3bf34b503aea516a31918a8d930aba3dac7e94ec04caecd23fe6025e", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/jspi/mechanics.ts": "dc0fe4965b3ef8c0aff6674afd8bae2a38942ab934fa07fd2eb7db72b2462f17", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/jspi/mod.ts": "4d047b820b50c410ed946c62dc48286f8abe4787ce6ae5466cd0ae255d98943c", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/jspi/types.ts": "86929224733a764a148ac75a9d6b95d61ab4c8123a48fe956d998e97726a1432", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/plan/format.ts": "90e31bbc7137c2f80c0782e1431afb6f81827aab8d38dba1178b8761f1b3ea0a", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/plan/loader.ts": "107db77e724a7f74f161a5fd20e7110a6e6f182c46f18282eba650bc887dc876", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/task/mod.ts": "5decca8045dfd9743910e83d512258a7be3b0d0917954b8d9cdbac38e03f7dfb", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/task/scheduler.ts": "18a4404f620407bd867876115861ee0cf98f6f1ccd41c5f3c877ef90e429ef9c", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/task/streams.ts": "83b522a6393ba06fbdb87881bc6761f3fce9c03b85e9eda03d3befe7d2605a60", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/task/subtask.ts": "750b13a1318f62836bfd149f1b9144de5b017fd7a84adc8e2fb2151e63130fbc", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/task/thread.ts": "81fe38b37a1ec130803b478a24e428b19ee4e1ef8c0bae741395cd8d52751580", - "https://raw.githubusercontent.com/lann/deltic/pre-58b2404/runtime/src/task/waitable.ts": "5e1fc092e3d8f1fb4429d6a91d8886b3e474aa9ac6254e7924fd896c4929e1f9" + "workspace": { + "dependencies": [ + "jsr:@deltic/runtime@0.1.0-pre.ga67ee83" + ] } } diff --git a/justfile b/justfile index cccc491..a7edb11 100644 --- a/justfile +++ b/justfile @@ -68,3 +68,18 @@ test: # leg itself is `conformance-ct::run-deltic`. deltic-module-check: cd js/deltic && deno task check && deno task test + +# The one-version-everywhere gate: every `jsr:@deltic/*` import across +# BOTH deno.json files that carry deltic imports must agree on the exact +# same pinned version (the retired release-asset pin gate, generalized to +# every package, not just the runtime/embedder URL). +exam-deltic: + #!/usr/bin/env bash + set -euo pipefail + v=$(grep -ho 'jsr:@deltic/[a-z-]*@[^/"]*' js/deltic/deno.json conformance/driver-ct/deltic/deno.json \ + | sed 's/.*@//' | sort -u) + if [ "$(printf '%s\n' "$v" | wc -l)" != 1 ]; then + echo "deltic pin drift: $v" >&2 + exit 1 + fi + echo "deltic pin: $v" diff --git a/justfile.shared.just b/justfile.shared.just index 57047f0..1a723f1 100644 --- a/justfile.shared.just +++ b/justfile.shared.just @@ -22,3 +22,23 @@ build-component crate: {{root}}/target/wasm32-unknown-unknown/release/{{replace(crate, "-", "_")}}.wasm \ -o {{root}}/target/components/{{crate}}.wasm.tmp mv -f {{root}}/target/components/{{crate}}.wasm.tmp {{root}}/target/components/{{crate}}.wasm + +# Extract the deltic translator wasm from the pinned `@deltic/translator` +# JSR package's lock-pinned module cache into `out_dir` — no network, no +# sha256 bookkeeping (the JSR package's integrity lives in +# conformance/driver-ct/deltic/deno.lock, enforced by --frozen). Every +# browser leg that used to fetch a sha-pinned release asset now runs this +# instead. Resolves against conformance/driver-ct/deltic's import map (the +# single deltic pin site); asserts every module in the translator's graph +# resolves to the one pinned version before copying. +[private] +extract-deltic-translator out_dir: + #!/usr/bin/env bash + set -euo pipefail + mkdir -p {{out_dir}} + info=$(mktemp) + trap 'rm -f "$info"' EXIT + deno info --json --config {{root}}/conformance/driver-ct/deltic/deno.json --frozen \ + @deltic/translator > "$info" + pin=$(grep -o 'jsr:@deltic/runtime@[^/"]*' {{root}}/conformance/driver-ct/deltic/deno.json | head -1 | sed 's/.*@//') + python3 "{{root}}/scripts/extract-deltic-translator.py" "$info" {{out_dir}} "$pin" diff --git a/scripts/extract-deltic-translator.py b/scripts/extract-deltic-translator.py new file mode 100755 index 0000000..110b519 --- /dev/null +++ b/scripts/extract-deltic-translator.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +"""Extract the deltic translator wasm from a `deno info --json` graph. + +Used by justfile.shared.just's extract-deltic-translator recipe: every +browser leg that used to fetch a sha256-pinned GitHub release asset now +copies the translator wasm straight out of the `@deltic/translator` JSR +package's lock-pinned module cache instead (no network, no sha +bookkeeping — the package's integrity lives in +conformance/driver-ct/deltic/deno.lock, enforced by --frozen). + +Usage: extract-deltic-translator.py +""" +import json +import sys + + +def main() -> None: + info_path, out_dir, pin = sys.argv[1], sys.argv[2], sys.argv[3] + graph = json.load(open(info_path)) + mods = [m for m in graph["modules"] if "/@deltic/" in m.get("specifier", "")] + bad = {m["specifier"] for m in mods if pin not in m["specifier"]} + if bad: + sys.exit(f"pin drift in translator graph (expected {pin}): {bad}") + asset = next(m for m in mods if m["specifier"].endswith("/translator_shim.wasm")) + # Deno's on-disk remote cache appends a `// denoCacheMetadata={...}` + # trailer after the module body (observed empirically: the cached + # file is larger than the graph's reported `size`, and the trailer is + # plain text appended after the wasm bytes) — truncate to the + # authoritative size the graph reports before copying, or the + # trailer corrupts the wasm module (`WebAssembly.compile` fails with + # "unexpected section" near EOF). + with open(asset["local"], "rb") as f: + data = f.read(asset["size"]) + with open(out_dir + "/deltic-translator-shim.wasm", "wb") as f: + f.write(data) + + +if __name__ == "__main__": + main()