| <!DOCTYPE html> |
| <meta charset=utf-8> |
| <title>Web Locks API: Lock held with Promise that is GC'd (Chromium-specific, relies on gc/internals)</title> |
| <link rel=help href="https://github.com/inexorabletash/web-locks"> |
| <script src="/js-test-resources/gc.js"></script> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| <script> |
| 'use strict'; |
| |
| // For uncaught rejections. |
| setup({allow_uncaught_exception: true}); |
| |
| // Wait for a promise in a subsequent task (not just microtask in same task). |
| function task(t) { |
| return new Promise(resolve => { |
| t.step_timeout(resolve, 0); |
| }); |
| } |
| |
| promise_test(async t => { |
| let res = `${self.location.pathname}-${t.name}`; |
| let observe_lock, observe_promise; |
| |
| // Acquire the lock, and keep it alive via a promise that never resolves. |
| let resolve, acquired = new Promise(r => { resolve = r; }); |
| navigator.locks.request(res, lock => { |
| resolve(); |
| |
| // Neither |lock| nor |promise| are retained. |
| const promise = new Promise(() => {}); |
| observe_lock = internals.observeGC(lock); |
| observe_promise = internals.observeGC(promise); |
| return promise; |
| }); |
| await acquired; |
| |
| // Drain the microtask queue and trigger a GC. |
| await task(t); |
| |
| asyncGC(async function () { |
| assert_true(observe_lock.wasCollected, 'Lock should be collected'); |
| assert_true(observe_promise.wasCollected, 'Promise should be collected'); |
| |
| // Now try and request the lock. |
| let lock = 'should be overwritten'; |
| await navigator.locks.request(res, {ifAvailable: true}, l => { |
| lock = l; |
| }); |
| assert_equals(lock, null, 'Lock acquisition should have failed'); |
| }); |
| }, 'GC of waiting promise does not cause lock to be released'); |
| |
| </script> |