From 14662ee44f12827d9f898e0cb9ceaede1c1f3b4f Mon Sep 17 00:00:00 2001 From: Andreas Butler Date: Thu, 31 Jan 2019 18:59:35 +0000 Subject: [PATCH] Bug 1523562 [wpt PR 14420] - [WebLocks]: Modifying weblocks algos to be O(1), a=testonly Automatic update from web-platform-tests [WebLocks]: Modifying weblocks algos to be O(1) The behaviour of the request/release operations of web locks are modified to be O(1) instead of their currently O(n) worst case runtime. Additionally the query-order wpt is modified to reflect the new spec requirement that the state returned by navigator.locks.query need only respect ordering for requested locks per resource. Bug: 913014 Change-Id: I819f8c27c995cb698a7c8b2c75ee80d32c744f07 Spec: https://wicg.github.io/web-locks/#algorithms Reviewed-on: https://chromium-review.googlesource.com/c/1367910 Commit-Queue: Andreas Butler Reviewed-by: Victor Costan Reviewed-by: Joshua Bell Reviewed-by: Daniel Murphy Cr-Commit-Position: refs/heads/master@{#621833} -- wpt-commits: 27085bc4fef9a55a5f5dd530c6e8ff798ff8c6c4 wpt-pr: 14420 --- .../query-order.tentative.https.any.js | 110 --------------- .../query-ordering.tentative.https.html | 130 ++++++++++++++++++ .../tests/web-locks/resources/helpers.js | 4 +- .../tests/web-locks/resources/iframe.html | 9 ++ 4 files changed, 141 insertions(+), 112 deletions(-) delete mode 100644 testing/web-platform/tests/web-locks/query-order.tentative.https.any.js create mode 100644 testing/web-platform/tests/web-locks/query-ordering.tentative.https.html diff --git a/testing/web-platform/tests/web-locks/query-order.tentative.https.any.js b/testing/web-platform/tests/web-locks/query-order.tentative.https.any.js deleted file mode 100644 index 3317cd02eb9a..000000000000 --- a/testing/web-platform/tests/web-locks/query-order.tentative.https.any.js +++ /dev/null @@ -1,110 +0,0 @@ -// META: title=Web Locks API: navigator.locks.query ordering -// META: script=resources/helpers.js -// META: global=window,dedicatedworker,sharedworker,serviceworker - -'use strict'; - -// Grab a lock and hold until a release function is called. Resolves -// to a release function. -function getLockAndHoldUntilReleased(name, options) { - let release; - const promise = new Promise(resolve => { release = resolve; }); - return new Promise(resolve => { - navigator.locks.request(name, options || {}, lock => { - resolve(release); - return promise; - }).catch(_ => {}); - }); -} - -promise_test(async t => { - const res1 = uniqueName(t); - const res2 = uniqueName(t); - const res3 = uniqueName(t); - - // These will never be released. - await Promise.all([ - getLockAndHoldUntilReleased(res1), - getLockAndHoldUntilReleased(res2), - getLockAndHoldUntilReleased(res3) - ]); - - // These requests should be blocked. - navigator.locks.request(res3, {mode: 'shared'}, lock => {}); - navigator.locks.request(res2, {mode: 'shared'}, lock => {}); - navigator.locks.request(res1, {mode: 'shared'}, lock => {}); - - const state = await navigator.locks.query(); - - const relevant_pending_names = state.pending.map(lock => lock.name) - .filter(name => [res1, res2, res3].includes(name)); - - assert_array_equals(relevant_pending_names, [res3, res2, res1], - 'Pending locks should appear in order.'); -}, 'Requests appear in state in order made'); - -promise_test(async t => { - const res1 = uniqueName(t); - const res2 = uniqueName(t); - const res3 = uniqueName(t); - - // These should be granted, and will be held until released. - const [release1, release2, release3] = await Promise.all([ - getLockAndHoldUntilReleased(res1), - getLockAndHoldUntilReleased(res2), - getLockAndHoldUntilReleased(res3) - ]); - - // These requests should be blocked. - const requests = [ - getLockAndHoldUntilReleased(res1), - getLockAndHoldUntilReleased(res2), - getLockAndHoldUntilReleased(res3) - ]; - - // Ensure the requests have had a chance to get queued by - // waiting for something else to make it through the queue. - await navigator.locks.request(uniqueName(t), lock => {}); - - // Now release the previous holders. - release2(); - release3(); - release1(); - - // Wait until the subsequent requests make it through. - await Promise.all(requests); - - const state = await navigator.locks.query(); - const relevant_held_names = state.held.map(lock => lock.name) - .filter(name => [res1, res2, res3].includes(name)); - - assert_array_equals(relevant_held_names, [res2, res3, res1], - 'Held locks should appear in granted order.'); -}, 'Held locks appear in state in order granted'); - -promise_test(async t => { - const res1 = uniqueName(t); - const res2 = uniqueName(t); - const res3 = uniqueName(t); - - // These should be granted, and will be held until stolen. - await Promise.all([ - getLockAndHoldUntilReleased(res1), - getLockAndHoldUntilReleased(res2), - getLockAndHoldUntilReleased(res3) - ]); - - // Steal in a different order. - await Promise.all([ - getLockAndHoldUntilReleased(res3, {steal: true}), - getLockAndHoldUntilReleased(res1, {steal: true}), - getLockAndHoldUntilReleased(res2, {steal: true}) - ]); - - const state = await navigator.locks.query(); - const relevant_held_names = state.held.map(lock => lock.name) - .filter(name => [res1, res2, res3].includes(name)); - - assert_array_equals(relevant_held_names, [res3, res1, res2], - 'Held locks should appear in granted order.'); -}, 'Held locks appear in state in order granted, including when stolen'); diff --git a/testing/web-platform/tests/web-locks/query-ordering.tentative.https.html b/testing/web-platform/tests/web-locks/query-ordering.tentative.https.html new file mode 100644 index 000000000000..bbbee3880b7c --- /dev/null +++ b/testing/web-platform/tests/web-locks/query-ordering.tentative.https.html @@ -0,0 +1,130 @@ + + +Web Locks API: navigator.locks.query ordering + + + + + + diff --git a/testing/web-platform/tests/web-locks/resources/helpers.js b/testing/web-platform/tests/web-locks/resources/helpers.js index d6a4af45fa71..9723ff4f1d85 100644 --- a/testing/web-platform/tests/web-locks/resources/helpers.js +++ b/testing/web-platform/tests/web-locks/resources/helpers.js @@ -5,8 +5,8 @@ // test case name. This is useful to avoid lock interference between // test cases. let res_num = 0; - self.uniqueName = testCase => { - return `${self.location.pathname}-${testCase.name}-${++res_num}`; + self.uniqueName = (testCase, prefix) => { + return `${self.location.pathname}-${prefix}-${testCase.name}-${++res_num}`; }; // Inject an iframe showing the given url into the page, and resolve diff --git a/testing/web-platform/tests/web-locks/resources/iframe.html b/testing/web-platform/tests/web-locks/resources/iframe.html index d3799f44f96b..ba63c77bae50 100644 --- a/testing/web-platform/tests/web-locks/resources/iframe.html +++ b/testing/web-platform/tests/web-locks/resources/iframe.html @@ -38,6 +38,15 @@ self.addEventListener('message', e => { held.delete(e.data.lock_id); respond({ack: 'release', lock_id: e.data.lock_id}); break; + + case 'client_id': + navigator.locks.request(e.data.name, async lock => { + const lock_state = await navigator.locks.query(); + const held_lock = + lock_state.held.filter(l => l.name === lock.name)[0]; + respond({ack: 'client_id', client_id: held_lock.clientId}); + }); + break; } });