<!DOCTYPE html>
<script src="../../resources/gc.js"></script>
<script src="../../resources/js-test.js"></script>
<script src="resources/shared.js"></script>
<script>
description("Verify that that key cursors weakly hold request, and work if request is GC'd");
indexedDBTest(prepareDatabase, onOpen);
function prepareDatabase(evt)
{
preamble(evt);
evalAndLog("db = event.target.result");
evalAndLog("store = db.createObjectStore('store')");
store.put("value1", "key1");
store.put("value2", "key2");
}
let finishJsCalls = 0;
// Similar to `base::BarrierCallback`, this function must be called twice for the test
// to be considered finished.
function halfFinishJsTest() {
if (++finishJsCalls == 2) finishJSTest();
}
function onOpen(evt)
{
preamble(evt);
evalAndLog("db = event.target.result");
evalAndLog("tx = db.transaction('store', 'readonly', {durability: 'relaxed'})");
evalAndLog("store = tx.objectStore('store')");
evalAndLog("cursorRequest = store.openKeyCursor()");
cursorRequest.onsuccess = function openCursorRequestSuccess(evt) {
preamble(evt);
debug("Result will be checked later, to ensure that lazy access is safe");
};
evalAndLog("otherRequest = store.get(0)");
otherRequest.onsuccess = function otherRequestSuccess(evt) {
preamble(evt);
debug("Verify that the request's result can be accessed lazily:");
evalAndLog("gc()");
evalAndLog("cursor = cursorRequest.result");
shouldBeNonNull("cursor");
shouldBeEqualToString("cursor.key", "key1");
evalAndLog("cursorRequest.extra = 123");
evalAndLog("cursor.extra = 456");
// Assign a new handler to inspect the request and cursor indirectly.
cursorRequest.onsuccess = function cursorContinueSuccess(evt) {
preamble(evt);
evalAndLog("cursor = event.target.result");
shouldBeNonNull("cursor");
shouldBeEqualToString("cursor.key", "key2");
shouldBe("event.target.extra", "123");
shouldBe("cursor.extra", "456");
};
debug("Ensure request is not released if cursor is still around.");
cursorRequestObservation = internals.observeGC(cursorRequest);
evalAndLog("cursorRequest = null");
evalAndLog("gc()");
shouldBeFalse("cursorRequestObservation.wasCollected");
evalAndLog("cursor.continue()");
cursorObservation = internals.observeGC(cursor);
evalAndLog("cursor = null");
evalAndLog("gc()");
shouldBeFalse("cursorObservation.wasCollected");
evalAndLog("finalRequest = store.get(0)");
finalRequest.onsuccess = function finalRequestSuccess(evt) {
preamble(evt);
shouldBeEqualToString("cursor.key", "key2");
// Access objects in an inner function to avoid references to
// objects remaining live on this function's stack frame
// (http://crbug.com/595672/).
(() => { cursorObservation = internals.observeGC(cursor); })();
evalAndLog("cursor = null");
asyncGC(function () {
shouldBeTrue("cursorRequestObservation.wasCollected");
shouldBeTrue("cursorObservation.wasCollected");
halfFinishJsTest();
});
};
};
tx.oncomplete = halfFinishJsTest;
}
</script>