Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

// META: global=window,worker
// META: title=IDBCursor.continuePrimaryKey() - Exception Orders
// META: script=resources/support.js
// META: timeout=long
'use strict';
function setup_test_store(db) {
const records = [
{iKey: 'A', pKey: 1}, {iKey: 'A', pKey: 2}, {iKey: 'A', pKey: 3},
{iKey: 'A', pKey: 4}, {iKey: 'B', pKey: 5}, {iKey: 'B', pKey: 6},
{iKey: 'B', pKey: 7}, {iKey: 'C', pKey: 8}, {iKey: 'C', pKey: 9},
{iKey: 'D', pKey: 10}
];
const store = db.createObjectStore('test', {keyPath: 'pKey'});
store.createIndex('idx', 'iKey');
for (let i = 0; i < records.length; i++) {
store.add(records[i]);
}
return store;
}
indexeddb_test(function(t, db, txn) {
const store = setup_test_store(db);
const cursor_rq = store.index('idx').openCursor();
let cursor;
cursor_rq.onerror = t.unreached_func('openCursor should succeed');
cursor_rq.onsuccess = t.step_func((e) => {
cursor = e.target.result;
assert_true(!!cursor, 'acquire cursor');
store.deleteIndex('idx');
});
txn.oncomplete = t.step_func(() => {
assert_throws_dom('TransactionInactiveError', () => {
cursor.continuePrimaryKey('A', 4);
}, 'transaction-state check should precede deletion check');
t.done();
});
}, null, 'TransactionInactiveError v.s. InvalidStateError(deleted index)');
indexeddb_test(
function(t, db, txn) {
const store = setup_test_store(db);
const cursor_rq = store.openCursor();
let cursor;
cursor_rq.onerror = t.unreached_func('openCursor should succeed');
cursor_rq.onsuccess = t.step_func((e) => {
cursor = e.target.result;
assert_true(!!cursor, 'acquire cursor');
db.deleteObjectStore('test');
assert_throws_dom('InvalidStateError', () => {
cursor.continuePrimaryKey('A', 4);
}, 'deletion check should precede index source check');
t.done();
});
},
null,
'InvalidStateError(deleted source) v.s. InvalidAccessError(incorrect source)');
indexeddb_test(
function(t, db, txn) {
const store = setup_test_store(db);
const cursor_rq = store.index('idx').openCursor(null, 'nextunique');
let cursor;
cursor_rq.onerror = t.unreached_func('openCursor should succeed');
cursor_rq.onsuccess = t.step_func((e) => {
cursor = e.target.result;
assert_true(!!cursor, 'acquire cursor');
store.deleteIndex('idx');
assert_throws_dom('InvalidStateError', () => {
cursor.continuePrimaryKey('A', 4);
}, 'deletion check should precede cursor direction check');
t.done();
});
},
null,
'InvalidStateError(deleted source) v.s. InvalidAccessError(incorrect direction)');
indexeddb_test(
function(t, db, txn) {
const store = db.createObjectStore('test', {keyPath: 'pKey'});
store.add({iKey: 'A', pKey: 1});
const cursor_rq =
store.createIndex('idx', 'iKey').openCursor(null, 'nextunique');
let cursor;
cursor_rq.onerror = t.unreached_func('openCursor should succeed');
cursor_rq.onsuccess = t.step_func((e) => {
if (e.target.result) {
cursor = e.target.result;
cursor.continue();
return;
}
assert_throws_dom('InvalidAccessError', () => {
cursor.continuePrimaryKey('A', 4);
}, 'direction check should precede got_value_flag check');
t.done();
});
},
null,
'InvalidAccessError(incorrect direction) v.s. InvalidStateError(iteration complete)');
indexeddb_test(
function(t, db, txn) {
const store = db.createObjectStore('test', {keyPath: 'pKey'});
store.add({iKey: 'A', pKey: 1});
const cursor_rq =
store.createIndex('idx', 'iKey').openCursor(null, 'nextunique');
let cursor;
cursor_rq.onerror = t.unreached_func('openCursor should succeed');
cursor_rq.onsuccess = t.step_func((e) => {
if (!cursor) {
cursor = e.target.result;
assert_true(!!cursor, 'acquire cursor');
cursor.continue();
assert_throws_dom('InvalidAccessError', () => {
cursor.continuePrimaryKey('A', 4);
}, 'direction check should precede iteration ongoing check');
t.done();
}
});
},
null,
'InvalidAccessError(incorrect direction) v.s. InvalidStateError(iteration ongoing)');
indexeddb_test(
function(t, db, txn) {
const store = setup_test_store(db);
const cursor_rq = store.openCursor();
let cursor;
cursor_rq.onerror = t.unreached_func('openCursor should succeed');
cursor_rq.onsuccess = t.step_func((e) => {
if (!cursor) {
cursor = e.target.result;
assert_true(!!cursor, 'acquire cursor');
cursor.continue();
assert_throws_dom('InvalidAccessError', () => {
cursor.continuePrimaryKey('A', 4);
}, 'index source check should precede iteration ongoing check');
t.done();
}
});
},
null,
'InvalidAccessError(incorrect source) v.s. InvalidStateError(iteration ongoing)');
indexeddb_test(
function(t, db, txn) {
const store = db.createObjectStore('test', {keyPath: 'pKey'});
store.add({iKey: 'A', pKey: 1});
const cursor_rq = store.openCursor();
let cursor;
cursor_rq.onerror = t.unreached_func('openCursor should succeed');
cursor_rq.onsuccess = t.step_func((e) => {
if (e.target.result) {
cursor = e.target.result;
cursor.continue();
return;
}
assert_throws_dom('InvalidAccessError', () => {
cursor.continuePrimaryKey('A', 4);
}, 'index source check should precede got_value_flag check');
t.done();
});
},
null,
'InvalidAccessError(incorrect source) v.s. InvalidStateError(iteration complete)');
indexeddb_test(function(t, db, txn) {
const store = setup_test_store(db);
const cursor_rq = store.index('idx').openCursor();
let cursor;
cursor_rq.onerror = t.unreached_func('openCursor should succeed');
cursor_rq.onsuccess = t.step_func((e) => {
if (!cursor) {
cursor = e.target.result;
assert_true(!!cursor, 'acquire cursor');
cursor.continue();
assert_throws_dom('InvalidStateError', () => {
cursor.continuePrimaryKey(null, 4);
}, 'iteration ongoing check should precede unset key check');
t.done();
}
});
}, null, 'InvalidStateError(iteration ongoing) v.s. DataError(unset key)');
indexeddb_test(function(t, db, txn) {
const store = db.createObjectStore('test', {keyPath: 'pKey'});
store.add({iKey: 'A', pKey: 1});
const cursor_rq = store.createIndex('idx', 'iKey').openCursor();
let cursor;
cursor_rq.onerror = t.unreached_func('openCursor should succeed');
cursor_rq.onsuccess = t.step_func((e) => {
if (e.target.result) {
cursor = e.target.result;
cursor.continue();
return;
}
assert_throws_dom('InvalidStateError', () => {
cursor.continuePrimaryKey(null, 4);
}, 'got_value_flag check should precede unset key check');
t.done();
});
}, null, 'InvalidStateError(iteration complete) v.s. DataError(unset key)');
indexeddb_test(function(t, db, txn) {
const store = setup_test_store(db);
const cursor_rq = store.index('idx').openCursor();
let cursor;
cursor_rq.onerror = t.unreached_func('openCursor should succeed');
cursor_rq.onsuccess = t.step_func((e) => {
cursor = e.target.result;
assert_true(!!cursor, 'acquire cursor');
assert_throws_dom('DataError', () => {
cursor.continuePrimaryKey(null, 4);
}, 'DataError is expected if key is unset.');
t.done();
});
}, null, 'DataError(unset key)');
indexeddb_test(function(t, db, txn) {
const store = setup_test_store(db);
const cursor_rq = store.index('idx').openCursor();
let cursor;
cursor_rq.onerror = t.unreached_func('openCursor should succeed');
cursor_rq.onsuccess = t.step_func((e) => {
cursor = e.target.result;
assert_true(!!cursor, 'acquire cursor');
assert_throws_dom('DataError', () => {
cursor.continuePrimaryKey('A', null);
}, 'DataError is expected if primary key is unset.');
t.done();
});
}, null, 'DataError(unset primary key)');
indexeddb_test(function(t, db, txn) {
const store = setup_test_store(db);
const cursor_rq = store.index('idx').openCursor(IDBKeyRange.lowerBound('B'));
let cursor;
cursor_rq.onerror = t.unreached_func('openCursor should succeed');
cursor_rq.onsuccess = t.step_func((e) => {
cursor = e.target.result;
assert_true(!!cursor, 'acquire cursor');
assert_equals(cursor.key, 'B', 'expected key');
assert_equals(cursor.primaryKey, 5, 'expected primary key');
assert_throws_dom('DataError', () => {
cursor.continuePrimaryKey('A', 6);
}, 'DataError is expected if key is lower then current one.');
assert_throws_dom('DataError', () => {
cursor.continuePrimaryKey('B', 5);
}, 'DataError is expected if primary key is equal to current one.');
assert_throws_dom('DataError', () => {
cursor.continuePrimaryKey('B', 4);
}, 'DataError is expected if primary key is lower than current one.');
t.done();
});
}, null, 'DataError(keys are lower then current one) in \'next\' direction');
indexeddb_test(function(t, db, txn) {
const store = setup_test_store(db);
const cursor_rq =
store.index('idx').openCursor(IDBKeyRange.upperBound('B'), 'prev');
let cursor;
cursor_rq.onerror = t.unreached_func('openCursor should succeed');
cursor_rq.onsuccess = t.step_func(function(e) {
cursor = e.target.result;
assert_true(!!cursor, 'acquire cursor');
assert_equals(cursor.key, 'B', 'expected key');
assert_equals(cursor.primaryKey, 7, 'expected primary key');
assert_throws_dom('DataError', () => {
cursor.continuePrimaryKey('C', 6);
}, 'DataError is expected if key is larger then current one.');
assert_throws_dom('DataError', () => {
cursor.continuePrimaryKey('B', 7);
}, 'DataError is expected if primary key is equal to current one.');
assert_throws_dom('DataError', () => {
cursor.continuePrimaryKey('B', 8);
}, 'DataError is expected if primary key is larger than current one.');
t.done();
});
}, null, 'DataError(keys are larger then current one) in \'prev\' direction');