From 0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 03:47:29 +0200 Subject: Adding upstream version 115.8.0esr. Signed-off-by: Daniel Baumann --- .../tests/web-locks/resources/helpers.js | 83 ++++++++++++++++++++++ .../tests/web-locks/resources/iframe-parent.html | 37 ++++++++++ .../tests/web-locks/resources/iframe.html | 52 ++++++++++++++ .../tests/web-locks/resources/parentworker.js | 10 +++ .../web-locks/resources/partitioned-parent.html | 30 ++++++++ .../tests/web-locks/resources/service-worker.js | 7 ++ .../web-locks/resources/sw-controlled-iframe.html | 35 +++++++++ .../tests/web-locks/resources/worker.js | 56 +++++++++++++++ 8 files changed, 310 insertions(+) create mode 100644 testing/web-platform/tests/web-locks/resources/helpers.js create mode 100644 testing/web-platform/tests/web-locks/resources/iframe-parent.html create mode 100644 testing/web-platform/tests/web-locks/resources/iframe.html create mode 100644 testing/web-platform/tests/web-locks/resources/parentworker.js create mode 100644 testing/web-platform/tests/web-locks/resources/partitioned-parent.html create mode 100644 testing/web-platform/tests/web-locks/resources/service-worker.js create mode 100644 testing/web-platform/tests/web-locks/resources/sw-controlled-iframe.html create mode 100644 testing/web-platform/tests/web-locks/resources/worker.js (limited to 'testing/web-platform/tests/web-locks/resources') diff --git a/testing/web-platform/tests/web-locks/resources/helpers.js b/testing/web-platform/tests/web-locks/resources/helpers.js new file mode 100644 index 0000000000..4b3311eee6 --- /dev/null +++ b/testing/web-platform/tests/web-locks/resources/helpers.js @@ -0,0 +1,83 @@ +// Test helpers used by multiple Web Locks API tests. +(() => { + + // Generate a unique resource identifier, using the script path and + // test case name. This is useful to avoid lock interference between + // test cases. + let res_num = 0; + self.uniqueName = (testCase, prefix) => { + return `${self.location.pathname}-${prefix}-${testCase.name}-${++res_num}`; + }; + self.uniqueNameByQuery = () => { + const prefix = new URL(location.href).searchParams.get('prefix'); + return `${prefix}-${++res_num}`; + } + + // Inject an iframe showing the given url into the page, and resolve + // the returned promise when the frame is loaded. + self.iframe = url => new Promise(resolve => { + const element = document.createElement('iframe'); + element.addEventListener( + 'load', () => { resolve(element); }, { once: true }); + element.src = url; + document.documentElement.appendChild(element); + }); + + // Post a message to the target frame, and resolve the returned + // promise when a response comes back. The posted data is annotated + // with unique id to track the response. This assumes the use of + // 'iframe.html' as the frame, which implements this protocol. + let next_request_id = 0; + self.postToFrameAndWait = (frame, data) => { + const iframe_window = frame.contentWindow; + data.rqid = next_request_id++; + iframe_window.postMessage(data, '*'); + return new Promise(resolve => { + const listener = event => { + if (event.source !== iframe_window || event.data.rqid !== data.rqid) + return; + self.removeEventListener('message', listener); + resolve(event.data); + }; + self.addEventListener('message', listener); + }); + }; + + // Post a message to the target worker, and resolve the returned + // promise when a response comes back. The posted data is annotated + // with unique id to track the response. This assumes the use of + // 'worker.js' as the worker, which implements this protocol. + self.postToWorkerAndWait = (worker, data) => { + return new Promise(resolve => { + data.rqid = next_request_id++; + worker.postMessage(data); + const listener = event => { + if (event.data.rqid !== data.rqid) + return; + worker.removeEventListener('message', listener); + resolve(event.data); + }; + worker.addEventListener('message', listener); + }); + }; + + /** + * Request a lock and hold it until the subtest ends. + * @param {*} t test runner object + * @param {string} name lock name + * @param {LockOptions=} options lock options + * @returns + */ + self.requestLockAndHold = (t, name, options = {}) => { + return navigator.locks.request(name, options, () => { + return new Promise(resolve => t.add_cleanup(resolve)); + }); + }; + + self.makePromiseAndResolveFunc = () => { + let resolve; + const promise = new Promise(r => { resolve = r; }); + return [promise, resolve]; + }; + +})(); diff --git a/testing/web-platform/tests/web-locks/resources/iframe-parent.html b/testing/web-platform/tests/web-locks/resources/iframe-parent.html new file mode 100644 index 0000000000..ec63045b4a --- /dev/null +++ b/testing/web-platform/tests/web-locks/resources/iframe-parent.html @@ -0,0 +1,37 @@ + +Helper IFrame + diff --git a/testing/web-platform/tests/web-locks/resources/iframe.html b/testing/web-platform/tests/web-locks/resources/iframe.html new file mode 100644 index 0000000000..ba63c77bae --- /dev/null +++ b/testing/web-platform/tests/web-locks/resources/iframe.html @@ -0,0 +1,52 @@ + +Helper IFrame + diff --git a/testing/web-platform/tests/web-locks/resources/parentworker.js b/testing/web-platform/tests/web-locks/resources/parentworker.js new file mode 100644 index 0000000000..2b2b2c2028 --- /dev/null +++ b/testing/web-platform/tests/web-locks/resources/parentworker.js @@ -0,0 +1,10 @@ +// Just transparently forwards things to the child worker + +importScripts("/web-locks/resources/helpers.js"); +const worker = new Worker("/web-locks/resources/worker.js"); + +self.addEventListener("message", async ev => { + const data = await postToWorkerAndWait(worker, ev.data); + data.rqid = ev.data.rqid; + postMessage(data); +}); diff --git a/testing/web-platform/tests/web-locks/resources/partitioned-parent.html b/testing/web-platform/tests/web-locks/resources/partitioned-parent.html new file mode 100644 index 0000000000..ec19c8dbaa --- /dev/null +++ b/testing/web-platform/tests/web-locks/resources/partitioned-parent.html @@ -0,0 +1,30 @@ + + + + diff --git a/testing/web-platform/tests/web-locks/resources/service-worker.js b/testing/web-platform/tests/web-locks/resources/service-worker.js new file mode 100644 index 0000000000..027863e33e --- /dev/null +++ b/testing/web-platform/tests/web-locks/resources/service-worker.js @@ -0,0 +1,7 @@ +// Responds to '/clientId' with the request's clientId. +self.addEventListener('fetch', e => { + if (new URL(e.request.url).pathname === '/clientId') { + e.respondWith(new Response(JSON.stringify({clientId: e.clientId}))); + return; + } +}); diff --git a/testing/web-platform/tests/web-locks/resources/sw-controlled-iframe.html b/testing/web-platform/tests/web-locks/resources/sw-controlled-iframe.html new file mode 100644 index 0000000000..bc5c9bdb83 --- /dev/null +++ b/testing/web-platform/tests/web-locks/resources/sw-controlled-iframe.html @@ -0,0 +1,35 @@ + + +iframe used in clientId test + diff --git a/testing/web-platform/tests/web-locks/resources/worker.js b/testing/web-platform/tests/web-locks/resources/worker.js new file mode 100644 index 0000000000..cc71631ba6 --- /dev/null +++ b/testing/web-platform/tests/web-locks/resources/worker.js @@ -0,0 +1,56 @@ +'use strict'; + +// Map of id => function that releases a lock. + +const held = new Map(); +let next_lock_id = 1; + +function processMessage(e) { + const target = this; + + function respond(data) { + target.postMessage(Object.assign(data, {rqid: e.data.rqid})); + } + + switch (e.data.op) { + case 'request': { + const controller = new AbortController(); + navigator.locks.request( + e.data.name, { + mode: e.data.mode || 'exclusive', + ifAvailable: e.data.ifAvailable || false, + signal: e.data.abortImmediately ? controller.signal : undefined, + }, lock => { + if (lock === null) { + respond({ack: 'request', failed: true}); + return; + } + let lock_id = next_lock_id++; + let release; + const promise = new Promise(r => { release = r; }); + held.set(lock_id, release); + respond({ack: 'request', lock_id: lock_id}); + return promise; + }).catch(e => { + respond({ack: 'request', error: e.name}); + }); + if (e.data.abortImmediately) { + controller.abort(); + } + break; + } + + case 'release': + held.get(e.data.lock_id)(); + held.delete(e.data.lock_id); + respond({ack: 'release', lock_id: e.data.lock_id}); + break; + } +} + +self.addEventListener('message', processMessage); + +self.addEventListener('connect', ev => { + // Shared worker case + ev.ports[0].onmessage = processMessage; +}); -- cgit v1.2.3