1 if (this.importScripts) {
2 importScripts('../../../resources/js-test.js');
3 importScripts('shared.js');
6 description("Test that expected exceptions are thrown per IndexedDB spec.");
8 indexedDBTest(prepareDatabase, testDatabase);
9 function prepareDatabase()
11 db = event.target.result;
13 evalAndLog("store = db.createObjectStore('store')");
14 evalAndLog("index = store.createIndex('index', 'id')");
15 evalAndLog("store.put({id: 'a'}, 1)");
16 evalAndLog("store.put({id: 'b'}, 2)");
17 evalAndLog("store.put({id: 'c'}, 3)");
18 evalAndLog("store.put({id: 'd'}, 4)");
19 evalAndLog("store.put({id: 'e'}, 5)");
20 evalAndLog("store.put({id: 'f'}, 6)");
21 evalAndLog("store.put({id: 'g'}, 7)");
22 evalAndLog("store.put({id: 'h'}, 8)");
23 evalAndLog("store.put({id: 'i'}, 9)");
24 evalAndLog("store.put({id: 'j'}, 10)");
25 evalAndLog("otherStore = db.createObjectStore('otherStore')");
26 evalAndLog("inlineKeyStore = db.createObjectStore('inlineKeyStore', {keyPath: 'id'})");
28 evalAndLog("request = inlineKeyStore.put({id: 0})");
29 shouldBeEqualToString("request.readyState", "pending");
32 debug("3.2.1 The IDBRequest Interface");
35 debug("IDBRequest.error");
36 debug("When the done flag is false, getting this property must throw a DOMException of type InvalidStateError.");
37 evalAndExpectException("request.error", "DOMException.INVALID_STATE_ERR", "'InvalidStateError'");
40 debug("IDBRequest.result");
41 debug("When the done flag is false, getting this property must throw a DOMException of type InvalidStateError.");
42 evalAndExpectException("request.result", "DOMException.INVALID_STATE_ERR", "'InvalidStateError'");
45 debug("3.2.3 Opening a database");
48 debug("IDBFactory.cmp()");
49 debug("One of the supplied keys was not a valid key.");
50 evalAndExpectException("indexedDB.cmp(null, 0)", "0", "'DataError'");
53 function testDatabase()
55 evalAndLog("db.close()");
58 debug("3.2.4 Database");
60 request = evalAndLog("indexedDB.open(dbname, 2)");
61 request.onerror = unexpectedErrorCallback;
62 request.onblocked = unexpectedBlockedCallback;
63 request.onsuccess = checkTransactionAndObjectStoreExceptions;
64 request.onupgradeneeded = function() {
66 var trans = request.transaction;
67 trans.onabort = unexpectedAbortCallback;
70 debug("IDBDatabase.createObjectStore()");
71 debug("If an objectStore with the same name already exists, the implementation must throw a DOMException of type ConstraintError.");
72 evalAndExpectException("db.createObjectStore('store')", "0", "'ConstraintError'");
73 debug("If keyPath is not a valid key path then a DOMException of type SyntaxError must be thrown.");
74 evalAndExpectException("db.createObjectStore('fail', {keyPath: '-invalid-'})", "DOMException.SYNTAX_ERR", "'SyntaxError'");
75 debug("If the optionalParameters parameter is specified, and autoIncrement is set to true, and the keyPath parameter is specified to the empty string, or specified to an Array, this function must throw a InvalidAccessError exception.");
76 evalAndExpectException("db.createObjectStore('fail', {autoIncrement: true, keyPath: ''})", "DOMException.INVALID_ACCESS_ERR", "'InvalidAccessError'");
77 evalAndExpectException("db.createObjectStore('fail', {autoIncrement: true, keyPath: ['a']})", "DOMException.INVALID_ACCESS_ERR", "'InvalidAccessError'");
80 debug("IDBDatabase.deleteObjectStore()");
81 debug("There is no object store with the given name, compared in a case-sensitive manner, in the connected database.");
82 evalAndExpectException("db.deleteObjectStore('no-such-store')", "DOMException.NOT_FOUND_ERR", "'NotFoundError'");
85 debug("IDBDatabase.transaction()");
86 debug('If this method is called on IDBDatabase object for which a "versionchange" transaction is still running, a InvalidStateError exception must be thrown.');
87 evalAndExpectException("db.transaction('store')", "DOMException.INVALID_STATE_ERR", "'InvalidStateError'");
91 function checkTransactionAndObjectStoreExceptions()
93 debug("One of the names provided in the storeNames argument doesn't exist in this database.");
94 evalAndExpectException("db.transaction('no-such-store')", "DOMException.NOT_FOUND_ERR", "'NotFoundError'");
95 debug("The value for the mode parameter is invalid.");
96 evalAndExpectExceptionClass("db.transaction('store', 'invalid-mode')", "TypeError");
97 debug("The function was called with an empty list of store names");
98 evalAndExpectException("db.transaction([])", "DOMException.INVALID_ACCESS_ERR", "'InvalidAccessError'");
101 debug("One more IDBDatabase.createObjectStore() test:");
102 debug('If this function is called from outside a "versionchange" transaction callback ... the implementation must throw a DOMException of type InvalidStateError.');
103 evalAndExpectException("db.createObjectStore('fail')", "DOMException.INVALID_STATE_ERR", "'InvalidStateError'");
106 debug("One more IDBDatabase.deleteObjectStore() test:");
107 debug('If this function is called from outside a "versionchange" transaction callback ... the implementation must throw a DOMException of type InvalidStateError.');
108 evalAndExpectException("db.deleteObjectStore('fail')", "DOMException.INVALID_STATE_ERR", "'InvalidStateError'");
110 prepareStoreAndIndex();
113 function prepareStoreAndIndex()
116 debug("Prepare an object store and index from an inactive transaction for later use.");
117 evalAndLog("finishedTransaction = inactiveTransaction = db.transaction('store')");
118 inactiveTransaction.onabort = unexpectedAbortCallback;
119 evalAndLog("storeFromInactiveTransaction = inactiveTransaction.objectStore('store')");
120 evalAndLog("indexFromInactiveTransaction = storeFromInactiveTransaction.index('index')");
121 evalAndLog("request = storeFromInactiveTransaction.openCursor()");
122 request.onerror = unexpectedErrorCallback;
123 request.onsuccess = function() {
124 evalAndLog("cursorFromInactiveTransaction = request.result");
126 inactiveTransaction.oncomplete = testObjectStore;
129 function testObjectStore()
132 debug("3.2.5 Object Store");
133 evalAndLog("ro_transaction = db.transaction('store', 'readonly')");
134 evalAndLog("storeFromReadOnlyTransaction = ro_transaction.objectStore('store')");
135 evalAndLog("rw_transaction = db.transaction('store', 'readwrite')");
136 evalAndLog("store = rw_transaction.objectStore('store')");
139 debug("IDBObjectStore.add()");
140 debug('This method throws a DOMException of type ReadOnlyError if the transaction which this IDBObjectStore belongs to is has its mode set to "readonly".');
141 evalAndExpectException("storeFromReadOnlyTransaction.add(0, 0)", "0", "'ReadOnlyError'");
142 // "If any of the following conditions are true, this method throws a DOMException of type DataError:" - covered in objectstore-basics.html
143 debug("The transaction this IDBObjectStore belongs to is not active.");
144 evalAndExpectException("storeFromInactiveTransaction.add(0, 0)", "0", "'TransactionInactiveError'");
145 // "Occurs if a request is made on a source object that has been deleted or removed." - covered in deleted-objects.html
146 debug("The data being stored could not be cloned by the internal structured cloning algorithm.");
147 evalAndExpectException("store.add(self, 0)", "DOMException.DATA_CLONE_ERR"); // FIXME: Test 'DataCloneError' name when DOM4 exceptions are used in binding.
150 debug("IDBObjectStore.clear()");
151 debug('This method throws a DOMException of type ReadOnlyError if the transaction which this IDBObjectStore belongs to is has its mode set to "readonly".');
152 evalAndExpectException("storeFromReadOnlyTransaction.clear()", "0", "'ReadOnlyError'");
153 debug("The transaction this IDBObjectStore belongs to is not active.");
154 evalAndExpectException("storeFromInactiveTransaction.clear()", "0", "'TransactionInactiveError'");
155 // "Occurs if a request is made on a source object that has been deleted or removed." - covered in deleted-objects.html
158 debug("IDBObjectStore.count()");
159 debug("If the optional key parameter is not a valid key or a key range, this method throws a DOMException of type DataError.");
160 evalAndExpectException("store.count({})", "0", "'DataError'");
161 debug("The transaction this IDBObjectStore belongs to is not active.");
162 evalAndExpectException("storeFromInactiveTransaction.count()", "0", "'TransactionInactiveError'");
163 // "Occurs if a request is made on a source object that has been deleted or removed." - covered in deleted-objects.html
166 debug("IDBObjectStore.delete()");
167 debug('This method throws a DOMException of type ReadOnlyError if the transaction which this IDBObjectStore belongs to is has its mode set to "readonly".');
168 evalAndExpectException("storeFromReadOnlyTransaction.delete(0)", "0", "'ReadOnlyError'");
169 debug("If the key parameter is not a valid key or a key range this method throws a DOMException of type DataError.");
170 evalAndExpectException("store.delete({})", "0", "'DataError'");
171 debug("The transaction this IDBObjectStore belongs to is not active.");
172 evalAndExpectException("storeFromInactiveTransaction.add(0, 0)", "0", "'TransactionInactiveError'");
173 // "Occurs if a request is made on a source object that has been deleted or removed." - covered in deleted-objects.html
176 debug("IDBObjectStore.get()");
177 debug("If the key parameter is not a valid key or a key range, this method throws a DOMException of type DataError.");
178 evalAndExpectException("store.get({})", "0", "'DataError'");
179 debug("The transaction this IDBObjectStore belongs to is not active.");
180 evalAndExpectException("storeFromInactiveTransaction.get(0)", "0", "'TransactionInactiveError'");
181 // "Occurs if a request is made on a source object that has been deleted or removed." - covered in deleted-objects.html
184 debug("IDBObjectStore.index()");
185 debug("There is no index with the given name, compared in a case-sensitive manner, in the connected database.");
186 evalAndExpectException("store.index('no-such-index')", "DOMException.NOT_FOUND_ERR", "'NotFoundError'");
187 debug("Occurs if a request is made on a source object that has been deleted or removed, or if the transaction the object store belongs to has finished.");
188 evalAndExpectException("storeFromInactiveTransaction.index('index')", "DOMException.INVALID_STATE_ERR", "'InvalidStateError'");
189 // "Occurs if a request is made on a source object that has been deleted or removed." - covered in deleted-objects.html
192 debug("IDBObjectStore.openCursor()");
193 debug("If the range parameter is specified but is not a valid key or a key range, this method throws a DOMException of type DataError.");
194 evalAndExpectException("store.openCursor({})", "0", "'DataError'");
195 debug("The transaction this IDBObjectStore belongs to is not active.");
196 evalAndExpectException("storeFromInactiveTransaction.openCursor()", "0", "'TransactionInactiveError'");
197 debug("The value for the direction parameter is invalid.");
198 evalAndExpectExceptionClass("store.openCursor(0, 'invalid-direction')", "TypeError");
199 // "Occurs if a request is made on a source object that has been deleted or removed." - covered in deleted-objects.html
202 debug("IDBObjectStore.openKeyCursor()");
203 debug("If the range parameter is specified but is not a valid key or a key range, this method throws a DOMException of type DataError.");
204 evalAndExpectException("store.openKeyCursor({})", "0", "'DataError'");
205 debug("The transaction this IDBObjectStore belongs to is not active.");
206 evalAndExpectException("storeFromInactiveTransaction.openKeyCursor()", "0", "'TransactionInactiveError'");
207 debug("The value for the direction parameter is invalid.");
208 evalAndExpectExceptionClass("store.openKeyCursor(0, 'invalid-direction')", "TypeError");
209 // "Occurs if a request is made on a source object that has been deleted or removed." - covered in deleted-objects.html
212 debug("IDBObjectStore.put()");
213 debug('This method throws a DOMException of type ReadOnlyError if the transaction which this IDBObjectStore belongs to is has its mode set to "readonly".');
214 evalAndExpectException("storeFromReadOnlyTransaction.put(0, 0)", "0", "'ReadOnlyError'");
215 // "If any of the following conditions are true, this method throws a DOMException of type DataError:" - covered in objectstore-basics.html
216 debug("The transaction this IDBObjectStore belongs to is not active.");
217 evalAndExpectException("storeFromInactiveTransaction.put(0, 0)", "0", "'TransactionInactiveError'");
218 // "Occurs if a request is made on a source object that has been deleted or removed." - covered in deleted-objects.html
219 debug("The data being stored could not be cloned by the internal structured cloning algorithm.");
220 evalAndExpectException("store.put(self, 0)", "DOMException.DATA_CLONE_ERR"); // FIXME: Test 'DataCloneError' name when DOM4 exceptions are used in binding.
222 evalAndLog("db.close()");
223 evalAndLog("ro_transaction.oncomplete = transactionComplete");
224 evalAndLog("rw_transaction.oncomplete = transactionComplete");
227 var numCompleted = 0;
228 function transactionComplete(evt)
232 if (numCompleted == 1) {
233 debug("First transaction completed");
236 evalAndLog("request = indexedDB.open(dbname, 3)");
237 request.onerror = unexpectedErrorCallback;
238 request.onblocked = unexpectedBlockedCallback;
239 evalAndLog("request.onupgradeneeded = onUpgradeNeeded3");
242 function onUpgradeNeeded3()
245 var trans = request.transaction;
246 trans.onabort = unexpectedAbortCallback;
247 trans.oncomplete = testOutsideVersionChangeTransaction;
248 store = trans.objectStore('store');
251 debug("IDBObjectStore.createIndex()");
252 debug("If an index with the same name already exists, the implementation must throw a DOMException of type ConstraintError. ");
253 evalAndExpectException("store.createIndex('index', 'keyPath')", "0", "'ConstraintError'");
254 debug("If keyPath is not a valid key path then a DOMException of type SyntaxError must be thrown.");
255 evalAndExpectException("store.createIndex('fail', '-invalid-')", "DOMException.SYNTAX_ERR", "'SyntaxError'");
256 debug("If keyPath is an Array and the multiEntry property in the optionalParameters is true, then a DOMException of type InvalidAccessError must be thrown.");
257 evalAndExpectException("store.createIndex('fail', ['a'], {multiEntry: true})", "DOMException.INVALID_ACCESS_ERR", "'InvalidAccessError'");
258 // "Occurs if a request is made on a source object that has been deleted or removed." - covered in deleted-objects.html
261 debug("IDBObjectStore.deleteIndex()");
262 debug("There is no index with the given name, compared in a case-sensitive manner, in the connected database.");
263 evalAndExpectException("store.deleteIndex('no-such-index')", "DOMException.NOT_FOUND_ERR", "'NotFoundError'");
266 function testOutsideVersionChangeTransaction() {
268 debug("One more IDBObjectStore.createIndex() test:");
269 debug('If this function is called from outside a "versionchange" transaction callback ... the implementation must throw a DOMException of type InvalidStateError.');
270 evalAndExpectException("db.transaction('store').objectStore('store').createIndex('fail', 'keyPath')", "DOMException.INVALID_STATE_ERR", "'InvalidStateError'");
273 debug("One more IDBObjectStore.deleteIndex() test:");
274 debug('If this function is called from outside a "versionchange" transaction callback ... the implementation must throw a DOMException of type InvalidStateError.');
275 evalAndExpectException("db.transaction('store').objectStore('store').deleteIndex('fail', 'keyPath')", "DOMException.INVALID_STATE_ERR", "'InvalidStateError'");
282 debug("3.2.6 Index");
283 evalAndLog("indexFromReadOnlyTransaction = db.transaction('store', 'readonly').objectStore('store').index('index')");
284 evalAndLog("index = db.transaction('store', 'readwrite').objectStore('store').index('index')");
287 debug("IDBIndex.count()");
288 debug("If the optional key parameter is not a valid key or a key range, this method throws a DOMException of type DataError.");
289 evalAndExpectException("index.count({})", "0", "'DataError'");
290 debug("The transaction this IDBIndex belongs to is not active.");
291 evalAndExpectException("indexFromInactiveTransaction.count()", "0", "'TransactionInactiveError'");
292 // "Occurs if a request is made on a source object that has been deleted or removed." - covered in deleted-objects.html
295 debug("IDBIndex.get()");
296 debug("If the key parameter is not a valid key or a key range, this method throws a DOMException of type DataError.");
297 evalAndExpectException("index.get({})", "0", "'DataError'");
298 debug("The transaction this IDBIndex belongs to is not active.");
299 evalAndExpectException("indexFromInactiveTransaction.get(0)", "0", "'TransactionInactiveError'");
300 // "Occurs if a request is made on a source object that has been deleted or removed." - covered in deleted-objects.html
303 debug("IDBIndex.getKey()");
304 debug("If the key parameter is not a valid key or a key range, this method throws a DOMException of type DataError.");
305 evalAndExpectException("index.getKey({})", "0", "'DataError'");
306 debug("The transaction this IDBIndex belongs to is not active.");
307 evalAndExpectException("indexFromInactiveTransaction.getKey(0)", "0", "'TransactionInactiveError'");
308 // "Occurs if a request is made on a source object that has been deleted or removed." - covered in deleted-objects.html
311 debug("IDBIndex.openCursor()");
312 debug("If the range parameter is specified but is not a valid key or a key range, this method throws a DOMException of type DataError.");
313 evalAndExpectException("index.openCursor({})", "0", "'DataError'");
314 debug("The transaction this IDBIndex belongs to is not active.");
315 evalAndExpectException("indexFromInactiveTransaction.openCursor()", "0", "'TransactionInactiveError'");
316 debug("The value for the direction parameter is invalid.");
317 evalAndExpectExceptionClass("index.openCursor(0, 'invalid-direction')", "TypeError");
318 // "Occurs if a request is made on a source object that has been deleted or removed." - covered in deleted-objects.html
321 debug("IDBIndex.openKeyCursor()");
322 debug("If the range parameter is specified but is not a valid key or a key range, this method throws a DOMException of type DataError.");
323 evalAndExpectException("index.openKeyCursor({})", "0", "'DataError'");
324 debug("The transaction this IDBIndex belongs to is not active.");
325 evalAndExpectException("indexFromInactiveTransaction.openKeyCursor()", "0", "'TransactionInactiveError'");
326 debug("The value for the direction parameter is invalid.");
327 evalAndExpectExceptionClass("index.openKeyCursor(0, 'invalid-direction')", "TypeError");
328 // "Occurs if a request is made on a source object that has been deleted or removed." - covered in deleted-objects.html
333 function testCursor()
336 debug("3.2.7 Cursor");
337 evalAndLog("transaction = db.transaction(['store', 'inlineKeyStore'], 'readwrite')");
341 function makeCursor() {
342 evalAndLog("request = transaction.objectStore('store').openCursor()");
343 primaryCursorRequest = request;
344 request.onerror = unexpectedErrorCallback;
345 request.onsuccess = function() {
346 evalAndLog("cursor = request.result");
347 request.onsuccess = null;
352 function makeKeyCursor() {
353 evalAndLog("request = transaction.objectStore('store').index('index').openKeyCursor()");
354 request.onerror = unexpectedErrorCallback;
355 request.onsuccess = function() {
356 evalAndLog("keyCursor = request.result");
357 request.onsuccess = null;
362 function makeReverseCursor() {
363 evalAndLog("request = transaction.objectStore('store').openCursor(IDBKeyRange.lowerBound(-Infinity), 'prev')");
364 request.onerror = unexpectedErrorCallback;
365 request.onsuccess = function() {
366 evalAndLog("reverseCursor = request.result");
367 request.onsuccess = null;
372 function makeInlineCursor() {
373 evalAndLog("request = transaction.objectStore('inlineKeyStore').openCursor()");
374 request.onerror = unexpectedErrorCallback;
375 request.onsuccess = function() {
376 evalAndLog("inlineCursor = request.result");
377 request.onsuccess = null;
382 function testCursorAdvance() {
384 debug("IDBCursor.advance()");
385 debug("Calling this method more than once before new cursor data has been loaded is not allowed and results in a DOMException of type InvalidStateError being thrown.");
386 debug("If the value for count is 0 (zero) or a negative number, this method must throw a JavaScript TypeError exception.");
387 evalAndExpectExceptionClass("cursor.advance(0)", "TypeError");
388 evalAndLog("cursor.advance(1)");
389 evalAndExpectException("cursor.advance(1)", "DOMException.INVALID_STATE_ERR", "'InvalidStateError'");
390 debug("The transaction this IDBCursor belongs to is not active.");
391 evalAndExpectException("cursorFromInactiveTransaction.advance(1)", "0", "'TransactionInactiveError'");
392 primaryCursorRequest.onsuccess = testCursorContinue;
395 function testCursorContinue() {
397 debug("IDBCursor.continue()");
398 debug("The parameter is not a valid key.");
399 evalAndExpectException("cursor.continue({})", "0", "'DataError'");
400 debug("The parameter is less than or equal to this cursor's position and this cursor's direction is \"next\" or \"nextunique\".");
401 evalAndExpectException("cursor.continue(-Infinity)", "0", "'DataError'");
402 debug("The parameter is greater than or equal to this cursor's position and this cursor's direction is \"prev\" or \"prevunique\".");
403 evalAndExpectException("reverseCursor.continue(100)", "0", "'DataError'");
404 debug("Calling this method more than once before new cursor data has been loaded is not allowed and results in a DOMException of type InvalidStateError being thrown.");
405 evalAndLog("cursor.continue()");
406 evalAndExpectException("cursor.continue()", "DOMException.INVALID_STATE_ERR", "'InvalidStateError'");
407 debug("The transaction this IDBCursor belongs to is not active.");
408 evalAndExpectException("cursorFromInactiveTransaction.continue()", "0", "'TransactionInactiveError'");
412 function testCursorDelete() {
414 debug("IDBCursor.delete()");
415 debug("If this cursor's got value flag is false, or if this cursor was created using openKeyCursor a DOMException of type InvalidStateError is thrown.");
416 evalAndExpectException("keyCursor.delete()", "DOMException.INVALID_STATE_ERR", "'InvalidStateError'");
417 debug("The transaction this IDBCursor belongs to is not active.");
418 evalAndExpectException("cursorFromInactiveTransaction.delete()", "0", "'TransactionInactiveError'");
419 primaryCursorRequest.onsuccess = testCursorUpdate;
422 function testCursorUpdate() {
424 debug("IDBCursor.update()");
425 debug("If this cursor's got value flag is false or if this cursor was created using openKeyCursor. This method throws a DOMException of type InvalidStateError.");
426 evalAndExpectException("keyCursor.update({})", "DOMException.INVALID_STATE_ERR", "'InvalidStateError'");
427 debug("If the effective object store of this cursor uses in-line keys and evaluating the key path of the value parameter results in a different value than the cursor's effective key, this method throws a DOMException of type DataError.");
428 evalAndExpectException("inlineCursor.update({id: 1})", "0", "'DataError'");
429 debug("If the structured clone algorithm throws an exception, that exception is rethrown.");
430 evalAndExpectException("cursor.update(self)", "DOMException.DATA_CLONE_ERR"); // FIXME: Test 'DataCloneError' name when DOM4 exceptions are used in binding.
431 debug("The transaction this IDBCursor belongs to is not active.");
432 evalAndExpectException("cursorFromInactiveTransaction.update({})", "0", "'TransactionInactiveError'");
434 primaryCursorRequest.onsuccess = null;
435 makeReadOnlyCursor();
438 // Can't have both transactions running at once, so these tests must be separated out.
439 function makeReadOnlyCursor() {
440 evalAndLog("readOnlyTransaction = db.transaction('store', 'readonly')");
441 evalAndLog("request = readOnlyTransaction.objectStore('store').openCursor()");
442 request.onerror = unexpectedErrorCallback;
443 request.onsuccess = function() {
444 evalAndLog("cursorFromReadOnlyTransaction = request.result");
445 doReadOnlyCursorTests();
449 function doReadOnlyCursorTests() {
451 debug("One more IDBCursor.delete() test:");
452 debug('This method throws a DOMException of type ReadOnlyError if the transaction which this IDBCursor belongs to has its mode set to "readonly".');
453 evalAndExpectException("cursorFromReadOnlyTransaction.delete()", "0", "'ReadOnlyError'");
456 debug("One more IDBCursor.update() test:");
457 debug('This method throws a DOMException of type ReadOnlyError if the transaction which this IDBCursor belongs to has its mode set to "readonly".');
458 evalAndExpectException("cursorFromReadOnlyTransaction.update({})", "0", "'ReadOnlyError'");
464 function testTransaction()
467 debug("3.2.8 Transaction");
470 debug("IDBTransaction.abort()");
471 debug("If this transaction is finished, throw a DOMException of type InvalidStateError. ");
472 evalAndExpectException("finishedTransaction.abort()", "DOMException.INVALID_STATE_ERR", "'InvalidStateError'");
473 debug("If the requested object store is not in this transaction's scope.");
474 evalAndExpectException("db.transaction('store').objectStore('otherStore')", "DOMException.NOT_FOUND_ERR", "'NotFoundError'");