|  | // META: global=window,worker | 
|  | // META: title=IndexedDB: IDBCursor method continuePrimaryKey() | 
|  | // META: script=resources/support.js | 
|  |  | 
|  | // Spec: http://w3c.github.io/IndexedDB/#dom-idbcursor-continueprimarykey | 
|  |  | 
|  | 'use strict'; | 
|  |  | 
|  | indexeddb_test( | 
|  | (t, db, txn) => { | 
|  | const store = db.createObjectStore('store'); | 
|  | const index = store.createIndex('index', 'indexKey', {multiEntry: true}); | 
|  |  | 
|  | store.put({indexKey: ['a', 'b']}, 1); | 
|  | store.put({indexKey: ['a', 'b']}, 2); | 
|  | store.put({indexKey: ['a', 'b']}, 3); | 
|  | store.put({indexKey: ['b']}, 4); | 
|  |  | 
|  | const expectedIndexEntries = [ | 
|  | {key: 'a', primaryKey: 1}, | 
|  | {key: 'a', primaryKey: 2}, | 
|  | {key: 'a', primaryKey: 3}, | 
|  | {key: 'b', primaryKey: 1}, | 
|  | {key: 'b', primaryKey: 2}, | 
|  | {key: 'b', primaryKey: 3}, | 
|  | {key: 'b', primaryKey: 4}, | 
|  | ]; | 
|  |  | 
|  | const request = index.openCursor(); | 
|  | request.onerror = t.unreached_func('IDBIndex.openCursor should not fail'); | 
|  | request.onsuccess = t.step_func(() => { | 
|  | const cursor = request.result; | 
|  | const expectedEntry = expectedIndexEntries.shift(); | 
|  | if (expectedEntry) { | 
|  | assert_equals( | 
|  | cursor.key, expectedEntry.key, | 
|  | 'The index entry keys should reflect the object store contents'); | 
|  | assert_equals( | 
|  | cursor.primaryKey, expectedEntry.primaryKey, | 
|  | 'The index entry primary keys should reflect the object store ' + | 
|  | 'contents'); | 
|  | cursor.continue(); | 
|  | } else { | 
|  | assert_equals( | 
|  | cursor, null, | 
|  | 'The index should not have entries that do not reflect the ' + | 
|  | 'object store contents'); | 
|  | } | 
|  | }); | 
|  | }, | 
|  | (t, db) => { | 
|  | const testCases = [ | 
|  | // Continuing index key. | 
|  | { | 
|  | call: cursor => { | 
|  | cursor.continue(); | 
|  | }, | 
|  | result: {key: 'a', primaryKey: 2} | 
|  | }, | 
|  | { | 
|  | call: cursor => { | 
|  | cursor.continue('a'); | 
|  | }, | 
|  | exception: 'DataError' | 
|  | }, | 
|  | { | 
|  | call: cursor => { | 
|  | cursor.continue('b'); | 
|  | }, | 
|  | result: {key: 'b', primaryKey: 1} | 
|  | }, | 
|  | { | 
|  | call: cursor => { | 
|  | cursor.continue('c'); | 
|  | }, | 
|  | result: null | 
|  | }, | 
|  |  | 
|  | // Called w/ index key and primary key. | 
|  | { | 
|  | call: cursor => { | 
|  | cursor.continuePrimaryKey('a', 3); | 
|  | }, | 
|  | result: {key: 'a', primaryKey: 3} | 
|  | }, | 
|  | { | 
|  | call: cursor => { | 
|  | cursor.continuePrimaryKey('a', 4); | 
|  | }, | 
|  | result: {key: 'b', primaryKey: 1} | 
|  | }, | 
|  | { | 
|  | call: cursor => { | 
|  | cursor.continuePrimaryKey('b', 1); | 
|  | }, | 
|  | result: {key: 'b', primaryKey: 1} | 
|  | }, | 
|  | { | 
|  | call: cursor => { | 
|  | cursor.continuePrimaryKey('b', 4); | 
|  | }, | 
|  | result: {key: 'b', primaryKey: 4} | 
|  | }, | 
|  | { | 
|  | call: cursor => { | 
|  | cursor.continuePrimaryKey('b', 5); | 
|  | }, | 
|  | result: null | 
|  | }, | 
|  | { | 
|  | call: cursor => { | 
|  | cursor.continuePrimaryKey('c', 1); | 
|  | }, | 
|  | result: null | 
|  | }, | 
|  |  | 
|  | // Called w/ primary key but w/o index key. | 
|  | { | 
|  | call: cursor => { | 
|  | cursor.continuePrimaryKey(null, 1); | 
|  | }, | 
|  | exception: 'DataError' | 
|  | }, | 
|  | { | 
|  | call: cursor => { | 
|  | cursor.continuePrimaryKey(null, 2); | 
|  | }, | 
|  | exception: 'DataError' | 
|  | }, | 
|  | { | 
|  | call: cursor => { | 
|  | cursor.continuePrimaryKey(null, 3); | 
|  | }, | 
|  | exception: 'DataError' | 
|  | }, | 
|  | { | 
|  | call: cursor => { | 
|  | cursor.continuePrimaryKey(null, 4); | 
|  | }, | 
|  | exception: 'DataError' | 
|  | }, | 
|  | { | 
|  | call: cursor => { | 
|  | cursor.continuePrimaryKey(null, 5); | 
|  | }, | 
|  | exception: 'DataError' | 
|  | }, | 
|  |  | 
|  | // Called w/ index key but w/o primary key. | 
|  | { | 
|  | call: cursor => { | 
|  | cursor.continuePrimaryKey('a', null); | 
|  | }, | 
|  | exception: 'DataError' | 
|  | }, | 
|  | ]; | 
|  |  | 
|  | const verifyContinueCalls = () => { | 
|  | if (!testCases.length) { | 
|  | t.done(); | 
|  | return; | 
|  | } | 
|  |  | 
|  | const testCase = testCases.shift(); | 
|  |  | 
|  | const txn = db.transaction('store', 'readonly'); | 
|  | txn.oncomplete = t.step_func(verifyContinueCalls); | 
|  |  | 
|  | const request = txn.objectStore('store').index('index').openCursor(); | 
|  | let calledContinue = false; | 
|  | request.onerror = | 
|  | t.unreached_func('IDBIndex.openCursor should not fail'); | 
|  | request.onsuccess = t.step_func(() => { | 
|  | const cursor = request.result; | 
|  | if (calledContinue) { | 
|  | if (testCase.result) { | 
|  | assert_equals( | 
|  | cursor.key, testCase.result.key, | 
|  | `${testCase.call.toString()} - result key`); | 
|  | assert_equals( | 
|  | cursor.primaryKey, testCase.result.primaryKey, | 
|  | `${testCase.call.toString()} - result primary key`); | 
|  | } else { | 
|  | assert_equals(cursor, null); | 
|  | } | 
|  | } else { | 
|  | calledContinue = true; | 
|  | if ('exception' in testCase) { | 
|  | assert_throws_dom(testCase.exception, () => { | 
|  | testCase.call(cursor); | 
|  | }, testCase.call.toString()); | 
|  | } else { | 
|  | testCase.call(cursor); | 
|  | } | 
|  | } | 
|  | }); | 
|  | }; | 
|  | verifyContinueCalls(); | 
|  | }); |