diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
commit | 43a97878ce14b72f0981164f87f2e35e14151312 (patch) | |
tree | 620249daf56c0258faa40cbdcf9cfba06de2a846 /testing/web-platform/tests/streams/transferable/resources | |
parent | Initial commit. (diff) | |
download | firefox-upstream.tar.xz firefox-upstream.zip |
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/streams/transferable/resources')
11 files changed, 295 insertions, 0 deletions
diff --git a/testing/web-platform/tests/streams/transferable/resources/create-wasm-module.js b/testing/web-platform/tests/streams/transferable/resources/create-wasm-module.js new file mode 100644 index 0000000000..37064af95c --- /dev/null +++ b/testing/web-platform/tests/streams/transferable/resources/create-wasm-module.js @@ -0,0 +1,11 @@ +// There aren't many cloneable types that will cause an error on +// deserialization. WASM modules have the property that it's an error to +// deserialize them cross-site, which works for our purposes. +async function createWasmModule() { + // It doesn't matter what the module is, so we use one from another + // test. + const response = + await fetch("/wasm/serialization/module/resources/incrementer.wasm"); + const ab = await response.arrayBuffer(); + return WebAssembly.compile(ab); +} diff --git a/testing/web-platform/tests/streams/transferable/resources/deserialize-error-frame.html b/testing/web-platform/tests/streams/transferable/resources/deserialize-error-frame.html new file mode 100644 index 0000000000..5ec2fcda2c --- /dev/null +++ b/testing/web-platform/tests/streams/transferable/resources/deserialize-error-frame.html @@ -0,0 +1,39 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="create-wasm-module.js"></script> +<script> +async_test(t => { + parent.postMessage('init done', '*'); + window.addEventListener('message', async evt => { + if (evt.data.constructor.name !== 'WritableStream') { + return; + } + const ws = evt.data; + const writer = ws.getWriter(); + const module = await createWasmModule(); + writer.write(module); + await promise_rejects_dom(t, 'DataCloneError', writer.closed, + 'should reject with a DataCloneError'); + t.done(); + // Signal that this test is done. When both tests are done the iframe will + // be removed. + parent.postMessage('ws done', '*'); + }); +}, 'a WritableStream deserialization failure should result in a DataCloneError'); + +async_test(t => { + window.addEventListener('message', async evt => { + if (evt.data.constructor.name !== 'ReadableStream') { + return; + } + const rs = evt.data; + const reader = rs.getReader(); + await promise_rejects_dom(t, 'DataCloneError', reader.read(), + 'should reject with a DataCloneError'); + t.done(); + // Signal that this test is done. When both tests are done the iframe will + // be removed. + parent.postMessage('rs done', '*'); + }); +}, 'a ReadableStream deserialization failure should result in a DataCloneError'); +</script> diff --git a/testing/web-platform/tests/streams/transferable/resources/echo-iframe.html b/testing/web-platform/tests/streams/transferable/resources/echo-iframe.html new file mode 100644 index 0000000000..68f6850343 --- /dev/null +++ b/testing/web-platform/tests/streams/transferable/resources/echo-iframe.html @@ -0,0 +1,7 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<script> +addEventListener('message', evt => { + evt.source.postMessage(evt.data, '*', [evt.data]); +}); +</script> diff --git a/testing/web-platform/tests/streams/transferable/resources/echo-worker.js b/testing/web-platform/tests/streams/transferable/resources/echo-worker.js new file mode 100644 index 0000000000..806c237108 --- /dev/null +++ b/testing/web-platform/tests/streams/transferable/resources/echo-worker.js @@ -0,0 +1,2 @@ +// A worker that just transfers back any message that is sent to it. +onmessage = evt => postMessage(evt.data, [evt.data]); diff --git a/testing/web-platform/tests/streams/transferable/resources/helpers.js b/testing/web-platform/tests/streams/transferable/resources/helpers.js new file mode 100644 index 0000000000..12504537f9 --- /dev/null +++ b/testing/web-platform/tests/streams/transferable/resources/helpers.js @@ -0,0 +1,132 @@ +'use strict'; + +(() => { + // Create a ReadableStream that will pass the tests in + // testTransferredReadableStream(), below. + function createOriginalReadableStream() { + return new ReadableStream({ + start(controller) { + controller.enqueue('a'); + controller.close(); + } + }); + } + + // Common tests to roughly determine that |rs| is a correctly transferred + // version of a stream created by createOriginalReadableStream(). + function testTransferredReadableStream(rs) { + assert_equals(rs.constructor, ReadableStream, + 'rs should be a ReadableStream in this realm'); + assert_true(rs instanceof ReadableStream, + 'instanceof check should pass'); + + // Perform a brand-check on |rs| in the process of calling getReader(). + const reader = ReadableStream.prototype.getReader.call(rs); + + return reader.read().then(({value, done}) => { + assert_false(done, 'done should be false'); + assert_equals(value, 'a', 'value should be "a"'); + return reader.read(); + }).then(({done}) => { + assert_true(done, 'done should be true'); + }); + } + + function testMessage(msg) { + assert_array_equals(msg.ports, [], 'there should be no ports in the event'); + return testTransferredReadableStream(msg.data); + } + + function testMessageEvent(target) { + return new Promise((resolve, reject) => { + target.addEventListener('message', ev => { + try { + resolve(testMessage(ev)); + } catch (e) { + reject(e); + } + }, {once: true}); + }); + } + + function testMessageEventOrErrorMessage(target) { + return new Promise((resolve, reject) => { + target.addEventListener('message', ev => { + if (typeof ev.data === 'string') { + // Assume it's an error message and reject with it. + reject(ev.data); + return; + } + + try { + resolve(testMessage(ev)); + } catch (e) { + reject(e); + } + }, {once: true}); + }); + } + + function checkTestResults(target) { + return new Promise((resolve, reject) => { + target.onmessage = msg => { + // testharness.js sends us objects which we need to ignore. + if (typeof msg.data !== 'string') + return; + + if (msg.data === 'OK') { + resolve(); + } else { + reject(msg.data); + } + }; + }); + } + + // These tests assume that a transferred ReadableStream will behave the same + // regardless of how it was transferred. This enables us to simply transfer the + // stream to ourselves. + function createTransferredReadableStream(underlyingSource) { + const original = new ReadableStream(underlyingSource); + const promise = new Promise((resolve, reject) => { + addEventListener('message', msg => { + const rs = msg.data; + if (rs instanceof ReadableStream) { + resolve(rs); + } else { + reject(new Error(`what is this thing: "${rs}"?`)); + } + }, {once: true}); + }); + postMessage(original, '*', [original]); + return promise; + } + + function recordingTransferredReadableStream(underlyingSource, strategy) { + const original = recordingReadableStream(underlyingSource, strategy); + const promise = new Promise((resolve, reject) => { + addEventListener('message', msg => { + const rs = msg.data; + if (rs instanceof ReadableStream) { + rs.events = original.events; + rs.eventsWithoutPulls = original.eventsWithoutPulls; + rs.controller = original.controller; + resolve(rs); + } else { + reject(new Error(`what is this thing: "${rs}"?`)); + } + }, {once: true}); + }); + postMessage(original, '*', [original]); + return promise; + } + + self.createOriginalReadableStream = createOriginalReadableStream; + self.testMessage = testMessage; + self.testMessageEvent = testMessageEvent; + self.testMessageEventOrErrorMessage = testMessageEventOrErrorMessage; + self.checkTestResults = checkTestResults; + self.createTransferredReadableStream = createTransferredReadableStream; + self.recordingTransferredReadableStream = recordingTransferredReadableStream; + +})(); diff --git a/testing/web-platform/tests/streams/transferable/resources/receiving-shared-worker.js b/testing/web-platform/tests/streams/transferable/resources/receiving-shared-worker.js new file mode 100644 index 0000000000..84f779c3db --- /dev/null +++ b/testing/web-platform/tests/streams/transferable/resources/receiving-shared-worker.js @@ -0,0 +1,11 @@ +'use strict'; +importScripts('/resources/testharness.js', 'helpers.js'); + +onconnect = evt => { + const port = evt.source; + const promise = testMessageEvent(port); + port.start(); + promise + .then(() => port.postMessage('OK')) + .catch(err => port.postMessage(`BAD: ${err}`)); +}; diff --git a/testing/web-platform/tests/streams/transferable/resources/receiving-worker.js b/testing/web-platform/tests/streams/transferable/resources/receiving-worker.js new file mode 100644 index 0000000000..4ebb9c5f8f --- /dev/null +++ b/testing/web-platform/tests/streams/transferable/resources/receiving-worker.js @@ -0,0 +1,7 @@ +'use strict'; +importScripts('/resources/testharness.js', 'helpers.js'); + +const promise = testMessageEvent(self); +promise + .then(() => postMessage('OK')) + .catch(err => postMessage(`BAD: ${err}`)); diff --git a/testing/web-platform/tests/streams/transferable/resources/sending-shared-worker.js b/testing/web-platform/tests/streams/transferable/resources/sending-shared-worker.js new file mode 100644 index 0000000000..e579077894 --- /dev/null +++ b/testing/web-platform/tests/streams/transferable/resources/sending-shared-worker.js @@ -0,0 +1,12 @@ +'use strict'; +importScripts('helpers.js'); + +onconnect = msg => { + const port = msg.source; + const orig = createOriginalReadableStream(); + try { + port.postMessage(orig, [orig]); + } catch (e) { + port.postMessage(e.message); + } +}; diff --git a/testing/web-platform/tests/streams/transferable/resources/sending-worker.js b/testing/web-platform/tests/streams/transferable/resources/sending-worker.js new file mode 100644 index 0000000000..0b79733f74 --- /dev/null +++ b/testing/web-platform/tests/streams/transferable/resources/sending-worker.js @@ -0,0 +1,5 @@ +'use strict'; +importScripts('helpers.js'); + +const orig = createOriginalReadableStream(); +postMessage(orig, [orig]); diff --git a/testing/web-platform/tests/streams/transferable/resources/service-worker-iframe.html b/testing/web-platform/tests/streams/transferable/resources/service-worker-iframe.html new file mode 100644 index 0000000000..348d067c92 --- /dev/null +++ b/testing/web-platform/tests/streams/transferable/resources/service-worker-iframe.html @@ -0,0 +1,39 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<script src="/resources/testharness.js"></script> +<script src="helpers.js"></script> +<script> +'use strict'; + +setup({ + explicit_done: true +}); + +function startTests() { + promise_test(() => { + const orig = createOriginalReadableStream(); + const promise = checkTestResults(navigator.serviceWorker); + navigator.serviceWorker.controller.postMessage(orig, [orig]); + assert_true(orig.locked, 'the original stream should be locked'); + return promise; + }, 'serviceWorker.controller.postMessage should be able to transfer a ' + + 'ReadableStream'); + + promise_test(() => { + const promise = testMessageEventOrErrorMessage(navigator.serviceWorker); + navigator.serviceWorker.controller.postMessage('SEND'); + return promise; + }, 'postMessage in a service worker should be able to transfer ReadableStream'); + + done(); +} + +// Delay running the tests until we get a message from the page telling us to. +// This is to work around an issue where testharness.js doesn't detect +// completion of the tests if they fail too early. +onmessage = msg => { + if (msg.data === 'explicit trigger') + startTests(); +}; + +</script> diff --git a/testing/web-platform/tests/streams/transferable/resources/service-worker.js b/testing/web-platform/tests/streams/transferable/resources/service-worker.js new file mode 100644 index 0000000000..af76b6c11b --- /dev/null +++ b/testing/web-platform/tests/streams/transferable/resources/service-worker.js @@ -0,0 +1,30 @@ +'use strict'; +importScripts('/resources/testharness.js', 'helpers.js'); + +onmessage = msg => { + const client = msg.source; + if (msg.data === 'SEND') { + sendingTest(client); + } else { + receivingTest(msg, client); + } +}; + +function sendingTest(client) { + const orig = createOriginalReadableStream(); + try { + client.postMessage(orig, [orig]); + } catch (e) { + client.postMessage(e.message); + } +} + +function receivingTest(msg, client) { + try { + msg.waitUntil(testMessage(msg) + .then(() => client.postMessage('OK')) + .catch(e => client.postMessage(`BAD: ${e}`))); + } catch (e) { + client.postMessage(`BAD: ${e}`); + } +} |