Skip to content

[WebCrypto] Make serialization tests global-agnostic#59939

Open
panva wants to merge 2 commits into
web-platform-tests:masterfrom
panva:refactor-cryptokey-serialization
Open

[WebCrypto] Make serialization tests global-agnostic#59939
panva wants to merge 2 commits into
web-platform-tests:masterfrom
panva:refactor-cryptokey-serialization

Conversation

@panva
Copy link
Copy Markdown
Contributor

@panva panva commented May 18, 2026

A followup to 2aa7252

Update the CryptoKey serialization tests to use MessageChannel.postMessage() for the serialization/deserialization round trip instead of opening a popup window. This keeps the structured clone coverage while allowing the tests to run in any global, including workers and non-browser WPT runners.

Rename the serialization tests from .https.window.js to .https.any.js now that they no longer depend on Window-only APIs. Mark the Ed448 and X448 serialization tests as tentative, matching their current WebCrypto status.

Remove the now-unused popup helper page.

spec-wise this is the same structured serialization path

  • window.postMessage() runs StructuredSerializeWithTransfer(message, transfer), then later StructuredDeserializeWithTransfer(...) into the target window realm.
  • MessagePort.postMessage() also runs StructuredSerializeWithTransfer(message, transfer), then later StructuredDeserializeWithTransfer(...) for the receiving port’s realm.
  • CryptoKey is defined as a [Serializable] platform object in WebCrypto, and its serialization/deserialization steps preserve [[type]], [[extractable]], [[algorithm]], [[usages]], and [[handle]].

FYI/cc @hubertchao

Use MessageChannel.postMessage() instead of a popup window for
CryptoKey serialization round trips. This keeps the structured clone
coverage while allowing the tests to run in server runtimes.

Rename the tests from .https.window.js to .https.any.js, mark the
Ed448 and X448 cases as tentative, and remove the unused popup page.

Signed-off-by: Filip Skokan <panva.ip@gmail.com>
Comment on lines +2 to +14
function structuredCloneViaMessageChannel(data, t) {
const channel = new MessageChannel();
t.add_cleanup(() => {
channel.port1.close();
channel.port2.close();
});

const result = waitForEvent(channel.port1, 'message');
channel.port1.start();
channel.port2.postMessage(data);

return result.then(evt => evt.data);
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason not to just use structuredClone() instead?

Copy link
Copy Markdown
Contributor Author

@panva panva May 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MessageChannel is closer to @hubertchao's original test I think as it tests an async messaging serialization path where structuredClone() is synchronous?

Copy link
Copy Markdown
Member

@twiss twiss May 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think for serialization it's equivalent, because the spec says:

window.postMessage() performs StructuredSerializeWithTransfer on its arguments, but is careful to do so immediately, inside the synchronous portion of its algorithm. (...)

(and the same seems to be true for MessagePort.postMessage().

The deserialization does happen later (in the case of postMessage), but I don't think that really matters for the purpose of testing (de)serialization specifically?

For completeness:

The structuredClone(value, options) method steps are:

  1. Let serialized be ? StructuredSerializeWithTransfer(value, options["transfer"]).
  2. Let deserializeRecord be ? StructuredDeserializeWithTransfer(serialized, this's relevant realm).
  3. Return deserializeRecord.[[Deserialized]].

so essentially the same as this function except fully synchronously.

Copy link
Copy Markdown
Contributor Author

@panva panva May 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know, but @hubertchao said this in their commit

(The other main way to do CryptoKey serialization is to use an IndexedDB.
Posting messages was simpler.)

So on the off chance I'm missing something I wanted to stick to an async method instead.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went with postMessage initially in the test because the only 2 ways @davidben and I thought of to test serialization was that or IndexedDB; the async part of the test wasn't important.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hubertchao ok, so we may change it to structuredClone?

Copy link
Copy Markdown
Contributor Author

@panva panva May 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@hubertchao as an aside - i've checked out chrome canary with the pqc flag and updated the UI and test vector harness in https://panva.github.io/hpke/?native to account for missing cSHAKE256 that's needed for HPKE deterministic key derivation. ML-KEM-{768, 1024} and ChaCha20-Poly1305 HPKE vectors pass.

Screenshot 2026-05-18 at 13 21 57 Screenshot 2026-05-18 at 13 22 03 Screenshot 2026-05-18 at 13 22 19

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants