Files
sousa-gecko/testing/web-platform/mozilla/tests/webtransport/weak-promise.https.any.js
T
Valentin Gosu fe3adabeb5 Bug 1958291 - Make sure WebTransport CYCLE_COLLECTION calls UNLINK_PRESERVED_WRAPPER r=necko-reviewers,kershaw
The absence of NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER meant that
even when GCd, the WebTransport object was still retrievable when calling
weakref.deref(), but all its members were garbage collected already.
This lead to a null deref when trying to access target.ready

Differential Revision: https://phabricator.services.mozilla.com/D271550
2025-11-07 15:56:05 +00:00

65 lines
1.9 KiB
JavaScript

// META: global=window,worker
// META: script=/common/get-host-info.sub.js
// META: script=/webtransport/resources/webtransport-test-helpers.sub.js
// META: script=/common/utils.js
// META: script=/common/gc.js
'use strict';
async function timeout(cmd) {
const timer = new Promise((resolve, reject) => {
const id = setTimeout(() => {
clearTimeout(id)
reject(new Error("Promise timed out!"))
}, 750)
})
return Promise.race([cmd, timer])
}
// This is a test for bug 1958291
// A weakref should deref to null if the object has been GCd
// but a bug in the implementation of NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN
// made it so that only its members were GCd, leading to target.ready dereferencing
// a null pointer.
promise_test(async t => {
// Create first WebTransport connection and a WeakRef to it
let wt1 = new WebTransport(
webtransport_url(`query.py?token=${token()}`)
);
const weakref = new WeakRef(wt1);
// Create second WebTransport connection
const wt2 = new WebTransport(
webtransport_url(`query.py?token=${token()}`)
);
t.add_cleanup(() => wt2.close());
// Remove strong reference to wt1
wt1 = undefined;
await wt2.ready;
// Trigger garbage collection
await garbageCollect();
// Create bidirectional streams on wt2
for (let i = 0; i < 8; i++) {
await timeout(wt2.createBidirectionalStream({}));
}
// Try to dereference the weakref
const target = weakref.deref();
// The object may have been garbage collected (target === undefined)
// or it may still be alive (target !== undefined). Both are valid outcomes.
if (target !== undefined) {
// Object survived GC, verify it's still accessible
try {
await timeout(target.ready);
} catch (e) {
// Timeout or connection error is acceptable
}
}
// If target is undefined, the object was successfully garbage collected
}, 'WebTransport garbage collection behavior with WeakRef');