summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/html/webappapis/structured-clone/structured-clone-battery-of-tests-with-transferables.js
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/html/webappapis/structured-clone/structured-clone-battery-of-tests-with-transferables.js')
-rw-r--r--testing/web-platform/tests/html/webappapis/structured-clone/structured-clone-battery-of-tests-with-transferables.js169
1 files changed, 169 insertions, 0 deletions
diff --git a/testing/web-platform/tests/html/webappapis/structured-clone/structured-clone-battery-of-tests-with-transferables.js b/testing/web-platform/tests/html/webappapis/structured-clone/structured-clone-battery-of-tests-with-transferables.js
new file mode 100644
index 0000000000..23cf4f651a
--- /dev/null
+++ b/testing/web-platform/tests/html/webappapis/structured-clone/structured-clone-battery-of-tests-with-transferables.js
@@ -0,0 +1,169 @@
+structuredCloneBatteryOfTests.push({
+ description: 'ArrayBuffer',
+ async f(runner) {
+ const buffer = new Uint8Array([1]).buffer;
+ const copy = await runner.structuredClone(buffer, [buffer]);
+ assert_equals(buffer.byteLength, 0);
+ assert_equals(copy.byteLength, 1);
+ }
+});
+
+structuredCloneBatteryOfTests.push({
+ description: 'MessagePort',
+ async f(runner) {
+ const {port1, port2} = new MessageChannel();
+ const copy = await runner.structuredClone(port2, [port2]);
+ const msg = new Promise(resolve => port1.onmessage = resolve);
+ copy.postMessage('ohai');
+ assert_equals((await msg).data, 'ohai');
+ }
+});
+
+// TODO: ImageBitmap
+
+structuredCloneBatteryOfTests.push({
+ description: 'A detached ArrayBuffer cannot be transferred',
+ async f(runner, t) {
+ const buffer = new ArrayBuffer();
+ await runner.structuredClone(buffer, [buffer]);
+ await promise_rejects_dom(
+ t,
+ "DataCloneError",
+ runner.structuredClone(buffer, [buffer])
+ );
+ }
+});
+
+structuredCloneBatteryOfTests.push({
+ description: 'A detached platform object cannot be transferred',
+ async f(runner, t) {
+ const {port1} = new MessageChannel();
+ await runner.structuredClone(port1, [port1]);
+ await promise_rejects_dom(
+ t,
+ "DataCloneError",
+ runner.structuredClone(port1, [port1])
+ );
+ }
+});
+
+structuredCloneBatteryOfTests.push({
+ description: 'Transferring a non-transferable platform object fails',
+ async f(runner, t) {
+ const blob = new Blob();
+ await promise_rejects_dom(
+ t,
+ "DataCloneError",
+ runner.structuredClone(blob, [blob])
+ );
+ }
+});
+
+structuredCloneBatteryOfTests.push({
+ description: 'An object whose interface is deleted from the global object must still be received',
+ async f(runner) {
+ const {port1} = new MessageChannel();
+ const messagePortInterface = globalThis.MessagePort;
+ delete globalThis.MessagePort;
+ try {
+ const transfer = await runner.structuredClone(port1, [port1]);
+ assert_true(transfer instanceof messagePortInterface);
+ } finally {
+ globalThis.MessagePort = messagePortInterface;
+ }
+ }
+});
+
+structuredCloneBatteryOfTests.push({
+ description: 'A subclass instance will be received as its closest transferable superclass',
+ async f(runner) {
+ // MessagePort doesn't have a constructor, so we must use something else.
+
+ // Make sure that ReadableStream is transferable before we test its subclasses.
+ try {
+ const stream = new ReadableStream();
+ await runner.structuredClone(stream, [stream]);
+ } catch(err) {
+ if (err instanceof DOMException && err.code === DOMException.DATA_CLONE_ERR) {
+ throw new OptionalFeatureUnsupportedError("ReadableStream isn't transferable");
+ } else {
+ throw err;
+ }
+ }
+
+ class ReadableStreamSubclass extends ReadableStream {}
+ const original = new ReadableStreamSubclass();
+ const transfer = await runner.structuredClone(original, [original]);
+ assert_equals(Object.getPrototypeOf(transfer), ReadableStream.prototype);
+ }
+});
+
+structuredCloneBatteryOfTests.push({
+ description: 'Resizable ArrayBuffer is transferable',
+ async f(runner) {
+ const buffer = new ArrayBuffer(16, { maxByteLength: 1024 });
+ const copy = await runner.structuredClone(buffer, [buffer]);
+ assert_equals(buffer.byteLength, 0);
+ assert_equals(copy.byteLength, 16);
+ assert_equals(copy.maxByteLength, 1024);
+ assert_true(copy.resizable);
+ }
+});
+
+structuredCloneBatteryOfTests.push({
+ description: 'Length-tracking TypedArray is transferable',
+ async f(runner) {
+ const ab = new ArrayBuffer(16, { maxByteLength: 1024 });
+ const ta = new Uint8Array(ab);
+ const copy = await runner.structuredClone(ta, [ab]);
+ assert_equals(ab.byteLength, 0);
+ assert_equals(copy.buffer.byteLength, 16);
+ assert_equals(copy.buffer.maxByteLength, 1024);
+ assert_true(copy.buffer.resizable);
+ copy.buffer.resize(32);
+ assert_equals(copy.byteLength, 32);
+ }
+});
+
+structuredCloneBatteryOfTests.push({
+ description: 'Length-tracking DataView is transferable',
+ async f(runner) {
+ const ab = new ArrayBuffer(16, { maxByteLength: 1024 });
+ const dv = new DataView(ab);
+ const copy = await runner.structuredClone(dv, [ab]);
+ assert_equals(ab.byteLength, 0);
+ assert_equals(copy.buffer.byteLength, 16);
+ assert_equals(copy.buffer.maxByteLength, 1024);
+ assert_true(copy.buffer.resizable);
+ copy.buffer.resize(32);
+ assert_equals(copy.byteLength, 32);
+ }
+});
+
+structuredCloneBatteryOfTests.push({
+ description: 'Transferring OOB TypedArray throws',
+ async f(runner, t) {
+ const ab = new ArrayBuffer(16, { maxByteLength: 1024 });
+ const ta = new Uint8Array(ab, 8);
+ ab.resize(0);
+ await promise_rejects_dom(
+ t,
+ "DataCloneError",
+ runner.structuredClone(ta, [ab])
+ );
+ }
+});
+
+structuredCloneBatteryOfTests.push({
+ description: 'Transferring OOB DataView throws',
+ async f(runner, t) {
+ const ab = new ArrayBuffer(16, { maxByteLength: 1024 });
+ const dv = new DataView(ab, 8);
+ ab.resize(0);
+ await promise_rejects_dom(
+ t,
+ "DataCloneError",
+ runner.structuredClone(dv, [ab])
+ );
+ }
+});