Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions js/runner-polyengine/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,12 @@ repo bundles one worker entry — the polyengine engine surface, the message
loop, and its own host module, resolved through one import map — and
passes `workerMain({ polyengine, suiteImports })` its inlined engine and an
import-record factory. One bundle means one embedder module instance,
which is what keeps `instanceof ComponentException` true across the host-module
boundary; workers resolve no import maps, so this is the only sound
shape. The stock `browser-worker.mjs` is `workerMain()` with the
which is what keeps stateful handles (streams, futures) minted through it
usable across the host-module boundary — `@polyengine/protocol`'s errors
and brand checks (e.g. `isComponentException`) are cross-copy safe by
construction (its own stable version line), but the embedder's runtime
machinery is not; workers resolve no import maps, so this is the only
sound shape. The stock `browser-worker.mjs` is `workerMain()` with the
bundleUrl-loading defaults.

## Pinning
Expand All @@ -72,9 +75,13 @@ bump is one diff. Between releases every green polyengine `main` commit
also publishes `<next>-pre.g<shorthash>` prereleases (unordered hash
versions — pin exactly) for when a not-yet-released commit is needed.

- `deno.json` — the import map holds the five `jsr:@polyengine/...@<version>`
specifiers. `@polyengine/runtime/embedder` is mapped because
`@polyengine/wasi` imports it by bare specifier.
- `deno.json` — the import map holds the five lockstep
`jsr:@polyengine/{ct-runner,runtime/embedder,runtime/shim,translator,wasi}@<version>`
specifiers plus a sixth, independently-versioned `@polyengine/protocol`
pin. `@polyengine/runtime/embedder` is mapped because
`browser-bundle-entry.ts` (and downstream bundled-worker consumers)
import it directly — as of upstream A22, `@polyengine/wasi` itself is
protocol-only internally, so this mapping is no longer for wasi's sake.
`minimumDependencyAge` exempts the `@polyengine` scope so same-day
publishes resolve (Deno >= 2.9 for the wildcard exclude).
- `deno.lock` — carries JSR package integrity for that graph and is
Expand Down
10 changes: 10 additions & 0 deletions js/runner-polyengine/browser-bundle-entry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@
// (`just polyengine-assets` builds it; verify-polyengine/viewer-build consume it.)

