summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/web-locks/signal.tentative.https.any.js
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/web-locks/signal.tentative.https.any.js')
-rw-r--r--testing/web-platform/tests/web-locks/signal.tentative.https.any.js261
1 files changed, 261 insertions, 0 deletions
diff --git a/testing/web-platform/tests/web-locks/signal.tentative.https.any.js b/testing/web-platform/tests/web-locks/signal.tentative.https.any.js
new file mode 100644
index 0000000000..5a37e3ae87
--- /dev/null
+++ b/testing/web-platform/tests/web-locks/signal.tentative.https.any.js
@@ -0,0 +1,261 @@
+// META: title=Web Locks API: AbortSignal integration
+// META: script=resources/helpers.js
+// META: global=window,dedicatedworker,sharedworker,serviceworker
+
+'use strict';
+
+promise_test(async t => {
+ const res = uniqueName(t);
+
+ // These cases should not work:
+ for (const signal of ['string', 12.34, false, {}, Symbol(), () => {}, self]) {
+ await promise_rejects_js(
+ t, TypeError,
+ navigator.locks.request(
+ res, {signal}, t.unreached_func('callback should not run')),
+ 'Bindings should throw if the signal option is a not an AbortSignal');
+ }
+}, 'The signal option must be an AbortSignal');
+
+promise_test(async t => {
+ const res = uniqueName(t);
+ const controller = new AbortController();
+ controller.abort();
+
+ await promise_rejects_dom(
+ t, 'AbortError',
+ navigator.locks.request(res, {signal: controller.signal},
+ t.unreached_func('callback should not run')),
+ 'Request should reject with AbortError');
+}, 'Passing an already aborted signal aborts');
+
+promise_test(async t => {
+ const res = uniqueName(t);
+
+ const controller = new AbortController();
+ const reason = 'My dog ate it.';
+ controller.abort(reason);
+
+ const promise =
+ navigator.locks.request(res, {signal: controller.signal},
+ t.unreached_func('callback should not run'));
+
+ await promise_rejects_exactly(
+ t, reason, promise, "Rejection should give the abort reason");
+}, 'Passing an already aborted signal rejects with the custom abort reason.');
+
+promise_test(async t => {
+ const res = uniqueName(t);
+
+ const controller = new AbortController();
+ controller.abort();
+
+ const promise =
+ navigator.locks.request(res, {signal: controller.signal},
+ t.unreached_func('callback should not run'));
+
+ await promise_rejects_exactly(
+ t, controller.signal.reason, promise,
+ "Rejection should give the abort reason");
+}, 'Passing an already aborted signal rejects with the default abort reason.');
+
+promise_test(async t => {
+ const res = uniqueName(t);
+
+ // Grab a lock and hold it until this subtest completes.
+ requestLockAndHold(t, res);
+
+ const controller = new AbortController();
+
+ const promise =
+ navigator.locks.request(res, {signal: controller.signal},
+ t.unreached_func('callback should not run'));
+
+ // Verify the request is enqueued:
+ const state = await navigator.locks.query();
+ assert_equals(state.held.filter(lock => lock.name === res).length, 1,
+ 'Number of held locks');
+ assert_equals(state.pending.filter(lock => lock.name === res).length, 1,
+ 'Number of pending locks');
+
+ const rejected = promise_rejects_dom(
+ t, 'AbortError', promise, 'Request should reject with AbortError');
+
+ controller.abort();
+
+ await rejected;
+
+}, 'An aborted request results in AbortError');
+
+promise_test(async t => {
+ const res = uniqueName(t);
+
+ // Grab a lock and hold it until this subtest completes.
+ requestLockAndHold(t, res);
+
+ const controller = new AbortController();
+
+ const promise =
+ navigator.locks.request(res, {signal: controller.signal}, lock => {});
+
+ // Verify the request is enqueued:
+ const state = await navigator.locks.query();
+ assert_equals(state.held.filter(lock => lock.name === res).length, 1,
+ 'Number of held locks');
+ assert_equals(state.pending.filter(lock => lock.name === res).length, 1,
+ 'Number of pending locks');
+
+ const rejected = promise_rejects_dom(
+ t, 'AbortError', promise, 'Request should reject with AbortError');
+
+ let callback_called = false;
+ t.step_timeout(() => {
+ callback_called = true;
+ controller.abort();
+ }, 10);
+
+ await rejected;
+ assert_true(callback_called, 'timeout should have caused the abort');
+
+}, 'Abort after a timeout');
+
+promise_test(async t => {
+ const res = uniqueName(t);
+
+ const controller = new AbortController();
+
+ let got_lock = false;
+ await navigator.locks.request(
+ res, {signal: controller.signal}, async lock => { got_lock = true; });
+
+ assert_true(got_lock, 'Lock should be acquired if abort is not signaled.');
+
+}, 'Signal that is not aborted');
+
+promise_test(async t => {
+ const res = uniqueName(t);
+
+ const controller = new AbortController();
+
+ let got_lock = false;
+ const p = navigator.locks.request(
+ res, {signal: controller.signal}, lock => { got_lock = true; });
+
+ // Even though lock is grantable, this abort should be processed synchronously.
+ controller.abort();
+
+ await promise_rejects_dom(t, 'AbortError', p, 'Request should abort');
+
+ assert_false(got_lock, 'Request should be aborted if signal is synchronous');
+
+ await navigator.locks.request(res, lock => { got_lock = true; });
+ assert_true(got_lock, 'Subsequent request should not be blocked');
+
+}, 'Synchronously signaled abort');
+
+promise_test(async t => {
+ const res = uniqueName(t);
+
+ const controller = new AbortController();
+
+ // Make a promise that resolves when the lock is acquired.
+ const [acquired_promise, acquired_func] = makePromiseAndResolveFunc();
+
+ // Request the lock.
+ let release_func;
+ const released_promise = navigator.locks.request(
+ res, {signal: controller.signal}, lock => {
+ acquired_func();
+
+ // Hold lock until release_func is called.
+ const [waiting_promise, waiting_func] = makePromiseAndResolveFunc();
+ release_func = waiting_func;
+ return waiting_promise;
+ });
+
+ // Wait for the lock to be acquired.
+ await acquired_promise;
+
+ // Signal an abort.
+ controller.abort();
+
+ // Release the lock.
+ release_func('resolved ok');
+
+ assert_equals(await released_promise, 'resolved ok',
+ 'Lock released promise should not reject');
+
+}, 'Abort signaled after lock granted');
+
+promise_test(async t => {
+ const res = uniqueName(t);
+
+ const controller = new AbortController();
+
+ // Make a promise that resolves when the lock is acquired.
+ const [acquired_promise, acquired_func] = makePromiseAndResolveFunc();
+
+ // Request the lock.
+ let release_func;
+ const released_promise = navigator.locks.request(
+ res, {signal: controller.signal}, lock => {
+ acquired_func();
+
+ // Hold lock until release_func is called.
+ const [waiting_promise, waiting_func] = makePromiseAndResolveFunc();
+ release_func = waiting_func;
+ return waiting_promise;
+ });
+
+ // Wait for the lock to be acquired.
+ await acquired_promise;
+
+ // Release the lock.
+ release_func('resolved ok');
+
+ // Signal an abort.
+ controller.abort();
+
+ assert_equals(await released_promise, 'resolved ok',
+ 'Lock released promise should not reject');
+
+}, 'Abort signaled after lock released');
+
+promise_test(async t => {
+ const res = uniqueName(t);
+
+ const controller = new AbortController();
+ const first = requestLockAndHold(t, res, { signal: controller.signal });
+ const next = navigator.locks.request(res, () => "resolved");
+ controller.abort();
+
+ await promise_rejects_dom(t, "AbortError", first, "Request should abort");
+ assert_equals(
+ await next,
+ "resolved",
+ "The next request is processed after abort"
+ );
+}, "Abort should process the next pending lock request");
+
+promise_test(async t => {
+ const res = uniqueName(t);
+
+ const controller = new AbortController();
+ const promise = requestLockAndHold(t, res, { signal: controller.signal });
+
+ const reason = "My cat handled it";
+ controller.abort(reason);
+
+ await promise_rejects_exactly(t, reason, promise, "Rejection should give the abort reason");
+}, "Aborted promise should reject with the custom abort reason");
+
+promise_test(async t => {
+ const res = uniqueName(t);
+
+ const controller = new AbortController();
+ const promise = requestLockAndHold(t, res, { signal: controller.signal });
+
+ controller.abort();
+
+ await promise_rejects_exactly(t, controller.signal.reason, promise, "Should be the same reason");
+}, "Aborted promise should reject with the default abort reason");