Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / LayoutTests / storage / indexeddb / resources / exceptions.js
1 if (this.importScripts) {
2     importScripts('../../../resources/js-test.js');
3     importScripts('shared.js');
4 }
5
6 description("Test that expected exceptions are thrown per IndexedDB spec.");
7
8 indexedDBTest(prepareDatabase, testDatabase);
9 function prepareDatabase()
10 {
11     db = event.target.result;
12
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'})");
27
28     evalAndLog("request = inlineKeyStore.put({id: 0})");
29     shouldBeEqualToString("request.readyState", "pending");
30
31     debug("");
32     debug("3.2.1 The IDBRequest Interface");
33
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'");
38
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'");
43
44     debug("");
45     debug("3.2.3 Opening a database");
46
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'");
51 }
52
53 function testDatabase()
54 {
55     evalAndLog("db.close()");
56
57     debug("");
58     debug("3.2.4 Database");
59
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;
68
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'");
78
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'");
83
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     };
89 }
90
91 function checkTransactionAndObjectStoreExceptions()
92 {
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'");
99
100     debug("");
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'");
104
105     debug("");
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'");
109
110     prepareStoreAndIndex();
111 }
112
113 function prepareStoreAndIndex()
114 {
115     debug("");
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");
125     };
126     inactiveTransaction.oncomplete = testObjectStore;
127 }
128
129 function testObjectStore()
130 {
131     debug("");
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')");
137
138     debug("");
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.
148
149     debug("");
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
156
157     debug("");
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
164
165     debug("");
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
174
175     debug("");
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
182
183     debug("");
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
190
191     debug("");
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
200
201     debug("");
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
210
211     debug("");
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.
221
222     evalAndLog("db.close()");
223     evalAndLog("ro_transaction.oncomplete = transactionComplete");
224     evalAndLog("rw_transaction.oncomplete = transactionComplete");
225 }
226
227 var numCompleted = 0;
228 function transactionComplete(evt)
229 {
230     preamble(evt);
231     numCompleted++;
232     if (numCompleted == 1) {
233         debug("First transaction completed");
234         return;
235     }
236     evalAndLog("request = indexedDB.open(dbname, 3)");
237     request.onerror = unexpectedErrorCallback;
238     request.onblocked = unexpectedBlockedCallback;
239     evalAndLog("request.onupgradeneeded = onUpgradeNeeded3");
240 }
241
242 function onUpgradeNeeded3()
243 {
244     db = request.result;
245     var trans = request.transaction;
246     trans.onabort = unexpectedAbortCallback;
247     trans.oncomplete = testOutsideVersionChangeTransaction;
248     store = trans.objectStore('store');
249
250     debug("");
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
259
260     debug("");
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'");
264 }
265
266 function testOutsideVersionChangeTransaction() {
267     debug("");
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'");
271
272     debug("");
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'");
276     testIndex();
277 }
278
279 function testIndex()
280 {
281     debug("");
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')");
285
286     debug("");
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
293
294     debug("");
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
301
302     debug("");
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
309
310     debug("");
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
319
320     debug("");
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
329
330     testCursor();
331 }
332
333 function testCursor()
334 {
335     debug("");
336     debug("3.2.7 Cursor");
337     evalAndLog("transaction = db.transaction(['store', 'inlineKeyStore'], 'readwrite')");
338
339     makeCursor();
340
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;
348             makeKeyCursor();
349         };
350     }
351
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;
358             makeReverseCursor();
359         };
360     }
361
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;
368             makeInlineCursor();
369         };
370     }
371
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;
378             testCursorAdvance();
379         };
380     }
381
382     function testCursorAdvance() {
383         debug("");
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;
393     }
394
395     function testCursorContinue() {
396         debug("");
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'");
409         testCursorDelete();
410     }
411
412     function testCursorDelete() {
413         debug("");
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;
420     }
421
422     function testCursorUpdate() {
423         debug("");
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'");
433
434         primaryCursorRequest.onsuccess = null;
435         makeReadOnlyCursor();
436     }
437
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();
446         };
447     }
448
449     function doReadOnlyCursorTests() {
450        debug("");
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'");
454
455        debug("");
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'");
459
460        testTransaction();
461     }
462 }
463
464 function testTransaction()
465 {
466     debug("");
467     debug("3.2.8 Transaction");
468
469     debug("");
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'");
475
476     finishJSTest();
477 }