summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/web-locks/acquire.https.any.js
blob: 54ae6f30e7add6f45c6b5ba7161999b5a6078871 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// META: title=Web Locks API: navigator.locks.request method
// META: script=resources/helpers.js
// META: global=window,dedicatedworker,sharedworker,serviceworker

'use strict';

promise_test(async t => {
  const res = uniqueName(t);
  await promise_rejects_js(t, TypeError, navigator.locks.request());
  await promise_rejects_js(t, TypeError, navigator.locks.request(res));
}, 'navigator.locks.request requires a name and a callback');

promise_test(async t => {
  const res = uniqueName(t);
  await promise_rejects_js(
    t, TypeError,
    navigator.locks.request(res, {mode: 'foo'}, lock => {}));
  await promise_rejects_js(
    t, TypeError,
    navigator.locks.request(res, {mode: null }, lock => {}));
  assert_equals(await navigator.locks.request(
    res, {mode: 'exclusive'}, lock => lock.mode), 'exclusive',
                'mode is exclusive');
  assert_equals(await navigator.locks.request(
    res, {mode: 'shared'}, lock => lock.mode), 'shared',
                'mode is shared');
}, 'mode must be "shared" or "exclusive"');

promise_test(async t => {
  const res = uniqueName(t);
  await promise_rejects_dom(
    t, 'NotSupportedError',
    navigator.locks.request(
      res, {steal: true, ifAvailable: true}, lock => {}),
    "A NotSupportedError should be thrown if both " +
    "'steal' and 'ifAvailable' are specified.");
}, "The 'steal' and 'ifAvailable' options are mutually exclusive");

promise_test(async t => {
  const res = uniqueName(t);
  await promise_rejects_dom(
    t, 'NotSupportedError',
    navigator.locks.request(res, {mode: 'shared', steal: true}, lock => {}),
    'Request with mode=shared and steal=true should fail');
}, "The 'steal' option must be used with exclusive locks");

promise_test(async t => {
  const res = uniqueName(t);
  const controller = new AbortController();
  await promise_rejects_dom(
    t, 'NotSupportedError',
    navigator.locks.request(
      res, {signal: controller.signal, steal: true}, lock => {}),
    'Request with signal and steal=true should fail');
}, "The 'signal' and 'steal' options are mutually exclusive");

promise_test(async t => {
  const res = uniqueName(t);
  const controller = new AbortController();
  await promise_rejects_dom(
    t, 'NotSupportedError',
    navigator.locks.request(
      res, {signal: controller.signal, ifAvailable: true}, lock => {}),
    'Request with signal and ifAvailable=true should fail');
}, "The 'signal' and 'ifAvailable' options are mutually exclusive");

promise_test(async t => {
  const res = uniqueName(t);
  await promise_rejects_js(
    t, TypeError, navigator.locks.request(res, undefined));
  await promise_rejects_js(
    t, TypeError, navigator.locks.request(res, null));
  await promise_rejects_js(
    t, TypeError, navigator.locks.request(res, 123));
  await promise_rejects_js(
    t, TypeError, navigator.locks.request(res, 'abc'));
  await promise_rejects_js(
    t, TypeError, navigator.locks.request(res, []));
  await promise_rejects_js(
    t, TypeError, navigator.locks.request(res, {}));
  await promise_rejects_js(
    t, TypeError, navigator.locks.request(res, new Promise(r => {})));
}, 'callback must be a function');

promise_test(async t => {
  const res = uniqueName(t);
  let release;
  const promise = new Promise(r => { release = r; });

  let returned = navigator.locks.request(res, lock => { return promise; });

  const order = [];

  returned.then(() => { order.push('returned'); });
  promise.then(() => { order.push('holding'); });

  release();

  await Promise.all([returned, promise]);

  assert_array_equals(order, ['holding', 'returned']);

}, 'navigator.locks.request\'s returned promise resolves after' +
   ' lock is released');

promise_test(async t => {
  const res = uniqueName(t);
  const test_error = {name: 'test'};
  const p = navigator.locks.request(res, lock => {
    throw test_error;
  });
  assert_equals(Promise.resolve(p), p, 'request() result is a Promise');
  await promise_rejects_exactly(t, test_error, p, 'result should reject');
}, 'Returned Promise rejects if callback throws synchronously');

promise_test(async t => {
  const res = uniqueName(t);
  const test_error = {name: 'test'};
  const p = navigator.locks.request(res, async lock => {
    throw test_error;
  });
  assert_equals(Promise.resolve(p), p, 'request() result is a Promise');
  await promise_rejects_exactly(t, test_error, p, 'result should reject');
}, 'Returned Promise rejects if callback throws asynchronously');

promise_test(async t => {
  const res = uniqueName(t);
  let then_invoked = false;
  const test_error = { then: _ => { then_invoked = true; } };
  const p = navigator.locks.request(res, async lock => {
    throw test_error;
  });
  assert_equals(Promise.resolve(p), p, 'request() result is a Promise');
  await promise_rejects_exactly(t, test_error, p, 'result should reject');
  assert_false(then_invoked, 'then() should not be invoked');
}, 'If callback throws a thenable, its then() should not be invoked');