Skip to content

Commit

Permalink
test: run webmessaging/broadcastchannel WPT
Browse files Browse the repository at this point in the history
Refs: nodejs#38803

PR-URL: nodejs#41962
Reviewed-By: Colin Ihrig <[email protected]>
Reviewed-By: Benjamin Gruenbaum <[email protected]>
Reviewed-By: Mestery <[email protected]>
  • Loading branch information
bnoordhuis authored and bengl committed Feb 21, 2022
1 parent 2ab877f commit 602acb2
Show file tree
Hide file tree
Showing 20 changed files with 1,353 additions and 0 deletions.
120 changes: 120 additions & 0 deletions test/fixtures/wpt/webmessaging/broadcastchannel/basics.any.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
async_test(t => {
let c1 = new BroadcastChannel('eventType');
let c2 = new BroadcastChannel('eventType');

c2.onmessage = t.step_func(e => {
assert_true(e instanceof MessageEvent);
assert_equals(e.target, c2);
assert_equals(e.type, 'message');
assert_equals(e.origin, location.origin, 'origin');
assert_equals(e.data, 'hello world');
assert_equals(e.source, null, 'source');
t.done();
});
c1.postMessage('hello world');
}, 'postMessage results in correct event');

async_test(t => {
let c1 = new BroadcastChannel('order');
let c2 = new BroadcastChannel('order');
let c3 = new BroadcastChannel('order');

let events = [];
let doneCount = 0;
let handler = t.step_func(e => {
events.push(e);
if (e.data == 'done') {
doneCount++;
if (doneCount == 2) {
assert_equals(events.length, 6);
assert_equals(events[0].target, c2, 'target for event 0');
assert_equals(events[0].data, 'from c1');
assert_equals(events[1].target, c3, 'target for event 1');
assert_equals(events[1].data, 'from c1');
assert_equals(events[2].target, c1, 'target for event 2');
assert_equals(events[2].data, 'from c3');
assert_equals(events[3].target, c2, 'target for event 3');
assert_equals(events[3].data, 'from c3');
assert_equals(events[4].target, c1, 'target for event 4');
assert_equals(events[4].data, 'done');
assert_equals(events[5].target, c3, 'target for event 5');
assert_equals(events[5].data, 'done');
t.done();
}
}
});
c1.onmessage = handler;
c2.onmessage = handler;
c3.onmessage = handler;

c1.postMessage('from c1');
c3.postMessage('from c3');
c2.postMessage('done');
}, 'messages are delivered in port creation order');

async_test(t => {
let c1 = new BroadcastChannel('closed');
let c2 = new BroadcastChannel('closed');
let c3 = new BroadcastChannel('closed');

c2.onmessage = t.unreached_func();
c2.close();
c3.onmessage = t.step_func(() => t.done());
c1.postMessage('test');
}, 'messages aren\'t delivered to a closed port');

async_test(t => {
let c1 = new BroadcastChannel('closed');
let c2 = new BroadcastChannel('closed');
let c3 = new BroadcastChannel('closed');

c2.onmessage = t.unreached_func();
c3.onmessage = t.step_func(() => t.done());
c1.postMessage('test');
c2.close();
}, 'messages aren\'t delivered to a port closed after calling postMessage.');

async_test(t => {
let c1 = new BroadcastChannel('create-in-onmessage');
let c2 = new BroadcastChannel('create-in-onmessage');

c2.onmessage = t.step_func(e => {
assert_equals(e.data, 'first');
c2.close();
let c3 = new BroadcastChannel('create-in-onmessage');
c3.onmessage = t.step_func(event => {
assert_equals(event.data, 'done');
t.done();
});
c1.postMessage('done');
});
c1.postMessage('first');
c2.postMessage('second');
}, 'closing and creating channels during message delivery works correctly');

async_test(t => {
let c1 = new BroadcastChannel('close-in-onmessage');
let c2 = new BroadcastChannel('close-in-onmessage');
let c3 = new BroadcastChannel('close-in-onmessage');
let events = [];
c1.onmessage = e => events.push('c1: ' + e.data);
c2.onmessage = e => events.push('c2: ' + e.data);
c3.onmessage = e => events.push('c3: ' + e.data);

// c2 closes itself when it receives the first message
c2.addEventListener('message', e => {
c2.close();
});

c3.addEventListener('message', t.step_func(e => {
if (e.data == 'done') {
assert_array_equals(events, [
'c2: first',
'c3: first',
'c3: done']);
t.done();
}
}));
c1.postMessage('first');
c1.postMessage('done');
}, 'Closing a channel in onmessage prevents already queued tasks from firing onmessage events');
83 changes: 83 additions & 0 deletions test/fixtures/wpt/webmessaging/broadcastchannel/blobs.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<!DOCTYPE html>
<meta charset=utf-8>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
async_test(t => {
const c1 = new BroadcastChannel('blob');
const c2 = new BroadcastChannel('blob');
const c3 = new BroadcastChannel('blob');

let readCount = 0;
c2.onmessage = t.step_func(e => {
// check blob
assert_true('blob' in e.data);
assert_true(e.data.blob instanceof Blob);
assert_equals(e.data.blob.size, 6);
const reader = new FileReader();
reader.onerror = t.unreached_func();
reader.onload = t.step_func(() => {
assert_equals(reader.result, 'foobar');
if (++readCount == 2)
t.done();
});
reader.readAsText(e.data.blob);
});
c3.onmessage = c2.onmessage;
(() => {
c1.postMessage({blob: new Blob(['foo', 'bar'])});
})();
// TODO(https://github.com/web-platform-tests/wpt/issues/7899): Change to
// some sort of cross-browser GC trigger.
if (self.gc) self.gc();
}, 'Blobs work on BroadcastChannel');