export * from "@polyengine/runtime/embedder";
// A22: @polyengine/runtime@0.5.0's embedder dropped its A9 courtesy
// re-exports (error classes/predicates, brands, handle classes, suspending,
// realm crossing, copy registry) — that vocabulary now lives only in
// @polyengine/protocol. worker-main.mjs's and README.md's "Browser leg"
// section document downstream bundled workers relying on `ComponentException`
// (and, by the same contract, the rest of the vocabulary) being reachable
// off this bundle's exports alongside the embedder machinery, so it is
// re-exported here too. No name collisions: the embedder no longer exports
// these names (contracts/embedder-api.md A22; brief rule 5).
export * from "@polyengine/protocol";
export { Translator } from "@polyengine/runtime/shim";
export * from "@polyengine/ct-runner";
export { wasi } from "@polyengine/wasi";
Expand Down
32 changes: 22 additions & 10 deletions js/runner-polyengine/deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,35 @@
// packages must carry the SAME version — `just verify-polyengine`'s pin
// gate asserts that repo-wide.
//
// `@polyengine/runtime/embedder` is mapped because `@polyengine/wasi`
// imports it by bare specifier. `@polyengine/translator` ships the translator
// `@polyengine/runtime/embedder` is mapped because `browser-bundle-entry.ts`
// (and this runner leg's downstream bundled-worker consumers) import it
// directly for the embedder machinery it still carries post-A22 (the wasi
// module itself is protocol-only internally as of 0.5.0, so this mapping
// no longer exists for wasi's sake — see contracts/embedder-api.md A22).
// Applications that load the embedder in more than one config must still
// resolve ONE runtime version: stateful handles minted by one copy are
// refused by another. Published host modules couple only to
// `@polyengine/protocol`, whose copies are harmless by construction (its
// own independent version line, see polyengine-pin-gate's CONTRACT note).
// `@polyengine/translator` ships the translator
// wasm built from the same commit: the Deno leg loads it through the
// module graph (`defaultTranslator()`, permission-free) and the browser
// leg extracts it from the lock-pinned module cache — no release-asset
// fetch, no sha bookkeeping. `deno.lock` carries JSR package integrity
// and is enforced with `--frozen` everywhere.
//
// Bumping: change the version in these five specifiers, delete deno.lock,
// re-run `deno install --entrypoint runner.ts browser-bundle-entry.ts` in
// this directory, and commit the diff (see README.md "Pinning").
// Bumping: change the version in these five lockstep specifiers, delete
// deno.lock, re-run `deno install --entrypoint runner.ts
// browser-bundle-entry.ts` in this directory, and commit the diff (see
// README.md "Pinning"). `@polyengine/protocol` is on its own independent
// version line (currently 0.2.2) and is bumped separately.
"imports": {
"@polyengine/ct-runner": "jsr:@polyengine/ct-runner@0.4.0",
"@polyengine/runtime/embedder": "jsr:@polyengine/runtime@0.4.0/embedder",
"@polyengine/runtime/shim": "jsr:@polyengine/runtime@0.4.0/shim",
"@polyengine/translator": "jsr:@polyengine/translator@0.4.0",
"@polyengine/wasi": "jsr:@polyengine/wasi@0.4.0"
"@polyengine/ct-runner": "jsr:@polyengine/ct-runner@0.5.0",
"@polyengine/protocol": "jsr:@polyengine/protocol@0.2.2",
"@polyengine/runtime/embedder": "jsr:@polyengine/runtime@0.5.0/embedder",
"@polyengine/runtime/shim": "jsr:@polyengine/runtime@0.5.0/shim",
"@polyengine/translator": "jsr:@polyengine/translator@0.5.0",
"@polyengine/wasi": "jsr:@polyengine/wasi@0.5.0"
},
// Deno's supply-chain minimum-dependency-age gate (24h default) applies
// even to exact prerelease pins; polyengine publishes per commit, so the
Expand Down
52 changes: 27 additions & 25 deletions js/runner-polyengine/deno.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion js/runner-polyengine/engine.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
* @param {object} [input.hostImports] SUT host-import record fragments
* (interface id -> implementation), merged over the engine's wasi +
* test-context imports. MUST be built against the same embedder module
* instance as `bundle` (one ComponentException class; see worker-main.mjs).
* instance as `bundle` (one runtime copy for handle interop; see
* worker-main.mjs — `@polyengine/protocol` vocabulary like
* ComponentException is cross-copy safe by construction).
* @returns {Promise<{newTests: () => Promise<object>, Context, tagsOf}>}
*/
export async function loadSuite(
Expand Down
6 changes: 3 additions & 3 deletions js/runner-polyengine/worker-main.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
// (`polymorph:websocket/connections`, `polymorph:webcrypto/*`, …) that
// the stock worker cannot supply: workers resolve no import maps, so the
// host module and the polyengine engine must arrive in ONE bundle or the
// embedder module loads twice and `instanceof ComponentException` stops
// holding across the boundary. The downstream pattern is a bundled worker
// entry:
// embedder module loads twice and stateful handles (streams, futures)
// minted through one copy are refused by the other. The downstream pattern
// is a bundled worker entry:
//
// // worker-entry.ts — deno bundle --platform browser
// import * as polyengine from "./browser-bundle-entry.ts"; // jsr:@polyengine/*
Expand Down
6 changes: 5 additions & 1 deletion justfile
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,11 @@ polyengine-pin-gate:
#!/usr/bin/env bash
set -euo pipefail
configs=(js/runner-polyengine/deno.json)
v=$(grep -ho 'jsr:@polyengine/[a-z-]*@[^/"]*' "${configs[@]}" | sed 's/.*@//' | sort -u)
# A22: @polyengine/protocol is a second, independently-versioned line
# (repo-internal configs may exact-pin it too now) — exclude it from the
# lockstep-version extraction the same way it's excluded below against
# the lock, so pinning it in deno.json doesn't read as drift.
v=$(grep -ho 'jsr:@polyengine/[a-z-]*@[^/"]*' "${configs[@]}" | grep -v '^jsr:@polyengine/protocol@' | sed 's/.*@//' | sort -u)
test -n "$v" || { echo "polyengine pin gate: no jsr:@polyengine specifiers found" >&2; exit 1; }
[ "$(printf '%s\n' "$v" | wc -l)" = 1 ] || { echo "polyengine pin drift: $v" >&2; exit 1; }
python3 - "$v" js/runner-polyengine/deno.lock <<'PY'
Expand Down
Loading