mirror of
https://github.com/LadybirdBrowser/ladybird
synced 2026-05-02 04:27:12 +02:00
LibWeb/IndexedDB: Prevent copying and moving of RequestList
RequestList cannot be copied or moved, because m_pending_request_queue contains lambdas that store pointers to the original RequestList and completion steps that we don't have a reference to. Fixes a bunch of WPT regressions and imports the ones that work.
This commit is contained in:
committed by
Jelle Raaijmakers
parent
4ede2cdf18
commit
85e8d2ba38
Notes:
github-actions[bot]
2025-10-23 12:44:02 +00:00
Author: https://github.com/Lubrsi Commit: https://github.com/LadybirdBrowser/ladybird/commit/85e8d2ba38b Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/6429 Reviewed-by: https://github.com/gmta ✅
@@ -0,0 +1,116 @@
|
||||
// META: global=window,worker
|
||||
// META: title=IndexedDB: The source of requests made against cursors
|
||||
// META: script=resources/support.js
|
||||
|
||||
// Spec: https://w3c.github.io/IndexedDB/#dom-idbrequest-source
|
||||
|
||||
'use strict';
|
||||
|
||||
// Setup each test by populating an object store with an index for the cursor to
|
||||
// iterate and manipulate.
|
||||
function initializeDatabase(db) {
|
||||
const store = db.createObjectStore('store', {autoIncrement: true});
|
||||
store.createIndex('index', /*keypath=*/ 'value');
|
||||
store.put({value: 'z'});
|
||||
store.put({value: 'y'});
|
||||
store.put({value: 'x'});
|
||||
store.put({value: 'w'});
|
||||
}
|
||||
|
||||
function isIndex(cursorSourceType) {
|
||||
return cursorSourceType === 'IDBIndex';
|
||||
}
|
||||
|
||||
// Return the object store or index, depending on the test's `cursorSourceType`.
|
||||
function getCursorSource(transaction, cursorSourceType) {
|
||||
let cursorSource = transaction.objectStore('store');
|
||||
if (isIndex(cursorSourceType)) {
|
||||
cursorSource = cursorSource.index('index');
|
||||
}
|
||||
return cursorSource;
|
||||
}
|
||||
|
||||
// Verify the request source after calling delete() or update() on the cursor.
|
||||
function cursor_request_source_test(
|
||||
cursorSourceType, createRequestFunctionName, createRequestFunctionArgs) {
|
||||
indexeddb_test(
|
||||
(t, db) => initializeDatabase(db),
|
||||
(t, db) => {
|
||||
const tx = db.transaction('store', 'readwrite');
|
||||
const cursorSource = getCursorSource(tx, cursorSourceType);
|
||||
|
||||
// Open the cursor.
|
||||
const openCursorRequest = cursorSource.openCursor();
|
||||
openCursorRequest.onerror =
|
||||
t.unreached_func('The cursor must not fail to open.');
|
||||
|
||||
openCursorRequest.onsuccess = t.step_func(e => {
|
||||
// Use the cursor to create a new request.
|
||||
const cursor = e.target.result;
|
||||
const request =
|
||||
cursor[createRequestFunctionName](...createRequestFunctionArgs);
|
||||
assert_equals(
|
||||
request.source, cursor,
|
||||
`The request's source must be the cursor itself.`);
|
||||
t.done();
|
||||
});
|
||||
},
|
||||
`The source of the request from ${cursorSourceType}::${
|
||||
createRequestFunctionName}() is the cursor itself`);
|
||||
}
|
||||
|
||||
// Verify the request source after calling openCursor() or openKeyCursor() and
|
||||
// then using the cursor to iterate.
|
||||
function open_cursor_request_source_test(
|
||||
cursorSourceType, openCursorFunctionName) {
|
||||
indexeddb_test(
|
||||
(t, db) => initializeDatabase(db),
|
||||
(t, db) => {
|
||||
const tx = db.transaction('store', 'readonly');
|
||||
const cursorSource = getCursorSource(tx, cursorSourceType);
|
||||
|
||||
// Open the cursor.
|
||||
const openCursorRequest = cursorSource[openCursorFunctionName]();
|
||||
openCursorRequest.onerror =
|
||||
t.unreached_func('The cursor must not fail to open or iterate.');
|
||||
|
||||
assert_equals(
|
||||
openCursorRequest.source, cursorSource,
|
||||
'The request source must be the opener of the cursor.');
|
||||
|
||||
// Verify the cursor's `request.source` after iterating with
|
||||
// `advance()`, `continue()`, and `continuePrimaryKey()`.
|
||||
let iterationCount = 0;
|
||||
openCursorRequest.onsuccess = t.step_func(e => {
|
||||
assert_equals(
|
||||
openCursorRequest.source, cursorSource,
|
||||
'The request source must be the opener of the cursor after iterating.');
|
||||
|
||||
const cursor = e.target.result;
|
||||
++iterationCount;
|
||||
|
||||
if (iterationCount == 1) {
|
||||
cursor.advance(1);
|
||||
} else if (iterationCount == 2) {
|
||||
cursor.continue();
|
||||
} else if (iterationCount == 3 && isIndex(cursorSourceType)) {
|
||||
cursor.continuePrimaryKey('z', 0);
|
||||
} else {
|
||||
t.done();
|
||||
}
|
||||
});
|
||||
},
|
||||
`${cursorSourceType}::${
|
||||
openCursorFunctionName}'s request source must be the ${
|
||||
cursorSourceType} instance that opened the cursor`);
|
||||
}
|
||||
|
||||
open_cursor_request_source_test('IDBObjectStore', 'openCursor');
|
||||
open_cursor_request_source_test('IDBObjectStore', 'openKeyCursor');
|
||||
open_cursor_request_source_test('IDBIndex', 'openCursor');
|
||||
open_cursor_request_source_test('IDBIndex', 'openKeyCursor');
|
||||
|
||||
cursor_request_source_test('IDBObjectStore', 'update', /*args=*/[0]);
|
||||
cursor_request_source_test('IDBObjectStore', 'delete', /*args=*/[]);
|
||||
cursor_request_source_test('IDBIndex', 'update', /*args=*/[0]);
|
||||
cursor_request_source_test('IDBIndex', 'delete', /*args=*/[]);
|
||||
Reference in New Issue
Block a user