ping-openmls-sdk 0.6.13 → 0.6.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/worker.cjs +16 -12
- package/dist/worker.cjs.map +1 -1
- package/dist/worker.js +16 -12
- package/dist/worker.js.map +1 -1
- package/package.json +1 -1
- package/wasm/ping_wasm.d.ts +3 -3
- package/wasm/ping_wasm.js +10 -10
- package/wasm/ping_wasm_bg.wasm +0 -0
- package/wasm/ping_wasm_bg.wasm.d.ts +3 -3
package/dist/worker.cjs
CHANGED
|
@@ -59,7 +59,21 @@ async function ensureWasm() {
|
|
|
59
59
|
wasmReady = (0, import_ping_wasm.default)().then(() => void 0);
|
|
60
60
|
return wasmReady;
|
|
61
61
|
}
|
|
62
|
-
|
|
62
|
+
var dispatchChain = Promise.resolve();
|
|
63
|
+
async function runRequest(msg) {
|
|
64
|
+
try {
|
|
65
|
+
const value = await dispatch(msg);
|
|
66
|
+
self.postMessage({ kind: "result", id: msg.id, ok: true, value });
|
|
67
|
+
} catch (e) {
|
|
68
|
+
self.postMessage({
|
|
69
|
+
kind: "result",
|
|
70
|
+
id: msg.id,
|
|
71
|
+
ok: false,
|
|
72
|
+
error: e instanceof Error ? e.message : String(e)
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
self.onmessage = (ev) => {
|
|
63
77
|
const msg = ev.data;
|
|
64
78
|
if (msg.kind === "storage.reply") {
|
|
65
79
|
const slot = pendingStorage.get(msg.id);
|
|
@@ -77,17 +91,7 @@ self.onmessage = async (ev) => {
|
|
|
77
91
|
}
|
|
78
92
|
return;
|
|
79
93
|
}
|
|
80
|
-
|
|
81
|
-
const value = await dispatch(msg);
|
|
82
|
-
self.postMessage({ kind: "result", id: msg.id, ok: true, value });
|
|
83
|
-
} catch (e) {
|
|
84
|
-
self.postMessage({
|
|
85
|
-
kind: "result",
|
|
86
|
-
id: msg.id,
|
|
87
|
-
ok: false,
|
|
88
|
-
error: e instanceof Error ? e.message : String(e)
|
|
89
|
-
});
|
|
90
|
-
}
|
|
94
|
+
dispatchChain = dispatchChain.then(() => runRequest(msg));
|
|
91
95
|
};
|
|
92
96
|
async function dispatch(msg) {
|
|
93
97
|
await ensureWasm();
|
package/dist/worker.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/worker.ts"],"sourcesContent":["// Web Worker entry. Owns the WASM `PingClient` instance. Receives Requests from the main thread\n// and posts Responses back. Storage / Transport calls back to the main thread are tracked by id.\n//\n// The WASM module is loaded lazily on the first `init` so that ephemeral identity-only spawns\n// (used by `MessagingClient.generateIdentity()`) don't pay the cost.\n\n/// <reference lib=\"webworker\" />\n\nimport init, {\n PingClient,\n sealLinkingTicket as wasmSealLinkingTicket,\n openLinkingTicket as wasmOpenLinkingTicket,\n hpkeSeal as wasmHpkeSeal,\n hpkeOpen as wasmHpkeOpen,\n decodeCatchupSnapshot as wasmDecodeCatchupSnapshot,\n generateMnemonicPhrase as wasmGenerateMnemonicPhrase,\n normalizeMnemonicPhrase as wasmNormalizeMnemonicPhrase,\n encryptBackup as wasmEncryptBackup,\n decryptBackup as wasmDecryptBackup,\n sealHistoryBundle as wasmSealHistoryBundle,\n openHistoryBundle as wasmOpenHistoryBundle,\n} from \"../wasm/ping_wasm\";\nimport type { Request, Response } from \"./protocol\";\nimport type { MessageEnvelope } from \"./types\";\n\ndeclare const self: DedicatedWorkerGlobalScope;\n\nlet client: PingClient | null = null;\nlet wasmReady: Promise<void> | null = null;\n\nconst pendingStorage = new Map<number, (r: { ok: boolean; value: unknown }) => void>();\nconst pendingTransport = new Map<number, (r: { ok: boolean; value: unknown }) => void>();\nlet nextStorageId = 1;\nlet nextTransportId = 1;\n\nconst proxyStorage = {\n get: (namespace: string, key: string) => callMain<Uint8Array | null>(\"storage\", \"get\", [namespace, key]),\n put: (namespace: string, key: string, value: Uint8Array) =>\n callMain<void>(\"storage\", \"put\", [namespace, key, value]),\n del: (namespace: string, key: string) => callMain<void>(\"storage\", \"del\", [namespace, key]),\n listKeys: (namespace: string, prefix: string) =>\n callMain<string[]>(\"storage\", \"listKeys\", [namespace, prefix]),\n};\nconst proxyTransport = {\n send: (envelope: MessageEnvelope) => callMain<void>(\"transport\", \"send\", [envelope]),\n fetchSince: (conv: Uint8Array, cursor: Uint8Array, limit: number) =>\n callMain<MessageEnvelope[]>(\"transport\", \"fetchSince\", [conv, cursor, limit]),\n discoverDevices: (userId: Uint8Array) => callMain<unknown[]>(\"transport\", \"discoverDevices\", [userId]),\n // Optional on the host (see `Transport.setNextWelcomeRecipients` in types.ts).\n // The main-thread dispatch (index.ts `handleWorker → case \"transport.call\"`)\n // resolves `undefined` to a `transport.reply { ok: true, value: undefined }`\n // when the host hasn't implemented the method, which we treat as a no-op.\n setNextWelcomeRecipients: (conv: Uint8Array, recipients: Uint8Array[]) =>\n callMain<void>(\"transport\", \"setNextWelcomeRecipients\", [conv, recipients]),\n};\n\nfunction callMain<T>(kind: \"storage\" | \"transport\", method: string, args: unknown[]): Promise<T> {\n return new Promise((resolve, reject) => {\n const id = kind === \"storage\" ? nextStorageId++ : nextTransportId++;\n const map = kind === \"storage\" ? pendingStorage : pendingTransport;\n map.set(id, ({ ok, value }) => ok ? resolve(value as T) : reject(new Error(String(value))));\n self.postMessage({ kind: `${kind}.call`, id, method, args } as Response);\n });\n}\n\nasync function ensureWasm() {\n if (wasmReady) return wasmReady;\n // The bundled wasm path is rewritten by the build script to be relative to `dist/`.\n wasmReady = init().then(() => undefined);\n return wasmReady;\n}\n\nself.onmessage = async (ev: MessageEvent<Request>) => {\n const msg = ev.data;\n\n // Storage / transport responses from the main thread.\n if (msg.kind === \"storage.reply\") {\n const slot = pendingStorage.get(msg.id);\n if (slot) {\n pendingStorage.delete(msg.id);\n msg.ok ? slot({ ok: true, value: msg.value })\n : slot({ ok: false, value: msg.error });\n }\n return;\n }\n if (msg.kind === \"transport.reply\") {\n const slot = pendingTransport.get(msg.id);\n if (slot) {\n pendingTransport.delete(msg.id);\n msg.ok ? slot({ ok: true, value: msg.value })\n : slot({ ok: false, value: msg.error });\n }\n return;\n }\n\n try {\n const value = await dispatch(msg);\n (self.postMessage as (m: Response) => void)({ kind: \"result\", id: msg.id, ok: true, value });\n } catch (e) {\n (self.postMessage as (m: Response) => void)({\n kind: \"result\", id: msg.id, ok: false, error: e instanceof Error ? e.message : String(e),\n });\n }\n};\n\nasync function dispatch(msg: Request): Promise<unknown> {\n await ensureWasm();\n switch (msg.kind) {\n case \"init\": {\n client = await PingClient.init(\n msg.identityExport, msg.deviceLabel,\n proxyStorage as unknown as never,\n proxyTransport as unknown as never,\n msg.nowMs,\n // Optional Ed25519 device signing secret — see protocol.ts\n // and ClientConfig.deviceSigningSecretKey. Forwarding `null`\n // explicitly when absent so the wasm-bindgen `Option<Vec<u8>>`\n // shape is matched correctly.\n msg.deviceSigningSecretKey ?? null,\n );\n // Wire decrypted application-message callback back to the main thread.\n client.onMessage((m: unknown) => {\n (self.postMessage as (m: Response) => void)({ kind: \"event.message\", msg: m as never });\n });\n return null;\n }\n case \"generateIdentity\":\n return PingClient.generateIdentity();\n case \"userId\": return ensureClient().userId();\n case \"deviceId\": return ensureClient().deviceId();\n case \"freshKeyPackage\": return ensureClient().freshKeyPackage();\n case \"createConversation\":\n return await ensureClient().createConversation(msg.name ?? undefined, msg.nowMs);\n case \"joinConversation\": {\n const id = await ensureClient().joinConversation(msg.welcome, msg.nowMs) as Uint8Array;\n // Notify the main thread that we just entered a new conversation. We forward the\n // Welcome's `sender_device` so the host can label \"joined chat with <inviter>\".\n (self.postMessage as (m: Response) => void)({\n kind: \"event.conversation\",\n id,\n epoch: 0,\n sender: msg.welcome.sender_device,\n });\n return id;\n }\n case \"listConversations\":\n return ensureClient().listConversations();\n case \"members\":\n return ensureClient().members(msg.conv);\n case \"send\":\n return await ensureClient().send(msg.conv, msg.plaintext, msg.nowMs);\n case \"addMembers\":\n // wasm-bindgen takes the entries as a plain array of {deviceId, keyPackage};\n // serde-wasm-bindgen on the Rust side deserialises into Vec<JsAddMemberEntry>.\n return await ensureClient().addMembers(msg.conv, msg.entries, msg.nowMs);\n case \"admitDeviceToChats\":\n // Per-chat add for a newly-linked device. Returns Vec<JsAdmitChatOutcome>\n // — the host inspects per-entry status to decide whether to retry.\n return await ensureClient().admitDeviceToChats(msg.deviceId, msg.entries, msg.nowMs);\n case \"removeMembers\":\n // wasm-bindgen exposes Vec<u32> as Uint32Array; convert from the protocol's number[].\n return await ensureClient().removeMembers(msg.conv, new Uint32Array(msg.leaves), msg.nowMs);\n case \"revokeDevice\":\n // [CR-2] returns the array of Commit envelopes the SDK has already broadcast.\n return await ensureClient().revokeDevice(msg.deviceId, msg.nowMs);\n case \"processEnvelope\": {\n const result = await ensureClient().processEnvelope(msg.envelope, msg.nowMs);\n (self.postMessage as (m: Response) => void)({\n kind: \"event.conversation\",\n id: msg.envelope.conversation_id,\n epoch: msg.envelope.epoch,\n });\n return result;\n }\n case \"syncConversations\":\n return await ensureClient().syncConversations(msg.nowMs);\n case \"buildLinkingTicket\":\n return await ensureClient().buildLinkingTicket(\n msg.newDeviceId, msg.newDeviceKp, msg.lastAppEvents, msg.nowMs,\n );\n case \"consumeLinkingTicket\":\n await ensureClient().consumeLinkingTicket(msg.ticket, msg.nowMs);\n return null;\n case \"decodeCatchupSnapshot\":\n // Pure WASM — no client state required. The new device may call this in an\n // ephemeral worker before init() completes.\n return wasmDecodeCatchupSnapshot(msg.snapshotBytes);\n case \"exportConversationSecret\":\n // wasm-bindgen returns a Uint8Array sized to `length`. The bytes are a secret —\n // the main thread is responsible for clearing the typed array when done.\n return ensureClient().exportConversationSecret(\n msg.conv, msg.label, msg.context, msg.length,\n );\n case \"sealLinkingTicket\":\n // Pure WASM call — no client state required. Lets a sender seal a ticket from an\n // ephemeral worker without standing up the full PingClient.\n return wasmSealLinkingTicket(msg.ticket, msg.newDevicePub);\n case \"openLinkingTicket\":\n // Same — runs without an initialised client, which is the receiving device's\n // pre-bootstrap state (it has the X25519 ephemeral key but no identity yet).\n return wasmOpenLinkingTicket(msg.sealed, msg.newDevicePriv);\n case \"hpkeSeal\":\n // Generic HPKE seal for app-layer envelopes (e.g. linking auth envelope).\n return wasmHpkeSeal(msg.plaintext, msg.recipientPub, msg.info);\n case \"hpkeOpen\":\n return wasmHpkeOpen(msg.sealed, msg.recipientPriv, msg.info);\n case \"exportConversationStateSnapshot\":\n // [CR-7] state snapshot bytes are a secret (past epoch keys); the main thread\n // is responsible for clearing the typed array when done.\n return ensureClient().exportConversationStateSnapshot(msg.conv, msg.nowMs);\n case \"importStateSnapshot\":\n // [CR-7] returns the imported conversation id as a Uint8Array.\n return await ensureClient().importStateSnapshot(msg.snapshotBytes, msg.nowMs);\n // Recovery — all pure WASM; no client state required.\n case \"generateMnemonicPhrase\":\n return wasmGenerateMnemonicPhrase();\n case \"normalizeMnemonicPhrase\":\n return wasmNormalizeMnemonicPhrase(msg.phrase);\n case \"encryptBackup\":\n return wasmEncryptBackup(\n msg.mnemonicPhrase, msg.accountId, msg.identityExport,\n msg.deviceGroupSnapshot,\n // Map idiomatic camelCase → the snake_case keys serde expects on the\n // WASM boundary (matches the decrypt view's account_id / group_state_bytes).\n msg.conversationSnapshots.map((c) => ({\n conversation_id: c.conversationId,\n group_state_bytes: c.groupStateBytes,\n })),\n msg.createdAtMs,\n );\n case \"decryptBackup\":\n return wasmDecryptBackup(msg.blob, msg.mnemonicPhrase);\n case \"sealHistoryBundle\":\n return wasmSealHistoryBundle(msg.bundle, msg.recipientPub, msg.senderIdentitySecret);\n case \"openHistoryBundle\":\n return wasmOpenHistoryBundle(msg.sealed, msg.recipientPriv, msg.senderIdentityPub);\n default:\n throw new Error(`unknown request kind: ${(msg as { kind: string }).kind}`);\n }\n}\n\nfunction ensureClient(): PingClient {\n if (!client) throw new Error(\"client not initialised\");\n return client;\n}\n"],"mappings":"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","names":["init","wasmDecodeCatchupSnapshot","wasmSealLinkingTicket","wasmOpenLinkingTicket","wasmHpkeSeal","wasmHpkeOpen","wasmGenerateMnemonicPhrase","wasmNormalizeMnemonicPhrase","wasmEncryptBackup","wasmDecryptBackup","wasmSealHistoryBundle","wasmOpenHistoryBundle"]}
|
|
1
|
+
{"version":3,"sources":["../src/worker.ts"],"sourcesContent":["// Web Worker entry. Owns the WASM `PingClient` instance. Receives Requests from the main thread\n// and posts Responses back. Storage / Transport calls back to the main thread are tracked by id.\n//\n// The WASM module is loaded lazily on the first `init` so that ephemeral identity-only spawns\n// (used by `MessagingClient.generateIdentity()`) don't pay the cost.\n\n/// <reference lib=\"webworker\" />\n\nimport init, {\n PingClient,\n sealLinkingTicket as wasmSealLinkingTicket,\n openLinkingTicket as wasmOpenLinkingTicket,\n hpkeSeal as wasmHpkeSeal,\n hpkeOpen as wasmHpkeOpen,\n decodeCatchupSnapshot as wasmDecodeCatchupSnapshot,\n generateMnemonicPhrase as wasmGenerateMnemonicPhrase,\n normalizeMnemonicPhrase as wasmNormalizeMnemonicPhrase,\n encryptBackup as wasmEncryptBackup,\n decryptBackup as wasmDecryptBackup,\n sealHistoryBundle as wasmSealHistoryBundle,\n openHistoryBundle as wasmOpenHistoryBundle,\n} from \"../wasm/ping_wasm\";\nimport type { Request, Response } from \"./protocol\";\nimport type { MessageEnvelope } from \"./types\";\n\ndeclare const self: DedicatedWorkerGlobalScope;\n\nlet client: PingClient | null = null;\nlet wasmReady: Promise<void> | null = null;\n\nconst pendingStorage = new Map<number, (r: { ok: boolean; value: unknown }) => void>();\nconst pendingTransport = new Map<number, (r: { ok: boolean; value: unknown }) => void>();\nlet nextStorageId = 1;\nlet nextTransportId = 1;\n\nconst proxyStorage = {\n get: (namespace: string, key: string) => callMain<Uint8Array | null>(\"storage\", \"get\", [namespace, key]),\n put: (namespace: string, key: string, value: Uint8Array) =>\n callMain<void>(\"storage\", \"put\", [namespace, key, value]),\n del: (namespace: string, key: string) => callMain<void>(\"storage\", \"del\", [namespace, key]),\n listKeys: (namespace: string, prefix: string) =>\n callMain<string[]>(\"storage\", \"listKeys\", [namespace, prefix]),\n};\nconst proxyTransport = {\n send: (envelope: MessageEnvelope) => callMain<void>(\"transport\", \"send\", [envelope]),\n fetchSince: (conv: Uint8Array, cursor: Uint8Array, limit: number) =>\n callMain<MessageEnvelope[]>(\"transport\", \"fetchSince\", [conv, cursor, limit]),\n discoverDevices: (userId: Uint8Array) => callMain<unknown[]>(\"transport\", \"discoverDevices\", [userId]),\n // Optional on the host (see `Transport.setNextWelcomeRecipients` in types.ts).\n // The main-thread dispatch (index.ts `handleWorker → case \"transport.call\"`)\n // resolves `undefined` to a `transport.reply { ok: true, value: undefined }`\n // when the host hasn't implemented the method, which we treat as a no-op.\n setNextWelcomeRecipients: (conv: Uint8Array, recipients: Uint8Array[]) =>\n callMain<void>(\"transport\", \"setNextWelcomeRecipients\", [conv, recipients]),\n};\n\nfunction callMain<T>(kind: \"storage\" | \"transport\", method: string, args: unknown[]): Promise<T> {\n return new Promise((resolve, reject) => {\n const id = kind === \"storage\" ? nextStorageId++ : nextTransportId++;\n const map = kind === \"storage\" ? pendingStorage : pendingTransport;\n map.set(id, ({ ok, value }) => ok ? resolve(value as T) : reject(new Error(String(value))));\n self.postMessage({ kind: `${kind}.call`, id, method, args } as Response);\n });\n}\n\nasync function ensureWasm() {\n if (wasmReady) return wasmReady;\n // The bundled wasm path is rewritten by the build script to be relative to `dist/`.\n wasmReady = init().then(() => undefined);\n return wasmReady;\n}\n\n// The WASM `PingClient` is SINGLE-THREADED (this one worker). Its async\n// methods hold internal locks across `.await` (e.g. a `conversations`\n// RwLock guard kept while `snapshot_to_storage` awaits IndexedDB). If we\n// let `onmessage` dispatch a SECOND top-level request while the first is\n// suspended at an await, the two WASM calls interleave on the single\n// thread, the second re-acquires a held lock, and `parking_lot`'s wasm\n// stub `panic!`s with \"Parking not supported on this platform\" — which\n// poisons the module (`RuntimeError: unreachable`) and breaks every\n// subsequent call. We therefore SERIALIZE top-level request dispatch:\n// each request runs to completion before the next begins.\n//\n// CRUCIAL: `storage.reply` / `transport.reply` are NOT serialized — an\n// in-flight request awaits those replies (via `callMain`), so queuing\n// them behind the request would deadlock. They resolve pending callbacks\n// immediately, exactly as before.\nlet dispatchChain: Promise<void> = Promise.resolve();\n\nasync function runRequest(msg: Request): Promise<void> {\n try {\n const value = await dispatch(msg);\n (self.postMessage as (m: Response) => void)({ kind: \"result\", id: msg.id, ok: true, value });\n } catch (e) {\n (self.postMessage as (m: Response) => void)({\n kind: \"result\", id: msg.id, ok: false, error: e instanceof Error ? e.message : String(e),\n });\n }\n}\n\nself.onmessage = (ev: MessageEvent<Request>) => {\n const msg = ev.data;\n\n // Storage / transport responses from the main thread — handle\n // immediately (they unblock the in-flight request). Never queued.\n if (msg.kind === \"storage.reply\") {\n const slot = pendingStorage.get(msg.id);\n if (slot) {\n pendingStorage.delete(msg.id);\n msg.ok ? slot({ ok: true, value: msg.value })\n : slot({ ok: false, value: msg.error });\n }\n return;\n }\n if (msg.kind === \"transport.reply\") {\n const slot = pendingTransport.get(msg.id);\n if (slot) {\n pendingTransport.delete(msg.id);\n msg.ok ? slot({ ok: true, value: msg.value })\n : slot({ ok: false, value: msg.error });\n }\n return;\n }\n\n // Top-level client request — chain it after the previous one so only a\n // single WASM call is ever in flight. `runRequest` never rejects (it\n // posts the error as a result), so the chain can't break.\n dispatchChain = dispatchChain.then(() => runRequest(msg));\n};\n\nasync function dispatch(msg: Request): Promise<unknown> {\n await ensureWasm();\n switch (msg.kind) {\n case \"init\": {\n client = await PingClient.init(\n msg.identityExport, msg.deviceLabel,\n proxyStorage as unknown as never,\n proxyTransport as unknown as never,\n msg.nowMs,\n // Optional Ed25519 device signing secret — see protocol.ts\n // and ClientConfig.deviceSigningSecretKey. Forwarding `null`\n // explicitly when absent so the wasm-bindgen `Option<Vec<u8>>`\n // shape is matched correctly.\n msg.deviceSigningSecretKey ?? null,\n );\n // Wire decrypted application-message callback back to the main thread.\n client.onMessage((m: unknown) => {\n (self.postMessage as (m: Response) => void)({ kind: \"event.message\", msg: m as never });\n });\n return null;\n }\n case \"generateIdentity\":\n return PingClient.generateIdentity();\n case \"userId\": return ensureClient().userId();\n case \"deviceId\": return ensureClient().deviceId();\n case \"freshKeyPackage\": return ensureClient().freshKeyPackage();\n case \"createConversation\":\n return await ensureClient().createConversation(msg.name ?? undefined, msg.nowMs);\n case \"joinConversation\": {\n const id = await ensureClient().joinConversation(msg.welcome, msg.nowMs) as Uint8Array;\n // Notify the main thread that we just entered a new conversation. We forward the\n // Welcome's `sender_device` so the host can label \"joined chat with <inviter>\".\n (self.postMessage as (m: Response) => void)({\n kind: \"event.conversation\",\n id,\n epoch: 0,\n sender: msg.welcome.sender_device,\n });\n return id;\n }\n case \"listConversations\":\n return ensureClient().listConversations();\n case \"members\":\n return ensureClient().members(msg.conv);\n case \"send\":\n return await ensureClient().send(msg.conv, msg.plaintext, msg.nowMs);\n case \"addMembers\":\n // wasm-bindgen takes the entries as a plain array of {deviceId, keyPackage};\n // serde-wasm-bindgen on the Rust side deserialises into Vec<JsAddMemberEntry>.\n return await ensureClient().addMembers(msg.conv, msg.entries, msg.nowMs);\n case \"admitDeviceToChats\":\n // Per-chat add for a newly-linked device. Returns Vec<JsAdmitChatOutcome>\n // — the host inspects per-entry status to decide whether to retry.\n return await ensureClient().admitDeviceToChats(msg.deviceId, msg.entries, msg.nowMs);\n case \"removeMembers\":\n // wasm-bindgen exposes Vec<u32> as Uint32Array; convert from the protocol's number[].\n return await ensureClient().removeMembers(msg.conv, new Uint32Array(msg.leaves), msg.nowMs);\n case \"revokeDevice\":\n // [CR-2] returns the array of Commit envelopes the SDK has already broadcast.\n return await ensureClient().revokeDevice(msg.deviceId, msg.nowMs);\n case \"processEnvelope\": {\n const result = await ensureClient().processEnvelope(msg.envelope, msg.nowMs);\n (self.postMessage as (m: Response) => void)({\n kind: \"event.conversation\",\n id: msg.envelope.conversation_id,\n epoch: msg.envelope.epoch,\n });\n return result;\n }\n case \"syncConversations\":\n return await ensureClient().syncConversations(msg.nowMs);\n case \"buildLinkingTicket\":\n return await ensureClient().buildLinkingTicket(\n msg.newDeviceId, msg.newDeviceKp, msg.lastAppEvents, msg.nowMs,\n );\n case \"consumeLinkingTicket\":\n await ensureClient().consumeLinkingTicket(msg.ticket, msg.nowMs);\n return null;\n case \"decodeCatchupSnapshot\":\n // Pure WASM — no client state required. The new device may call this in an\n // ephemeral worker before init() completes.\n return wasmDecodeCatchupSnapshot(msg.snapshotBytes);\n case \"exportConversationSecret\":\n // wasm-bindgen returns a Uint8Array sized to `length`. The bytes are a secret —\n // the main thread is responsible for clearing the typed array when done.\n return ensureClient().exportConversationSecret(\n msg.conv, msg.label, msg.context, msg.length,\n );\n case \"sealLinkingTicket\":\n // Pure WASM call — no client state required. Lets a sender seal a ticket from an\n // ephemeral worker without standing up the full PingClient.\n return wasmSealLinkingTicket(msg.ticket, msg.newDevicePub);\n case \"openLinkingTicket\":\n // Same — runs without an initialised client, which is the receiving device's\n // pre-bootstrap state (it has the X25519 ephemeral key but no identity yet).\n return wasmOpenLinkingTicket(msg.sealed, msg.newDevicePriv);\n case \"hpkeSeal\":\n // Generic HPKE seal for app-layer envelopes (e.g. linking auth envelope).\n return wasmHpkeSeal(msg.plaintext, msg.recipientPub, msg.info);\n case \"hpkeOpen\":\n return wasmHpkeOpen(msg.sealed, msg.recipientPriv, msg.info);\n case \"exportConversationStateSnapshot\":\n // [CR-7] state snapshot bytes are a secret (past epoch keys); the main thread\n // is responsible for clearing the typed array when done.\n return ensureClient().exportConversationStateSnapshot(msg.conv, msg.nowMs);\n case \"importStateSnapshot\":\n // [CR-7] returns the imported conversation id as a Uint8Array.\n return await ensureClient().importStateSnapshot(msg.snapshotBytes, msg.nowMs);\n // Recovery — all pure WASM; no client state required.\n case \"generateMnemonicPhrase\":\n return wasmGenerateMnemonicPhrase();\n case \"normalizeMnemonicPhrase\":\n return wasmNormalizeMnemonicPhrase(msg.phrase);\n case \"encryptBackup\":\n return wasmEncryptBackup(\n msg.mnemonicPhrase, msg.accountId, msg.identityExport,\n msg.deviceGroupSnapshot,\n // Map idiomatic camelCase → the snake_case keys serde expects on the\n // WASM boundary (matches the decrypt view's account_id / group_state_bytes).\n msg.conversationSnapshots.map((c) => ({\n conversation_id: c.conversationId,\n group_state_bytes: c.groupStateBytes,\n })),\n msg.createdAtMs,\n );\n case \"decryptBackup\":\n return wasmDecryptBackup(msg.blob, msg.mnemonicPhrase);\n case \"sealHistoryBundle\":\n return wasmSealHistoryBundle(msg.bundle, msg.recipientPub, msg.senderIdentitySecret);\n case \"openHistoryBundle\":\n return wasmOpenHistoryBundle(msg.sealed, msg.recipientPriv, msg.senderIdentityPub);\n default:\n throw new Error(`unknown request kind: ${(msg as { kind: string }).kind}`);\n }\n}\n\nfunction ensureClient(): PingClient {\n if (!client) throw new Error(\"client not initialised\");\n return client;\n}\n"],"mappings":"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","names":["init","wasmDecodeCatchupSnapshot","wasmSealLinkingTicket","wasmOpenLinkingTicket","wasmHpkeSeal","wasmHpkeOpen","wasmGenerateMnemonicPhrase","wasmNormalizeMnemonicPhrase","wasmEncryptBackup","wasmDecryptBackup","wasmSealHistoryBundle","wasmOpenHistoryBundle"]}
|
package/dist/worker.js
CHANGED
|
@@ -48,7 +48,21 @@ async function ensureWasm() {
|
|
|
48
48
|
wasmReady = init().then(() => void 0);
|
|
49
49
|
return wasmReady;
|
|
50
50
|
}
|
|
51
|
-
|
|
51
|
+
var dispatchChain = Promise.resolve();
|
|
52
|
+
async function runRequest(msg) {
|
|
53
|
+
try {
|
|
54
|
+
const value = await dispatch(msg);
|
|
55
|
+
self.postMessage({ kind: "result", id: msg.id, ok: true, value });
|
|
56
|
+
} catch (e) {
|
|
57
|
+
self.postMessage({
|
|
58
|
+
kind: "result",
|
|
59
|
+
id: msg.id,
|
|
60
|
+
ok: false,
|
|
61
|
+
error: e instanceof Error ? e.message : String(e)
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
self.onmessage = (ev) => {
|
|
52
66
|
const msg = ev.data;
|
|
53
67
|
if (msg.kind === "storage.reply") {
|
|
54
68
|
const slot = pendingStorage.get(msg.id);
|
|
@@ -66,17 +80,7 @@ self.onmessage = async (ev) => {
|
|
|
66
80
|
}
|
|
67
81
|
return;
|
|
68
82
|
}
|
|
69
|
-
|
|
70
|
-
const value = await dispatch(msg);
|
|
71
|
-
self.postMessage({ kind: "result", id: msg.id, ok: true, value });
|
|
72
|
-
} catch (e) {
|
|
73
|
-
self.postMessage({
|
|
74
|
-
kind: "result",
|
|
75
|
-
id: msg.id,
|
|
76
|
-
ok: false,
|
|
77
|
-
error: e instanceof Error ? e.message : String(e)
|
|
78
|
-
});
|
|
79
|
-
}
|
|
83
|
+
dispatchChain = dispatchChain.then(() => runRequest(msg));
|
|
80
84
|
};
|
|
81
85
|
async function dispatch(msg) {
|
|
82
86
|
await ensureWasm();
|
package/dist/worker.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/worker.ts"],"sourcesContent":["// Web Worker entry. Owns the WASM `PingClient` instance. Receives Requests from the main thread\n// and posts Responses back. Storage / Transport calls back to the main thread are tracked by id.\n//\n// The WASM module is loaded lazily on the first `init` so that ephemeral identity-only spawns\n// (used by `MessagingClient.generateIdentity()`) don't pay the cost.\n\n/// <reference lib=\"webworker\" />\n\nimport init, {\n PingClient,\n sealLinkingTicket as wasmSealLinkingTicket,\n openLinkingTicket as wasmOpenLinkingTicket,\n hpkeSeal as wasmHpkeSeal,\n hpkeOpen as wasmHpkeOpen,\n decodeCatchupSnapshot as wasmDecodeCatchupSnapshot,\n generateMnemonicPhrase as wasmGenerateMnemonicPhrase,\n normalizeMnemonicPhrase as wasmNormalizeMnemonicPhrase,\n encryptBackup as wasmEncryptBackup,\n decryptBackup as wasmDecryptBackup,\n sealHistoryBundle as wasmSealHistoryBundle,\n openHistoryBundle as wasmOpenHistoryBundle,\n} from \"../wasm/ping_wasm\";\nimport type { Request, Response } from \"./protocol\";\nimport type { MessageEnvelope } from \"./types\";\n\ndeclare const self: DedicatedWorkerGlobalScope;\n\nlet client: PingClient | null = null;\nlet wasmReady: Promise<void> | null = null;\n\nconst pendingStorage = new Map<number, (r: { ok: boolean; value: unknown }) => void>();\nconst pendingTransport = new Map<number, (r: { ok: boolean; value: unknown }) => void>();\nlet nextStorageId = 1;\nlet nextTransportId = 1;\n\nconst proxyStorage = {\n get: (namespace: string, key: string) => callMain<Uint8Array | null>(\"storage\", \"get\", [namespace, key]),\n put: (namespace: string, key: string, value: Uint8Array) =>\n callMain<void>(\"storage\", \"put\", [namespace, key, value]),\n del: (namespace: string, key: string) => callMain<void>(\"storage\", \"del\", [namespace, key]),\n listKeys: (namespace: string, prefix: string) =>\n callMain<string[]>(\"storage\", \"listKeys\", [namespace, prefix]),\n};\nconst proxyTransport = {\n send: (envelope: MessageEnvelope) => callMain<void>(\"transport\", \"send\", [envelope]),\n fetchSince: (conv: Uint8Array, cursor: Uint8Array, limit: number) =>\n callMain<MessageEnvelope[]>(\"transport\", \"fetchSince\", [conv, cursor, limit]),\n discoverDevices: (userId: Uint8Array) => callMain<unknown[]>(\"transport\", \"discoverDevices\", [userId]),\n // Optional on the host (see `Transport.setNextWelcomeRecipients` in types.ts).\n // The main-thread dispatch (index.ts `handleWorker → case \"transport.call\"`)\n // resolves `undefined` to a `transport.reply { ok: true, value: undefined }`\n // when the host hasn't implemented the method, which we treat as a no-op.\n setNextWelcomeRecipients: (conv: Uint8Array, recipients: Uint8Array[]) =>\n callMain<void>(\"transport\", \"setNextWelcomeRecipients\", [conv, recipients]),\n};\n\nfunction callMain<T>(kind: \"storage\" | \"transport\", method: string, args: unknown[]): Promise<T> {\n return new Promise((resolve, reject) => {\n const id = kind === \"storage\" ? nextStorageId++ : nextTransportId++;\n const map = kind === \"storage\" ? pendingStorage : pendingTransport;\n map.set(id, ({ ok, value }) => ok ? resolve(value as T) : reject(new Error(String(value))));\n self.postMessage({ kind: `${kind}.call`, id, method, args } as Response);\n });\n}\n\nasync function ensureWasm() {\n if (wasmReady) return wasmReady;\n // The bundled wasm path is rewritten by the build script to be relative to `dist/`.\n wasmReady = init().then(() => undefined);\n return wasmReady;\n}\n\nself.onmessage = async (ev: MessageEvent<Request>) => {\n const msg = ev.data;\n\n // Storage / transport responses from the main thread.\n if (msg.kind === \"storage.reply\") {\n const slot = pendingStorage.get(msg.id);\n if (slot) {\n pendingStorage.delete(msg.id);\n msg.ok ? slot({ ok: true, value: msg.value })\n : slot({ ok: false, value: msg.error });\n }\n return;\n }\n if (msg.kind === \"transport.reply\") {\n const slot = pendingTransport.get(msg.id);\n if (slot) {\n pendingTransport.delete(msg.id);\n msg.ok ? slot({ ok: true, value: msg.value })\n : slot({ ok: false, value: msg.error });\n }\n return;\n }\n\n try {\n const value = await dispatch(msg);\n (self.postMessage as (m: Response) => void)({ kind: \"result\", id: msg.id, ok: true, value });\n } catch (e) {\n (self.postMessage as (m: Response) => void)({\n kind: \"result\", id: msg.id, ok: false, error: e instanceof Error ? e.message : String(e),\n });\n }\n};\n\nasync function dispatch(msg: Request): Promise<unknown> {\n await ensureWasm();\n switch (msg.kind) {\n case \"init\": {\n client = await PingClient.init(\n msg.identityExport, msg.deviceLabel,\n proxyStorage as unknown as never,\n proxyTransport as unknown as never,\n msg.nowMs,\n // Optional Ed25519 device signing secret — see protocol.ts\n // and ClientConfig.deviceSigningSecretKey. Forwarding `null`\n // explicitly when absent so the wasm-bindgen `Option<Vec<u8>>`\n // shape is matched correctly.\n msg.deviceSigningSecretKey ?? null,\n );\n // Wire decrypted application-message callback back to the main thread.\n client.onMessage((m: unknown) => {\n (self.postMessage as (m: Response) => void)({ kind: \"event.message\", msg: m as never });\n });\n return null;\n }\n case \"generateIdentity\":\n return PingClient.generateIdentity();\n case \"userId\": return ensureClient().userId();\n case \"deviceId\": return ensureClient().deviceId();\n case \"freshKeyPackage\": return ensureClient().freshKeyPackage();\n case \"createConversation\":\n return await ensureClient().createConversation(msg.name ?? undefined, msg.nowMs);\n case \"joinConversation\": {\n const id = await ensureClient().joinConversation(msg.welcome, msg.nowMs) as Uint8Array;\n // Notify the main thread that we just entered a new conversation. We forward the\n // Welcome's `sender_device` so the host can label \"joined chat with <inviter>\".\n (self.postMessage as (m: Response) => void)({\n kind: \"event.conversation\",\n id,\n epoch: 0,\n sender: msg.welcome.sender_device,\n });\n return id;\n }\n case \"listConversations\":\n return ensureClient().listConversations();\n case \"members\":\n return ensureClient().members(msg.conv);\n case \"send\":\n return await ensureClient().send(msg.conv, msg.plaintext, msg.nowMs);\n case \"addMembers\":\n // wasm-bindgen takes the entries as a plain array of {deviceId, keyPackage};\n // serde-wasm-bindgen on the Rust side deserialises into Vec<JsAddMemberEntry>.\n return await ensureClient().addMembers(msg.conv, msg.entries, msg.nowMs);\n case \"admitDeviceToChats\":\n // Per-chat add for a newly-linked device. Returns Vec<JsAdmitChatOutcome>\n // — the host inspects per-entry status to decide whether to retry.\n return await ensureClient().admitDeviceToChats(msg.deviceId, msg.entries, msg.nowMs);\n case \"removeMembers\":\n // wasm-bindgen exposes Vec<u32> as Uint32Array; convert from the protocol's number[].\n return await ensureClient().removeMembers(msg.conv, new Uint32Array(msg.leaves), msg.nowMs);\n case \"revokeDevice\":\n // [CR-2] returns the array of Commit envelopes the SDK has already broadcast.\n return await ensureClient().revokeDevice(msg.deviceId, msg.nowMs);\n case \"processEnvelope\": {\n const result = await ensureClient().processEnvelope(msg.envelope, msg.nowMs);\n (self.postMessage as (m: Response) => void)({\n kind: \"event.conversation\",\n id: msg.envelope.conversation_id,\n epoch: msg.envelope.epoch,\n });\n return result;\n }\n case \"syncConversations\":\n return await ensureClient().syncConversations(msg.nowMs);\n case \"buildLinkingTicket\":\n return await ensureClient().buildLinkingTicket(\n msg.newDeviceId, msg.newDeviceKp, msg.lastAppEvents, msg.nowMs,\n );\n case \"consumeLinkingTicket\":\n await ensureClient().consumeLinkingTicket(msg.ticket, msg.nowMs);\n return null;\n case \"decodeCatchupSnapshot\":\n // Pure WASM — no client state required. The new device may call this in an\n // ephemeral worker before init() completes.\n return wasmDecodeCatchupSnapshot(msg.snapshotBytes);\n case \"exportConversationSecret\":\n // wasm-bindgen returns a Uint8Array sized to `length`. The bytes are a secret —\n // the main thread is responsible for clearing the typed array when done.\n return ensureClient().exportConversationSecret(\n msg.conv, msg.label, msg.context, msg.length,\n );\n case \"sealLinkingTicket\":\n // Pure WASM call — no client state required. Lets a sender seal a ticket from an\n // ephemeral worker without standing up the full PingClient.\n return wasmSealLinkingTicket(msg.ticket, msg.newDevicePub);\n case \"openLinkingTicket\":\n // Same — runs without an initialised client, which is the receiving device's\n // pre-bootstrap state (it has the X25519 ephemeral key but no identity yet).\n return wasmOpenLinkingTicket(msg.sealed, msg.newDevicePriv);\n case \"hpkeSeal\":\n // Generic HPKE seal for app-layer envelopes (e.g. linking auth envelope).\n return wasmHpkeSeal(msg.plaintext, msg.recipientPub, msg.info);\n case \"hpkeOpen\":\n return wasmHpkeOpen(msg.sealed, msg.recipientPriv, msg.info);\n case \"exportConversationStateSnapshot\":\n // [CR-7] state snapshot bytes are a secret (past epoch keys); the main thread\n // is responsible for clearing the typed array when done.\n return ensureClient().exportConversationStateSnapshot(msg.conv, msg.nowMs);\n case \"importStateSnapshot\":\n // [CR-7] returns the imported conversation id as a Uint8Array.\n return await ensureClient().importStateSnapshot(msg.snapshotBytes, msg.nowMs);\n // Recovery — all pure WASM; no client state required.\n case \"generateMnemonicPhrase\":\n return wasmGenerateMnemonicPhrase();\n case \"normalizeMnemonicPhrase\":\n return wasmNormalizeMnemonicPhrase(msg.phrase);\n case \"encryptBackup\":\n return wasmEncryptBackup(\n msg.mnemonicPhrase, msg.accountId, msg.identityExport,\n msg.deviceGroupSnapshot,\n // Map idiomatic camelCase → the snake_case keys serde expects on the\n // WASM boundary (matches the decrypt view's account_id / group_state_bytes).\n msg.conversationSnapshots.map((c) => ({\n conversation_id: c.conversationId,\n group_state_bytes: c.groupStateBytes,\n })),\n msg.createdAtMs,\n );\n case \"decryptBackup\":\n return wasmDecryptBackup(msg.blob, msg.mnemonicPhrase);\n case \"sealHistoryBundle\":\n return wasmSealHistoryBundle(msg.bundle, msg.recipientPub, msg.senderIdentitySecret);\n case \"openHistoryBundle\":\n return wasmOpenHistoryBundle(msg.sealed, msg.recipientPriv, msg.senderIdentityPub);\n default:\n throw new Error(`unknown request kind: ${(msg as { kind: string }).kind}`);\n }\n}\n\nfunction ensureClient(): PingClient {\n if (!client) throw new Error(\"client not initialised\");\n return client;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/worker.ts"],"sourcesContent":["// Web Worker entry. Owns the WASM `PingClient` instance. Receives Requests from the main thread\n// and posts Responses back. Storage / Transport calls back to the main thread are tracked by id.\n//\n// The WASM module is loaded lazily on the first `init` so that ephemeral identity-only spawns\n// (used by `MessagingClient.generateIdentity()`) don't pay the cost.\n\n/// <reference lib=\"webworker\" />\n\nimport init, {\n PingClient,\n sealLinkingTicket as wasmSealLinkingTicket,\n openLinkingTicket as wasmOpenLinkingTicket,\n hpkeSeal as wasmHpkeSeal,\n hpkeOpen as wasmHpkeOpen,\n decodeCatchupSnapshot as wasmDecodeCatchupSnapshot,\n generateMnemonicPhrase as wasmGenerateMnemonicPhrase,\n normalizeMnemonicPhrase as wasmNormalizeMnemonicPhrase,\n encryptBackup as wasmEncryptBackup,\n decryptBackup as wasmDecryptBackup,\n sealHistoryBundle as wasmSealHistoryBundle,\n openHistoryBundle as wasmOpenHistoryBundle,\n} from \"../wasm/ping_wasm\";\nimport type { Request, Response } from \"./protocol\";\nimport type { MessageEnvelope } from \"./types\";\n\ndeclare const self: DedicatedWorkerGlobalScope;\n\nlet client: PingClient | null = null;\nlet wasmReady: Promise<void> | null = null;\n\nconst pendingStorage = new Map<number, (r: { ok: boolean; value: unknown }) => void>();\nconst pendingTransport = new Map<number, (r: { ok: boolean; value: unknown }) => void>();\nlet nextStorageId = 1;\nlet nextTransportId = 1;\n\nconst proxyStorage = {\n get: (namespace: string, key: string) => callMain<Uint8Array | null>(\"storage\", \"get\", [namespace, key]),\n put: (namespace: string, key: string, value: Uint8Array) =>\n callMain<void>(\"storage\", \"put\", [namespace, key, value]),\n del: (namespace: string, key: string) => callMain<void>(\"storage\", \"del\", [namespace, key]),\n listKeys: (namespace: string, prefix: string) =>\n callMain<string[]>(\"storage\", \"listKeys\", [namespace, prefix]),\n};\nconst proxyTransport = {\n send: (envelope: MessageEnvelope) => callMain<void>(\"transport\", \"send\", [envelope]),\n fetchSince: (conv: Uint8Array, cursor: Uint8Array, limit: number) =>\n callMain<MessageEnvelope[]>(\"transport\", \"fetchSince\", [conv, cursor, limit]),\n discoverDevices: (userId: Uint8Array) => callMain<unknown[]>(\"transport\", \"discoverDevices\", [userId]),\n // Optional on the host (see `Transport.setNextWelcomeRecipients` in types.ts).\n // The main-thread dispatch (index.ts `handleWorker → case \"transport.call\"`)\n // resolves `undefined` to a `transport.reply { ok: true, value: undefined }`\n // when the host hasn't implemented the method, which we treat as a no-op.\n setNextWelcomeRecipients: (conv: Uint8Array, recipients: Uint8Array[]) =>\n callMain<void>(\"transport\", \"setNextWelcomeRecipients\", [conv, recipients]),\n};\n\nfunction callMain<T>(kind: \"storage\" | \"transport\", method: string, args: unknown[]): Promise<T> {\n return new Promise((resolve, reject) => {\n const id = kind === \"storage\" ? nextStorageId++ : nextTransportId++;\n const map = kind === \"storage\" ? pendingStorage : pendingTransport;\n map.set(id, ({ ok, value }) => ok ? resolve(value as T) : reject(new Error(String(value))));\n self.postMessage({ kind: `${kind}.call`, id, method, args } as Response);\n });\n}\n\nasync function ensureWasm() {\n if (wasmReady) return wasmReady;\n // The bundled wasm path is rewritten by the build script to be relative to `dist/`.\n wasmReady = init().then(() => undefined);\n return wasmReady;\n}\n\n// The WASM `PingClient` is SINGLE-THREADED (this one worker). Its async\n// methods hold internal locks across `.await` (e.g. a `conversations`\n// RwLock guard kept while `snapshot_to_storage` awaits IndexedDB). If we\n// let `onmessage` dispatch a SECOND top-level request while the first is\n// suspended at an await, the two WASM calls interleave on the single\n// thread, the second re-acquires a held lock, and `parking_lot`'s wasm\n// stub `panic!`s with \"Parking not supported on this platform\" — which\n// poisons the module (`RuntimeError: unreachable`) and breaks every\n// subsequent call. We therefore SERIALIZE top-level request dispatch:\n// each request runs to completion before the next begins.\n//\n// CRUCIAL: `storage.reply` / `transport.reply` are NOT serialized — an\n// in-flight request awaits those replies (via `callMain`), so queuing\n// them behind the request would deadlock. They resolve pending callbacks\n// immediately, exactly as before.\nlet dispatchChain: Promise<void> = Promise.resolve();\n\nasync function runRequest(msg: Request): Promise<void> {\n try {\n const value = await dispatch(msg);\n (self.postMessage as (m: Response) => void)({ kind: \"result\", id: msg.id, ok: true, value });\n } catch (e) {\n (self.postMessage as (m: Response) => void)({\n kind: \"result\", id: msg.id, ok: false, error: e instanceof Error ? e.message : String(e),\n });\n }\n}\n\nself.onmessage = (ev: MessageEvent<Request>) => {\n const msg = ev.data;\n\n // Storage / transport responses from the main thread — handle\n // immediately (they unblock the in-flight request). Never queued.\n if (msg.kind === \"storage.reply\") {\n const slot = pendingStorage.get(msg.id);\n if (slot) {\n pendingStorage.delete(msg.id);\n msg.ok ? slot({ ok: true, value: msg.value })\n : slot({ ok: false, value: msg.error });\n }\n return;\n }\n if (msg.kind === \"transport.reply\") {\n const slot = pendingTransport.get(msg.id);\n if (slot) {\n pendingTransport.delete(msg.id);\n msg.ok ? slot({ ok: true, value: msg.value })\n : slot({ ok: false, value: msg.error });\n }\n return;\n }\n\n // Top-level client request — chain it after the previous one so only a\n // single WASM call is ever in flight. `runRequest` never rejects (it\n // posts the error as a result), so the chain can't break.\n dispatchChain = dispatchChain.then(() => runRequest(msg));\n};\n\nasync function dispatch(msg: Request): Promise<unknown> {\n await ensureWasm();\n switch (msg.kind) {\n case \"init\": {\n client = await PingClient.init(\n msg.identityExport, msg.deviceLabel,\n proxyStorage as unknown as never,\n proxyTransport as unknown as never,\n msg.nowMs,\n // Optional Ed25519 device signing secret — see protocol.ts\n // and ClientConfig.deviceSigningSecretKey. Forwarding `null`\n // explicitly when absent so the wasm-bindgen `Option<Vec<u8>>`\n // shape is matched correctly.\n msg.deviceSigningSecretKey ?? null,\n );\n // Wire decrypted application-message callback back to the main thread.\n client.onMessage((m: unknown) => {\n (self.postMessage as (m: Response) => void)({ kind: \"event.message\", msg: m as never });\n });\n return null;\n }\n case \"generateIdentity\":\n return PingClient.generateIdentity();\n case \"userId\": return ensureClient().userId();\n case \"deviceId\": return ensureClient().deviceId();\n case \"freshKeyPackage\": return ensureClient().freshKeyPackage();\n case \"createConversation\":\n return await ensureClient().createConversation(msg.name ?? undefined, msg.nowMs);\n case \"joinConversation\": {\n const id = await ensureClient().joinConversation(msg.welcome, msg.nowMs) as Uint8Array;\n // Notify the main thread that we just entered a new conversation. We forward the\n // Welcome's `sender_device` so the host can label \"joined chat with <inviter>\".\n (self.postMessage as (m: Response) => void)({\n kind: \"event.conversation\",\n id,\n epoch: 0,\n sender: msg.welcome.sender_device,\n });\n return id;\n }\n case \"listConversations\":\n return ensureClient().listConversations();\n case \"members\":\n return ensureClient().members(msg.conv);\n case \"send\":\n return await ensureClient().send(msg.conv, msg.plaintext, msg.nowMs);\n case \"addMembers\":\n // wasm-bindgen takes the entries as a plain array of {deviceId, keyPackage};\n // serde-wasm-bindgen on the Rust side deserialises into Vec<JsAddMemberEntry>.\n return await ensureClient().addMembers(msg.conv, msg.entries, msg.nowMs);\n case \"admitDeviceToChats\":\n // Per-chat add for a newly-linked device. Returns Vec<JsAdmitChatOutcome>\n // — the host inspects per-entry status to decide whether to retry.\n return await ensureClient().admitDeviceToChats(msg.deviceId, msg.entries, msg.nowMs);\n case \"removeMembers\":\n // wasm-bindgen exposes Vec<u32> as Uint32Array; convert from the protocol's number[].\n return await ensureClient().removeMembers(msg.conv, new Uint32Array(msg.leaves), msg.nowMs);\n case \"revokeDevice\":\n // [CR-2] returns the array of Commit envelopes the SDK has already broadcast.\n return await ensureClient().revokeDevice(msg.deviceId, msg.nowMs);\n case \"processEnvelope\": {\n const result = await ensureClient().processEnvelope(msg.envelope, msg.nowMs);\n (self.postMessage as (m: Response) => void)({\n kind: \"event.conversation\",\n id: msg.envelope.conversation_id,\n epoch: msg.envelope.epoch,\n });\n return result;\n }\n case \"syncConversations\":\n return await ensureClient().syncConversations(msg.nowMs);\n case \"buildLinkingTicket\":\n return await ensureClient().buildLinkingTicket(\n msg.newDeviceId, msg.newDeviceKp, msg.lastAppEvents, msg.nowMs,\n );\n case \"consumeLinkingTicket\":\n await ensureClient().consumeLinkingTicket(msg.ticket, msg.nowMs);\n return null;\n case \"decodeCatchupSnapshot\":\n // Pure WASM — no client state required. The new device may call this in an\n // ephemeral worker before init() completes.\n return wasmDecodeCatchupSnapshot(msg.snapshotBytes);\n case \"exportConversationSecret\":\n // wasm-bindgen returns a Uint8Array sized to `length`. The bytes are a secret —\n // the main thread is responsible for clearing the typed array when done.\n return ensureClient().exportConversationSecret(\n msg.conv, msg.label, msg.context, msg.length,\n );\n case \"sealLinkingTicket\":\n // Pure WASM call — no client state required. Lets a sender seal a ticket from an\n // ephemeral worker without standing up the full PingClient.\n return wasmSealLinkingTicket(msg.ticket, msg.newDevicePub);\n case \"openLinkingTicket\":\n // Same — runs without an initialised client, which is the receiving device's\n // pre-bootstrap state (it has the X25519 ephemeral key but no identity yet).\n return wasmOpenLinkingTicket(msg.sealed, msg.newDevicePriv);\n case \"hpkeSeal\":\n // Generic HPKE seal for app-layer envelopes (e.g. linking auth envelope).\n return wasmHpkeSeal(msg.plaintext, msg.recipientPub, msg.info);\n case \"hpkeOpen\":\n return wasmHpkeOpen(msg.sealed, msg.recipientPriv, msg.info);\n case \"exportConversationStateSnapshot\":\n // [CR-7] state snapshot bytes are a secret (past epoch keys); the main thread\n // is responsible for clearing the typed array when done.\n return ensureClient().exportConversationStateSnapshot(msg.conv, msg.nowMs);\n case \"importStateSnapshot\":\n // [CR-7] returns the imported conversation id as a Uint8Array.\n return await ensureClient().importStateSnapshot(msg.snapshotBytes, msg.nowMs);\n // Recovery — all pure WASM; no client state required.\n case \"generateMnemonicPhrase\":\n return wasmGenerateMnemonicPhrase();\n case \"normalizeMnemonicPhrase\":\n return wasmNormalizeMnemonicPhrase(msg.phrase);\n case \"encryptBackup\":\n return wasmEncryptBackup(\n msg.mnemonicPhrase, msg.accountId, msg.identityExport,\n msg.deviceGroupSnapshot,\n // Map idiomatic camelCase → the snake_case keys serde expects on the\n // WASM boundary (matches the decrypt view's account_id / group_state_bytes).\n msg.conversationSnapshots.map((c) => ({\n conversation_id: c.conversationId,\n group_state_bytes: c.groupStateBytes,\n })),\n msg.createdAtMs,\n );\n case \"decryptBackup\":\n return wasmDecryptBackup(msg.blob, msg.mnemonicPhrase);\n case \"sealHistoryBundle\":\n return wasmSealHistoryBundle(msg.bundle, msg.recipientPub, msg.senderIdentitySecret);\n case \"openHistoryBundle\":\n return wasmOpenHistoryBundle(msg.sealed, msg.recipientPriv, msg.senderIdentityPub);\n default:\n throw new Error(`unknown request kind: ${(msg as { kind: string }).kind}`);\n }\n}\n\nfunction ensureClient(): PingClient {\n if (!client) throw new Error(\"client not initialised\");\n return client;\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
package/wasm/ping_wasm.d.ts
CHANGED
|
@@ -318,9 +318,9 @@ export interface InitOutput {
|
|
|
318
318
|
readonly wasmbindgentestcontext_include_ignored: (a: number, b: number) => void;
|
|
319
319
|
readonly wasmbindgentestcontext_new: (a: number) => number;
|
|
320
320
|
readonly wasmbindgentestcontext_run: (a: number, b: number, c: number) => number;
|
|
321
|
-
readonly
|
|
322
|
-
readonly
|
|
323
|
-
readonly
|
|
321
|
+
readonly __wasm_bindgen_func_elem_2828: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
322
|
+
readonly __wasm_bindgen_func_elem_2814: (a: number, b: number, c: number, d: number) => void;
|
|
323
|
+
readonly __wasm_bindgen_func_elem_2838: (a: number, b: number, c: number, d: number) => void;
|
|
324
324
|
readonly __wbindgen_export: (a: number, b: number) => number;
|
|
325
325
|
readonly __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
|
|
326
326
|
readonly __wbindgen_export3: (a: number) => void;
|
package/wasm/ping_wasm.js
CHANGED
|
@@ -1115,7 +1115,7 @@ function __wbg_get_imports() {
|
|
|
1115
1115
|
const a = state0.a;
|
|
1116
1116
|
state0.a = 0;
|
|
1117
1117
|
try {
|
|
1118
|
-
return
|
|
1118
|
+
return __wasm_bindgen_func_elem_2828(a, state0.b, arg0, arg1, arg2);
|
|
1119
1119
|
} finally {
|
|
1120
1120
|
state0.a = a;
|
|
1121
1121
|
}
|
|
@@ -1256,7 +1256,7 @@ function __wbg_get_imports() {
|
|
|
1256
1256
|
const a = state0.a;
|
|
1257
1257
|
state0.a = 0;
|
|
1258
1258
|
try {
|
|
1259
|
-
return
|
|
1259
|
+
return __wasm_bindgen_func_elem_2838(a, state0.b, arg0, arg1);
|
|
1260
1260
|
} finally {
|
|
1261
1261
|
state0.a = a;
|
|
1262
1262
|
}
|
|
@@ -1433,8 +1433,8 @@ function __wbg_get_imports() {
|
|
|
1433
1433
|
return addHeapObject(ret);
|
|
1434
1434
|
},
|
|
1435
1435
|
__wbindgen_cast_0000000000000001: function(arg0, arg1) {
|
|
1436
|
-
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx:
|
|
1437
|
-
const ret = makeMutClosure(arg0, arg1,
|
|
1436
|
+
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 774, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
|
|
1437
|
+
const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_2814);
|
|
1438
1438
|
return addHeapObject(ret);
|
|
1439
1439
|
},
|
|
1440
1440
|
__wbindgen_cast_0000000000000002: function(arg0) {
|
|
@@ -1478,10 +1478,10 @@ function __wbg_get_imports() {
|
|
|
1478
1478
|
};
|
|
1479
1479
|
}
|
|
1480
1480
|
|
|
1481
|
-
function
|
|
1481
|
+
function __wasm_bindgen_func_elem_2814(arg0, arg1, arg2) {
|
|
1482
1482
|
try {
|
|
1483
1483
|
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
1484
|
-
wasm.
|
|
1484
|
+
wasm.__wasm_bindgen_func_elem_2814(retptr, arg0, arg1, addHeapObject(arg2));
|
|
1485
1485
|
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
1486
1486
|
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
1487
1487
|
if (r1) {
|
|
@@ -1492,12 +1492,12 @@ function __wasm_bindgen_func_elem_2820(arg0, arg1, arg2) {
|
|
|
1492
1492
|
}
|
|
1493
1493
|
}
|
|
1494
1494
|
|
|
1495
|
-
function
|
|
1496
|
-
wasm.
|
|
1495
|
+
function __wasm_bindgen_func_elem_2838(arg0, arg1, arg2, arg3) {
|
|
1496
|
+
wasm.__wasm_bindgen_func_elem_2838(arg0, arg1, addHeapObject(arg2), addHeapObject(arg3));
|
|
1497
1497
|
}
|
|
1498
1498
|
|
|
1499
|
-
function
|
|
1500
|
-
wasm.
|
|
1499
|
+
function __wasm_bindgen_func_elem_2828(arg0, arg1, arg2, arg3, arg4) {
|
|
1500
|
+
wasm.__wasm_bindgen_func_elem_2828(arg0, arg1, addHeapObject(arg2), arg3, addHeapObject(arg4));
|
|
1501
1501
|
}
|
|
1502
1502
|
|
|
1503
1503
|
const WasmBindgenTestContextFinalization = (typeof FinalizationRegistry === 'undefined')
|
package/wasm/ping_wasm_bg.wasm
CHANGED
|
Binary file
|
|
@@ -51,9 +51,9 @@ export const wasmbindgentestcontext_filtered_count: (a: number, b: number) => vo
|
|
|
51
51
|
export const wasmbindgentestcontext_include_ignored: (a: number, b: number) => void;
|
|
52
52
|
export const wasmbindgentestcontext_new: (a: number) => number;
|
|
53
53
|
export const wasmbindgentestcontext_run: (a: number, b: number, c: number) => number;
|
|
54
|
-
export const
|
|
55
|
-
export const
|
|
56
|
-
export const
|
|
54
|
+
export const __wasm_bindgen_func_elem_2828: (a: number, b: number, c: number, d: number, e: number) => void;
|
|
55
|
+
export const __wasm_bindgen_func_elem_2814: (a: number, b: number, c: number, d: number) => void;
|
|
56
|
+
export const __wasm_bindgen_func_elem_2838: (a: number, b: number, c: number, d: number) => void;
|
|
57
57
|
export const __wbindgen_export: (a: number, b: number) => number;
|
|
58
58
|
export const __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
|
|
59
59
|
export const __wbindgen_export3: (a: number) => void;
|