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
2 changes: 1 addition & 1 deletion conformance/driver-ct/deltic/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ that version in **two** places, cross-checked by
SAME `@deltic/runtime/embedder` version (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
module loads twice and `instanceof ComponentException` stops holding across the
boundary).

Both `deno.json` files also carry
Expand Down
2 changes: 1 addition & 1 deletion conformance/driver-ct/deltic/browser/worker-entry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// exact-pinned JSR import map), 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`
// embedder module instance — which is what keeps `instanceof ComponentException`
// 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).
Expand Down
12 changes: 6 additions & 6 deletions conformance/driver-ct/deltic/deno.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{
"//": "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. The hash names one upstream commit; deno.lock carries integrity, --frozen enforced; the pin gate (just conformance-ct::deltic-pin-check) asserts one @deltic version repo-wide.",
"//": "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 ComponentException` stops holding across the module boundary. The hash names one upstream commit; deno.lock carries integrity, --frozen enforced; the pin gate (just conformance-ct::deltic-pin-check) asserts one @deltic version repo-wide.",
"imports": {
"@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",
"@deltic/ct-runner": "jsr:@deltic/ct-runner@0.1.0-pre.g078aa15",
"@deltic/runtime/embedder": "jsr:@deltic/runtime@0.1.0-pre.g078aa15/embedder",
"@deltic/runtime/shim": "jsr:@deltic/runtime@0.1.0-pre.g078aa15/shim",
"@deltic/wasi-shims": "jsr:@deltic/wasi-shims@0.1.0-pre.g078aa15",
"@deltic/translator": "jsr:@deltic/translator@0.1.0-pre.g078aa15",
"@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/*"] },
Expand Down
48 changes: 28 additions & 20 deletions conformance/driver-ct/deltic/deno.lock

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

2 changes: 1 addition & 1 deletion conformance/driver-ct/deltic/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
// `@deltic/runtime/embedder` by bare specifier internally; this leg's
// `deno.json` AND `js/deltic/deno.json` must map that specifier to the
// IDENTICAL exact-pinned JSR version, or the embedder module loads twice
// and `instanceof WitError` stops holding across the module boundary.
// and `instanceof ComponentException` stops holding across the module boundary.
// `just conformance-ct::deltic-pin-check` gates that.

