Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / LayoutTests / storage / indexeddb / resources / exceptions.js
blob30d8c109e6bd2eca3f8a5d47aa431fd09935831a
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");
31     debug("");
32     debug("3.2.1 The IDBRequest Interface");
34     debug("");
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'");
39     debug("");
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'");
44     debug("");
45     debug("3.2.3 Opening a database");
47     debug("");
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()");
57     debug("");
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() {
65         db = request.result;
66         var trans = request.transaction;
67         trans.onabort = unexpectedAbortCallback;
69         debug("");
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'");
79         debug("");
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'");
84         debug("");
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'");
88     };
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 'versionchange' value for the mode parameter can only be set internally during upgradeneeded.");
98     evalAndExpectExceptionClass("db.transaction('store', 'versionchange')", "TypeError");
99     debug("The function was called with an empty list of store names");
100     evalAndExpectException("db.transaction([])", "DOMException.INVALID_ACCESS_ERR", "'InvalidAccessError'");
102     debug("");
103     debug("One more IDBDatabase.createObjectStore() test:");
104     debug('If this function is called from outside a "versionchange" transaction callback ... the implementation must throw a DOMException of type InvalidStateError.');
105     evalAndExpectException("db.createObjectStore('fail')", "DOMException.INVALID_STATE_ERR", "'InvalidStateError'");
107     debug("");
108     debug("One more IDBDatabase.deleteObjectStore() test:");
109     debug('If this function is called from outside a "versionchange" transaction callback ... the implementation must throw a DOMException of type InvalidStateError.');
110     evalAndExpectException("db.deleteObjectStore('fail')", "DOMException.INVALID_STATE_ERR", "'InvalidStateError'");
112     prepareStoreAndIndex();
115 function prepareStoreAndIndex()
117     debug("");
118     debug("Prepare an object store and index from an inactive transaction for later use.");
119     evalAndLog("finishedTransaction = inactiveTransaction = db.transaction('store')");
120     inactiveTransaction.onabort = unexpectedAbortCallback;
121     evalAndLog("storeFromInactiveTransaction = inactiveTransaction.objectStore('store')");
122     evalAndLog("indexFromInactiveTransaction = storeFromInactiveTransaction.index('index')");
123     evalAndLog("request = storeFromInactiveTransaction.openCursor()");
124     request.onerror = unexpectedErrorCallback;
125     request.onsuccess = function() {
126         evalAndLog("cursorFromInactiveTransaction = request.result");
127     };
128     inactiveTransaction.oncomplete = testObjectStore;
131 function testObjectStore()
133     debug("");
134     debug("3.2.5 Object Store");
135     evalAndLog("ro_transaction = db.transaction('store', 'readonly')");
136     evalAndLog("storeFromReadOnlyTransaction = ro_transaction.objectStore('store')");
137     evalAndLog("rw_transaction = db.transaction('store', 'readwrite')");
138     evalAndLog("store = rw_transaction.objectStore('store')");
140     debug("");
141     debug("IDBObjectStore.add()");
142     debug('This method throws a DOMException of type ReadOnlyError if the transaction which this IDBObjectStore belongs to is has its mode set to "readonly".');
143     evalAndExpectException("storeFromReadOnlyTransaction.add(0, 0)", "0", "'ReadOnlyError'");
144     // "If any of the following conditions are true, this method throws a DOMException of type DataError:" - covered in objectstore-basics.html
145     debug("The transaction this IDBObjectStore belongs to is not active.");
146     evalAndExpectException("storeFromInactiveTransaction.add(0, 0)", "0", "'TransactionInactiveError'");
147     // "Occurs if a request is made on a source object that has been deleted or removed." - covered in deleted-objects.html
148     debug("The data being stored could not be cloned by the internal structured cloning algorithm.");
149     evalAndExpectException("store.add(self, 0)", "DOMException.DATA_CLONE_ERR"); // FIXME: Test 'DataCloneError' name when DOM4 exceptions are used in binding.
151     debug("");
152     debug("IDBObjectStore.clear()");
153     debug('This method throws a DOMException of type ReadOnlyError if the transaction which this IDBObjectStore belongs to is has its mode set to "readonly".');
154     evalAndExpectException("storeFromReadOnlyTransaction.clear()", "0", "'ReadOnlyError'");
155     debug("The transaction this IDBObjectStore belongs to is not active.");
156     evalAndExpectException("storeFromInactiveTransaction.clear()", "0", "'TransactionInactiveError'");
157     // "Occurs if a request is made on a source object that has been deleted or removed." - covered in deleted-objects.html
159     debug("");
160     debug("IDBObjectStore.count()");
161     debug("If the optional key parameter is not a valid key or a key range, this method throws a DOMException of type DataError.");
162     evalAndExpectException("store.count({})", "0", "'DataError'");
163     debug("The transaction this IDBObjectStore belongs to is not active.");
164     evalAndExpectException("storeFromInactiveTransaction.count()", "0", "'TransactionInactiveError'");
165     // "Occurs if a request is made on a source object that has been deleted or removed." - covered in deleted-objects.html
167     debug("");
168     debug("IDBObjectStore.delete()");
169     debug('This method throws a DOMException of type ReadOnlyError if the transaction which this IDBObjectStore belongs to is has its mode set to "readonly".');
170     evalAndExpectException("storeFromReadOnlyTransaction.delete(0)", "0", "'ReadOnlyError'");
171     debug("If the key parameter is not a valid key or a key range this method throws a DOMException of type DataError.");
172     evalAndExpectException("store.delete({})", "0", "'DataError'");
173     debug("The transaction this IDBObjectStore belongs to is not active.");
174     evalAndExpectException("storeFromInactiveTransaction.add(0, 0)", "0", "'TransactionInactiveError'");
175     // "Occurs if a request is made on a source object that has been deleted or removed." - covered in deleted-objects.html
177     debug("");
178     debug("IDBObjectStore.get()");
179     debug("If the key parameter is not a valid key or a key range, this method throws a DOMException of type DataError.");
180     evalAndExpectException("store.get({})", "0", "'DataError'");
181     debug("The transaction this IDBObjectStore belongs to is not active.");
182     evalAndExpectException("storeFromInactiveTransaction.get(0)", "0", "'TransactionInactiveError'");
183     // "Occurs if a request is made on a source object that has been deleted or removed." - covered in deleted-objects.html
185     debug("");
186     debug("IDBObjectStore.getAll()");
187     debug("If the key parameter is not a valid key or a key range, this method throws a DOMException of type DataError.");
188     evalAndExpectException("store.getAll({})", "0", "'DataError'");
189     debug("The transaction this IDBObjectStore belongs to is not active.");
190     evalAndExpectException("storeFromInactiveTransaction.getAll(0)", "0", "'TransactionInactiveError'");
191     // "Occurs if a request is made on a source object that has been deleted or removed." - covered in deleted-objects.html
193     debug("");
194     debug("IDBObjectStore.getAllKeys()");
195     debug("If the key parameter is not a valid key or a key range, this method throws a DOMException of type DataError.");
196     evalAndExpectException("store.getAllKeys({})", "0", "'DataError'");
197     debug("The transaction this IDBObjectStore belongs to is not active.");
198     evalAndExpectException("storeFromInactiveTransaction.getAllKeys(0)", "0", "'TransactionInactiveError'");
199     // "Occurs if a request is made on a source object that has been deleted or removed." - covered in deleted-objects.html
200     //
201     debug("");
202     debug("IDBObjectStore.index()");
203     debug("There is no index with the given name, compared in a case-sensitive manner, in the connected database.");
204     evalAndExpectException("store.index('no-such-index')", "DOMException.NOT_FOUND_ERR", "'NotFoundError'");
205     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.");
206     evalAndExpectException("storeFromInactiveTransaction.index('index')", "DOMException.INVALID_STATE_ERR", "'InvalidStateError'");
207     // "Occurs if a request is made on a source object that has been deleted or removed." - covered in deleted-objects.html
209     debug("");
210     debug("IDBObjectStore.openCursor()");
211     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.");
212     evalAndExpectException("store.openCursor({})", "0", "'DataError'");
213     debug("The transaction this IDBObjectStore belongs to is not active.");
214     evalAndExpectException("storeFromInactiveTransaction.openCursor()", "0", "'TransactionInactiveError'");
215     debug("The value for the direction parameter is invalid.");
216     evalAndExpectExceptionClass("store.openCursor(0, 'invalid-direction')", "TypeError");
217     // "Occurs if a request is made on a source object that has been deleted or removed." - covered in deleted-objects.html
219     debug("");
220     debug("IDBObjectStore.openKeyCursor()");
221     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.");
222     evalAndExpectException("store.openKeyCursor({})", "0", "'DataError'");
223     debug("The transaction this IDBObjectStore belongs to is not active.");
224     evalAndExpectException("storeFromInactiveTransaction.openKeyCursor()", "0", "'TransactionInactiveError'");
225     debug("The value for the direction parameter is invalid.");
226     evalAndExpectExceptionClass("store.openKeyCursor(0, 'invalid-direction')", "TypeError");
227     // "Occurs if a request is made on a source object that has been deleted or removed." - covered in deleted-objects.html
229     debug("");
230     debug("IDBObjectStore.put()");
231     debug('This method throws a DOMException of type ReadOnlyError if the transaction which this IDBObjectStore belongs to is has its mode set to "readonly".');
232     evalAndExpectException("storeFromReadOnlyTransaction.put(0, 0)", "0", "'ReadOnlyError'");
233     // "If any of the following conditions are true, this method throws a DOMException of type DataError:" - covered in objectstore-basics.html
234     debug("The transaction this IDBObjectStore belongs to is not active.");
235     evalAndExpectException("storeFromInactiveTransaction.put(0, 0)", "0", "'TransactionInactiveError'");
236     // "Occurs if a request is made on a source object that has been deleted or removed." - covered in deleted-objects.html
237     debug("The data being stored could not be cloned by the internal structured cloning algorithm.");
238     evalAndExpectException("store.put(self, 0)", "DOMException.DATA_CLONE_ERR"); // FIXME: Test 'DataCloneError' name when DOM4 exceptions are used in binding.
240     evalAndLog("db.close()");
241     evalAndLog("ro_transaction.oncomplete = transactionComplete");
242     evalAndLog("rw_transaction.oncomplete = transactionComplete");
245 var numCompleted = 0;
246 function transactionComplete(evt)
248     preamble(evt);
249     numCompleted++;
250     if (numCompleted == 1) {
251         debug("First transaction completed");
252         return;
253     }
254     evalAndLog("request = indexedDB.open(dbname, 3)");
255     request.onerror = unexpectedErrorCallback;
256     request.onblocked = unexpectedBlockedCallback;
257     evalAndLog("request.onupgradeneeded = onUpgradeNeeded3");
260 function onUpgradeNeeded3()
262     db = request.result;
263     var trans = request.transaction;
264     trans.onabort = unexpectedAbortCallback;
265     trans.oncomplete = testOutsideVersionChangeTransaction;
266     store = trans.objectStore('store');
268     debug("");
269     debug("IDBObjectStore.createIndex()");
270     debug("If an index with the same name already exists, the implementation must throw a DOMException of type ConstraintError. ");
271     evalAndExpectException("store.createIndex('index', 'keyPath')", "0", "'ConstraintError'");
272     debug("If keyPath is not a valid key path then a DOMException of type SyntaxError must be thrown.");
273     evalAndExpectException("store.createIndex('fail', '-invalid-')", "DOMException.SYNTAX_ERR", "'SyntaxError'");
274     debug("If keyPath is an Array and the multiEntry property in the optionalParameters is true, then a DOMException of type InvalidAccessError must be thrown.");
275     evalAndExpectException("store.createIndex('fail', ['a'], {multiEntry: true})", "DOMException.INVALID_ACCESS_ERR", "'InvalidAccessError'");
276     // "Occurs if a request is made on a source object that has been deleted or removed." - covered in deleted-objects.html
278     debug("");
279     debug("IDBObjectStore.deleteIndex()");
280     debug("There is no index with the given name, compared in a case-sensitive manner, in the connected database.");
281     evalAndExpectException("store.deleteIndex('no-such-index')", "DOMException.NOT_FOUND_ERR", "'NotFoundError'");
284 function testOutsideVersionChangeTransaction() {
285     debug("");
286     debug("One more IDBObjectStore.createIndex() test:");
287     debug('If this function is called from outside a "versionchange" transaction callback ... the implementation must throw a DOMException of type InvalidStateError.');
288     evalAndExpectException("db.transaction('store').objectStore('store').createIndex('fail', 'keyPath')", "DOMException.INVALID_STATE_ERR", "'InvalidStateError'");
290     debug("");
291     debug("One more IDBObjectStore.deleteIndex() test:");
292     debug('If this function is called from outside a "versionchange" transaction callback ... the implementation must throw a DOMException of type InvalidStateError.');
293     evalAndExpectException("db.transaction('store').objectStore('store').deleteIndex('fail', 'keyPath')", "DOMException.INVALID_STATE_ERR", "'InvalidStateError'");
294     testIndex();
297 function testIndex()
299     debug("");
300     debug("3.2.6 Index");
301     evalAndLog("indexFromReadOnlyTransaction = db.transaction('store', 'readonly').objectStore('store').index('index')");
302     evalAndLog("index = db.transaction('store', 'readwrite').objectStore('store').index('index')");
304     debug("");
305     debug("IDBIndex.count()");
306     debug("If the optional key parameter is not a valid key or a key range, this method throws a DOMException of type DataError.");
307     evalAndExpectException("index.count({})", "0", "'DataError'");
308     debug("The transaction this IDBIndex belongs to is not active.");
309     evalAndExpectException("indexFromInactiveTransaction.count()", "0", "'TransactionInactiveError'");
310     // "Occurs if a request is made on a source object that has been deleted or removed." - covered in deleted-objects.html
312     debug("");
313     debug("IDBIndex.get()");
314     debug("If the key parameter is not a valid key or a key range, this method throws a DOMException of type DataError.");
315     evalAndExpectException("index.get({})", "0", "'DataError'");
316     debug("The transaction this IDBIndex belongs to is not active.");
317     evalAndExpectException("indexFromInactiveTransaction.get(0)", "0", "'TransactionInactiveError'");
318     // "Occurs if a request is made on a source object that has been deleted or removed." - covered in deleted-objects.html
319     //
320     debug("");
321     debug("IDBIndex.getAll()");
322     debug("If the key parameter is not a valid key or a key range, this method throws a DOMException of type DataError.");
323     evalAndExpectException("index.getAll({})", "0", "'DataError'");
324     debug("The transaction this IDBIndex belongs to is not active.");
325     evalAndExpectException("indexFromInactiveTransaction.getAll(0)", "0", "'TransactionInactiveError'");
326     // "Occurs if a request is made on a source object that has been deleted or removed." - covered in deleted-objects.html
328     debug("");
329     debug("IDBIndex.getKey()");
330     debug("If the key parameter is not a valid key or a key range, this method throws a DOMException of type DataError.");
331     evalAndExpectException("index.getKey({})", "0", "'DataError'");
332     debug("The transaction this IDBIndex belongs to is not active.");
333     evalAndExpectException("indexFromInactiveTransaction.getKey(0)", "0", "'TransactionInactiveError'");
334     // "Occurs if a request is made on a source object that has been deleted or removed." - covered in deleted-objects.html
336     debug("");
337     debug("IDBIndex.getAllKeys()");
338     debug("If the key parameter is not a valid key or a key range, this method throws a DOMException of type DataError.");
339     evalAndExpectException("index.getAllKeys({})", "0", "'DataError'");
340     debug("The transaction this IDBIndex belongs to is not active.");
341     evalAndExpectException("indexFromInactiveTransaction.getAllKeys(0)", "0", "'TransactionInactiveError'");
342     // "Occurs if a request is made on a source object that has been deleted or removed." - covered in deleted-objects.html
344     debug("");
345     debug("IDBIndex.openCursor()");
346     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.");
347     evalAndExpectException("index.openCursor({})", "0", "'DataError'");
348     debug("The transaction this IDBIndex belongs to is not active.");
349     evalAndExpectException("indexFromInactiveTransaction.openCursor()", "0", "'TransactionInactiveError'");
350     debug("The value for the direction parameter is invalid.");
351     evalAndExpectExceptionClass("index.openCursor(0, 'invalid-direction')", "TypeError");
352     // "Occurs if a request is made on a source object that has been deleted or removed." - covered in deleted-objects.html
354     debug("");
355     debug("IDBIndex.openKeyCursor()");
356     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.");
357     evalAndExpectException("index.openKeyCursor({})", "0", "'DataError'");
358     debug("The transaction this IDBIndex belongs to is not active.");
359     evalAndExpectException("indexFromInactiveTransaction.openKeyCursor()", "0", "'TransactionInactiveError'");
360     debug("The value for the direction parameter is invalid.");
361     evalAndExpectExceptionClass("index.openKeyCursor(0, 'invalid-direction')", "TypeError");
362     // "Occurs if a request is made on a source object that has been deleted or removed." - covered in deleted-objects.html
364     testCursor();
367 function testCursor()
369     debug("");
370     debug("3.2.7 Cursor");
371     evalAndLog("transaction = db.transaction(['store', 'inlineKeyStore'], 'readwrite')");
373     makeCursor();
375     function makeCursor() {
376         evalAndLog("request = transaction.objectStore('store').openCursor()");
377         primaryCursorRequest = request;
378         request.onerror = unexpectedErrorCallback;
379         request.onsuccess = function() {
380             evalAndLog("cursor = request.result");
381             request.onsuccess = null;
382             makeKeyCursor();
383         };
384     }
386     function makeKeyCursor() {
387         evalAndLog("request = transaction.objectStore('store').index('index').openKeyCursor()");
388         request.onerror = unexpectedErrorCallback;
389         request.onsuccess = function() {
390             evalAndLog("keyCursor = request.result");
391             request.onsuccess = null;
392             makeReverseCursor();
393         };
394     }
396     function makeReverseCursor() {
397         evalAndLog("request = transaction.objectStore('store').openCursor(IDBKeyRange.lowerBound(-Infinity), 'prev')");
398         request.onerror = unexpectedErrorCallback;
399         request.onsuccess = function() {
400             evalAndLog("reverseCursor = request.result");
401             request.onsuccess = null;
402             makeInlineCursor();
403         };
404     }
406     function makeInlineCursor() {
407         evalAndLog("request = transaction.objectStore('inlineKeyStore').openCursor()");
408         request.onerror = unexpectedErrorCallback;
409         request.onsuccess = function() {
410             evalAndLog("inlineCursor = request.result");
411             request.onsuccess = null;
412             testCursorAdvance();
413         };
414     }
416     function testCursorAdvance() {
417         debug("");
418         debug("IDBCursor.advance()");
419         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.");
420         debug("If the value for count is 0 (zero) or a negative number, this method must throw a JavaScript TypeError exception.");
421         evalAndExpectExceptionClass("cursor.advance(0)", "TypeError");
422         evalAndLog("cursor.advance(1)");
423         evalAndExpectException("cursor.advance(1)", "DOMException.INVALID_STATE_ERR", "'InvalidStateError'");
424         debug("The transaction this IDBCursor belongs to is not active.");
425         evalAndExpectException("cursorFromInactiveTransaction.advance(1)", "0", "'TransactionInactiveError'");
426         primaryCursorRequest.onsuccess = testCursorContinue;
427     }
429     function testCursorContinue() {
430         debug("");
431         debug("IDBCursor.continue()");
432         debug("The parameter is not a valid key.");
433         evalAndExpectException("cursor.continue({})", "0", "'DataError'");
434         debug("The parameter is less than or equal to this cursor's position and this cursor's direction is \"next\" or \"nextunique\".");
435         evalAndExpectException("cursor.continue(-Infinity)", "0", "'DataError'");
436         debug("The parameter is greater than or equal to this cursor's position and this cursor's direction is \"prev\" or \"prevunique\".");
437         evalAndExpectException("reverseCursor.continue(100)", "0", "'DataError'");
438         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.");
439         evalAndLog("cursor.continue()");
440         evalAndExpectException("cursor.continue()", "DOMException.INVALID_STATE_ERR", "'InvalidStateError'");
441         debug("The transaction this IDBCursor belongs to is not active.");
442         evalAndExpectException("cursorFromInactiveTransaction.continue()", "0", "'TransactionInactiveError'");
443         testCursorDelete();
444     }
446     function testCursorDelete() {
447         debug("");
448         debug("IDBCursor.delete()");
449         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.");
450         evalAndExpectException("keyCursor.delete()", "DOMException.INVALID_STATE_ERR", "'InvalidStateError'");
451         debug("The transaction this IDBCursor belongs to is not active.");
452         evalAndExpectException("cursorFromInactiveTransaction.delete()", "0", "'TransactionInactiveError'");
453         primaryCursorRequest.onsuccess = testCursorUpdate;
454     }
456     function testCursorUpdate() {
457         debug("");
458         debug("IDBCursor.update()");
459         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.");
460         evalAndExpectException("keyCursor.update({})", "DOMException.INVALID_STATE_ERR", "'InvalidStateError'");
461         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.");
462         evalAndExpectException("inlineCursor.update({id: 1})", "0", "'DataError'");
463         debug("If the structured clone algorithm throws an exception, that exception is rethrown.");
464         evalAndExpectException("cursor.update(self)", "DOMException.DATA_CLONE_ERR"); // FIXME: Test 'DataCloneError' name when DOM4 exceptions are used in binding.
465         debug("The transaction this IDBCursor belongs to is not active.");
466         evalAndExpectException("cursorFromInactiveTransaction.update({})", "0", "'TransactionInactiveError'");
468         primaryCursorRequest.onsuccess = null;
469         makeReadOnlyCursor();
470     }
472     // Can't have both transactions running at once, so these tests must be separated out.
473     function makeReadOnlyCursor() {
474         evalAndLog("readOnlyTransaction = db.transaction('store', 'readonly')");
475         evalAndLog("request = readOnlyTransaction.objectStore('store').openCursor()");
476         request.onerror = unexpectedErrorCallback;
477         request.onsuccess = function() {
478             evalAndLog("cursorFromReadOnlyTransaction = request.result");
479             doReadOnlyCursorTests();
480         };
481     }
483     function doReadOnlyCursorTests() {
484        debug("");
485        debug("One more IDBCursor.delete() test:");
486        debug('This method throws a DOMException of type ReadOnlyError if the transaction which this IDBCursor belongs to has its mode set to "readonly".');
487        evalAndExpectException("cursorFromReadOnlyTransaction.delete()", "0", "'ReadOnlyError'");
489        debug("");
490        debug("One more IDBCursor.update() test:");
491        debug('This method throws a DOMException of type ReadOnlyError if the transaction which this IDBCursor belongs to has its mode set to "readonly".');
492        evalAndExpectException("cursorFromReadOnlyTransaction.update({})", "0", "'ReadOnlyError'");
494        testTransaction();
495     }
498 function testTransaction()
500     debug("");
501     debug("3.2.8 Transaction");
503     debug("");
504     debug("IDBTransaction.abort()");
505     debug("If this transaction is finished, throw a DOMException of type InvalidStateError. ");
506     evalAndExpectException("finishedTransaction.abort()", "DOMException.INVALID_STATE_ERR", "'InvalidStateError'");
507     debug("If the requested object store is not in this transaction's scope.");
508     evalAndExpectException("db.transaction('store').objectStore('otherStore')", "DOMException.NOT_FOUND_ERR", "'NotFoundError'");
510     finishJSTest();