async_test(t => {
const c1 = new BroadcastChannel('blobworker');
const c2 = new BroadcastChannel('blobworker');
const events = [];

const verifyEvents = function() {
assert_equals(events.length, 5);
assert_equals(events[0], 'from worker');
assert_equals(events[1], 'from worker');
assert_true(events[2].blob instanceof Blob);
assert_equals(events[2].blob.size, 11);
assert_true(events[3].blob instanceof Blob);
assert_equals(events[3].blob.size, 11);
assert_equals(events[4], 'done');
const reader = new FileReader();
reader.onerror = t.unreached_func();
reader.onload = t.step_func(() => {
assert_equals(reader.result, 'hello-world');
t.done();
});
reader.readAsText(events[3].blob);
};

let receivedDone = false;
let receivedWorkerDone = false;

c1.onmessage = e => events.push(e.data);
c2.onmessage = e => events.push(e.data);
c2.addEventListener('message', t.step_func(e => {
if (e.data.blob)
c1.postMessage('done');
if (e.data === 'done')
receivedDone = true;
if (receivedDone && receivedWorkerDone)
verifyEvents();
}));

const worker = new Worker('resources/worker.js');
worker.onmessage = t.step_func(e => {
receivedWorkerDone = true;
if (receivedDone && receivedWorkerDone)
verifyEvents();
});
worker.postMessage({channel: 'blobworker'});
worker.postMessage({blob: ['hello-world']});

}, 'Blobs work with workers on BroadcastChannel');

</script>
38 changes: 38 additions & 0 deletions test/fixtures/wpt/webmessaging/broadcastchannel/cross-origin.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<!DOCTYPE html>
<meta charset=utf-8>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
<!-- Pull in the with_iframe helper function from the service worker tests -->
<script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script>
<body>
<script>

const events = [];

function testCompletion(t) {
return new Promise((resolve) => {
window.addEventListener("message", t.step_func(e => {
if (e.data == 'done') {
assert_equals(events.length, 0);
resolve();
}
}));
});
}

promise_test(async t => {

const bc0 = new BroadcastChannel('no-cross-origin-messages');
bc0.onmessage = e => {window.events.push(e);};

const testResults = testCompletion(t);
const url = get_host_info().HTTPS_NOTSAMESITE_ORIGIN +
'/webmessaging/broadcastchannel/resources/cross-origin.html';
await with_iframe(url);

return testResults;
}, "Messages aren't delivered across origins");

</script>
</body>
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<!DOCTYPE html>
<meta charset=utf-8>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
<script src="/common/utils.js"></script>
<script src="/common/dispatcher/dispatcher.js"></script>
<!-- Pull in executor_path needed by newPopup / newIframe -->
<script src="/html/cross-origin-embedder-policy/credentialless/resources/common.js"></script>
<!-- Pull in newPopup / newIframe -->
<script src="/html/cross-origin-embedder-policy/anonymous-iframe/resources/common.js"></script>
<body>
<script>

const emit_script = (channel_name, message, done_queue_name) => `
const bc = new BroadcastChannel("${channel_name}");
bc.postMessage("${message}");
send("${done_queue_name}", "done");
`;

promise_test(async t => {
const origin = get_host_info().HTTPS_ORIGIN;
const not_same_site_origin = get_host_info().HTTPS_NOTSAMESITE_ORIGIN;
const response_queue_uuid = token();

const popup_init_script = `
const importScript = ${importScript};
await importScript("/html/cross-origin-embedder-policy/credentialless" +
"/resources/common.js");
await importScript("/html/cross-origin-embedder-policy/anonymous-iframe" +
"/resources/common.js");
await importScript("/common/utils.js");
send("${response_queue_uuid}", newIframe("${origin}"));
`;

// Create a same-origin iframe in a cross-site popup.
const not_same_site_popup_uuid = newPopup(t, not_same_site_origin);
send(not_same_site_popup_uuid, popup_init_script);
const iframe_1_uuid = await receive(response_queue_uuid);

// Create a same-origin iframe in a same-site popup.
const same_origin_popup_uuid = newPopup(t, origin);
send(same_origin_popup_uuid, popup_init_script);
const iframe_2_uuid = await receive(response_queue_uuid);

const channel_name = token();
const bc = new BroadcastChannel(channel_name);
bc.onmessage = t.step_func(e => {
assert_equals(e.data, "msg from iframe2");
t.done();
});

// Instruct the not-same-top-level-site iframe to send a message on the BC
// channel we are listening on. This message should not be received since
// the iframe should be in a different partition.
send(iframe_1_uuid,
emit_script(channel_name, "msg from iframe1", response_queue_uuid));
assert_equals(await receive(response_queue_uuid), "done");

// Now instruct the same-top-level-site iframe to send a BC message. By
// the time we send the script to execute, have it send the BC message,
// and then receive the BC message in our BC instance, it should be
// reasonable to assume that the message from the first iframe would have
// been delivered if it was going to be.
send(iframe_2_uuid,
emit_script(channel_name, "msg from iframe2", response_queue_uuid));
assert_equals(await receive(response_queue_uuid), "done");

}, "BroadcastChannel messages aren't received from a cross-partition iframe");

</script>
</body>
Loading

0 comments on commit 602acb2

Please sign in to comment.