import { Translator } from "@deltic/runtime/shim";
Expand Down
4 changes: 2 additions & 2 deletions js/deltic/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
host — one platform-WebCrypto-backed implementation of every
`polymorph:webcrypto@0.1.0` interface — rewritten over deltic's embedder
API (typed `Stream<T>` rather than jco's bare-payload `Stream`, and
`WitError` throws rather than `throw { tag, val }`). It was developed as
`ComponentException` throws rather than `throw { tag, val }`). It was developed as
deltic's own `ports/webcrypto` reference-host port and is upstreamed here
per [lann/deltic#40](https://github.com/lann/deltic/pull/40); the WIT
contract is [`wit/`](../../wit), and every doc comment quoting a contract
Expand Down Expand Up @@ -43,7 +43,7 @@ pinned JSR version as
[`conformance/driver-ct/deltic/deno.json`](../../conformance/driver-ct/deltic/deno.json).
deltic's `wasi-shims` module imports that specifier by bare name
internally; if the two configs ever disagreed, the embedder module would
load twice and `instanceof WitError` would stop holding across the
load twice and `instanceof ComponentException` would stop holding across the
boundary. Keep both import maps' version identical for that one entry —
`just conformance-ct::deltic-pin-check` gates that.

Expand Down
4 changes: 2 additions & 2 deletions js/deltic/deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
"name": "@polymorph/webcrypto-deltic",
"version": "0.0.0",
"exports": "./src/mod.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 exact-pinned JSR version, or the embedder module loads twice and `instanceof WitError` stops holding across the module boundary. The hash names one upstream commit; deno.lock carries integrity, --frozen enforced; the pin gate (just conformance-ct::deltic-pin-check) asserts one @deltic version repo-wide.",
"//": "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 exact-pinned JSR version, or the embedder module loads twice and `instanceof ComponentException` stops holding across the module boundary. The hash names one upstream commit; deno.lock carries integrity, --frozen enforced; the pin gate (just conformance-ct::deltic-pin-check) asserts one @deltic version repo-wide.",
"imports": {
"@deltic/runtime/embedder": "jsr:@deltic/runtime@0.1.0-pre.ga67ee83/embedder"
"@deltic/runtime/embedder": "jsr:@deltic/runtime@0.1.0-pre.g078aa15/embedder"
},
"minimumDependencyAge": { "age": "P1D", "exclude": ["jsr:@deltic/*"] },
"tasks": {
Expand Down
15 changes: 11 additions & 4 deletions js/deltic/deno.lock

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

47 changes: 24 additions & 23 deletions js/deltic/src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//
// Governing docs:
// - contracts/embedder-api.md §"Error model" — host imports report a WIT
// `result<_, error>` err case by throwing `new WitError(payload)`; an
// `result<_, error>` err case by throwing `new ComponentException(payload)`; an
// UNBRANDED throw becomes a host-fatal trap. That is a deliberate
// inversion of jco's convention (any stray `TypeError` was fed to the
// lift), which is why the polymorph reference wraps every platform call
Expand All @@ -13,47 +13,48 @@
// mapping targets.
//
// `error` is a WIT variant; per the value-mapping table
// (contracts/embedder-api.md §"Value mapping", `variant` row) its payload
// shape is `{ tag, val? }` with `val` absent for payloadless cases.
// (contracts/embedder-api.md §"Value mapping", `variant` row; A10) its
// payload shape is `{ kind, value? }` with `value` absent for payloadless
// cases.

import { WitError } from "@deltic/runtime/embedder";
import { ComponentException } from "@deltic/runtime/embedder";

/** The `types.error` payload shape (the value-mapping table's variant row). */
export type WcErrorPayload =
| { tag: "invalid-key"; val: string }
| { tag: "invalid-nonce"; val: string }
| { tag: "authentication-failed" }
| { tag: "not-extractable" }
| { tag: "unsupported"; val: string }
| { tag: "not-permitted"; val: string }
| { tag: "other"; val: string }
| { tag: "extension"; val: { origin: string; name: string; message: string } };
| { kind: "invalid-key"; value: string }
| { kind: "invalid-nonce"; value: string }
| { kind: "authentication-failed" }
| { kind: "not-extractable" }
| { kind: "unsupported"; value: string }
| { kind: "not-permitted"; value: string }
| { kind: "other"; value: string }
| { kind: "extension"; value: { origin: string; name: string; message: string } };

/** Throw the branded `result<_, error>` err value for a WIT-declared case. */
export function witError(payload: WcErrorPayload): never {
throw new WitError(payload);
throw new ComponentException(payload);
}

export function errInvalidKey(detail: string): never {
return witError({ tag: "invalid-key", val: detail });
return witError({ kind: "invalid-key", value: detail });
}
export function errInvalidNonce(detail: string): never {
return witError({ tag: "invalid-nonce", val: detail });
return witError({ kind: "invalid-nonce", value: detail });
}
export function errAuthenticationFailed(): never {
return witError({ tag: "authentication-failed" });
return witError({ kind: "authentication-failed" });
}
export function errNotExtractable(): never {
return witError({ tag: "not-extractable" });
return witError({ kind: "not-extractable" });
}
export function errUnsupported(detail: string): never {
return witError({ tag: "unsupported", val: detail });
return witError({ kind: "unsupported", value: detail });
}
export function errNotPermitted(detail: string): never {
return witError({ tag: "not-permitted", val: detail });
return witError({ kind: "not-permitted", value: detail });
}
export function errOther(detail: string): never {
return witError({ tag: "other", val: detail });
return witError({ kind: "other", value: detail });
}

/** The refusal an operation renders on a usage-denied key (reference parity: js/jco/webcrypto.js:162-164). */
Expand All @@ -75,16 +76,16 @@ function asPlatformError(err: unknown): { name: string | undefined; detail: stri
* js/jco/webcrypto.js:251-262). `NotSupportedError` is the WIT's
* "well-formed request this implementation does not serve"
* (`error.unsupported`); everything else platform-thrown is operational
* (`error.other`). Anything already a `WitError` passes through unchanged.
* An exception that is neither a `WitError` nor DOMException-shaped is a
* (`error.other`). Anything already a `ComponentException` passes through unchanged.
* An exception that is neither a `ComponentException` nor DOMException-shaped is a
* host bug, not a taxonomy case: it is rethrown as-is and becomes a trap
* per contracts/embedder-api.md's error model, not smuggled into `other`.
*/
export async function platformCall<T>(what: string, run: () => Promise<T>): Promise<T> {
try {
return await run();
} catch (err) {
if (err instanceof WitError) throw err;
if (err instanceof ComponentException) throw err;
const { name, detail } = asPlatformError(err);
if (err instanceof DOMException) {
if (name === "NotSupportedError") {
Expand Down
2 changes: 1 addition & 1 deletion js/deltic/src/mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
// (`../../../runtime/src/embedder/…`) to the pinned `@deltic/runtime/embedder`
// specifier this repo's import maps resolve (see ../README.md). It is the
// deltic-conventions sibling of [`js/jco/webcrypto.js`](../jco/webcrypto.js)
// — same behavioral reference host, `WitError` throws and typed `Stream<T>`
// — same behavioral reference host, `ComponentException` throws and typed `Stream<T>`
// instead of jco's bare-payload conventions. The WIT contract is
// [`wit/`](../../wit); every doc comment quoting a contract quotes it.
//
Expand Down
8 changes: 4 additions & 4 deletions js/deltic/src/platform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
// authority for which verdict each is.

import { errInvalidKey, errNotExtractable, errUnsupported, platformCall } from "./errors.ts";
import { WitError } from "@deltic/runtime/embedder";
import { ComponentException } from "@deltic/runtime/embedder";
import { asBufferSource } from "./util.ts";

const subtle = globalThis.crypto.subtle;
Expand Down Expand Up @@ -64,7 +64,7 @@ export async function importPlatformKey(
try {
return await subtle.importKey(format, asBufferSource(bytes), algorithm, extractable, usages);
} catch (err) {
if (err instanceof WitError) throw err;
if (err instanceof ComponentException) throw err;
invalidKey(err, what);
}
}
Expand All @@ -81,7 +81,7 @@ export async function importPlatformKeyJwk(
try {
return await subtle.importKey("jwk", jwk as JsonWebKey, algorithm, extractable, usages);
} catch (err) {
if (err instanceof WitError) throw err;
if (err instanceof ComponentException) throw err;
invalidKey(err, what);
}
}
Expand Down Expand Up @@ -206,7 +206,7 @@ export async function redactingInvalidKey<T>(what: string, run: () => Promise<T>
try {
return await run();
} catch (err) {
if (err instanceof WitError && (err.payload as { tag?: string })?.tag === "invalid-key") {
if (err instanceof ComponentException && (err.payload as { kind?: string })?.kind === "invalid-key") {
errInvalidKey(`invalid ${what}`);
}
throw err;
Expand Down
4 changes: 2 additions & 2 deletions js/deltic/src/publicEncryption.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ function oaepAlgorithm(entry: { hash: string; digestBytes: number }, modulusLeng
/** The named plaintext-bound condition: the signal to switch to hybrid wrapping (reference: webcrypto.js:5461). */
function errMessageTooLong(what: string, length: number, algorithm: OaepAlgorithm): never {
witError({
tag: "extension",
val: {
kind: "extension",
value: {
origin: "polymorph:webcrypto",
name: "message-too-long",
message: `${what} is ${length} bytes; this key's RSA-OAEP bound is ${algorithm.plaintextBound}`,
Expand Down
Loading
Loading