Web Locks: Throwing a thenable in callback shouldn't invoke it

An edge case first reported on github[1] - the result from the lock
acquisition callback should be the resolution of the call's promise.
If the result is itself a promise (or a thenable - i.e. has a then()
method), then it should be "unpacked" per normal promise handling.
This works! Also, if the result is an "abrupt completion" (i.e the
callback throws), that means the resolution should be an exception. So
far, so good! But if that exception is a thenable, it should not be
"unpacked" per normal promise handling. But this is what was happening
in Chrome!

The spec is fine here, it was just an implementation bug. Fix the
implementation and add a WPT to cover this case.

[1] https://github.com/w3c/web-locks/issues/77

Bug: 1250253
Change-Id: Ib38cd1ff48d5f25e1939f50e614ce623c2d10a35
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4064307
Commit-Queue: Joshua Bell <jsbell@chromium.org>
Reviewed-by: Ayu Ishii <ayui@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1077650}
diff --git a/web-locks/acquire.tentative.https.any.js b/web-locks/acquire.tentative.https.any.js
index fd7689b..54ae6f3 100644
--- a/web-locks/acquire.tentative.https.any.js
+++ b/web-locks/acquire.tentative.https.any.js
@@ -122,3 +122,15 @@
   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');