summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/IndexedDB
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/IndexedDB')
-rw-r--r--testing/web-platform/tests/IndexedDB/OWNERS7
-rw-r--r--testing/web-platform/tests/IndexedDB/README.md8
-rw-r--r--testing/web-platform/tests/IndexedDB/abort-in-initial-upgradeneeded.html35
-rw-r--r--testing/web-platform/tests/IndexedDB/close-in-upgradeneeded.html39
-rw-r--r--testing/web-platform/tests/IndexedDB/cursor-overloads.htm88
-rw-r--r--testing/web-platform/tests/IndexedDB/idb_binary_key_conversion.htm79
-rw-r--r--testing/web-platform/tests/IndexedDB/idb_webworkers.htm33
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor-advance-continue-async.htm186
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor-advance-invalid.htm188
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor-advance.htm243
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor-continue.htm240
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor-continuePrimaryKey-exception-order.htm382
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor-direction-index-keyrange.htm82
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor-direction-index.htm81
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor-direction-objectstore-keyrange.htm77
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor-direction-objectstore.htm80
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor-direction.htm73
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor-key.htm57
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor-primarykey.htm61
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor-reused.htm69
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor-source.htm68
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_advance_index.htm57
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_advance_index2.htm47
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_advance_index3.htm47
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_advance_index5.htm55
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_advance_index6.htm37
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_advance_index7.htm39
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_advance_index8.htm38
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_advance_index9.htm37
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_advance_objectstore.htm54
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_advance_objectstore2.htm40
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_advance_objectstore3.htm42
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_advance_objectstore4.htm41
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_advance_objectstore5.htm36
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_continue_index.htm52
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_continue_index2.htm49
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_continue_index3.htm54
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_continue_index4.htm65
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_continue_index5.htm64
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_continue_index6.htm64
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_continue_index7.htm38
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_continue_index8.htm38
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_continue_invalid.htm54
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_continue_objectstore.htm46
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_continue_objectstore2.htm40
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_continue_objectstore3.htm40
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_continue_objectstore4.htm57
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_continue_objectstore5.htm42
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_continue_objectstore6.htm37
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_delete_index.htm69
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_delete_index2.htm42
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_delete_index3.htm40
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_delete_index4.htm38
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_delete_index5.htm39
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_delete_objectstore.htm65
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_delete_objectstore2.htm40
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_delete_objectstore3.htm39
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_delete_objectstore4.htm37
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_delete_objectstore5.htm41
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_iterating.htm110
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_iterating_index.htm53
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_iterating_index2.htm53
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_iterating_objectstore.htm51
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_iterating_objectstore2.htm51
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_update_index.htm64
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_update_index2.htm40
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_update_index3.htm41
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_update_index4.htm39
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_update_index5.htm45
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_update_index6.htm41
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_update_index7.htm41
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_update_index8.htm45
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_update_objectstore.htm60
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_update_objectstore2.htm38
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_update_objectstore3.htm40
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_update_objectstore4.htm39
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_update_objectstore5.htm41
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_update_objectstore6.htm43
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_update_objectstore7.htm39
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_update_objectstore8.htm39
-rw-r--r--testing/web-platform/tests/IndexedDB/idbcursor_update_objectstore9.htm45
-rw-r--r--testing/web-platform/tests/IndexedDB/idbdatabase_close.htm43
-rw-r--r--testing/web-platform/tests/IndexedDB/idbdatabase_close2.htm39
-rw-r--r--testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore-createIndex-emptyname.htm45
-rw-r--r--testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore.htm29
-rw-r--r--testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore10-1000ends.htm37
-rw-r--r--testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore10-emptyname.htm38
-rw-r--r--testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore11.htm25
-rw-r--r--testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore2.htm33
-rw-r--r--testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore3.htm24
-rw-r--r--testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore4.htm27
-rw-r--r--testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore5.htm33
-rw-r--r--testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore6.htm30
-rw-r--r--testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore7.htm25
-rw-r--r--testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore8-parameters.htm39
-rw-r--r--testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore9-invalidparameters.htm29
-rw-r--r--testing/web-platform/tests/IndexedDB/idbdatabase_deleteObjectStore.htm25
-rw-r--r--testing/web-platform/tests/IndexedDB/idbdatabase_deleteObjectStore2.htm31
-rw-r--r--testing/web-platform/tests/IndexedDB/idbdatabase_deleteObjectStore3.htm23
-rw-r--r--testing/web-platform/tests/IndexedDB/idbdatabase_deleteObjectStore4-not_reused.htm42
-rw-r--r--testing/web-platform/tests/IndexedDB/idbdatabase_transaction.htm24
-rw-r--r--testing/web-platform/tests/IndexedDB/idbdatabase_transaction2.htm27
-rw-r--r--testing/web-platform/tests/IndexedDB/idbdatabase_transaction3.htm28
-rw-r--r--testing/web-platform/tests/IndexedDB/idbdatabase_transaction4.htm26
-rw-r--r--testing/web-platform/tests/IndexedDB/idbdatabase_transaction5.htm22
-rw-r--r--testing/web-platform/tests/IndexedDB/idbfactory_cmp.htm21
-rw-r--r--testing/web-platform/tests/IndexedDB/idbfactory_cmp2.htm41
-rw-r--r--testing/web-platform/tests/IndexedDB/idbfactory_cmp3.htm27
-rw-r--r--testing/web-platform/tests/IndexedDB/idbfactory_cmp4.htm40
-rw-r--r--testing/web-platform/tests/IndexedDB/idbfactory_deleteDatabase.htm25
-rw-r--r--testing/web-platform/tests/IndexedDB/idbfactory_deleteDatabase2.htm27
-rw-r--r--testing/web-platform/tests/IndexedDB/idbfactory_deleteDatabase3.htm33
-rw-r--r--testing/web-platform/tests/IndexedDB/idbfactory_deleteDatabase4.htm58
-rw-r--r--testing/web-platform/tests/IndexedDB/idbfactory_open.htm18
-rw-r--r--testing/web-platform/tests/IndexedDB/idbfactory_open10.htm91
-rw-r--r--testing/web-platform/tests/IndexedDB/idbfactory_open11.htm60
-rw-r--r--testing/web-platform/tests/IndexedDB/idbfactory_open12.htm50
-rw-r--r--testing/web-platform/tests/IndexedDB/idbfactory_open2.htm20
-rw-r--r--testing/web-platform/tests/IndexedDB/idbfactory_open3.htm27
-rw-r--r--testing/web-platform/tests/IndexedDB/idbfactory_open4.htm20
-rw-r--r--testing/web-platform/tests/IndexedDB/idbfactory_open5.htm18
-rw-r--r--testing/web-platform/tests/IndexedDB/idbfactory_open6.htm34
-rw-r--r--testing/web-platform/tests/IndexedDB/idbfactory_open7.htm38
-rw-r--r--testing/web-platform/tests/IndexedDB/idbfactory_open8.htm27
-rw-r--r--testing/web-platform/tests/IndexedDB/idbfactory_open9.htm71
-rw-r--r--testing/web-platform/tests/IndexedDB/idbindex-multientry-arraykeypath.htm23
-rw-r--r--testing/web-platform/tests/IndexedDB/idbindex-multientry-big.htm58
-rw-r--r--testing/web-platform/tests/IndexedDB/idbindex-multientry.htm53
-rw-r--r--testing/web-platform/tests/IndexedDB/idbindex-rename-abort.html110
-rw-r--r--testing/web-platform/tests/IndexedDB/idbindex-rename-errors.html130
-rw-r--r--testing/web-platform/tests/IndexedDB/idbindex-rename.html299
-rw-r--r--testing/web-platform/tests/IndexedDB/idbindex_count.htm37
-rw-r--r--testing/web-platform/tests/IndexedDB/idbindex_count2.htm37
-rw-r--r--testing/web-platform/tests/IndexedDB/idbindex_count3.htm28
-rw-r--r--testing/web-platform/tests/IndexedDB/idbindex_count4.htm37
-rw-r--r--testing/web-platform/tests/IndexedDB/idbindex_get.htm36
-rw-r--r--testing/web-platform/tests/IndexedDB/idbindex_get2.htm39
-rw-r--r--testing/web-platform/tests/IndexedDB/idbindex_get3.htm27
-rw-r--r--testing/web-platform/tests/IndexedDB/idbindex_get4.htm39
-rw-r--r--testing/web-platform/tests/IndexedDB/idbindex_get5.htm26
-rw-r--r--testing/web-platform/tests/IndexedDB/idbindex_get6.htm29
-rw-r--r--testing/web-platform/tests/IndexedDB/idbindex_get7.htm32
-rw-r--r--testing/web-platform/tests/IndexedDB/idbindex_get8.htm27
-rw-r--r--testing/web-platform/tests/IndexedDB/idbindex_getAll.html232
-rw-r--r--testing/web-platform/tests/IndexedDB/idbindex_getAllKeys.html207
-rw-r--r--testing/web-platform/tests/IndexedDB/idbindex_getKey.htm38
-rw-r--r--testing/web-platform/tests/IndexedDB/idbindex_getKey2.htm39
-rw-r--r--testing/web-platform/tests/IndexedDB/idbindex_getKey3.htm28
-rw-r--r--testing/web-platform/tests/IndexedDB/idbindex_getKey4.htm38
-rw-r--r--testing/web-platform/tests/IndexedDB/idbindex_getKey5.htm26
-rw-r--r--testing/web-platform/tests/IndexedDB/idbindex_getKey6.htm29
-rw-r--r--testing/web-platform/tests/IndexedDB/idbindex_getKey7.htm32
-rw-r--r--testing/web-platform/tests/IndexedDB/idbindex_getKey8.htm27
-rw-r--r--testing/web-platform/tests/IndexedDB/idbindex_indexNames.htm34
-rw-r--r--testing/web-platform/tests/IndexedDB/idbindex_openCursor.htm29
-rw-r--r--testing/web-platform/tests/IndexedDB/idbindex_openCursor2.htm32
-rw-r--r--testing/web-platform/tests/IndexedDB/idbindex_openCursor3.htm27
-rw-r--r--testing/web-platform/tests/IndexedDB/idbindex_openKeyCursor.htm28
-rw-r--r--testing/web-platform/tests/IndexedDB/idbindex_openKeyCursor2.htm29
-rw-r--r--testing/web-platform/tests/IndexedDB/idbindex_openKeyCursor3.htm32
-rw-r--r--testing/web-platform/tests/IndexedDB/idbindex_openKeyCursor4.htm27
-rw-r--r--testing/web-platform/tests/IndexedDB/idbkeyrange-includes.htm61
-rw-r--r--testing/web-platform/tests/IndexedDB/idbkeyrange.htm67
-rw-r--r--testing/web-platform/tests/IndexedDB/idbkeyrange_incorrect.htm92
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore-rename-abort.html120
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore-rename-errors.html118
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore-rename-store.html367
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_add.htm35
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_add10.htm29
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_add11.htm29
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_add12.htm29
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_add13.htm29
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_add14.htm32
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_add15.htm31
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_add16.htm25
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_add2.htm36
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_add3.htm39
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_add4.htm40
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_add5.htm34
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_add6.htm47
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_add7.htm47
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_add8.htm47
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_add9.htm27
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_clear.htm41
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_clear2.htm43
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_clear3.htm36
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_clear4.htm25
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_count.htm35
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_count2.htm35
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_count3.htm31
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_count4.htm25
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex.htm30
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex10.htm24
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex11.htm23
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex12.htm31
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex13.htm31
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex14-exception_order.htm89
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex2.htm41
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex3-usable-right-away.htm38
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex4-deleteIndex-event_order.htm66
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex5-emptykeypath.htm38
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex6-event_order.htm75
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex7-event_order.htm80
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex8-valid_keys.htm54
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex9-emptyname.htm41
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_delete.htm46
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_delete2.htm27
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_delete3.htm47
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_delete4.htm48
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_delete5.htm32
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_delete6.htm36
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_delete7.htm27
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_deleteIndex.htm43
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_deleted.htm49
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_get.htm35
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_get2.htm35
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_get3.htm34
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_get4.htm27
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_get5.htm31
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_get6.htm30
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_get7.htm29
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_getAll.html174
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_getAllKeys.html167
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_index.htm34
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_openCursor.htm42
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_openCursor_invalid.htm50
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_openKeyCursor.htm139
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_put.htm35
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_put10.htm29
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_put11.htm29
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_put12.htm29
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_put13.htm29
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_put14.htm32
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_put15.htm31
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_put16.htm25
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_put2.htm36
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_put3.htm48
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_put4.htm40
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_put5.htm34
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_put6.htm47
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_put7.htm47
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_put8.htm47
-rw-r--r--testing/web-platform/tests/IndexedDB/idbobjectstore_put9.htm27
-rw-r--r--testing/web-platform/tests/IndexedDB/idbtransaction-oncomplete.htm53
-rw-r--r--testing/web-platform/tests/IndexedDB/idbtransaction.htm46
-rw-r--r--testing/web-platform/tests/IndexedDB/idbtransaction_abort.htm41
-rw-r--r--testing/web-platform/tests/IndexedDB/idbtransaction_objectStoreNames.html164
-rw-r--r--testing/web-platform/tests/IndexedDB/idbversionchangeevent.htm66
-rw-r--r--testing/web-platform/tests/IndexedDB/idbworker.js34
-rw-r--r--testing/web-platform/tests/IndexedDB/index_sort_order.htm51
-rw-r--r--testing/web-platform/tests/IndexedDB/interfaces.html50
-rw-r--r--testing/web-platform/tests/IndexedDB/interfaces.idl156
-rw-r--r--testing/web-platform/tests/IndexedDB/interfaces.worker.js37
-rw-r--r--testing/web-platform/tests/IndexedDB/key_invalid.htm129
-rw-r--r--testing/web-platform/tests/IndexedDB/key_valid.html75
-rw-r--r--testing/web-platform/tests/IndexedDB/keygenerator-constrainterror.htm73
-rw-r--r--testing/web-platform/tests/IndexedDB/keygenerator-overflow.htm70
-rw-r--r--testing/web-platform/tests/IndexedDB/keygenerator.htm65
-rw-r--r--testing/web-platform/tests/IndexedDB/keyorder.htm175
-rw-r--r--testing/web-platform/tests/IndexedDB/keypath.htm146
-rw-r--r--testing/web-platform/tests/IndexedDB/keypath_invalid.htm65
-rw-r--r--testing/web-platform/tests/IndexedDB/keypath_maxsize.htm63
-rw-r--r--testing/web-platform/tests/IndexedDB/list_ordering.htm61
-rw-r--r--testing/web-platform/tests/IndexedDB/objectstore_keyorder.htm49
-rw-r--r--testing/web-platform/tests/IndexedDB/request_bubble-and-capture.htm69
-rw-r--r--testing/web-platform/tests/IndexedDB/string-list-ordering.htm85
-rw-r--r--testing/web-platform/tests/IndexedDB/support-promises.js200
-rw-r--r--testing/web-platform/tests/IndexedDB/support.js123
-rw-r--r--testing/web-platform/tests/IndexedDB/transaction-abort-generator-revert.html108
-rw-r--r--testing/web-platform/tests/IndexedDB/transaction-abort-index-metadata-revert.html276
-rw-r--r--testing/web-platform/tests/IndexedDB/transaction-abort-multiple-metadata-revert.html291
-rw-r--r--testing/web-platform/tests/IndexedDB/transaction-abort-object-store-metadata-revert.html188
-rw-r--r--testing/web-platform/tests/IndexedDB/transaction-create_in_versionchange.htm82
-rw-r--r--testing/web-platform/tests/IndexedDB/transaction-lifetime-blocked.htm108
-rw-r--r--testing/web-platform/tests/IndexedDB/transaction-lifetime-empty.html89
-rw-r--r--testing/web-platform/tests/IndexedDB/transaction-lifetime.htm101
-rw-r--r--testing/web-platform/tests/IndexedDB/transaction-requestqueue.htm89
-rw-r--r--testing/web-platform/tests/IndexedDB/transaction_bubble-and-capture.htm75
-rw-r--r--testing/web-platform/tests/IndexedDB/value.htm40
-rw-r--r--testing/web-platform/tests/IndexedDB/value_recursive.htm66
-rw-r--r--testing/web-platform/tests/IndexedDB/writer-starvation.htm105
281 files changed, 16309 insertions, 0 deletions
diff --git a/testing/web-platform/tests/IndexedDB/OWNERS b/testing/web-platform/tests/IndexedDB/OWNERS
new file mode 100644
index 000000000..bd8dca9f6
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/OWNERS
@@ -0,0 +1,7 @@
+@Velmont
+@inexorabletash
+@chunywang
+@dumbmatter
+@zqzhang
+@yunxiaoxie
+@zhaozihao
diff --git a/testing/web-platform/tests/IndexedDB/README.md b/testing/web-platform/tests/IndexedDB/README.md
new file mode 100644
index 000000000..6b636d5f1
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/README.md
@@ -0,0 +1,8 @@
+This directory contains the Indexed Database API test suite.
+
+To run the tests in this test suite within a browser, go to: <http://w3c-test.org/IndexedDB/>.
+
+The latest Editor's Draft of Indexed Database API is: <http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html>.
+
+The latest W3C Technical Report of Indexed Database API is: <http://www.w3.org/TR/IndexedDB/>.
+
diff --git a/testing/web-platform/tests/IndexedDB/abort-in-initial-upgradeneeded.html b/testing/web-platform/tests/IndexedDB/abort-in-initial-upgradeneeded.html
new file mode 100644
index 000000000..6330ecb02
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/abort-in-initial-upgradeneeded.html
@@ -0,0 +1,35 @@
+<!doctype html>
+<!-- Submitted from TestTWF Paris -->
+<title>Test that an abort in the initial upgradeneeded sets version back to 0</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+
+var db, open_rq = createdb(async_test(), undefined, 2);
+
+open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ assert_equals(db.version, 2);
+ transaction = e.target.transaction;
+ transaction.oncomplete = fail(this, "unexpected transaction.complete");
+ transaction.onabort = function(e) {
+ assert_equals(e.target.db.version, 0);
+ }
+ db.onabort = function() {}
+
+ transaction.abort();
+}
+
+open_rq.onerror = function(e) {
+ assert_equals(open_rq, e.target);
+ assert_equals(e.target.result, undefined);
+ assert_equals(e.target.error.name, "AbortError");
+ assert_equals(db.version, 0);
+ assert_equals(open_rq.transaction, null);
+ this.done();
+}
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/close-in-upgradeneeded.html b/testing/web-platform/tests/IndexedDB/close-in-upgradeneeded.html
new file mode 100644
index 000000000..eda823a21
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/close-in-upgradeneeded.html
@@ -0,0 +1,39 @@
+<!doctype html>
+<!-- Submitted from TestTWF Paris -->
+<title>When db.close is called in upgradeneeded, the db is cleaned up on refresh</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+
+var open_rq = createdb(async_test())
+var sawTransactionComplete = false
+
+open_rq.onupgradeneeded = function(e) {
+ db = e.target.result
+ assert_equals(db.version, 1)
+
+ db.createObjectStore('os')
+ db.close()
+
+ e.target.transaction.oncomplete = function() { sawTransactionComplete = true }
+}
+
+open_rq.onerror = function(e) {
+ assert_true(sawTransactionComplete, "saw transaction.complete")
+
+ assert_equals(e.target.error.name, 'AbortError')
+ assert_equals(e.result, undefined)
+
+ assert_true(!!db)
+ assert_equals(db.version, 1)
+ assert_equals(db.objectStoreNames.length, 1)
+ assert_throws("InvalidStateError", function() { db.transaction('os') })
+
+ this.done()
+}
+
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/cursor-overloads.htm b/testing/web-platform/tests/IndexedDB/cursor-overloads.htm
new file mode 100644
index 000000000..343e5a4cc
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/cursor-overloads.htm
@@ -0,0 +1,88 @@
+<!--
+Test converted from WebKit:
+http://trac.webkit.org/browser/trunk/LayoutTests/storage/indexeddb/cursor-overloads.html
+-->
+
+<!DOCTYPE html>
+<!-- Submitted from TestTWF Paris -->
+<meta charset=utf-8>
+<title>Validate the overloads of IDBObjectStore.openCursor(), IDBIndex.openCursor() and IDBIndex.openKeyCursor()</title>
+<link rel=author href="mailto:romain.huet@gmail.com" title="Romain Huet">
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+
+ var db, trans, store, index;
+ var t = async_test();
+
+ var request = createdb(t);
+ request.onupgradeneeded = function(e) {
+ db = request.result;
+ store = db.createObjectStore('store');
+ index = store.createIndex('index', 'value');
+ store.put({value: 0}, 0);
+ trans = request.transaction;
+ trans.oncomplete = verifyOverloads;
+ };
+
+ function verifyOverloads() {
+ trans = db.transaction('store');
+ store = trans.objectStore('store');
+ index = store.index('index');
+
+ checkCursorDirection("store.openCursor()", "next");
+ checkCursorDirection("store.openCursor(0)", "next");
+ checkCursorDirection("store.openCursor(0, 'next')", "next");
+ checkCursorDirection("store.openCursor(0, 'nextunique')", "nextunique");
+ checkCursorDirection("store.openCursor(0, 'prev')", "prev");
+ checkCursorDirection("store.openCursor(0, 'prevunique')", "prevunique");
+
+ checkCursorDirection("store.openCursor(IDBKeyRange.only(0))", "next");
+ checkCursorDirection("store.openCursor(IDBKeyRange.only(0), 'next')", "next");
+ checkCursorDirection("store.openCursor(IDBKeyRange.only(0), 'nextunique')", "nextunique");
+ checkCursorDirection("store.openCursor(IDBKeyRange.only(0), 'prev')", "prev");
+ checkCursorDirection("store.openCursor(IDBKeyRange.only(0), 'prevunique')", "prevunique");
+
+ checkCursorDirection("index.openCursor()", "next");
+ checkCursorDirection("index.openCursor(0)", "next");
+ checkCursorDirection("index.openCursor(0, 'next')", "next");
+ checkCursorDirection("index.openCursor(0, 'nextunique')", "nextunique");
+ checkCursorDirection("index.openCursor(0, 'prev')", "prev");
+ checkCursorDirection("index.openCursor(0, 'prevunique')", "prevunique");
+
+ checkCursorDirection("index.openCursor(IDBKeyRange.only(0))", "next");
+ checkCursorDirection("index.openCursor(IDBKeyRange.only(0), 'next')", "next");
+ checkCursorDirection("index.openCursor(IDBKeyRange.only(0), 'nextunique')", "nextunique");
+ checkCursorDirection("index.openCursor(IDBKeyRange.only(0), 'prev')", "prev");
+ checkCursorDirection("index.openCursor(IDBKeyRange.only(0), 'prevunique')", "prevunique");
+
+ checkCursorDirection("index.openKeyCursor()", "next");
+ checkCursorDirection("index.openKeyCursor(0)", "next");
+ checkCursorDirection("index.openKeyCursor(0, 'next')", "next");
+ checkCursorDirection("index.openKeyCursor(0, 'nextunique')", "nextunique");
+ checkCursorDirection("index.openKeyCursor(0, 'prev')", "prev");
+ checkCursorDirection("index.openKeyCursor(0, 'prevunique')", "prevunique");
+
+ checkCursorDirection("index.openKeyCursor(IDBKeyRange.only(0))", "next");
+ checkCursorDirection("index.openKeyCursor(IDBKeyRange.only(0), 'next')", "next");
+ checkCursorDirection("index.openKeyCursor(IDBKeyRange.only(0), 'nextunique')", "nextunique");
+ checkCursorDirection("index.openKeyCursor(IDBKeyRange.only(0), 'prev')", "prev");
+ checkCursorDirection("index.openKeyCursor(IDBKeyRange.only(0), 'prevunique')", "prevunique");
+
+ t.done();
+ }
+
+ function checkCursorDirection(statement, direction) {
+ request = eval(statement);
+ request.onsuccess = function(event) {
+ assert_not_equals(event.target.result, null, "Check the result is not null")
+ assert_equals(event.target.result.direction, direction, "Check the result direction");
+ };
+ }
+
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/idb_binary_key_conversion.htm b/testing/web-platform/tests/IndexedDB/idb_binary_key_conversion.htm
new file mode 100644
index 000000000..b55e6324b
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idb_binary_key_conversion.htm
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Verify the coversion of various types of BufferSource</title>
+<link rel="author" title="Mozilla" href="https://www.mozilla.org">
+<link rel="help" href="http://w3c.github.io/IndexedDB/#key-construct">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+
+<script>
+ test(function() {
+ let binary = new ArrayBuffer(0);
+ let key = IDBKeyRange.lowerBound(binary).lower;
+
+ assert_true(key instanceof ArrayBuffer);
+ assert_equals(key.byteLength, 0);
+ assert_equals(key.byteLength, binary.byteLength);
+ }, "Empty ArrayBuffer");
+
+ test(function() {
+ let binary = new ArrayBuffer(4);
+ let dataView = new DataView(binary);
+ dataView.setUint32(0, 1234567890);
+
+ let key = IDBKeyRange.lowerBound(binary).lower;
+
+ assert_true(key instanceof ArrayBuffer);
+ assert_equals(key.byteLength, 4);
+ assert_equals(dataView.getUint32(0), new DataView(key).getUint32(0));
+ }, "ArrayBuffer");
+
+ test(function() {
+ let binary = new ArrayBuffer(4);
+ let dataView = new DataView(binary);
+ dataView.setUint32(0, 1234567890);
+
+ let key = IDBKeyRange.lowerBound(dataView).lower;
+
+ assert_true(key instanceof ArrayBuffer);
+ assert_equals(key.byteLength, 4);
+ assert_equals(dataView.getUint32(0), new DataView(key).getUint32(0));
+ }, "DataView");
+
+ test(function() {
+ let binary = new ArrayBuffer(4);
+ let dataView = new DataView(binary);
+ let int8Array = new Int8Array(binary);
+ int8Array.set([16, -32, 64, -128]);
+
+ let key = IDBKeyRange.lowerBound(int8Array).lower;
+ let keyInInt8Array = new Int8Array(key);
+
+ assert_true(key instanceof ArrayBuffer);
+ assert_equals(key.byteLength, 4);
+ for(let i = 0; i < int8Array.length; i++) {
+ assert_equals(keyInInt8Array[i], int8Array[i]);
+ }
+ }, "TypedArray(Int8Array)");
+
+ test(function() {
+ let binary = new ArrayBuffer(4);
+ let dataView = new DataView(binary);
+ let int8Array = new Int8Array(binary);
+ int8Array.set([16, -32, 64, -128]);
+
+ let key = IDBKeyRange.lowerBound([int8Array]).lower;
+
+ assert_true(key instanceof Array);
+ assert_true(key[0] instanceof ArrayBuffer);
+ assert_equals(key[0].byteLength, 4);
+
+ let keyInInt8Array = new Int8Array(key[0]);
+
+ for(let i = 0; i < int8Array.length; i++) {
+ assert_equals(keyInInt8Array[i], int8Array[i]);
+ }
+ }, "Array of TypedArray(Int8Array)");
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/idb_webworkers.htm b/testing/web-platform/tests/IndexedDB/idb_webworkers.htm
new file mode 100644
index 000000000..dba3a93f1
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idb_webworkers.htm
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<title>IndexedDB inside of a WebWorker </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db, count = 0,
+ t = async_test();
+
+ t.step(function() {
+ var worker = new Worker("idbworker.js");
+ worker.onmessage = t.step_func(function (e) {
+ switch(count) {
+ case 0:
+ assert_equals(e.data, true, 'worker has idb object')
+ break
+
+ case 1:
+ assert_equals(e.data, "test", "get(1) in worker")
+ t.done()
+ }
+
+ count++
+ });
+
+ worker.postMessage(1);
+ })
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor-advance-continue-async.htm b/testing/web-platform/tests/IndexedDB/idbcursor-advance-continue-async.htm
new file mode 100644
index 000000000..d1b6af3e1
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor-advance-continue-async.htm
@@ -0,0 +1,186 @@
+<!DOCTYPE html>
+<title>IDBCursor asyncness</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db, open;
+
+ setup(function() {
+ open = indexedDB.open('testdb-' + new Date().getTime());
+ open.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test");
+ objStore.createIndex("index", "");
+
+ objStore.add("data", 1);
+ objStore.add("data2", 2);
+ };
+ },
+ { explicit_done: true });
+
+
+ open.onsuccess = function() {
+
+
+ async_test(document.title + " - advance").step(function(e) {
+ var count = 0;
+ var rq = db.transaction("test").objectStore("test").openCursor();
+
+ rq.onsuccess = this.step_func(function(e) {
+ if (!e.target.result) {
+ assert_equals(count, 2, 'count');
+ this.done();
+ return;
+ }
+ var cursor = e.target.result;
+
+ switch(count) {
+ case 0:
+ assert_equals(cursor.value, "data")
+ assert_equals(cursor.key, 1)
+ cursor.advance(1)
+ assert_equals(cursor.value, "data")
+ assert_equals(cursor.key, 1)
+ break
+
+ case 1:
+ assert_equals(cursor.value, "data2")
+ assert_equals(cursor.key, 2)
+ cursor.advance(1)
+ assert_equals(cursor.value, "data2")
+ assert_equals(cursor.key, 2)
+ break
+
+ default:
+ assert_unreached("Unexpected count: " + count)
+ }
+
+ count++;
+ });
+ rq.onerror = fail(this, "unexpected error")
+ });
+
+
+ async_test(document.title + " - continue").step(function(e) {
+ var count = 0;
+ var rq = db.transaction("test").objectStore("test").index("index").openCursor();
+
+ rq.onsuccess = this.step_func(function(e) {
+ if (!e.target.result) {
+ assert_equals(count, 2, 'count');
+ this.done();
+ return;
+ }
+ var cursor = e.target.result;
+
+ switch(count) {
+ case 0:
+ assert_equals(cursor.value, "data")
+ assert_equals(cursor.key, "data")
+ assert_equals(cursor.primaryKey, 1)
+ cursor.continue("data2")
+ assert_equals(cursor.value, "data")
+ assert_equals(cursor.key, "data")
+ assert_equals(cursor.primaryKey, 1)
+ break
+
+ case 1:
+ assert_equals(cursor.value, "data2")
+ assert_equals(cursor.key, "data2")
+ assert_equals(cursor.primaryKey, 2)
+ cursor.continue()
+ assert_equals(cursor.value, "data2")
+ assert_equals(cursor.key, "data2")
+ assert_equals(cursor.primaryKey, 2)
+ break
+
+ default:
+ assert_unreached("Unexpected count: " + count)
+ }
+
+ count++;
+ });
+ rq.onerror = fail(this, "unexpected error")
+ });
+
+
+ async_test(document.title + " - fresh advance still async").step(function(e) {
+ var count = 0;
+ var rq = db.transaction("test").objectStore("test").index("index").openCursor();
+
+ rq.onsuccess = this.step_func(function(e) {
+ if (!e.target.result) {
+ assert_equals(count, 2, 'count');
+ this.done();
+ return;
+ }
+ var cursor = e.target.result;
+ cursor.advance(1)
+
+ switch(count) {
+ case 0:
+ assert_equals(cursor.value, "data")
+ assert_equals(cursor.key, "data")
+ assert_equals(cursor.primaryKey, 1)
+ break
+
+ case 1:
+ assert_equals(cursor.value, "data2")
+ assert_equals(cursor.key, "data2")
+ assert_equals(cursor.primaryKey, 2)
+ break
+
+ default:
+ assert_unreached("Unexpected count: " + count)
+ }
+
+ count++;
+ });
+ rq.onerror = fail(this, "unexpected error")
+ });
+
+
+ async_test(document.title + " - fresh continue still async").step(function(e) {
+ var count = 0;
+ var rq = db.transaction("test").objectStore("test").openCursor();
+
+ rq.onsuccess = this.step_func(function(e) {
+ if (!e.target.result) {
+ assert_equals(count, 2, 'count');
+ this.done();
+ return;
+ }
+ var cursor = e.target.result;
+ cursor.continue()
+
+ switch(count) {
+ case 0:
+ assert_equals(cursor.value, "data")
+ assert_equals(cursor.key, 1)
+ break
+
+ case 1:
+ assert_equals(cursor.value, "data2")
+ assert_equals(cursor.key, 2)
+ break
+
+ default:
+ assert_unreached("Unexpected count: " + count)
+ }
+
+ count++;
+ });
+ rq.onerror = fail(this, "unexpected error")
+ });
+
+ // Stop blocking the testing system from hereon
+ done();
+ }
+
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor-advance-invalid.htm b/testing/web-platform/tests/IndexedDB/idbcursor-advance-invalid.htm
new file mode 100644
index 000000000..dda216b75
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor-advance-invalid.htm
@@ -0,0 +1,188 @@
+<!DOCTYPE html>
+<title>IDBCursor.advance() - invalid</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-advance-void-unsigned-long-count">
+<link rel=assert title="If the value for count is 0 (zero) or a negative number, this method must throw a JavaScript TypeError exception.">
+<link rel=assert title="TypeError The value passed into the count parameter was zero or a negative number.">
+<link rel=assert title="InvalidStateError The cursor is currently being iterated, or has iterated past its end.">
+<link rel=assert title="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. For example, calling advance() twice from the same onsuccess handler results in a DOMException of type InvalidStateError being thrown on the second call.">
+<link rel=assert title="Before this method returns, unless an exception was thrown, it sets the got value flag on the cursor to false.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db, open;
+
+ setup(function() {
+ open = indexedDB.open('testdb-' + new Date().getTime());
+ open.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test");
+ objStore.createIndex("index", "");
+
+ objStore.add("data", 1);
+ objStore.add("data2", 2);
+ };
+ },
+ { explicit_done: true });
+
+
+ open.onsuccess = function() {
+
+ async_test(document.title + " - attempt to call advance twice").step(function(e) {
+ var count = 0;
+ var rq = db.transaction("test").objectStore("test").index("index").openCursor();
+
+ rq.onsuccess = this.step_func(function(e) {
+ if (!e.target.result) {
+ assert_equals(count, 2, 'count');
+ this.done();
+ return;
+ }
+ var cursor = e.target.result;
+
+ cursor.advance(1);
+
+ // Second try
+ assert_throws('InvalidStateError',
+ function() { cursor.advance(1); }, 'second advance');
+
+ assert_throws('InvalidStateError',
+ function() { cursor.advance(3); }, 'third advance');
+
+ count++;
+ });
+ rq.onerror = fail(this, "unexpected error")
+ });
+
+
+ async_test(document.title + " - pass something other than number").step(function(e) {
+ var rq = db.transaction("test").objectStore("test").index("index").openCursor();
+
+ rq.onsuccess = this.step_func(function(e) {
+ var cursor = e.target.result;
+
+ assert_throws({ name: "TypeError" },
+ function() { cursor.advance(document); });
+
+ assert_throws({ name: "TypeError" },
+ function() { cursor.advance({}); });
+
+ assert_throws({ name: "TypeError" },
+ function() { cursor.advance([]); });
+
+ assert_throws({ name: "TypeError" },
+ function() { cursor.advance(""); });
+
+ assert_throws({ name: "TypeError" },
+ function() { cursor.advance("1 2"); });
+
+ this.done();
+ });
+ rq.onerror = fail(this, "unexpected error")
+ });
+
+
+ async_test(document.title + " - pass null/undefined").step(function(e) {
+ var rq = db.transaction("test").objectStore("test").index("index").openCursor();
+
+ rq.onsuccess = this.step_func(function(e) {
+ var cursor = e.target.result;
+
+ assert_throws({ name: "TypeError" },
+ function() { cursor.advance(null); });
+
+ assert_throws({ name: "TypeError" },
+ function() { cursor.advance(undefined); });
+
+ var myvar = null;
+ assert_throws({ name: "TypeError" },
+ function() { cursor.advance(myvar); });
+
+ this.done();
+ });
+ rq.onerror = fail(this, "unexpected error")
+ });
+
+
+ async_test(document.title + " - missing argument").step(function(e) {
+ var rq = db.transaction("test").objectStore("test").index("index").openCursor();
+
+ rq.onsuccess = this.step_func(function(e) {
+ var cursor = e.target.result;
+
+ assert_throws({ name: "TypeError" },
+ function() { cursor.advance(); });
+
+ this.done();
+ });
+ rq.onerror = fail(this, "unexpected error")
+ });
+
+
+ async_test(document.title + " - pass negative numbers").step(function(e) {
+ var rq = db.transaction("test").objectStore("test").index("index").openCursor();
+
+ rq.onsuccess = this.step_func(function(e) {
+ var cursor = e.target.result;
+
+ assert_throws({ name: "TypeError" },
+ function() { cursor.advance(-1); });
+
+ assert_throws({ name: "TypeError" },
+ function() { cursor.advance(NaN); });
+
+ assert_throws({ name: "TypeError" },
+ function() { cursor.advance(0); });
+
+ assert_throws({ name: "TypeError" },
+ function() { cursor.advance(-0); });
+
+ assert_throws({ name: "TypeError" },
+ function() { cursor.advance(Infinity); });
+
+ assert_throws({ name: "TypeError" },
+ function() { cursor.advance(-Infinity); });
+
+ var myvar = -999999;
+ assert_throws({ name: "TypeError" },
+ function() { cursor.advance(myvar); });
+
+ this.done();
+ });
+ rq.onerror = fail(this, "unexpected error")
+ });
+
+
+ async_test(document.title + " - got value not set on exception").step(function(e) {
+ var count = 0;
+ var rq = db.transaction("test").objectStore("test").index("index").openCursor();
+
+ rq.onsuccess = this.step_func(function(e) {
+ var cursor = e.target.result;
+ if (!cursor)
+ {
+ assert_equals(count, 2, "count runs");
+ this.done();
+ return;
+ }
+
+ assert_throws({ name: "TypeError" },
+ function() { cursor.advance(0); });
+
+ cursor.advance(1);
+ count++;
+ });
+ rq.onerror = fail(this, "unexpected error")
+ });
+
+
+ // Stop blocking the testing system from hereon
+ done();
+ }
+
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor-advance.htm b/testing/web-platform/tests/IndexedDB/idbcursor-advance.htm
new file mode 100644
index 000000000..f4ecbc0e5
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor-advance.htm
@@ -0,0 +1,243 @@
+<!DOCTYPE html>
+<title>IDBCursor.advance()</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db, open;
+
+ setup(function() {
+ open = indexedDB.open("testdb-" + new Date().getTime());
+ open.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test");
+ objStore.createIndex("index", "");
+
+ objStore.add("cupcake", 5);
+ objStore.add("pancake", 3); // Yes, it is intended
+ objStore.add("pie", 1);
+ objStore.add("pie", 4);
+ objStore.add("taco", 2);
+ };
+ },
+ { explicit_done: true });
+
+
+ open.onsuccess = function() {
+
+ async_test(document.title + " - advances").step(function(e) {
+ var count = 0;
+ var rq = db.transaction("test").objectStore("test").index("index").openCursor();
+
+ rq.onsuccess = this.step_func(function(e) {
+ if (!e.target.result) {
+ assert_equals(count, 3, "count");
+ this.done();
+ return;
+ }
+ var cursor = e.target.result;
+
+ switch(count) {
+ case 0:
+ assert_equals(cursor.value, "cupcake");
+ assert_equals(cursor.primaryKey, 5);
+ break;
+
+ case 1:
+ assert_equals(cursor.value, "pie");
+ assert_equals(cursor.primaryKey, 1);
+ break;
+
+ case 2:
+ assert_equals(cursor.value, "taco");
+ assert_equals(cursor.primaryKey, 2);
+ break;
+
+ default:
+ assert_unreached("Unexpected count: " + count);
+ }
+
+ count++;
+ cursor.advance(2);
+ });
+ rq.onerror = fail(this, "unexpected error")
+ });
+
+ async_test(document.title + " - advances backwards").step(function(e) {
+ var count = 0;
+ var rq = db.transaction("test").objectStore("test").index("index").openCursor(null, "prev");
+
+ rq.onsuccess = this.step_func(function(e) {
+ if (!e.target.result) {
+ assert_equals(count, 3, "count");
+ this.done();
+ return;
+ }
+ var cursor = e.target.result;
+
+ switch(count) {
+ case 0:
+ assert_equals(cursor.value, "taco");
+ assert_equals(cursor.primaryKey, 2);
+ break;
+
+ case 1:
+ assert_equals(cursor.value, "pie");
+ assert_equals(cursor.primaryKey, 1);
+ break;
+
+ case 2:
+ assert_equals(cursor.value, "cupcake");
+ assert_equals(cursor.primaryKey, 5);
+ break;
+
+ default:
+ assert_unreached("Unexpected count: " + count);
+ }
+
+ count++;
+ cursor.advance(2);
+ });
+ rq.onerror = fail(this, "unexpected error")
+ });
+
+ async_test(document.title + " - skip far forward").step(function(e) {
+ var count = 0;
+ var rq = db.transaction("test").objectStore("test").index("index")
+ .openCursor();
+
+ rq.onsuccess = this.step_func(function(e) {
+ if (!e.target.result) {
+ assert_equals(count, 1, "count");
+ this.done();
+ return;
+ }
+ var cursor = e.target.result;
+
+ switch(count) {
+ case 0:
+ assert_equals(cursor.value, "cupcake");
+ assert_equals(cursor.primaryKey, 5);
+ break;
+
+ default:
+ assert_unreached("Unexpected count: " + count);
+ }
+
+ count++;
+ cursor.advance(100000);
+ });
+ rq.onerror = fail(this, "unexpected error")
+ });
+
+
+ async_test(document.title + " - within range").step(function(e) {
+ var count = 0;
+ var rq = db.transaction("test").objectStore("test").index("index")
+ .openCursor(IDBKeyRange.lowerBound("cupcake", true));
+
+ rq.onsuccess = this.step_func(function(e) {
+ if (!e.target.result) {
+ assert_equals(count, 2, "count");
+ this.done();
+ return;
+ }
+ var cursor = e.target.result;
+
+ switch(count) {
+ case 0:
+ assert_equals(cursor.value, "pancake");
+ assert_equals(cursor.primaryKey, 3);
+ break;
+
+ case 1:
+ assert_equals(cursor.value, "pie");
+ assert_equals(cursor.primaryKey, 4);
+ break;
+
+ default:
+ assert_unreached("Unexpected count: " + count);
+ }
+
+ count++;
+ cursor.advance(2);
+ });
+ rq.onerror = fail(this, "unexpected error")
+ });
+
+
+ async_test(document.title + " - within single key range").step(function(e) {
+ var count = 0;
+ var rq = db.transaction("test").objectStore("test").index("index")
+ .openCursor("pancake");
+
+ rq.onsuccess = this.step_func(function(e) {
+ if (!e.target.result) {
+ assert_equals(count, 1, "count");
+ this.done();
+ return;
+ }
+ var cursor = e.target.result;
+
+ switch(count) {
+ case 0:
+ assert_equals(cursor.value, "pancake");
+ assert_equals(cursor.primaryKey, 3);
+ break;
+
+ default:
+ assert_unreached("Unexpected count: " + count);
+ }
+
+ count++;
+ cursor.advance(1);
+ });
+ rq.onerror = fail(this, "unexpected error")
+ });
+
+
+ async_test(document.title + " - within single key range, with several results").step(function(e) {
+ var count = 0;
+ var rq = db.transaction("test").objectStore("test").index("index")
+ .openCursor("pie");
+
+ rq.onsuccess = this.step_func(function(e) {
+ if (!e.target.result) {
+ assert_equals(count, 2, "count");
+ this.done();
+ return;
+ }
+ var cursor = e.target.result;
+
+ switch(count) {
+ case 0:
+ assert_equals(cursor.value, "pie");
+ assert_equals(cursor.primaryKey, 1);
+ break;
+
+ case 1:
+ assert_equals(cursor.value, "pie");
+ assert_equals(cursor.primaryKey, 4);
+ break;
+
+ default:
+ assert_unreached("Unexpected count: " + count);
+ }
+
+ count++;
+ cursor.advance(1);
+ });
+ rq.onerror = fail(this, "unexpected error")
+ });
+
+
+ // Stop blocking the testing system from hereon
+ done();
+ }
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor-continue.htm b/testing/web-platform/tests/IndexedDB/idbcursor-continue.htm
new file mode 100644
index 000000000..968cd9cbd
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor-continue.htm
@@ -0,0 +1,240 @@
+<!DOCTYPE html>
+<title>IDBCursor.continue()</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-continue-void-any-key">
+<link rel=assert title="The next key to position this cursor at">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db, open;
+ var store = [ { value: "cupcake", key: 5 },
+ { value: "pancake", key: 3 },
+ { value: "pie", key: 1 },
+ { value: "pie", key: 4 },
+ { value: "taco", key: 2 } ];
+
+ setup(function() {
+ open = indexedDB.open('testdb-' + new Date().getTime());
+ open.onupgradeneeded = function(e) {
+ var os, i;
+ db = e.target.result;
+ os = db.createObjectStore("test");
+ os.createIndex("index", "");
+
+ for (i = 0; i < store.length; i++)
+ os.add(store[i].value, store[i].key);
+ };
+ },
+ { explicit_done: true });
+
+
+ open.onsuccess = function() {
+
+
+ async_test(document.title + " - continues").step(function(e) {
+ var count = 0;
+ var rq = db.transaction("test").objectStore("test").index("index").openCursor();
+
+ rq.onsuccess = this.step_func(function(e) {
+ if (!e.target.result) {
+ assert_equals(count, 5, 'count');
+ this.done();
+ return;
+ }
+ var cursor = e.target.result;
+
+ assert_equals(cursor.value, store[count].value);
+ assert_equals(cursor.primaryKey, store[count].key);
+
+ cursor.continue();
+
+ count++;
+ });
+ rq.onerror = fail(this, "unexpected error")
+ });
+
+
+ async_test(document.title + " - with given key").step(function(e) {
+ var count = 0;
+ var rq = db.transaction("test").objectStore("test").index("index").openCursor();
+
+ rq.onsuccess = this.step_func(function(e) {
+ if (!e.target.result) {
+ assert_equals(count, 3, 'count');
+ this.done();
+ return;
+ }
+ var cursor = e.target.result;
+
+ switch(count) {
+ case 0:
+ assert_equals(cursor.value, "cupcake");
+ assert_equals(cursor.primaryKey, 5);
+ cursor.continue("pie");
+ break;
+
+ case 1:
+ assert_equals(cursor.value, "pie");
+ assert_equals(cursor.primaryKey, 1);
+ cursor.continue("taco");
+ break;
+
+ case 2:
+ assert_equals(cursor.value, "taco");
+ assert_equals(cursor.primaryKey, 2);
+ cursor.continue();
+ break;
+
+ default:
+ assert_unreached("Unexpected count: " + count);
+ }
+
+ count++;
+ });
+ rq.onerror = fail(this, "unexpected error")
+ });
+
+
+ async_test(document.title + " - skip far forward").step(function(e) {
+ var count = 0;
+ var rq = db.transaction("test").objectStore("test").index("index")
+ .openCursor();
+
+ rq.onsuccess = this.step_func(function(e) {
+ if (!e.target.result) {
+ assert_equals(count, 1, 'count');
+ this.done();
+ return;
+ }
+ var cursor = e.target.result;
+
+ switch(count) {
+ case 0:
+ assert_equals(cursor.value, "cupcake");
+ assert_equals(cursor.primaryKey, 5);
+ break;
+
+ default:
+ assert_unreached("Unexpected count: " + count);
+ }
+
+ count++;
+ cursor.continue([]); // Arrays are always bigger than strings
+
+ });
+ rq.onerror = fail(this, "unexpected error2")
+ });
+
+
+ async_test(document.title + " - within range").step(function(e) {
+ var count = 0;
+ var rq = db.transaction("test").objectStore("test").index("index")
+ .openCursor(IDBKeyRange.lowerBound("cupcake", true));
+
+ rq.onsuccess = this.step_func(function(e) {
+ if (!e.target.result) {
+ assert_equals(count, 2, 'count');
+ this.done();
+ return;
+ }
+ var cursor = e.target.result;
+
+ switch(count) {
+ case 0:
+ assert_equals(cursor.value, "pancake");
+ assert_equals(cursor.primaryKey, 3);
+ cursor.continue("pie");
+ break;
+
+ case 1:
+ assert_equals(cursor.value, "pie");
+ assert_equals(cursor.primaryKey, 1);
+ cursor.continue("zzz");
+ break;
+
+ default:
+ assert_unreached("Unexpected count: " + count);
+ }
+
+ count++;
+ });
+ rq.onerror = fail(this, "unexpected error1")
+ });
+
+
+ async_test(document.title + " - within single key range").step(function(e) {
+ var count = 0;
+ var rq = db.transaction("test").objectStore("test").index("index")
+ .openCursor("pancake");
+
+ rq.onsuccess = this.step_func(function(e) {
+ if (!e.target.result) {
+ assert_equals(count, 1, 'count');
+ this.done();
+ return;
+ }
+ var cursor = e.target.result;
+
+ switch(count) {
+ case 0:
+ assert_equals(cursor.value, "pancake");
+ assert_equals(cursor.primaryKey, 3);
+ cursor.continue("pie");
+ break;
+
+ default:
+ assert_unreached("Unexpected count: " + count);
+ }
+
+ count++;
+ });
+ rq.onerror = fail(this, "unexpected error1")
+ });
+
+
+ async_test(document.title + " - within single key range, with several results").step(function(e) {
+ var count = 0;
+ var rq = db.transaction("test").objectStore("test").index("index")
+ .openCursor("pie");
+
+ rq.onsuccess = this.step_func(function(e) {
+ if (!e.target.result) {
+ assert_equals(count, 2, 'count');
+ this.done();
+ return;
+ }
+ var cursor = e.target.result;
+
+ switch(count) {
+ case 0:
+ assert_equals(cursor.value, "pie");
+ assert_equals(cursor.primaryKey, 1);
+ cursor.continue();
+ break;
+
+ case 1:
+ assert_equals(cursor.value, "pie");
+ assert_equals(cursor.primaryKey, 4);
+ cursor.continue();
+ break;
+
+ default:
+ assert_unreached("Unexpected count: " + count);
+ }
+
+ count++;
+ });
+ rq.onerror = fail(this, "unexpected error1")
+ });
+
+
+ // Stop blocking the testing system from hereon
+ done();
+ }
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor-continuePrimaryKey-exception-order.htm b/testing/web-platform/tests/IndexedDB/idbcursor-continuePrimaryKey-exception-order.htm
new file mode 100644
index 000000000..0d35218b9
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor-continuePrimaryKey-exception-order.htm
@@ -0,0 +1,382 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<meta name="timeout" content="long">
+<title>IDBCursor.continuePrimaryKey() - Exception Orders </title>
+<link rel="author" title="Mozilla" href="https://www.mozilla.org">
+<link rel="help" href="http://w3c.github.io/IndexedDB/#dom-idbcursor-continueprimarykey">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+function setup_test_store(db) {
+ var 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 } ];
+
+ var store = db.createObjectStore("test", { keyPath: "pKey" });
+ var index = store.createIndex("idx", "iKey");
+
+ for(var i = 0; i < records.length; i++) {
+ store.add(records[i]);
+ }
+
+ return store;
+}
+
+indexeddb_test(
+ function(t, db, txn) {
+ var store = setup_test_store(db);
+ var index = store.index("idx");
+ var cursor_rq = index.openCursor();
+ var 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");
+
+ store.deleteIndex("idx");
+ });
+ txn.oncomplete = function() {
+ assert_throws("TransactionInactiveError", function() {
+ 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) {
+ var store = setup_test_store(db);
+ var cursor_rq = store.openCursor();
+ var 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");
+
+ db.deleteObjectStore("test");
+
+ assert_throws("InvalidStateError", function() {
+ 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) {
+ var store = setup_test_store(db);
+ var index = store.index("idx");
+ var cursor_rq = index.openCursor(null, "nextunique");
+ var 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");
+
+ store.deleteIndex("idx");
+
+ assert_throws("InvalidStateError", function() {
+ 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) {
+ var store = db.createObjectStore("test", {keyPath:"pKey"});
+ var index = store.createIndex("idx", "iKey");
+
+ store.add({ iKey: "A", pKey: 1 });
+
+ var cursor_rq = index.openCursor(null, "nextunique");
+ var cursor;
+
+ cursor_rq.onerror = t.unreached_func('openCursor should succeed');
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ if (e.target.result) {
+ cursor = e.target.result;
+ cursor.continue();
+ return;
+ }
+
+ assert_throws("InvalidAccessError", function() {
+ 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) {
+ var store = db.createObjectStore("test", {keyPath:"pKey"});
+ var index = store.createIndex("idx", "iKey");
+
+ store.add({ iKey: "A", pKey: 1 });
+
+ var cursor_rq = index.openCursor(null, "nextunique");
+ var cursor;
+
+ cursor_rq.onerror = t.unreached_func('openCursor should succeed');
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ if (!cursor) {
+ cursor = e.target.result;
+ assert_true(!!cursor, "acquire cursor");
+
+ cursor.continue();
+
+ assert_throws("InvalidAccessError", function() {
+ 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) {
+ var store = setup_test_store(db);
+ var cursor_rq = store.openCursor();
+ var cursor;
+
+ cursor_rq.onerror = t.unreached_func('openCursor should succeed');
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ if (!cursor) {
+ cursor = e.target.result;
+ assert_true(!!cursor, "acquire cursor");
+
+ cursor.continue();
+
+ assert_throws("InvalidAccessError", function() {
+ 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) {
+ var store = db.createObjectStore("test", {keyPath:"pKey"});
+
+ store.add({ iKey: "A", pKey: 1 });
+
+ var cursor_rq = store.openCursor();
+ var cursor;
+
+ cursor_rq.onerror = t.unreached_func('openCursor should succeed');
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ if (e.target.result) {
+ cursor = e.target.result;
+ cursor.continue();
+ return;
+ }
+
+ assert_throws("InvalidAccessError", function() {
+ 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) {
+ var store = setup_test_store(db);
+ var index = store.index("idx");
+ var cursor_rq = index.openCursor();
+ var cursor;
+
+ cursor_rq.onerror = t.unreached_func('openCursor should succeed');
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ if (!cursor) {
+ cursor = e.target.result;
+ assert_true(!!cursor, "acquire cursor");
+
+ cursor.continue();
+
+ assert_throws("InvalidStateError", function() {
+ 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) {
+ var store = db.createObjectStore("test", {keyPath:"pKey"});
+ var index = store.createIndex("idx", "iKey");
+
+ store.add({ iKey: "A", pKey: 1 });
+
+ var cursor_rq = index.openCursor();
+ var cursor;
+
+ cursor_rq.onerror = t.unreached_func('openCursor should succeed');
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ if (e.target.result) {
+ cursor = e.target.result;
+ cursor.continue();
+ return;
+ }
+
+ assert_throws("InvalidStateError", function() {
+ 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) {
+ var store = setup_test_store(db);
+ var index = store.index("idx");
+ var cursor_rq = index.openCursor();
+ var 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_throws("DataError", function() {
+ cursor.continuePrimaryKey(null, 4);
+ }, "DataError is expected if key is unset.");
+ t.done();
+ });
+ },
+ null,
+ "DataError(unset key)"
+);
+
+indexeddb_test(
+ function(t, db, txn) {
+ var store = setup_test_store(db);
+ var index = store.index("idx");
+ var cursor_rq = index.openCursor();
+ var 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_throws("DataError", function() {
+ 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) {
+ var store = setup_test_store(db);
+ var index = store.index("idx");
+ var cursor_rq = index.openCursor(IDBKeyRange.lowerBound("B"));
+ var 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, 5, "expected primary key");
+
+ assert_throws("DataError", function() {
+ cursor.continuePrimaryKey("A", 6);
+ }, "DataError is expected if key is lower then current one.");
+
+ assert_throws("DataError", function() {
+ cursor.continuePrimaryKey("B", 5);
+ }, "DataError is expected if primary key is equal to current one.");
+
+ assert_throws("DataError", function() {
+ 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) {
+ var store = setup_test_store(db);
+ var index = store.index("idx");
+ var cursor_rq = index.openCursor(IDBKeyRange.upperBound("B"), "prev");
+ var 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("DataError", function() {
+ cursor.continuePrimaryKey("C", 6);
+ }, "DataError is expected if key is larger then current one.");
+
+ assert_throws("DataError", function() {
+ cursor.continuePrimaryKey("B", 7);
+ }, "DataError is expected if primary key is equal to current one.");
+
+ assert_throws("DataError", function() {
+ 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"
+);
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor-direction-index-keyrange.htm b/testing/web-platform/tests/IndexedDB/idbcursor-direction-index-keyrange.htm
new file mode 100644
index 000000000..c3f934037
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor-direction-index-keyrange.htm
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<title>IDBCursor direction - index with keyrange</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#cursor-iteration-operation">
+<link rel=assert title='If direction is "next", let found record be the first record in records which satisfy all of the following requirements'>
+<link rel=assert title="If position is defined, and source is an index, the record's key is equal to position and the record's value is greater than object store position or the record's key is greater than position.">
+<link rel=assert title='If direction is "prev", let found record be the last record in records which satisfy all of the following requirements'>
+<link rel=assert title="If position is defined, and source is an index, the record's key is equal to position and the record's value is less than object store position or the record's key is less than position.">
+<link rel=assert title="If range is defined, the record's key is in range.">
+<link rel=assert title="If temp record is defined, let found record be the first record in records whose key is equal to temp record's key.">
+<link rel=assert title="records is always sorted in ascending key order. In the case of source being an index, records is secondarily sorted in ascending value order.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var records = [ 1337, "Alice", "Bob", "Bob", "Greg", "Åke", ["Anne"] ];
+ var directions = ["next", "prev", "nextunique", "prevunique"];
+ var tests = {};
+
+ directions.forEach(function(dir) {
+ tests[dir] = async_test(document.title + ' - ' + dir);
+ });
+
+ var open_rq = indexedDB.open("testdb-" + new Date().getTime() + Math.random());
+
+ open_rq.onupgradeneeded = function(e) {
+ var objStore = e.target.result.createObjectStore("test");
+ objStore.createIndex("idx", "name");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add({ name: records[i] }, i);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var db = e.target.result;
+ db.onerror = fail_helper("db.onerror");
+
+
+ // The tests
+ testdir('next', ['Alice:1', 'Bob:2', 'Bob:3', 'Greg:4']);
+ testdir('prev', ['Greg:4', 'Bob:3', 'Bob:2', 'Alice:1']);
+ testdir('nextunique', ['Alice:1', 'Bob:2', 'Greg:4']);
+ testdir('prevunique', ['Greg:4', 'Bob:2', 'Alice:1']);
+
+
+ // Test function
+ function testdir(dir, expect) {
+ var count = 0;
+ var t = tests[dir];
+ var rq = db.transaction("test").objectStore("test").index("idx").openCursor(IDBKeyRange.bound("AA", "ZZ"), dir);
+ rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ if (!cursor) {
+ assert_equals(count, expect.length, "cursor runs");
+ t.done();
+ }
+ assert_equals(cursor.value.name + ":" + cursor.primaryKey, expect[count], "cursor.value");
+ count++;
+ cursor.continue();
+ });
+ rq.onerror = t.step_func(function(e) {
+ e.preventDefault();
+ e.stopPropagation();
+ assert_unreached("rq.onerror - " + e.message);
+ });
+ }
+ };
+
+ // Fail handling
+ function fail_helper(name) {
+ return function() {
+ directions.forEach(function(dir) {
+ tests[dir].step(function() { assert_unreached(name); });
+ });
+ };
+ }
+ open_rq.onblocked = fail_helper('open_rq.onblocked');
+ open_rq.onerror = fail_helper('open_rq.onerror');
+</script>
+
+<div id=log> </div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor-direction-index.htm b/testing/web-platform/tests/IndexedDB/idbcursor-direction-index.htm
new file mode 100644
index 000000000..39afcb24d
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor-direction-index.htm
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<title>IDBCursor direction - index</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#cursor-iteration-operation">
+<link rel=assert title='If direction is "next", let found record be the first record in records which satisfy all of the following requirements'>
+<link rel=assert title="If position is defined, and source is an object store, the record's key is greater than position.">
+<link rel=assert title='If direction is "prev", let found record be the last record in records which satisfy all of the following requirements'>
+<link rel=assert title="If position is defined, and source is an object store, the record's key is less than position.">
+<link rel=assert title="Set cursor's position to found record's key. If source is an index, set cursor's object store position to found record's value.">
+<link rel=assert title="Set cursor's key to found record's key.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var records = [ "Alice", "Bob", "Bob", "Greg" ];
+ var directions = ["next", "prev", "nextunique", "prevunique"];
+ var tests = {};
+
+ directions.forEach(function(dir) {
+ tests[dir] = async_test(document.title + ' - ' + dir);
+ });
+
+ var open_rq = indexedDB.open("testdb-" + new Date().getTime() + Math.random());
+
+ open_rq.onupgradeneeded = function(e) {
+ var objStore = e.target.result.createObjectStore("test");
+ objStore.createIndex("idx", "name");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add({ name: records[i] }, i);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var db = e.target.result;
+ db.onerror = fail_helper("db.onerror");
+
+
+ // The tests
+ testdir('next', ['Alice:0', 'Bob:1', 'Bob:2', 'Greg:3']);
+ testdir('prev', ['Greg:3', 'Bob:2', 'Bob:1', 'Alice:0']);
+ testdir('nextunique', ['Alice:0', 'Bob:1', 'Greg:3']);
+ testdir('prevunique', ['Greg:3', 'Bob:1', 'Alice:0']);
+
+
+ // Test function
+ function testdir(dir, expect) {
+ var count = 0;
+ var t = tests[dir];
+ var rq = db.transaction("test").objectStore("test").index("idx").openCursor(undefined, dir);
+ rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ if (!cursor) {
+ assert_equals(count, expect.length, "cursor runs");
+ t.done();
+ }
+ assert_equals(cursor.value.name + ":" + cursor.primaryKey, expect[count], "cursor.value");
+ count++;
+ cursor.continue();
+ });
+ rq.onerror = t.step_func(function(e) {
+ e.preventDefault();
+ e.stopPropagation();
+ assert_unreached("rq.onerror - " + e.message);
+ });
+ }
+ };
+
+ // Fail handling
+ function fail_helper(name) {
+ return function() {
+ directions.forEach(function(dir) {
+ tests[dir].step(function() { assert_unreached(name); });
+ });
+ };
+ }
+ open_rq.onblocked = fail_helper('open_rq.onblocked');
+ open_rq.onerror = fail_helper('open_rq.onerror');
+</script>
+
+<div id=log> </div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor-direction-objectstore-keyrange.htm b/testing/web-platform/tests/IndexedDB/idbcursor-direction-objectstore-keyrange.htm
new file mode 100644
index 000000000..2b2bf04bf
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor-direction-objectstore-keyrange.htm
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<title>IDBCursor direction - object store with keyrange</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#cursor-iteration-operation">
+<link rel=assert title='If direction is "next", let found record be the first record in records which satisfy all of the following requirements'>
+<link rel=assert title='If direction is "prev", let found record be the last record in records which satisfy all of the following requirements'>
+<link rel=assert title="If range is defined, the record's key is in range.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var records = [ 1337, "Alice", "Bob", "Greg", "Åke", ["Anne"] ];
+ var directions = ["next", "prev", "nextunique", "prevunique"];
+ var tests = {};
+
+ directions.forEach(function(dir) {
+ tests[dir] = async_test(document.title + ' - ' + dir);
+ });
+
+ var open_rq = indexedDB.open("testdb-" + new Date().getTime() + Math.random());
+
+ open_rq.onupgradeneeded = function(e) {
+ var objStore = e.target.result.createObjectStore("test");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i], records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var db = e.target.result;
+ db.onerror = fail_helper("db.onerror");
+
+
+ // The tests
+ testdir('next', ['Alice', 'Bob', 'Greg']);
+ testdir('prev', ['Greg', 'Bob', 'Alice']);
+ testdir('nextunique', ['Alice', 'Bob', 'Greg']);
+ testdir('prevunique', ['Greg', 'Bob', 'Alice']);
+
+
+ // Test function
+ function testdir(dir, expect) {
+ var count = 0;
+ var t = tests[dir];
+ var rq = db.transaction("test").objectStore("test").openCursor(IDBKeyRange.bound("AA", "ZZ"), dir);
+ rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ if (!cursor) {
+ assert_equals(count, expect.length, "cursor runs");
+ t.done();
+ }
+ assert_equals(cursor.value, expect[count], "cursor.value");
+ count++;
+ cursor.continue();
+ });
+ rq.onerror = t.step_func(function(e) {
+ e.preventDefault();
+ e.stopPropagation();
+ assert_unreached("rq.onerror - " + e.message);
+ });
+ }
+ };
+
+ // Fail handling
+ function fail_helper(name) {
+ return function() {
+ directions.forEach(function(dir) {
+ tests[dir].step(function() { assert_unreached(name); });
+ });
+ };
+ }
+ open_rq.onblocked = fail_helper('open_rq.onblocked');
+ open_rq.onerror = fail_helper('open_rq.onerror');
+</script>
+
+<div id=log> </div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor-direction-objectstore.htm b/testing/web-platform/tests/IndexedDB/idbcursor-direction-objectstore.htm
new file mode 100644
index 000000000..c02355395
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor-direction-objectstore.htm
@@ -0,0 +1,80 @@
+<!DOCTYPE html>
+<title>IDBCursor direction - object store</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#cursor-iteration-operation">
+<link rel=assert title='If direction is "next", let found record be the first record in records which satisfy all of the following requirements'>
+<link rel=assert title="If position is defined, and source is an object store, the record's key is greater than position.">
+<link rel=assert title='If direction is "prev", let found record be the last record in records which satisfy all of the following requirements'>
+<link rel=assert title="If position is defined, and source is an object store, the record's key is less than position.">
+<link rel=assert title="Set cursor's position to found record's key. If source is an index, set cursor's object store position to found record's value.">
+<link rel=assert title="Set cursor's key to found record's key.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var records = [ "Alice", "Bob", "Greg" ];
+ var directions = ["next", "prev", "nextunique", "prevunique"];
+ var tests = {};
+
+ directions.forEach(function(dir) {
+ tests[dir] = async_test(document.title + ' - ' + dir);
+ });
+
+ var open_rq = indexedDB.open("testdb-" + new Date().getTime() + Math.random());
+
+ open_rq.onupgradeneeded = function(e) {
+ var objStore = e.target.result.createObjectStore("test");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i], records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var db = e.target.result;
+ db.onerror = fail_helper("db.onerror");
+
+
+ // The tests
+ testdir('next', ['Alice', 'Bob', 'Greg']);
+ testdir('prev', ['Greg', 'Bob', 'Alice']);
+ testdir('nextunique', ['Alice', 'Bob', 'Greg']);
+ testdir('prevunique', ['Greg', 'Bob', 'Alice']);
+
+
+ // Test function
+ function testdir(dir, expect) {
+ var count = 0;
+ var t = tests[dir];
+ var rq = db.transaction("test").objectStore("test").openCursor(undefined, dir);
+ rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ if (!cursor) {
+ assert_equals(count, expect.length, "cursor runs");
+ t.done();
+ }
+ assert_equals(cursor.value, expect[count], "cursor.value");
+ count++;
+ cursor.continue();
+ });
+ rq.onerror = t.step_func(function(e) {
+ e.preventDefault();
+ e.stopPropagation();
+ assert_unreached("rq.onerror - " + e.message);
+ });
+ }
+ };
+
+ // Fail handling
+ function fail_helper(name) {
+ return function() {
+ directions.forEach(function(dir) {
+ tests[dir].step(function() { assert_unreached(name); });
+ });
+ };
+ }
+ open_rq.onblocked = fail_helper('open_rq.onblocked');
+ open_rq.onerror = fail_helper('open_rq.onerror');
+</script>
+
+<div id=log> </div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor-direction.htm b/testing/web-platform/tests/IndexedDB/idbcursor-direction.htm
new file mode 100644
index 000000000..b50eded79
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor-direction.htm
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<title>IDBCursor.direction</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ function cursor_direction(constant, dir)
+ {
+ var db,
+ t = async_test(document.title + " - " + dir),
+ expected = dir ? dir : "next";
+
+ var open_rq = createdb(t);
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test");
+
+ objStore.add("data", "key");
+ };
+
+ open_rq.onsuccess = t.step_func(function(e) {
+ var cursor_rq, count = 0;
+ var os = db.transaction("test")
+ .objectStore("test");
+ if (dir)
+ cursor_rq = os.openCursor(undefined, dir);
+ else
+ cursor_rq = os.openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ assert_equals(cursor.direction, constant, 'direction constant');
+ assert_equals(cursor.direction, expected, 'direction');
+ assert_readonly(cursor, 'direction');
+
+ count++;
+ if (count >= 2)
+ t.done();
+ });
+
+ var cursor_rq2 = db.transaction("test")
+ .objectStore("test")
+ .openCursor(undefined, constant);
+
+ cursor_rq2.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ assert_equals(cursor.direction, constant, 'direction constant (second try)');
+ assert_equals(cursor.direction, expected, 'direction (second try)');
+ assert_readonly(cursor, 'direction');
+
+ count++;
+ if (count >= 2)
+ t.done();
+ });
+
+ });
+ }
+
+ cursor_direction("next");
+ cursor_direction("next", "next");
+ cursor_direction("prev", "prev");
+ cursor_direction("nextunique", "nextunique");
+ cursor_direction("prevunique", "prevunique");
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor-key.htm b/testing/web-platform/tests/IndexedDB/idbcursor-key.htm
new file mode 100644
index 000000000..8014c4221
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor-key.htm
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<title>IDBCursor.key</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ function cursor_key(key)
+ {
+ var db,
+ t = async_test(document.title + " - " + key);
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test");
+
+ objStore.add("data", key);
+ };
+
+ open_rq.onsuccess = t.step_func(function(e) {
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ assert_equals(cursor.value, "data", "prequisite cursor.value");
+
+ assert_key_equals(cursor.key, key, 'key');
+ assert_readonly(cursor, 'key');
+
+ if (key instanceof Array) {
+ cursor.key.push("new");
+ key.push("new");
+
+ assert_key_equals(cursor.key, key, 'key after array push');
+
+ // But we can not change key (like readonly, just a bit different)
+ cursor.key = 10;
+ assert_key_equals(cursor.key, key, 'key after assignment');
+ }
+
+ t.done();
+ });
+ });
+ }
+
+ cursor_key(1);
+ cursor_key("key");
+ cursor_key(["my", "key"]);
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor-primarykey.htm b/testing/web-platform/tests/IndexedDB/idbcursor-primarykey.htm
new file mode 100644
index 000000000..2fe24ece8
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor-primarykey.htm
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<title>IDBCursor.primaryKey</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ function cursor_primarykey(key)
+ {
+ var db,
+ t = async_test(document.title + " - " + key);
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test");
+ objStore.createIndex("index", "");
+
+ objStore.add("data", key);
+ };
+
+ open_rq.onsuccess = t.step_func(function(e) {
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .index("index")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ assert_equals(cursor.value, "data", "prequisite cursor.value");
+ assert_equals(cursor.key, "data", "prequisite cursor.key");
+
+ assert_key_equals(cursor.primaryKey, key, 'primaryKey');
+ assert_readonly(cursor, 'primaryKey');
+
+ if (key instanceof Array) {
+ cursor.primaryKey.push("new");
+ key.push("new");
+
+ assert_key_equals(cursor.primaryKey, key, 'primaryKey after array push');
+
+ // But we can not change key (like readonly, just a bit different)
+ cursor.key = 10;
+ assert_key_equals(cursor.primaryKey, key, 'key after assignment');
+ }
+
+ t.done();
+ });
+ });
+ }
+
+ cursor_primarykey(1);
+ cursor_primarykey("key");
+ cursor_primarykey(["my", "key"]);
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor-reused.htm b/testing/web-platform/tests/IndexedDB/idbcursor-reused.htm
new file mode 100644
index 000000000..603041e7c
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor-reused.htm
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<title>IDBCursor is reused</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<meta rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-continue-void-any-key">
+<meta rel=assert title="Otherwise this method runs the steps for asynchronously executing a request. However, the steps are slightly modified such that instead of creating a new IDBRequest, it reuses the request originally created when this cursor was created. The done flag on the request is set to false before the request is returned. The steps are run with the cursor's source as source and the steps for iterating a cursor as operation, using this cursor as cursor and the key parameter as key.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db
+ var open_rq = createdb(async_test())
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result
+ var os = db.createObjectStore("test")
+
+ os.add("data", "k")
+ os.add("data2", "k2")
+ }
+
+ open_rq.onsuccess = function(e) {
+ var cursor
+ var count = 0
+ var rq = db.transaction("test").objectStore("test").openCursor()
+
+ rq.onsuccess = this.step_func(function(e)
+ {
+ switch(count)
+ {
+ case 0:
+ cursor = e.target.result
+
+ assert_equals(cursor.value, "data", "prequisite cursor.value")
+ cursor.custom_cursor_value = 1
+ e.target.custom_request_value = 2
+
+ cursor.continue()
+ break
+
+ case 1:
+ assert_equals(cursor.value, "data2", "prequisite cursor.value")
+ assert_equals(cursor.custom_cursor_value, 1, "custom cursor value")
+ assert_equals(e.target.custom_request_value, 2, "custom request value")
+
+ cursor.advance(1)
+ break
+
+ case 2:
+ assert_false(!!e.target.result, "got cursor")
+ assert_equals(cursor.custom_cursor_value, 1, "custom cursor value")
+ assert_equals(e.target.custom_request_value, 2, "custom request value")
+ break
+ }
+ count++
+ })
+
+ rq.transaction.oncomplete = this.step_func(function() {
+ assert_equals(count, 3, "cursor callback runs")
+ assert_equals(rq.custom_request_value, 2, "variable placed on old IDBRequest")
+ assert_equals(cursor.custom_cursor_value, 1, "custom cursor value (transaction.complete)")
+ this.done()
+ })
+ }
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor-source.htm b/testing/web-platform/tests/IndexedDB/idbcursor-source.htm
new file mode 100644
index 000000000..7e3746ae7
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor-source.htm
@@ -0,0 +1,68 @@
+<!DOCTYPE html>
+<title>IDBCursor.source</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ setup({ explicit_done: true });
+
+ var db;
+ var open_rq = indexedDB.open('testdb-' + new Date().getTime());
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("my_objectstore");
+ objStore.createIndex("my_index", "");
+
+ objStore.add("data", 1);
+ objStore.add("data2", 2);
+ };
+
+ function cursor_source(name, stringified_object, cursor_rq) {
+ var cursor;
+
+ cursor_rq.onsuccess = this.step_func(function(e) {
+ if (!e.target.result) {
+ return;
+ }
+ cursor = e.target.result;
+ assert_readonly(cursor, 'source');
+
+ // Direct try
+ assert_true(cursor.source instanceof Object, "source isobject");
+ assert_equals(cursor.source + "", stringified_object, "source");
+ assert_equals(cursor.source.name, name, "name");
+
+ cursor.continue();
+ });
+
+ cursor_rq.transaction.oncomplete = this.step_func(function(e) {
+ this.done();
+ });
+
+ cursor_rq.transaction.onerror = this.step_func(function(e) {
+ assert_unreached("Transaction got error. " + (e.target.error ? e.target.error.name : "unknown"));
+ });
+ }
+
+ open_rq.onsuccess = function() {
+ async_test(document.title + ' - IDBObjectStore').step(function() {
+ cursor_source.call(this, "my_objectstore", "[object IDBObjectStore]", db.transaction("my_objectstore")
+ .objectStore("my_objectstore")
+ .openCursor());
+ });
+
+ async_test(document.title + ' - IDBIndex').step(function() {
+ cursor_source.call(this, "my_index", "[object IDBIndex]", db.transaction("my_objectstore")
+ .objectStore("my_objectstore")
+ .index("my_index")
+ .openCursor());
+ });
+
+ done();
+ };
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_advance_index.htm b/testing/web-platform/tests/IndexedDB/idbcursor_advance_index.htm
new file mode 100644
index 000000000..0e5c51474
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_advance_index.htm
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<title>IDBCursor.advance() - index - iterate cursor number of times specified by count </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db,
+ count = 0,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" },
+ { pKey: "primaryKey_2", iKey: "indexKey_2" },
+ { pKey: "primaryKey_3", iKey: "indexKey_3" }];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var store = db.createObjectStore("test", {keyPath:"pKey"});
+ store.createIndex("idx", "iKey");
+
+ for(var i = 0; i < records.length; i++) {
+ store.add(records[i]);
+ }
+ };
+
+ open_rq.onsuccess = function (e) {
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .index("idx")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ assert_true(cursor instanceof IDBCursor);
+
+ switch(count) {
+ case 0:
+ count += 3;
+ cursor.advance(3);
+ break;
+ case 3:
+ var record = cursor.value;
+ assert_equals(record.pKey, records[count].pKey, "record.pKey");
+ assert_equals(record.iKey, records[count].iKey, "record.iKey");
+ t.done();
+ break;
+ default:
+ assert_unreached("unexpected count");
+ break;
+ }
+ });
+ }
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_advance_index2.htm b/testing/web-platform/tests/IndexedDB/idbcursor_advance_index2.htm
new file mode 100644
index 000000000..539c824e6
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_advance_index2.htm
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<title>IDBCursor.advance() - attempt to pass a count parameter that is not a number</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-advance-void-unsigned-long-count">
+<link rel=assert title="The value passed into the count parameter was zero or a negative number.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db,
+ t = async_test(document.title, {timeout: 10000}),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", {keyPath:"pKey"});
+
+ objStore.createIndex("index", "iKey");
+
+ for(var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .index("index")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ assert_true(cursor != null, "cursor exist");
+ assert_throws(new TypeError(),
+ function() { cursor.advance(document); });
+
+ t.done();
+ });
+ };
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_advance_index3.htm b/testing/web-platform/tests/IndexedDB/idbcursor_advance_index3.htm
new file mode 100644
index 000000000..5adf3f077
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_advance_index3.htm
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<title>IDBCursor.advance() - index - attempt to advance backwards</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-advance-void-unsigned-long-count">
+<link rel=assert title="The value passed into the count parameter was zero or a negative number.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script type="text/javascript">
+
+ var db,
+ t = async_test(document.title, {timeout: 10000}),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", { keyPath:"pKey" });
+
+ objStore.createIndex("index", "iKey");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .index("index")
+ .openCursor(undefined, "next");
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ assert_true(cursor != null, "cursor exist");
+ assert_throws(new TypeError(),
+ function() { cursor.advance(-1); });
+
+ t.done();
+ });
+ };
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_advance_index5.htm b/testing/web-platform/tests/IndexedDB/idbcursor_advance_index5.htm
new file mode 100644
index 000000000..452c0f142
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_advance_index5.htm
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<title>IDBCursor.advance() - index - iterate to the next record</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-advance-void-unsigned-long-count">
+<link rel=assert title="The operation runs the steps for iterating a cursor count number of times with null as key and this cursor as cursor.">
+<link rel=assert title="The number of advances forward the cursor should make.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ count = 0,
+ t = async_test(document.title, {timeout: 10000}),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" },
+ { pKey: "primaryKey_1-2", iKey: "indexKey_1" } ],
+ expected = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1-2", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result
+ var objStore = db.createObjectStore("test", { keyPath:"pKey" })
+
+ objStore.createIndex("index", "iKey")
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i])
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .index("index")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ if (!cursor) {
+ assert_equals(count, expected.length, "cursor run count")
+ t.done()
+ }
+
+ var record = cursor.value;
+ assert_equals(record.pKey, expected[count].pKey, "primary key");
+ assert_equals(record.iKey, expected[count].iKey, "index key");
+
+ cursor.advance(2);
+ count++;
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_advance_index6.htm b/testing/web-platform/tests/IndexedDB/idbcursor_advance_index6.htm
new file mode 100644
index 000000000..826cb1e1a
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_advance_index6.htm
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBCursor.advance() - index - throw TypeError</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-advance-void-unsigned-long-count">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test(),
+ records = [{ pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" }];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ var objStore = db.createObjectStore("store", {keyPath : "pKey"});
+ objStore.createIndex("index", "iKey");
+ for (var i = 0; i < records.length; i++) {
+ objStore.add(records[i]);
+ }
+ var rq = objStore.index("index").openCursor();
+ rq.onsuccess = t.step_func(function(event) {
+ var cursor = event.target.result;
+ assert_true(cursor instanceof IDBCursor);
+
+ assert_throws(new TypeError(), function() {
+ cursor.advance(0);
+ }, "Calling advance() with count argument 0 should throw TypeError.");
+
+ t.done();
+ });
+ }
+</script>
+
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_advance_index7.htm b/testing/web-platform/tests/IndexedDB/idbcursor_advance_index7.htm
new file mode 100644
index 000000000..8da5b618d
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_advance_index7.htm
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBCursor.advance() - index - throw TransactionInactiveError</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-advance-void-unsigned-long-count">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test(),
+ records = [{ pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" }];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ var objStore = db.createObjectStore("store", {keyPath : "pKey"});
+ objStore.createIndex("index", "iKey");
+ for (var i = 0; i < records.length; i++) {
+ objStore.add(records[i]);
+ }
+ var rq = objStore.index("index").openCursor();
+ rq.onsuccess = t.step_func(function(event) {
+ var cursor = event.target.result;
+ assert_true(cursor instanceof IDBCursor);
+
+ event.target.transaction.abort();
+ assert_throws("TransactionInactiveError", function() {
+ cursor.advance(1);
+ }, "Calling advance() should throws an exception TransactionInactiveError when the transaction is not active.");
+
+ t.done();
+ });
+ }
+
+</script>
+
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_advance_index8.htm b/testing/web-platform/tests/IndexedDB/idbcursor_advance_index8.htm
new file mode 100644
index 000000000..b5e64d4cd
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_advance_index8.htm
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBCursor.advance() - index - throw InvalidStateError</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-advance-void-unsigned-long-count">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test(),
+ records = [{ pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" }];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ var objStore = db.createObjectStore("store", {keyPath : "pKey"});
+ objStore.createIndex("index", "iKey");
+ for (var i = 0; i < records.length; i++) {
+ objStore.add(records[i]);
+ }
+ var rq = objStore.index("index").openCursor();
+ rq.onsuccess = t.step_func(function(event) {
+ var cursor = event.target.result;
+ assert_true(cursor instanceof IDBCursor);
+
+ cursor.advance(1);
+ assert_throws("InvalidStateError", function() {
+ cursor.advance(1);
+ }, "Calling advance() should throw DOMException when the cursor is currently being iterated.");
+
+ t.done();
+ });
+ }
+</script>
+
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_advance_index9.htm b/testing/web-platform/tests/IndexedDB/idbcursor_advance_index9.htm
new file mode 100644
index 000000000..517a573c4
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_advance_index9.htm
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBCursor.advance() - index - throw InvalidStateError caused by object store been deleted</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test(),
+ records = [{ pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" }];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ var objStore = db.createObjectStore("store", {keyPath : "pKey"});
+ objStore.createIndex("index", "iKey");
+ for (var i = 0; i < records.length; i++) {
+ objStore.add(records[i]);
+ }
+ var rq = objStore.index("index").openCursor();
+ rq.onsuccess = t.step_func(function(event) {
+ var cursor = event.target.result;
+ assert_true(cursor instanceof IDBCursor, "cursor exist");
+
+ db.deleteObjectStore("store");
+ assert_throws("InvalidStateError", function() {
+ cursor.advance(1);
+ }, "If the cursor's source or effective object store has been deleted, the implementation MUST throw a DOMException of type InvalidStateError");
+
+ t.done();
+ });
+ }
+</script>
+
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_advance_objectstore.htm b/testing/web-platform/tests/IndexedDB/idbcursor_advance_objectstore.htm
new file mode 100644
index 000000000..5ae9a813c
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_advance_objectstore.htm
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<title> IDBCursor.advance() - object store - iterate cursor number of times specified by count </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db,
+ count = 0,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0" },
+ { pKey: "primaryKey_1" },
+ { pKey: "primaryKey_2" },
+ { pKey: "primaryKey_3" }];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var store = db.createObjectStore("test", {keyPath:"pKey"});
+
+ for(var i = 0; i < records.length; i++) {
+ store.add(records[i]);
+ }
+ };
+
+ open_rq.onsuccess = function (e) {
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ assert_true(cursor instanceof IDBCursor);
+
+ switch(count) {
+ case 0:
+ count += 3;
+ cursor.advance(3);
+ break;
+ case 3:
+ assert_equals(cursor.value.pKey, records[count].pKey, "cursor.value.pKey");
+ t.done();
+ break;
+ default:
+ assert_unreached("unexpected count");
+ break;
+ }
+ });
+ }
+
+</script>
+
+<div id=log> </div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_advance_objectstore2.htm b/testing/web-platform/tests/IndexedDB/idbcursor_advance_objectstore2.htm
new file mode 100644
index 000000000..32478c141
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_advance_objectstore2.htm
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBCursor.advance() - object store - throw TypeError</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-advance-void-unsigned-long-count">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test(),
+ records = [{ pKey: "primaryKey_0"},
+ { pKey: "primaryKey_1"}];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ var objStore = db.createObjectStore("store", {keyPath:"pKey"});
+ for (var i = 0; i < records.length; i++) {
+ objStore.add(records[i]);
+ }
+ }
+
+ open_rq.onsuccess = function (event) {
+ var txn = db.transaction("store", "readwrite");
+ var rq = txn.objectStore("store").openCursor();
+ rq.onsuccess = t.step_func(function(event) {
+ var cursor = event.target.result;
+ assert_true(cursor instanceof IDBCursor);
+
+ assert_throws(new TypeError(), function() {
+ cursor.advance(0);
+ }, "Calling advance() with count argument 0 should throw TypeError.");
+
+ t.done();
+ });
+ }
+</script>
+
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_advance_objectstore3.htm b/testing/web-platform/tests/IndexedDB/idbcursor_advance_objectstore3.htm
new file mode 100644
index 000000000..1accd6631
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_advance_objectstore3.htm
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBCursor.advance() - object store - throw TransactionInactiveError</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-advance-void-unsigned-long-count">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test(),
+ records = [{ pKey: "primaryKey_0"},
+ { pKey: "primaryKey_1"}];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ var objStore = db.createObjectStore("store", {keyPath:"pKey"});
+ for (var i = 0; i < records.length; i++) {
+ objStore.add(records[i]);
+ }
+ }
+
+ open_rq.onsuccess = function (event) {
+ var txn = db.transaction("store", "readwrite");
+ var rq = txn.objectStore("store").openCursor();
+ rq.onsuccess = t.step_func(function(event) {
+ var cursor = event.target.result;
+ assert_true(cursor instanceof IDBCursor);
+
+ event.target.transaction.abort();
+ assert_throws("TransactionInactiveError", function() {
+ cursor.advance(1);
+ }, "Calling advance() should throws an exception TransactionInactiveError when the transaction is not active");
+
+ t.done();
+ });
+ }
+
+</script>
+
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_advance_objectstore4.htm b/testing/web-platform/tests/IndexedDB/idbcursor_advance_objectstore4.htm
new file mode 100644
index 000000000..387973169
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_advance_objectstore4.htm
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBCursor.advance() - object store - throw InvalidStateError</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-advance-void-unsigned-long-count">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test(),
+ records = [{ pKey: "primaryKey_0"},
+ { pKey: "primaryKey_1"}];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ var objStore = db.createObjectStore("store", {keyPath:"pKey"});
+ for (var i = 0; i < records.length; i++) {
+ objStore.add(records[i]);
+ }
+ }
+
+ open_rq.onsuccess = function (event) {
+ var txn = db.transaction("store", "readwrite");
+ var rq = txn.objectStore("store").openCursor();
+ rq.onsuccess = t.step_func(function(event) {
+ var cursor = event.target.result;
+ assert_true(cursor instanceof IDBCursor);
+
+ cursor.advance(1);
+ assert_throws("InvalidStateError", function() {
+ cursor.advance(1);
+ }, "Calling advance() should throw DOMException when the cursor is currently being iterated.");
+
+ t.done();
+ });
+ }
+</script>
+
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_advance_objectstore5.htm b/testing/web-platform/tests/IndexedDB/idbcursor_advance_objectstore5.htm
new file mode 100644
index 000000000..cb0859c63
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_advance_objectstore5.htm
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBCursor.advance() - object store - throw InvalidStateError caused by object store been deleted</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test(),
+ records = [{ pKey: "primaryKey_0"},
+ { pKey: "primaryKey_1"}];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ var objStore = db.createObjectStore("store", {keyPath:"pKey"});
+ for (var i = 0; i < records.length; i++) {
+ objStore.add(records[i]);
+ }
+ var rq = objStore.openCursor();
+ rq.onsuccess = t.step_func(function(event) {
+ var cursor = event.target.result;
+ assert_true(cursor instanceof IDBCursor, "cursor exist");
+
+ db.deleteObjectStore("store");
+ assert_throws("InvalidStateError", function() {
+ cursor.advance(1);
+ }, "If the cursor's source or effective object store has been deleted, the implementation MUST throw a DOMException of type InvalidStateError");
+
+ t.done();
+ });
+ }
+</script>
+
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_continue_index.htm b/testing/web-platform/tests/IndexedDB/idbcursor_continue_index.htm
new file mode 100644
index 000000000..8b0d079a9
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_continue_index.htm
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<title>IDBCursor.continue() - index - iterate to the next record</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-continue-void-any-key">
+<link rel=assert title="Otherwise this method runs the steps for asynchronously executing a request.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ count = 0,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" },
+ { pKey: "primaryKey_1-2", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", { keyPath:"pKey" });
+
+ objStore.createIndex("index", "iKey");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .index("index")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ if (!cursor) {
+ assert_equals(count, records.length, "cursor run count");
+ t.done();
+ }
+
+ var record = cursor.value;
+ assert_equals(record.pKey, records[count].pKey, "primary key");
+ assert_equals(record.iKey, records[count].iKey, "index key");
+
+ cursor.continue();
+ count++;
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_continue_index2.htm b/testing/web-platform/tests/IndexedDB/idbcursor_continue_index2.htm
new file mode 100644
index 000000000..d0eaef3d0
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_continue_index2.htm
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<title>IDBCursor.continue() - index - attempt to pass a key parameter that is not a valid key</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-continue-void-any-key">
+<link rel=assert title="If the key parameter is specified and fulfills any of these conditions this method must throw a DOMException of type DataError">
+<link rel=assert title="The parameter is not a valid key.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", {keyPath:"pKey"});
+
+ objStore.createIndex("index", "iKey");
+
+ for(var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .index("index")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ assert_throws("DataError",
+ function() { cursor.continue(document); });
+
+ assert_true(cursor instanceof IDBCursorWithValue, "cursor");
+
+ t.done();
+ });
+ };
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_continue_index3.htm b/testing/web-platform/tests/IndexedDB/idbcursor_continue_index3.htm
new file mode 100644
index 000000000..357dc157f
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_continue_index3.htm
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<title>IDBCursor.continue() - index - attempt to iterate to the previous record when the direction is set for the next record </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-continue-void-any-key">
+<link rel=assert title="The parameter is less than or equal to this cursor's position and this cursor's direction is 'next' or 'nextunique'.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", {keyPath:"pKey"});
+
+ objStore.createIndex("index", "iKey");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var count = 0;
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .index("index")
+ .openCursor(undefined, "next"); // XXX: Fx has issue with "undefined"
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ if (!cursor) {
+ assert_equals(count, 2, "ran number of times");
+ t.done();
+ }
+
+ // First time checks key equal, second time checks key less than
+ assert_throws("DataError",
+ function() { cursor.continue(records[0].iKey); });
+
+ cursor.continue();
+
+ count++;
+ });
+ };
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_continue_index4.htm b/testing/web-platform/tests/IndexedDB/idbcursor_continue_index4.htm
new file mode 100644
index 000000000..c5cfd85eb
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_continue_index4.htm
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<title>IDBCursor.continue() - index - attempt to iterate to the next record when the direction is set for the previous record</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-continue-void-any-key">
+<link rel=assert title="The parameter is greater than or equal to this cursor's position and this cursor's direction is 'prev' or 'prevunique'.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" },
+ { pKey: "primaryKey_2", iKey: "indexKey_2" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+
+ objStore.createIndex("index", "iKey");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var count = 0,
+ cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .index("index")
+ .openCursor(undefined, "prev"); // XXX Fx issues w undefined
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result,
+ record = cursor.value;
+
+ switch(count) {
+ case 0:
+ assert_equals(record.pKey, records[2].pKey, "first pKey");
+ assert_equals(record.iKey, records[2].iKey, "first iKey");
+ cursor.continue();
+ break;
+
+ case 1:
+ assert_equals(record.pKey, records[1].pKey, "second pKey");
+ assert_equals(record.iKey, records[1].iKey, "second iKey");
+ assert_throws("DataError",
+ function() { cursor.continue("indexKey_2"); });
+ t.done();
+ break;
+
+ default:
+ assert_unreached("Unexpected count value: " + count);
+ }
+
+ count++;
+ });
+ };
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_continue_index5.htm b/testing/web-platform/tests/IndexedDB/idbcursor_continue_index5.htm
new file mode 100644
index 000000000..abe0e658b
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_continue_index5.htm
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<title>IDBCursor.continue() - index - iterate using 'prevunique'</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#cursor-iteration-operation">
+<link rel=assert title='If direction is "prevunique", let temp record be the last record in records which satisfy all of the following requirements:'>
+<link rel=assert title="If position is defined, the record's key is less than position.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db,
+ t = async_test(document.title, {timeout: 10000}),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" },
+ { pKey: "primaryKey_1-2", iKey: "indexKey_1" },
+ { pKey: "primaryKey_2", iKey: "indexKey_2" } ],
+
+ expected = [ { pKey: "primaryKey_2", iKey: "indexKey_2" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" },
+ { pKey: "primaryKey_0", iKey: "indexKey_0" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+
+ objStore.createIndex("index", "iKey");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var count = 0,
+ cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .index("index")
+ .openCursor(undefined, 'prevunique');
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ if (!e.target.result) {
+ assert_equals(count, expected.length, 'count');
+ t.done();
+ return;
+ }
+ var cursor = e.target.result,
+ record = cursor.value;
+
+ assert_equals(record.pKey, expected[count].pKey, "pKey #" + count);
+ assert_equals(record.iKey, expected[count].iKey, "iKey #" + count);
+
+ assert_equals(cursor.key, expected[count].iKey, "cursor.key #" + count);
+ assert_equals(cursor.primaryKey, expected[count].pKey, "cursor.primaryKey #" + count);
+
+ count++;
+ cursor.continue(expected[count] ? expected[count].iKey : undefined);
+ });
+ };
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_continue_index6.htm b/testing/web-platform/tests/IndexedDB/idbcursor_continue_index6.htm
new file mode 100644
index 000000000..cf5bd4066
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_continue_index6.htm
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<title>IDBCursor.continue() - index - iterate using nextunique</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#cursor-iteration-operation">
+<link rel=assert title='If direction is "nextunique", let found record be the first record in records which satisfy all of the following requirements:'>
+<link rel=assert title="If position is defined, the record's key is greater than position.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db,
+ t = async_test(document.title, {timeout: 10000}),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" },
+ { pKey: "primaryKey_1-2", iKey: "indexKey_1" },
+ { pKey: "primaryKey_2", iKey: "indexKey_2" } ],
+
+ expected = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" },
+ { pKey: "primaryKey_2", iKey: "indexKey_2" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+
+ objStore.createIndex("index", "iKey");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var count = 0,
+ cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .index("index")
+ .openCursor(undefined, "nextunique");
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ if (!e.target.result) {
+ assert_equals(count, expected.length, 'count');
+ t.done();
+ return;
+ }
+ var cursor = e.target.result,
+ record = cursor.value;
+
+ assert_equals(record.pKey, expected[count].pKey, "pKey #" + count);
+ assert_equals(record.iKey, expected[count].iKey, "iKey #" + count);
+
+ assert_equals(cursor.key, expected[count].iKey, "cursor.key #" + count);
+ assert_equals(cursor.primaryKey, expected[count].pKey, "cursor.primaryKey #" + count);
+
+ count++;
+ cursor.continue(expected[count] ? expected[count].iKey : undefined);
+ });
+ };
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_continue_index7.htm b/testing/web-platform/tests/IndexedDB/idbcursor_continue_index7.htm
new file mode 100644
index 000000000..fed235685
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_continue_index7.htm
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBCursor.continue() - index - throw TransactionInactiveError</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ var objStore = db.createObjectStore("store", {keyPath : "pKey"});
+ objStore.createIndex("index", "iKey");
+ for (var i = 0; i < records.length; i++) {
+ objStore.add(records[i]);
+ }
+ var rq = objStore.index("index").openCursor();
+ rq.onsuccess = t.step_func(function(event) {
+ var cursor = event.target.result;
+ assert_true(cursor instanceof IDBCursor);
+
+ event.target.transaction.abort();
+ assert_throws("TransactionInactiveError", function() {
+ cursor.continue();
+ }, "Calling continue() should throws an exception TransactionInactiveError when the transaction is not active.");
+
+ t.done();
+ });
+ }
+
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_continue_index8.htm b/testing/web-platform/tests/IndexedDB/idbcursor_continue_index8.htm
new file mode 100644
index 000000000..4a574ec90
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_continue_index8.htm
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBCursor.continue() - index - throw InvalidStateError caused by object store been deleted</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ var objStore = db.createObjectStore("store", {keyPath : "pKey"});
+ objStore.createIndex("index", "iKey");
+ for (var i = 0; i < records.length; i++) {
+ objStore.add(records[i]);
+ }
+ var rq = objStore.index("index").openCursor();
+ rq.onsuccess = t.step_func(function(event) {
+ var cursor = event.target.result;
+ assert_true(cursor instanceof IDBCursor);
+
+ db.deleteObjectStore("store");
+ assert_throws("InvalidStateError", function() {
+ cursor.continue();
+ }, "If the cursor's source or effective object store has been deleted, the implementation MUST throw a DOMException of type InvalidStateError");
+
+ t.done();
+ });
+ }
+
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_continue_invalid.htm b/testing/web-platform/tests/IndexedDB/idbcursor_continue_invalid.htm
new file mode 100644
index 000000000..dea07bc91
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_continue_invalid.htm
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<title>IDBCursor.continue() - attempt to call continue two times</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db,
+ t = async_test(document.title, {timeout: 10000});
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test");
+
+ objStore.createIndex("index", "");
+
+ objStore.add("data", 1);
+ objStore.add("data2", 2);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var count = 0;
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .index("index")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ if (!e.target.result) {
+ assert_equals(count, 2, 'count');
+ t.done();
+ return;
+ }
+ var cursor = e.target.result;
+
+ cursor.continue(undefined);
+
+ // Second try
+ assert_throws('InvalidStateError',
+ function() { cursor.continue(); }, 'second continue');
+
+ assert_throws('InvalidStateError',
+ function() { cursor.continue(3); }, 'third continue');
+
+ count++;
+ });
+ };
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_continue_objectstore.htm b/testing/web-platform/tests/IndexedDB/idbcursor_continue_objectstore.htm
new file mode 100644
index 000000000..76750c969
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_continue_objectstore.htm
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<title>IDBCursor.continue() - object store - iterate to the next record</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db,
+ count = 0,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0" },
+ { pKey: "primaryKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", {autoIncrement:true, keyPath:"pKey"});
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var store = db.transaction("test")
+ .objectStore("test");
+
+ cursor_rq = store.openCursor();
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ if (!cursor) {
+ assert_equals(count, records.length, "cursor run count");
+ t.done();
+ }
+
+ var record = cursor.value;
+ assert_equals(record.pKey, records[count].pKey, "primary key");
+ assert_equals(record.iKey, records[count].iKey, "index key");
+
+ cursor.continue();
+ count++;
+ });
+ };
+</script>
+
+<div id=log> </div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_continue_objectstore2.htm b/testing/web-platform/tests/IndexedDB/idbcursor_continue_objectstore2.htm
new file mode 100644
index 000000000..14502330b
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_continue_objectstore2.htm
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<title>IDBCursor.continue() - object store - attempt to pass a key parameter is not a valid key </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0" },
+ { pKey: "primaryKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", {keyPath:"pKey"});
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ assert_true(cursor instanceof IDBCursor, "cursor exists");
+ assert_throws("DataError",
+ function() { cursor.continue(document); });
+
+ t.done();
+ });
+ };
+</script>
+
+<div id="log"> </div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_continue_objectstore3.htm b/testing/web-platform/tests/IndexedDB/idbcursor_continue_objectstore3.htm
new file mode 100644
index 000000000..a059b62e5
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_continue_objectstore3.htm
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<title>IDBCursor.continue() - object store - attempt to iterate to the previous record when the direction is set for the next record</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0" },
+ { pKey: "primaryKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", {keyPath:"pKey"});
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .openCursor(undefined, "next");
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ assert_true(cursor instanceof IDBCursor, "cursor exist");
+ assert_throws("DataError",
+ function() { cursor.continue(records[0].pKey); });
+
+ t.done();
+ });
+ };
+</script>
+
+<div id="log"> </div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_continue_objectstore4.htm b/testing/web-platform/tests/IndexedDB/idbcursor_continue_objectstore4.htm
new file mode 100644
index 000000000..b4819c733
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_continue_objectstore4.htm
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<title>IDBCursor.continue() - object store - attempt to iterate to the next record when the direction is set for the previous record </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0" },
+ { pKey: "primaryKey_1" },
+ { pKey: "primaryKey_2" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var count = 0,
+ cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .openCursor(null, "prev");
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ assert_true(cursor != null, "cursor exist");
+
+ switch(count) {
+ case 0:
+ assert_equals(cursor.value.pKey, records[2].pKey, "first cursor pkey");
+ cursor.continue(records[1].pKey);
+ break;
+
+ case 1:
+ assert_equals(cursor.value.pKey, records[1].pKey, "second cursor pkey");
+ assert_throws("DataError",
+ function() { cursor.continue(records[2].pKey); });
+ t.done();
+ break;
+
+ default:
+ assert_unreached("Unexpected count value: " + count);
+ }
+
+ count++;
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_continue_objectstore5.htm b/testing/web-platform/tests/IndexedDB/idbcursor_continue_objectstore5.htm
new file mode 100644
index 000000000..3c1943336
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_continue_objectstore5.htm
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBCursor.continue() - object store - throw TransactionInactiveError</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"> </div>
+<script>
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0" },
+ { pKey: "primaryKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", {keyPath:"pKey"});
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ assert_true(cursor instanceof IDBCursor, "cursor exists");
+
+ e.target.transaction.abort();
+ assert_throws("TransactionInactiveError", function() {
+ cursor.continue();
+ }, "Calling continue() should throws an exception TransactionInactiveError when the transaction is not active.");
+
+
+ t.done();
+ });
+ };
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_continue_objectstore6.htm b/testing/web-platform/tests/IndexedDB/idbcursor_continue_objectstore6.htm
new file mode 100644
index 000000000..f9d656ebf
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_continue_objectstore6.htm
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBCursor.continue() - object store - throw InvalidStateError caused by object store been deleted</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"> </div>
+<script>
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0" },
+ { pKey: "primaryKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", {keyPath:"pKey"});
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+
+ var cursor_rq = objStore.openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ assert_true(cursor instanceof IDBCursor, "cursor exists");
+
+ db.deleteObjectStore("test");
+ assert_throws("InvalidStateError", function() {
+ cursor.continue();
+ }, "If the cursor's source or effective object store has been deleted, the implementation MUST throw a DOMException of type InvalidStateError");
+
+ t.done();
+ });
+ }
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_delete_index.htm b/testing/web-platform/tests/IndexedDB/idbcursor_delete_index.htm
new file mode 100644
index 000000000..8cddcea99
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_delete_index.htm
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<title>IDBCursor.delete() - index - remove a record from the object store</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db,
+ count = 0,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+ objStore.createIndex("index", "iKey");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = t.step_func(CursorDeleteRecord);
+
+
+ function CursorDeleteRecord(e) {
+ var txn = db.transaction("test", "readwrite"),
+ cursor_rq = txn.objectStore("test")
+ .index("index")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ assert_true(cursor instanceof IDBCursor, "cursor exist");
+ cursor.delete();
+ });
+
+ txn.oncomplete = t.step_func(VerifyRecordWasDeleted);
+ }
+
+
+ function VerifyRecordWasDeleted(e) {
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ if (!cursor) {
+ assert_equals(count, 1, 'count');
+ t.done();
+ }
+
+ assert_equals(cursor.value.pKey, records[1].pKey);
+ assert_equals(cursor.value.iKey, records[1].iKey);
+ cursor.continue();
+ count++;
+ });
+ }
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_delete_index2.htm b/testing/web-platform/tests/IndexedDB/idbcursor_delete_index2.htm
new file mode 100644
index 000000000..a5147f754
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_delete_index2.htm
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<title>IDBCursor.delete() - index - attempt to remove a record in a read-only transaction</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+ objStore.createIndex("index", "iKey");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .index("index")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ assert_true(cursor instanceof IDBCursor, "cursor exist");
+ assert_throws('ReadOnlyError', function() { cursor.delete(); });
+ t.done();
+ });
+ }
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_delete_index3.htm b/testing/web-platform/tests/IndexedDB/idbcursor_delete_index3.htm
new file mode 100644
index 000000000..bb5722ee3
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_delete_index3.htm
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<title>IDBCursor.delete() - index - attempt to remove a record in an inactive transaction</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+ var index = objStore.createIndex("index", "iKey");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+
+ var cursor_rq = index.openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ assert_true(cursor instanceof IDBCursor, "cursor exist");
+ window.cursor = cursor;
+ });
+
+ e.target.transaction.oncomplete = t.step_func(function(e) {
+ assert_throws('TransactionInactiveError', function() { window.cursor.delete(); })
+ t.done();
+ });
+ }
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_delete_index4.htm b/testing/web-platform/tests/IndexedDB/idbcursor_delete_index4.htm
new file mode 100644
index 000000000..9b57bd681
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_delete_index4.htm
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBCursor.delete() - index - throw InvalidStateError caused by object store been deleted</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+
+ var db,
+ t = async_test(),
+ records = [{ pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" }];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ var objStore = db.createObjectStore("store", {keyPath : "pKey"});
+ objStore.createIndex("index", "iKey");
+ for (var i = 0; i < records.length; i++) {
+ objStore.add(records[i]);
+ }
+ var rq = objStore.index("index").openCursor();
+ rq.onsuccess = t.step_func(function(event) {
+ var cursor = event.target.result;
+ assert_true(cursor instanceof IDBCursor, "cursor exist");
+
+ db.deleteObjectStore("store");
+ assert_throws("InvalidStateError", function() {
+ cursor.delete();
+ }, "If the cursor's source or effective object store has been deleted, the implementation MUST throw a DOMException of type InvalidStateError");
+
+ t.done();
+ });
+ }
+
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_delete_index5.htm b/testing/web-platform/tests/IndexedDB/idbcursor_delete_index5.htm
new file mode 100644
index 000000000..66eacdebe
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_delete_index5.htm
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBCursor.delete() - index - throw InvalidStateError when the cursor is being iterated</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-delete-IDBRequest">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test(),
+ records = [{ pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" }];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ var objStore = db.createObjectStore("store", {keyPath : "pKey"});
+ objStore.createIndex("index", "iKey");
+ for (var i = 0; i < records.length; i++) {
+ objStore.add(records[i]);
+ }
+
+ var rq = objStore.index("index").openCursor();
+ rq.onsuccess = t.step_func(function(event) {
+ var cursor = event.target.result;
+ assert_true(cursor instanceof IDBCursor, "cursor exist");
+
+ cursor.continue();
+ assert_throws("InvalidStateError", function() {
+ cursor.delete();
+ });
+
+ t.done();
+ });
+ }
+</script>
+
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_delete_objectstore.htm b/testing/web-platform/tests/IndexedDB/idbcursor_delete_objectstore.htm
new file mode 100644
index 000000000..044a4e571
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_delete_objectstore.htm
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<title>IDBCursor.delete() - object store - remove a record from the object store </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db,
+ count = 0,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0" },
+ { pKey: "primaryKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = t.step_func(CursorDeleteRecord);
+
+
+ function CursorDeleteRecord(e) {
+ var txn = db.transaction("test", "readwrite"),
+ cursor_rq = txn.objectStore("test").openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ assert_true(cursor != null, "cursor exist");
+ cursor.delete();
+ });
+
+ txn.oncomplete = t.step_func(VerifyRecordWasDeleted);
+ }
+
+
+ function VerifyRecordWasDeleted(e) {
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ if (!cursor) {
+ assert_equals(count, 1, 'count');
+ t.done();
+ }
+
+ assert_equals(cursor.value.pKey, records[1].pKey);
+ count++;
+ cursor.continue();
+ });
+ }
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_delete_objectstore2.htm b/testing/web-platform/tests/IndexedDB/idbcursor_delete_objectstore2.htm
new file mode 100644
index 000000000..69521e66b
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_delete_objectstore2.htm
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<title>IDBCursor.delete() - object store - attempt to remove a record in a read-only transaction</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ assert_true(cursor != null, "cursor exist");
+ assert_throws('ReadOnlyError', function() { cursor.delete(); });
+ t.done();
+ });
+ }
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_delete_objectstore3.htm b/testing/web-platform/tests/IndexedDB/idbcursor_delete_objectstore3.htm
new file mode 100644
index 000000000..bdb8d93c3
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_delete_objectstore3.htm
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<title>IDBCursor.delete() - index - attempt to remove a record in an inactive transaction</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+
+ var cursor_rq = objStore.openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ assert_true(cursor instanceof IDBCursor, "cursor exist");
+ window.cursor = cursor;
+ });
+
+ e.target.transaction.oncomplete = t.step_func(function(e) {
+ assert_throws('TransactionInactiveError', function() { window.cursor.delete(); })
+ t.done();
+ });
+ }
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_delete_objectstore4.htm b/testing/web-platform/tests/IndexedDB/idbcursor_delete_objectstore4.htm
new file mode 100644
index 000000000..47bcd8b00
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_delete_objectstore4.htm
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBCursor.delete() - object store - throw InvalidStateError caused by object store been deleted</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+
+ var db,
+ t = async_test(),
+ records = [{ pKey: "primaryKey_0"},
+ { pKey: "primaryKey_1"}];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ var objStore = db.createObjectStore("store", {keyPath:"pKey"});
+ for (var i = 0; i < records.length; i++) {
+ objStore.add(records[i]);
+ }
+ var rq = objStore.openCursor();
+ rq.onsuccess = t.step_func(function(event) {
+ var cursor = event.target.result;
+ assert_true(cursor instanceof IDBCursor, "cursor exist");
+
+ db.deleteObjectStore("store");
+ assert_throws("InvalidStateError", function() {
+ cursor.delete();
+ }, "If the cursor's source or effective object store has been deleted, the implementation MUST throw a DOMException of type InvalidStateError");
+
+ t.done();
+ });
+ }
+
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_delete_objectstore5.htm b/testing/web-platform/tests/IndexedDB/idbcursor_delete_objectstore5.htm
new file mode 100644
index 000000000..b37e26126
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_delete_objectstore5.htm
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBCursor.delete() - object store - throw InvalidStateError when the cursor is being iterated</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-delete-IDBRequest">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test(),
+ records = [{ pKey: "primaryKey_0"},
+ { pKey: "primaryKey_1"}];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ var objStore = db.createObjectStore("store", {keyPath:"pKey"});
+ for (var i = 0; i < records.length; i++) {
+ objStore.add(records[i]);
+ }
+ }
+
+ open_rq.onsuccess = function (event) {
+ var txn = db.transaction("store", "readwrite");
+ var rq = txn.objectStore("store").openCursor();
+ rq.onsuccess = t.step_func(function(event) {
+ var cursor = event.target.result;
+ assert_true(cursor instanceof IDBCursor, "cursor exist");
+
+ cursor.continue();
+ assert_throws("InvalidStateError", function() {
+ cursor.delete();
+ });
+
+ t.done();
+ });
+ }
+</script>
+
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_iterating.htm b/testing/web-platform/tests/IndexedDB/idbcursor_iterating.htm
new file mode 100644
index 000000000..fd3cd0a69
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_iterating.htm
@@ -0,0 +1,110 @@
+<!DOCTYPE html>
+<title>IDBCursor.continue() - objectstore - delete next element, and iterate to it</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ count = 0,
+ t = async_test(document.title, {timeout: 10000});
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", { keyPath: "key" });
+
+ for (var i = 0; i < 500; i++)
+ objStore.add({ key: i, val: "val_"+i });
+
+ var rq = objStore.add({ key: 500, val: "val_500" });
+
+ rq.onsuccess = t.step_func(function() {
+ for (var i = 999; i > 500; i--)
+ objStore.add({ key: i, val: "val_"+i });
+ });
+
+ objStore.createIndex('index', ['key', 'val']);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test", "readwrite")
+ .objectStore("test")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result,
+ store = e.target.source;
+ if (!cursor) {
+ assert_equals(count, 997, "cursor run count");
+
+ var rq = e.target.source.count();
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, 995, "object count");
+ t.done();
+ });
+ return;
+ }
+
+ switch (cursor.key) {
+ case 10:
+ assert_equals(count, cursor.key, "count");
+ store.delete(11);
+ break;
+
+ case 12:
+ case 499:
+ case 500:
+ case 501:
+ assert_equals(count, cursor.key - 1, "count");
+ break;
+
+ // Delete the next key
+ case 510:
+ store.delete(511);
+ break;
+
+ // Delete randomly
+ case 512:
+ store.delete(611);
+ store.delete(499);
+ store.delete(500);
+ break;
+
+ // Delete and add a new key
+ case 520:
+ store.delete(521);
+ store.add({ key: 521, val: "new"});
+ break;
+
+ case 521:
+ assert_equals(cursor.value.val, "new");
+ break;
+
+ // We should only be here once although we're basically making the index
+ // "heavier" with its new key.
+ case 530:
+ assert_equals(cursor.value.val, "val_530");
+ cursor.update({ key: 530, val: "val_531" })
+
+ store.get(530).onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result.val, "val_531");
+ });
+ break;
+
+ // Shouldn't happen.
+ case 11:
+ case 511:
+ case 611:
+ assert_unreached(cursor.key + " should be deleted and never run");
+ break;
+ }
+
+ cursor.continue();
+ count++;
+ });
+ };
+</script>
+
+<div id="log"> </div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_iterating_index.htm b/testing/web-platform/tests/IndexedDB/idbcursor_iterating_index.htm
new file mode 100644
index 000000000..559cce6db
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_iterating_index.htm
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<title>IDBCursor.continue() - index - delete next element, and iterate to it</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ count = 0,
+ t = async_test(document.title, {timeout: 10000}),
+ records = [ { pKey: "primaryKey_0", obj: { iKey: "iKey_0" }},
+ { pKey: "primaryKey_1", obj: { iKey: "iKey_1" }},
+ { pKey: "primaryKey_2", obj: { iKey: "iKey_2" }} ],
+
+ expected = [ [ "primaryKey_2", "iKey_2" ],
+ [ "primaryKey_0", "iKey_0" ] ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", {keyPath:["pKey", "obj.iKey"]});
+ objStore.createIndex("index", [ "pKey", "obj.iKey" ]);
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test", "readwrite")
+ .objectStore("test")
+ .index("index")
+ .openCursor(null, "prev");
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ if (!cursor) {
+ assert_equals(count, 2, "cursor run count");
+ t.done();
+ }
+
+ if (count === 0) {
+ e.target.source.objectStore.delete(["primaryKey_1", "iKey_1"]);
+ }
+ assert_array_equals(cursor.key, expected[count], "primary key");
+
+ cursor.continue();
+ count++;
+ });
+ };
+</script>
+
+<div id="log"> </div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_iterating_index2.htm b/testing/web-platform/tests/IndexedDB/idbcursor_iterating_index2.htm
new file mode 100644
index 000000000..91a838350
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_iterating_index2.htm
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<title>IDBCursor.continue() - index - add next element, and iterate to it</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ count = 0,
+ t = async_test(document.title, {timeout: 10000}),
+ records = [ { pKey: "primaryKey_0", obj: { iKey: "iKey_0" }},
+ { pKey: "primaryKey_2", obj: { iKey: "iKey_2" }} ],
+
+ expected = [ [ "primaryKey_2", "iKey_2" ],
+ [ "primaryKey_1", "iKey_1" ],
+ [ "primaryKey_0", "iKey_0" ] ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", {keyPath:"pKey"});
+ objStore.createIndex("index", [ "pKey", "obj.iKey" ]);
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test", "readwrite")
+ .objectStore("test")
+ .index("index")
+ .openCursor(null, "prev");
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ if (!cursor) {
+ assert_equals(count, 3, "cursor run count");
+ t.done();
+ }
+
+ if (count === 0) {
+ e.target.source.objectStore.add({ pKey: "primaryKey_1", obj: { iKey: "iKey_1" } });
+ }
+ assert_array_equals(cursor.key, expected[count], "primary key");
+
+ cursor.continue();
+ count++;
+ });
+ };
+</script>
+
+<div id="log"> </div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_iterating_objectstore.htm b/testing/web-platform/tests/IndexedDB/idbcursor_iterating_objectstore.htm
new file mode 100644
index 000000000..db66c4db3
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_iterating_objectstore.htm
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<title>IDBCursor.continue() - objectstore - delete next element, and iterate to it</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ count = 0,
+ t = async_test(document.title, {timeout: 10000}),
+ records = [ { pKey: "primaryKey_0" },
+ { pKey: "primaryKey_1" },
+ { pKey: "primaryKey_2" } ],
+ expected_records = [ { pKey: "primaryKey_0" },
+ { pKey: "primaryKey_2" }];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", {keyPath:"pKey"});
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test", "readwrite")
+ .objectStore("test")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ if (!cursor) {
+ assert_equals(count, 2, "cursor run count");
+ t.done();
+ }
+
+ var record = cursor.value;
+ if (record.pKey == "primaryKey_0") {
+ e.target.source.delete("primaryKey_1");
+ }
+ assert_equals(record.pKey, expected_records[count].pKey, "primary key");
+
+ cursor.continue();
+ count++;
+ });
+ };
+</script>
+
+<div id="log"> </div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_iterating_objectstore2.htm b/testing/web-platform/tests/IndexedDB/idbcursor_iterating_objectstore2.htm
new file mode 100644
index 000000000..2374a854e
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_iterating_objectstore2.htm
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<title>IDBCursor.continue() - objectstore - add next element, and iterate to it</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ count = 0,
+ t = async_test(document.title, {timeout: 10000}),
+ records = [ { pKey: "primaryKey_0" },
+ { pKey: "primaryKey_2" } ],
+ expected_records = [ { pKey: "primaryKey_0" },
+ { pKey: "primaryKey_1" },
+ { pKey: "primaryKey_2" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", {keyPath:"pKey"});
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test", "readwrite")
+ .objectStore("test")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ if (!cursor) {
+ assert_equals(count, 3, "cursor run count");
+ t.done();
+ }
+
+ var record = cursor.value;
+ if (record.pKey == "primaryKey_0") {
+ e.target.source.add({ pKey: "primaryKey_1" });
+ }
+ assert_equals(record.pKey, expected_records[count].pKey, "primary key");
+
+ cursor.continue();
+ count++;
+ });
+ };
+</script>
+
+<div id="log"> </div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_update_index.htm b/testing/web-platform/tests/IndexedDB/idbcursor_update_index.htm
new file mode 100644
index 000000000..5fa1f940a
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_update_index.htm
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<title>IDBCursor.update() - index - modify a record in the object store </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db,
+ count = 0,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+ objStore.createIndex("index", "iKey");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+
+ // XXX: Gecko doesn't like this
+ //e.target.transaction.oncomplete = t.step_func(CursorUpdateRecord);
+ };
+
+ open_rq.onsuccess = CursorUpdateRecord;
+
+
+ function CursorUpdateRecord(e) {
+ var txn = db.transaction("test", "readwrite"),
+ cursor_rq = txn.objectStore("test")
+ .index("index")
+ .openCursor();
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ cursor.value.iKey += "_updated";
+ cursor.update(cursor.value);
+ });
+
+ txn.oncomplete = t.step_func(VerifyRecordWasUpdated);
+ }
+
+
+ function VerifyRecordWasUpdated(e) {
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ assert_equals(cursor.value.iKey, records[0].iKey + "_updated");
+ t.done();
+ });
+ }
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_update_index2.htm b/testing/web-platform/tests/IndexedDB/idbcursor_update_index2.htm
new file mode 100644
index 000000000..03f9c2712
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_update_index2.htm
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<title>IDBCursor.update() - index - attempt to modify a record in a read-only transaction</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+ objStore.createIndex("index", "iKey");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .index("index")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ assert_throws('ReadOnlyError', function() { cursor.update(cursor.value); });
+ t.done();
+ });
+ }
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_update_index3.htm b/testing/web-platform/tests/IndexedDB/idbcursor_update_index3.htm
new file mode 100644
index 000000000..0f7b2a1db
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_update_index3.htm
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<title>IDBCursor.update() - index - attempt to modify a record in an inactive transaction</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+ var index = objStore.createIndex("index", "iKey");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+
+ var cursor_rq = index.openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ assert_true(cursor instanceof IDBCursor, "cursor exist");
+ window.cursor = cursor;
+ window.record = cursor.value;
+ });
+
+ e.target.transaction.oncomplete = t.step_func(function(e) {
+ assert_throws('TransactionInactiveError', function() { window.cursor.update(window.record); })
+ t.done();
+ });
+ }
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_update_index4.htm b/testing/web-platform/tests/IndexedDB/idbcursor_update_index4.htm
new file mode 100644
index 000000000..ee60da0d2
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_update_index4.htm
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBCursor.update() - index - attempt to modify a record when object store been deleted</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ var objStore = db.createObjectStore("store", {keyPath : "pKey"});
+ objStore.createIndex("index", "iKey");
+ for (var i = 0; i < records.length; i++) {
+ objStore.add(records[i]);
+ }
+ var rq = objStore.index("index").openCursor();
+ rq.onsuccess = t.step_func(function(event) {
+ var cursor = event.target.result;
+ assert_true(cursor instanceof IDBCursor);
+
+ db.deleteObjectStore("store");
+ cursor.value.iKey += "_updated";
+ assert_throws("InvalidStateError", function() {
+ cursor.update(cursor.value);
+ }, "If the cursor's source or effective object store has been deleted, the implementation MUST throw a DOMException of type InvalidStateError");
+
+ t.done();
+ });
+ }
+
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_update_index5.htm b/testing/web-platform/tests/IndexedDB/idbcursor_update_index5.htm
new file mode 100644
index 000000000..a31528d16
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_update_index5.htm
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<title>IDBCursor.update() - index - throw DataCloneError</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-update-IDBRequest-any-value">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+ objStore.createIndex("index", "iKey");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test", "readwrite")
+ .objectStore("test")
+ .index("index")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ assert_true(cursor instanceof IDBCursor);
+
+ var record = cursor.value;
+ record.data = document;
+ assert_throws('DataCloneError', function() {
+ cursor.update(record);
+ });
+ t.done();
+ });
+ }
+</script>
+
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_update_index6.htm b/testing/web-platform/tests/IndexedDB/idbcursor_update_index6.htm
new file mode 100644
index 000000000..1e51b1354
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_update_index6.htm
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<title>IDBCursor.update() - index - no argument</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-update-IDBRequest-any-value">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+ objStore.createIndex("index", "iKey");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .index("index")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ assert_true(cursor instanceof IDBCursor);
+
+ assert_throws(new TypeError(), function() { cursor.update(); });
+ t.done();
+ });
+ }
+</script>
+
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_update_index7.htm b/testing/web-platform/tests/IndexedDB/idbcursor_update_index7.htm
new file mode 100644
index 000000000..1d464fbcd
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_update_index7.htm
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<title>IDBCursor.update() - index - throw DataError</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-update-IDBRequest-any-value">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+ objStore.createIndex("index", "iKey");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test", "readwrite")
+ .objectStore("test")
+ .index("index")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ assert_true(cursor instanceof IDBCursor);
+
+ assert_throws('DataError', function() { cursor.update(null); });
+ t.done();
+ });
+ }
+</script>
+
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_update_index8.htm b/testing/web-platform/tests/IndexedDB/idbcursor_update_index8.htm
new file mode 100644
index 000000000..3b9266dbe
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_update_index8.htm
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<title>IDBCursor.update() - index - throw InvalidStateError when the cursor is being iterated</title>
+<link rel="author" title="Mozilla" href="https://www.mozilla.org">
+<link rel="help" href="https://www.w3.org/TR/IndexedDB/#widl-IDBCursor-update-IDBRequest-any-value">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var objStore = db.createObjectStore("store", { keyPath: "pKey" });
+ objStore.createIndex("index", "iKey");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("store", "readwrite")
+ .objectStore("store")
+ .index("index")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ assert_true(cursor instanceof IDBCursor, "cursor exists");
+
+ cursor.continue();
+ assert_throws("InvalidStateError", function() {
+ cursor.update({ pKey: "primaryKey_0", iKey: "indexKey_0_updated" });
+ });
+
+ t.done();
+ });
+ }
+</script>
+
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_update_objectstore.htm b/testing/web-platform/tests/IndexedDB/idbcursor_update_objectstore.htm
new file mode 100644
index 000000000..8aa6a1372
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_update_objectstore.htm
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<title>IDBCursor.update() - objectstore - modify a record in the object store </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0" },
+ { pKey: "primaryKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+
+ // XXX: Gecko doesn't like this
+ //e.target.transaction.oncomplete = t.step_func(CursorUpdateRecord);
+ };
+
+ open_rq.onsuccess = CursorUpdateRecord;
+
+
+ function CursorUpdateRecord(e) {
+ var txn = db.transaction("test", "readwrite"),
+ cursor_rq = txn.objectStore("test")
+ .openCursor();
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ cursor.value.data = "New information!";
+ cursor.update(cursor.value);
+ });
+
+ txn.oncomplete = t.step_func(VerifyRecordWasUpdated);
+ }
+
+
+ function VerifyRecordWasUpdated(e) {
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ assert_equals(cursor.value.data, "New information!");
+ t.done();
+ });
+ }
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_update_objectstore2.htm b/testing/web-platform/tests/IndexedDB/idbcursor_update_objectstore2.htm
new file mode 100644
index 000000000..65c87bd95
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_update_objectstore2.htm
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<title>IDBCursor.update() - object store - attempt to modify a record in a read-only transaction</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test")
+ .objectStore("test")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ assert_throws('ReadOnlyError', function() { cursor.update(cursor.value); });
+ t.done();
+ });
+ }
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_update_objectstore3.htm b/testing/web-platform/tests/IndexedDB/idbcursor_update_objectstore3.htm
new file mode 100644
index 000000000..0ce59de29
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_update_objectstore3.htm
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<title>IDBCursor.update() - object store - attempt to modify a record in an inactive transaction</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+
+ var cursor_rq = objStore.openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ assert_true(cursor instanceof IDBCursor, "cursor exist");
+ window.cursor = cursor;
+ window.record = cursor.value;
+ });
+
+ e.target.transaction.oncomplete = t.step_func(function(e) {
+ assert_throws('TransactionInactiveError', function() { window.cursor.update(window.record); })
+ t.done();
+ });
+ }
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_update_objectstore4.htm b/testing/web-platform/tests/IndexedDB/idbcursor_update_objectstore4.htm
new file mode 100644
index 000000000..cbd0b1f92
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_update_objectstore4.htm
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<title>IDBCursor.update() - index - modify a record in the object store </title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db,
+ t = async_test(document.title, {timeout: 10000})
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test");
+
+ objStore.add("data", "key");
+ };
+
+ open_rq.onsuccess = t.step_func(function(e) {
+ var txn = db.transaction("test", "readwrite"),
+ cursor_rq = txn.objectStore("test")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ cursor.value = "new data!";
+ cursor.update(cursor.value).onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, "key");
+ t.done();
+ });
+ });
+ });
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_update_objectstore5.htm b/testing/web-platform/tests/IndexedDB/idbcursor_update_objectstore5.htm
new file mode 100644
index 000000000..5dfb82ca1
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_update_objectstore5.htm
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBCursor.update() - object store - attempt to modify a record when object store been deleted</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0" },
+ { pKey: "primaryKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", {keyPath:"pKey"});
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+
+ var cursor_rq = objStore.openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ assert_true(cursor instanceof IDBCursor, "cursor exists");
+
+ db.deleteObjectStore("test");
+ cursor.value += "_updated";
+ assert_throws("InvalidStateError", function() {
+ cursor.update(cursor.value);
+ }, "If the cursor's source or effective object store has been deleted, the implementation MUST throw a DOMException of type InvalidStateError");
+
+
+ t.done();
+ });
+ }
+
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_update_objectstore6.htm b/testing/web-platform/tests/IndexedDB/idbcursor_update_objectstore6.htm
new file mode 100644
index 000000000..16aa00dfa
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_update_objectstore6.htm
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<title>IDBCursor.update() - object store - throw DataCloneError</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-update-IDBRequest-any-value">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test", "readwrite")
+ .objectStore("test")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ assert_true(cursor instanceof IDBCursor);
+
+ var record = cursor.value;
+ record.data = document;
+ assert_throws('DataCloneError', function() {
+ cursor.update(record);
+ });
+ t.done();
+ });
+ }
+</script>
+
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_update_objectstore7.htm b/testing/web-platform/tests/IndexedDB/idbcursor_update_objectstore7.htm
new file mode 100644
index 000000000..b1b736cf0
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_update_objectstore7.htm
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<title>IDBCursor.update() - object store - no argument</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-update-IDBRequest-any-value">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test", "readwrite")
+ .objectStore("test")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ assert_true(cursor instanceof IDBCursor);
+
+ assert_throws(new TypeError(), function() { cursor.update(); });
+ t.done();
+ });
+ }
+</script>
+
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_update_objectstore8.htm b/testing/web-platform/tests/IndexedDB/idbcursor_update_objectstore8.htm
new file mode 100644
index 000000000..f0b8900d4
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_update_objectstore8.htm
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<title>IDBCursor.update() - object store - throw DataError</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBCursor-update-IDBRequest-any-value">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test(),
+ records = [ { pKey: "primaryKey_0", iKey: "indexKey_0" },
+ { pKey: "primaryKey_1", iKey: "indexKey_1" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var objStore = db.createObjectStore("test", { keyPath: "pKey" });
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("test", "readwrite")
+ .objectStore("test")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+ assert_true(cursor instanceof IDBCursor);
+
+ assert_throws('DataError', function() { cursor.update(null); });
+ t.done();
+ });
+ }
+</script>
+
diff --git a/testing/web-platform/tests/IndexedDB/idbcursor_update_objectstore9.htm b/testing/web-platform/tests/IndexedDB/idbcursor_update_objectstore9.htm
new file mode 100644
index 000000000..34aa78e6b
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbcursor_update_objectstore9.htm
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBCursor.update() - object store - throw InvalidStateError when the cursor is being iterated</title>
+<link rel="author" title="Mozilla" href="https://www.mozilla.org">
+<link rel="help" href="https://www.w3.org/TR/IndexedDB/#widl-IDBCursor-update-IDBRequest-any-value">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test(),
+ records = [{ pKey: "primaryKey_0", value: "value_0" },
+ { pKey: "primaryKey_1", value: "value_1" }];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+
+ var objStore = db.createObjectStore("store", {keyPath : "pKey"});
+
+ for (var i = 0; i < records.length; i++) {
+ objStore.add(records[i]);
+ }
+ }
+
+ open_rq.onsuccess = function(e) {
+ var cursor_rq = db.transaction("store", "readwrite")
+ .objectStore("store")
+ .openCursor();
+
+ cursor_rq.onsuccess = t.step_func(function(event) {
+ var cursor = event.target.result;
+ assert_true(cursor instanceof IDBCursor, "cursor exists");
+
+ cursor.continue();
+ assert_throws("InvalidStateError", function() {
+ cursor.update({ pKey: "primaryKey_0", value: "value_0_updated" });
+ });
+
+ t.done();
+ });
+ }
+</script>
+
diff --git a/testing/web-platform/tests/IndexedDB/idbdatabase_close.htm b/testing/web-platform/tests/IndexedDB/idbdatabase_close.htm
new file mode 100644
index 000000000..dc3f585a8
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbdatabase_close.htm
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<title>IDBDatabase.close() - unblock the version change transaction created by an open database request</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+var db;
+var versionchange_fired;
+var blocked_fired;
+var upgradeneeded_fired;
+var t = async_test();
+var open_rq = createdb(t);
+var counter = 0;
+
+open_rq.onupgradeneeded = function() {}
+open_rq.onsuccess = function(e) {
+ db = e.target.result;
+ db.onversionchange = t.step_func(function(e) {
+ versionchange_fired = counter++;
+ });
+ var rq = window.indexedDB.open(db.name, db.version + 1);
+ rq.onblocked = t.step_func(function (e) {
+ blocked_fired = counter++;
+ db.close();
+ });
+ rq.onupgradeneeded = t.step_func(function (e) {
+ upgradeneeded_fired = counter++;
+ });
+ rq.onsuccess = t.step_func(function (e) {
+ assert_equals(versionchange_fired, 0, 'versionchange event fired #')
+ assert_equals(blocked_fired, 1, 'block event fired #')
+ assert_equals(upgradeneeded_fired, 2, 'second upgradeneeded event fired #')
+
+ t.done();
+ });
+ rq.onerror = fail(t, 'Unexpected database deletion error');
+};
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbdatabase_close2.htm b/testing/web-platform/tests/IndexedDB/idbdatabase_close2.htm
new file mode 100644
index 000000000..68bafb946
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbdatabase_close2.htm
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<title>IDBDatabase.close() - unblock the delete database request</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+var db;
+var blocked_fired = false;
+var versionchange_fired = false;
+var t = async_test();
+var open_rq = createdb(t);
+
+open_rq.onupgradeneeded = t.step_func(function() {});
+open_rq.onsuccess = t.step_func(function(e) {
+ db = e.target.result;
+
+ db.onversionchange = t.step_func(function (e) {
+ versionchange_fired = true;
+ });
+
+ var rq = window.indexedDB.deleteDatabase(db.name);
+ rq.onblocked = t.step_func(function (e) {
+ blocked_fired = true;
+ db.close();
+ });
+ rq.onsuccess = t.step_func(function (e) {
+ assert_true(versionchange_fired, "versionchange event fired")
+ assert_true(blocked_fired, "block event fired")
+ t.done();
+ });
+ rq.onerror = fail(t, 'Unexpected database deletion error');
+});
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore-createIndex-emptyname.htm b/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore-createIndex-emptyname.htm
new file mode 100644
index 000000000..97f860a7a
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore-createIndex-emptyname.htm
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>IDBDatabase.createObjectStore() and IDBObjectStore.createIndex() - both with empty name</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db
+
+ var open_rq = createdb(async_test())
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result
+ var store = db.createObjectStore("")
+
+ for (var i = 0; i < 5; i++)
+ store.add({ idx: "object_" + i }, i)
+
+ store.createIndex("", "idx")
+
+ store.get(4)
+ .onsuccess = this.step_func(function(e) {
+ assert_equals(e.target.result.idx, 'object_4', 'result')
+ })
+ assert_equals(store.indexNames[0], "", "indexNames[0]")
+ assert_equals(store.indexNames.length, 1, "indexNames.length")
+ }
+
+ open_rq.onsuccess = function() {
+ var store = db.transaction("").objectStore("")
+
+ assert_equals(store.indexNames[0], "", "indexNames[0]")
+ assert_equals(store.indexNames.length, 1, "indexNames.length")
+
+ store.index("")
+ .get('object_4')
+ .onsuccess = this.step_func(function(e) {
+ assert_equals(e.target.result.idx, 'object_4', 'result')
+ this.done()
+ })
+ }
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore.htm b/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore.htm
new file mode 100644
index 000000000..36fe93250
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore.htm
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>IDBDatabase.createObjectStore() - returns an instance of IDBObjectStore</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+
+var t = async_test(),
+ open_rq = createdb(t)
+
+open_rq.onupgradeneeded = function(e) {
+ var db = e.target.result
+ var objStore = db.createObjectStore('instancetest')
+
+ assert_true(objStore instanceof IDBObjectStore, 'instanceof IDBObjectStore')
+}
+
+open_rq.onsuccess = function(e) {
+ var db = e.target.result
+ var objStore = db.transaction('instancetest').objectStore('instancetest')
+
+ assert_true(objStore instanceof IDBObjectStore, 'instanceof IDBObjectStore')
+ t.done()
+}
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore10-1000ends.htm b/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore10-1000ends.htm
new file mode 100644
index 000000000..d6e4a48ed
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore10-1000ends.htm
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<title>IDBDatabase.createObjectStore() - create 1000 object stores, add one item and delete</title>
+<meta name=timeout content=long>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+var db,
+ t = async_test(document.title, {timeout: 600000}),
+ open_rq = createdb(t)
+
+open_rq.onupgradeneeded = function(e) {
+ db = e.target.result
+ var st, i;
+ for (i = 0; i < 1000; i++)
+ {
+ st = db.createObjectStore("object_store_" + i)
+ st.add("test", 1);
+ }
+
+ st.get(1).onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, "test")
+ })
+}
+open_rq.onsuccess = function(e) {
+ db.close()
+ window.indexedDB.deleteDatabase(db.name).onsuccess = function(e) {
+ t.done()
+ }
+}
+</script>
+
+
+<div id="log"></div>
+
+
diff --git a/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore10-emptyname.htm b/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore10-emptyname.htm
new file mode 100644
index 000000000..cee4754a8
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore10-emptyname.htm
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>IDBDatabase.createObjectStore() - empty name</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db
+
+ var open_rq = createdb(async_test())
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result
+ var store = db.createObjectStore("")
+
+ for (var i = 0; i < 5; i++)
+ store.add("object_" + i, i)
+
+ assert_equals(db.objectStoreNames[0], "", "db.objectStoreNames[0]")
+ assert_equals(db.objectStoreNames.length, 1, "objectStoreNames.length")
+ }
+
+ open_rq.onsuccess = function() {
+ var store = db.transaction("").objectStore("")
+
+ store.get(2).onsuccess = this.step_func(function(e) {
+ assert_equals(e.target.result, "object_2")
+ })
+
+ assert_equals(db.objectStoreNames[0], "", "db.objectStoreNames[0]")
+ assert_equals(db.objectStoreNames.length, 1, "objectStoreNames.length")
+
+ this.done()
+ }
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore11.htm b/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore11.htm
new file mode 100644
index 000000000..ae78d46ba
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore11.htm
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBDatabase.createObjectStore() - attempting to create an existing object store with a different keyPath throw ConstraintError </title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBDatabase-createObjectStore-IDBObjectStore-DOMString-name-IDBObjectStoreParameters-optionalParameters">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test(),
+ open_rq = createdb(t);
+
+open_rq.onupgradeneeded = function (e) {
+ var db = e.target.result;
+ db.createObjectStore("store");
+ assert_throws("ConstraintError", function(){
+ db.createObjectStore("store", {
+ keyPath: "key1",
+ });
+ });
+ t.done();
+}
+</script>
+
diff --git a/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore2.htm b/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore2.htm
new file mode 100644
index 000000000..78f06ff9b
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore2.htm
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<title>IDBDatabase.createObjectStore() - object store 'name' and 'keyPath' properties are correctly set </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+var t = async_test(),
+ open_rq = createdb(t)
+
+open_rq.onupgradeneeded = function(e) {
+ var db = e.target.result,
+ objStore = db.createObjectStore("prop", { keyPath: "mykeypath" })
+
+ assert_equals(objStore.name, "prop", "object store name")
+ assert_equals(objStore.keyPath, "mykeypath", "key path")
+ assert_equals(objStore.autoIncrement, false, "auto increment")
+}
+
+open_rq.onsuccess = function(e) {
+ var db = e.target.result
+ var objStore = db.transaction('prop').objectStore('prop')
+
+ assert_equals(objStore.name, "prop", "object store name")
+ assert_equals(objStore.keyPath, "mykeypath", "key path")
+ assert_equals(objStore.autoIncrement, false, "auto increment")
+ t.done()
+}
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore3.htm b/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore3.htm
new file mode 100644
index 000000000..ccf4a2b5f
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore3.htm
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<title>IDBDatabase.createObjectStore() - attempt to create an object store outside of a version change transaction </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+var t = async_test(),
+ open_rq = createdb(t)
+
+open_rq.onupgradeneeded = function() {}
+open_rq.onsuccess = function (e) {
+ var db = e.target.result
+ assert_throws(
+ 'InvalidStateError',
+ function() { db.createObjectStore('fails') })
+ t.done();
+}
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore4.htm b/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore4.htm
new file mode 100644
index 000000000..07d787bd9
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore4.htm
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>IDBDatabase.createObjectStore() - attempt to create an object store that already exists </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+var t = async_test(),
+ open_rq = createdb(t)
+
+open_rq.onupgradeneeded = function(e) {
+ var db = e.target.result
+ db.createObjectStore("dupe")
+ assert_throws(
+ 'ConstraintError',
+ function() { db.createObjectStore("dupe") })
+
+ // Bonus test creating a new objectstore after the exception
+ db.createObjectStore("dupe ")
+ t.done()
+}
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore5.htm b/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore5.htm
new file mode 100644
index 000000000..7e205096e
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore5.htm
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<title>IDBDatabase.createObjectStore() - object store's name appears in database's list </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+var t = async_test(),
+ open_rq = createdb(t)
+
+open_rq.onupgradeneeded = function(e) {
+ var db = e.target.result
+
+ db.createObjectStore("My cool object store name")
+ assert_true(
+ db.objectStoreNames.contains("My cool object store name"),
+ 'objectStoreNames.contains')
+}
+
+open_rq.onsuccess = function(e) {
+ var db = e.target.result
+
+ assert_true(
+ db.objectStoreNames.contains("My cool object store name"),
+ 'objectStoreNames.contains (in success)')
+ t.done()
+}
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore6.htm b/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore6.htm
new file mode 100644
index 000000000..c1200c5f9
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore6.htm
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>IDBDatabase.createObjectStore() - attempt to create an object store with an invalid key path </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+var t = async_test(),
+ open_rq = createdb(t)
+
+open_rq.onupgradeneeded = function(e) {
+ var db = e.target.result
+
+ assert_throws('SyntaxError', function() {
+ db.createObjectStore("invalidkeypath", { keyPath: "Invalid Keypath" })
+ })
+
+ assert_throws('SyntaxError', function() {
+ db.createObjectStore("invalidkeypath", { autoIncrement: true,
+ keyPath: "Invalid Keypath" })
+ })
+
+ t.done()
+}
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore7.htm b/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore7.htm
new file mode 100644
index 000000000..358baeeec
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore7.htm
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<title>IDBDatabase.createObjectStore() - create an object store with an unknown optional parameter </title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+var t = async_test(document.title, {timeout: 10000}),
+ open_rq = createdb(t)
+
+open_rq.onupgradeneeded = function(e) {
+ var db = e.target.result
+ db.createObjectStore("with unknown param", { parameter: 0 });
+
+ t.done()
+}
+
+</script>
+
+
+<div id="log"></div>
+
+
diff --git a/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore8-parameters.htm b/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore8-parameters.htm
new file mode 100644
index 000000000..7cc69765b
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore8-parameters.htm
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStoreParameters</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<meta name=timeout content=long>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ function optionalParameters(desc, params) {
+ var t = async_test(document.title + " - " + desc);
+
+ createdb(t).onupgradeneeded = function(e) {
+ e.target.result.createObjectStore("store", params);
+
+ this.done();
+ };
+ }
+
+
+ optionalParameters("autoInc true", {autoIncrement: true});
+ optionalParameters("autoInc true, keyPath null", {autoIncrement: true, keyPath: null});
+ optionalParameters("autoInc true, keyPath undefined", {autoIncrement: true, keyPath: undefined});
+ optionalParameters("autoInc true, keyPath string", {autoIncrement: true, keyPath: "a"});
+
+ optionalParameters("autoInc false, keyPath empty", {autoIncrement: false, keyPath: ""});
+ optionalParameters("autoInc false, keyPath array", {autoIncrement: false, keyPath: ["h", "j"]});
+ optionalParameters("autoInc false, keyPath string", {autoIncrement: false, keyPath: "abc"});
+
+ optionalParameters("keyPath empty", {keyPath: ""});
+ optionalParameters("keyPath array", {keyPath: ["a","b"]});
+ optionalParameters("keyPath string", {keyPath: "abc"});
+ optionalParameters("keyPath null", {keyPath: null});
+ optionalParameters("keyPath undefined", {keyPath: undefined});
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore9-invalidparameters.htm b/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore9-invalidparameters.htm
new file mode 100644
index 000000000..0a6dc03a6
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbdatabase_createObjectStore9-invalidparameters.htm
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>createObjectStore: Invalid optionalParameters</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ function invalid_optionalParameters(desc, params) {
+ var t = async_test(document.title + " - " + desc);
+
+ createdb(t).onupgradeneeded = function(e) {
+ assert_throws(null, function() {
+ e.target.result.createObjectStore("store", params);
+ });
+
+ this.done();
+ };
+ }
+
+ invalid_optionalParameters("autoInc and empty keyPath", {autoIncrement: true, keyPath: ""});
+ invalid_optionalParameters("autoInc and keyPath array", {autoIncrement: true, keyPath: []});
+ invalid_optionalParameters("autoInc and keyPath array 2", {autoIncrement: true, keyPath: ["hey"]});
+ invalid_optionalParameters("autoInc and keyPath object", {autoIncrement: true, keyPath: {a:"hey", b:2}});
+
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbdatabase_deleteObjectStore.htm b/testing/web-platform/tests/IndexedDB/idbdatabase_deleteObjectStore.htm
new file mode 100644
index 000000000..b69570cc0
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbdatabase_deleteObjectStore.htm
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<title>IDBDatabase.deleteObjectStore() - object store's name is removed from database's list </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+var t = async_test(),
+ open_rq = createdb(t)
+
+open_rq.onupgradeneeded = function(e) {
+ var db = e.target.result
+
+ db.createObjectStore("deleted");
+ db.deleteObjectStore("deleted");
+ assert_false(db.objectStoreNames.contains("deleted"))
+
+ t.done()
+}
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbdatabase_deleteObjectStore2.htm b/testing/web-platform/tests/IndexedDB/idbdatabase_deleteObjectStore2.htm
new file mode 100644
index 000000000..3c1abe632
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbdatabase_deleteObjectStore2.htm
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<title>IDBDatabase.deleteObjectStore() - attempt to remove an object store outside of a version change transaction </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+var t = async_test(),
+ open_rq = createdb(t);
+
+open_rq.onupgradeneeded = function(e)
+{
+ var db = e.target.result,
+ objStore = db.createObjectStore("delete_outside");
+
+ e.target.transaction.oncomplete = t.step_func(function (e)
+ {
+ assert_throws('InvalidStateError',
+ function() { db.deleteObjectStore("delete_outside"); });
+ t.done();
+ });
+}
+
+</script>
+
+
+<div id="log"></div>
+
+
diff --git a/testing/web-platform/tests/IndexedDB/idbdatabase_deleteObjectStore3.htm b/testing/web-platform/tests/IndexedDB/idbdatabase_deleteObjectStore3.htm
new file mode 100644
index 000000000..cae00f9d2
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbdatabase_deleteObjectStore3.htm
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<title>IDBDatabase.deleteObjectStore() - attempt to remove an object store that does not exist </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+var t = async_test(),
+ open_rq = createdb(t);
+
+open_rq.onupgradeneeded = function(e)
+{
+ var db = e.target.result;
+ assert_throws('NotFoundError',
+ function() { db.deleteObjectStore('whatever'); });
+ t.done();
+}
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbdatabase_deleteObjectStore4-not_reused.htm b/testing/web-platform/tests/IndexedDB/idbdatabase_deleteObjectStore4-not_reused.htm
new file mode 100644
index 000000000..1cb6ff1ac
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbdatabase_deleteObjectStore4-not_reused.htm
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>IDBDatabase.deleteObjectStore() - the object store is not reused</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+
+var t = async_test(document.title, {timeout: 10000}),
+ keys = [],
+ open_rq = createdb(t)
+
+open_rq.onupgradeneeded = function(e) {
+ var db = e.target.result
+
+ var objStore = db.createObjectStore("resurrected", { autoIncrement: true, keyPath: "k" });
+ objStore.add({k:5}).onsuccess = function(e) { keys.push(e.target.result); }
+ objStore.add({}).onsuccess = function(e) { keys.push(e.target.result); }
+ objStore.createIndex("idx", "i");
+ assert_true(objStore.indexNames.contains("idx"));
+ assert_equals(objStore.keyPath, "k", "keyPath");
+
+ db.deleteObjectStore("resurrected");
+
+ var objStore2 = db.createObjectStore("resurrected", { autoIncrement: true });
+ objStore2.add("Unicorns'R'us").onsuccess = function(e) { keys.push(e.target.result); };
+ assert_false(objStore2.indexNames.contains("idx"), "index exist on new objstore");
+ assert_equals(objStore2.keyPath, null, "keyPath");
+
+ assert_throws("NotFoundError", function() { objStore2.index("idx"); });
+}
+
+open_rq.onsuccess = function(e) {
+ assert_array_equals(keys, [5, 6, 1], "keys");
+ t.done();
+}
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbdatabase_transaction.htm b/testing/web-platform/tests/IndexedDB/idbdatabase_transaction.htm
new file mode 100644
index 000000000..94de8b433
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbdatabase_transaction.htm
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<title>IDBDatabase.transaction() - attempt to open a transaction with invalid scope</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+var db,
+ t = async_test(),
+ open_rq = createdb(t);
+
+open_rq.onupgradeneeded = function() {};
+open_rq.onsuccess = function(e) {
+ db = e.target.result;
+
+ assert_throws('NotFoundError', function() { db.transaction('non-existing'); });
+ t.done();
+};
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbdatabase_transaction2.htm b/testing/web-platform/tests/IndexedDB/idbdatabase_transaction2.htm
new file mode 100644
index 000000000..310014bc5
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbdatabase_transaction2.htm
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>IDBDatabase.transaction() - opening a transaction defaults to a read-only mode </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+var db,
+ t = async_test(),
+ open_rq = createdb(t);
+
+open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ db.createObjectStore('readonly');
+};
+open_rq.onsuccess = function(e) {
+ var txn = db.transaction('readonly');
+ assert_equals(txn.mode, "readonly", 'txn.mode');
+
+ t.done();
+};
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbdatabase_transaction3.htm b/testing/web-platform/tests/IndexedDB/idbdatabase_transaction3.htm
new file mode 100644
index 000000000..9b353c710
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbdatabase_transaction3.htm
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>IDBDatabase.transaction() - attempt to open a transaction from closed database connection </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ open_rq = createdb(t);
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ db.createObjectStore('test');
+ };
+
+ open_rq.onsuccess = function(e) {
+ db.close();
+
+ assert_throws('InvalidStateError',
+ function() { db.transaction('test'); });
+
+ t.done();
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbdatabase_transaction4.htm b/testing/web-platform/tests/IndexedDB/idbdatabase_transaction4.htm
new file mode 100644
index 000000000..515c499b0
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbdatabase_transaction4.htm
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>IDBDatabase.transaction() - attempt to open a transaction with invalid mode </title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(document.title, {timeout: 10000}),
+ open_rq = createdb(t);
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ db.createObjectStore('test');
+ };
+
+ open_rq.onsuccess = function(e) {
+ assert_throws({ name: 'TypeError' },
+ function() { db.transaction('test', 'whatever'); });
+
+ t.done();
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbdatabase_transaction5.htm b/testing/web-platform/tests/IndexedDB/idbdatabase_transaction5.htm
new file mode 100644
index 000000000..b6b45ab9f
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbdatabase_transaction5.htm
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBDatabase.transaction() - If storeNames is an empty list, the implementation must throw a DOMException of type InvalidAccessError</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBDatabase-transaction-IDBTransaction-DOMString-sequence-DOMString--storeNames-IDBTransactionMode-mode">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+var db,
+ t = async_test(),
+ open_rq = createdb(t);
+
+open_rq.onupgradeneeded = function() {};
+open_rq.onsuccess = function(e) {
+ db = e.target.result;
+ assert_throws('InvalidAccessError', function() { db.transaction([]); });
+ t.done();
+};
+</script>
+
diff --git a/testing/web-platform/tests/IndexedDB/idbfactory_cmp.htm b/testing/web-platform/tests/IndexedDB/idbfactory_cmp.htm
new file mode 100644
index 000000000..7b301ece4
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbfactory_cmp.htm
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>IDBFactory.cmp() - compared keys return correct value</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ test(function() {
+ var greater = window.indexedDB.cmp(2, 1);
+ var equal = window.indexedDB.cmp(2, 2);
+ var less = window.indexedDB.cmp(1, 2);
+
+ assert_equals(greater, 1, "greater");
+ assert_equals(equal, 0, "equal");
+ assert_equals(less, -1, "less");
+ }, "IDBFactory.cmp()");
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbfactory_cmp2.htm b/testing/web-platform/tests/IndexedDB/idbfactory_cmp2.htm
new file mode 100644
index 000000000..446bb465c
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbfactory_cmp2.htm
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBFactory.cmp() - invalid key</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBFactory-cmp-short-any-first-any-second">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+<div id=log></div>
+<script>
+ test( function() {
+ assert_throws(new TypeError(), function() {
+ indexedDB.cmp();
+ });
+ }, "IDBFactory.cmp() - no argument");
+
+ test( function() {
+ assert_throws("DataError", function() {
+ indexedDB.cmp(null, null);
+ });
+ assert_throws("DataError", function() {
+ indexedDB.cmp(1, null);
+ });
+ assert_throws("DataError", function() {
+ indexedDB.cmp(null, 1);
+ });
+ }, "IDBFactory.cmp() - null");
+
+ test( function() {
+ assert_throws("DataError", function() {
+ indexedDB.cmp(NaN, NaN);
+ });
+ assert_throws("DataError", function() {
+ indexedDB.cmp(1, NaN);
+ });
+ assert_throws("DataError", function() {
+ indexedDB.cmp(NaN, 1);
+ });
+ }, "IDBFactory.cmp() - NaN");
+</script>
+
diff --git a/testing/web-platform/tests/IndexedDB/idbfactory_cmp3.htm b/testing/web-platform/tests/IndexedDB/idbfactory_cmp3.htm
new file mode 100644
index 000000000..749fd7b86
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbfactory_cmp3.htm
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>IDBFactory.cmp() - compared keys in different types</title>
+<link rel="author" title="Mozilla" href="https://www.mozilla.org">
+<link rel="help" href="http://w3c.github.io/IndexedDB/#key-construct">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+
+<script>
+ test(function() {
+ assert_equals(indexedDB.cmp([0], new Uint8Array([0])), 1, "Array > Binary");
+ }, "Array v.s. Binary");
+
+ test(function() {
+ assert_equals(indexedDB.cmp(new Uint8Array([0]), "0"), 1, "Binary > String");
+ }, "Binary v.s. String");
+
+ test(function() {
+ assert_equals(indexedDB.cmp("", new Date(0)), 1, "String > Date");
+ }, "String v.s. Date");
+
+ test(function() {
+ assert_equals(indexedDB.cmp(new Date(0), 0), 1, "Date > Number");
+ }, "Date v.s. Number");
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbfactory_cmp4.htm b/testing/web-platform/tests/IndexedDB/idbfactory_cmp4.htm
new file mode 100644
index 000000000..757e7c239
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbfactory_cmp4.htm
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>IDBFactory.cmp() - comparison of binary keys</title>
+<link rel="author" title="Mozilla" href="https://www.mozilla.org">
+<link rel="help" href="http://w3c.github.io/IndexedDB/#key-construct">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+
+<script>
+ test(function() {
+ assert_equals(indexedDB.cmp(new Int8Array([-1]), new Uint8Array([0])), 1,
+ "255(-1) shall be larger than 0");
+ }, "Compare in unsigned octet values (in the range [0, 255])");
+
+ test(function() {
+ assert_equals(indexedDB.cmp(
+ new Uint8Array([255, 254, 253]),
+ new Uint8Array([255, 253, 254])),
+ 1,
+ "[255, 254, 253] shall be larger than [255, 253, 254]");
+ }, "Compare values in then same length");
+
+ test(function() {
+ assert_equals(indexedDB.cmp(
+ new Uint8Array([255, 254]),
+ new Uint8Array([255, 253, 254])),
+ 1,
+ "[255, 254] shall be larger than [255, 253, 254]");
+ }, "Compare values in different lengths");
+
+ test(function() {
+ assert_equals(indexedDB.cmp(
+ new Uint8Array([255, 253, 254]),
+ new Uint8Array([255, 253])),
+ 1,
+ "[255, 253, 254] shall be larger than [255, 253]");
+ }, "Compare when the values in the range of their minimal length are the same");
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbfactory_deleteDatabase.htm b/testing/web-platform/tests/IndexedDB/idbfactory_deleteDatabase.htm
new file mode 100644
index 000000000..fd7a908d3
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbfactory_deleteDatabase.htm
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<title>IDBFactory.deleteDatabase() - request has no source </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var open_rq = createdb(async_test(), undefined, 9);
+
+ open_rq.onupgradeneeded = function(e) {};
+ open_rq.onsuccess = function(e) {
+ var db = e.target.result;
+ db.close();
+
+ var delete_rq = window.indexedDB.deleteDatabase(db.name);
+ delete_rq.onerror = fail(this, "Unexpected delete_rq.error event");
+ delete_rq.onsuccess = this.step_func( function (e) {
+ assert_equals(e.target.source, null, "event.target.source")
+ this.done();
+ });
+ }
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbfactory_deleteDatabase2.htm b/testing/web-platform/tests/IndexedDB/idbfactory_deleteDatabase2.htm
new file mode 100644
index 000000000..0c7c73a28
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbfactory_deleteDatabase2.htm
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>IDBFactory.deleteDatabase() - result of the request is set to undefined</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBFactory-deleteDatabase-IDBOpenDBRequest-DOMString-name">
+<meta name=assert title="If the steps above are successful, the implementation must set the result of the request to undefined and fire a success event at the request.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var open_rq = createdb(async_test(), undefined, 9);
+
+ open_rq.onupgradeneeded = function(e) {};
+ open_rq.onsuccess = function(e) {
+ var db = e.target.result;
+ db.close();
+
+ var delete_rq = window.indexedDB.deleteDatabase(db.name);
+ delete_rq.onerror = fail(this, "Unexpected delete_rq.error event");
+ delete_rq.onsuccess = this.step_func( function (e) {
+ assert_equals(e.target.result, undefined, "result");
+ this.done();
+ });
+ }
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbfactory_deleteDatabase3.htm b/testing/web-platform/tests/IndexedDB/idbfactory_deleteDatabase3.htm
new file mode 100644
index 000000000..e1cab41a5
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbfactory_deleteDatabase3.htm
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<title>IDBFactory.deleteDatabase() - success event</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBFactory-deleteDatabase-IDBOpenDBRequest-DOMString-name">
+<meta name=assert title="If the steps above are successful, the implementation must set the result of the request to undefined and fire a success event at the request. The event must implement the IDBVersionChangeEvent interface and have oldVersion set to database version and have the newVersion property set to null.">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db
+ var open_rq = createdb(async_test(document.title, {timeout: 10000}), undefined, 9)
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result
+ db.createObjectStore('os')
+ }
+ open_rq.onsuccess = function(e) {
+ db.close()
+
+ var delete_rq = window.indexedDB.deleteDatabase(db.name)
+ delete_rq.onerror = fail(this, "Unexpected delete_rq.error event")
+ delete_rq.onsuccess = this.step_func( function (e) {
+ assert_equals(e.oldVersion, 9, "oldVersion")
+ assert_equals(e.newVersion, null, "newVersion")
+ assert_equals(e.target.result, undefined, "result")
+ assert_true(e instanceof IDBVersionChangeEvent, "e instanceof IDBVersionChangeEvent")
+ this.done()
+ })
+ }
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbfactory_deleteDatabase4.htm b/testing/web-platform/tests/IndexedDB/idbfactory_deleteDatabase4.htm
new file mode 100644
index 000000000..3a4e9944d
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbfactory_deleteDatabase4.htm
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<title>Test events opening a second database when one connection is open already</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<div id="log"></div>
+
+<script>
+
+ var t = async_test("Delete an existing database");
+
+ t.step(function() {
+ var openrq = indexedDB.open('db', 3);
+
+ openrq.onupgradeneeded = function(e) {
+ e.target.result.createObjectStore('store');
+ };
+ openrq.onsuccess = t.step_func(function(e) {
+ db = e.target.result;
+
+ // Errors
+ db.onversionchange = fail(t, "db.versionchange");
+ db.onerror = fail(t, "db.error");
+ db.abort = fail(t, "db.abort");
+
+ setTimeout(t.step_func(Second), 4);
+ db.close();
+ });
+
+ // Errors
+ openrq.onerror = fail(t, "open.error");
+ openrq.onblocked = fail(t, "open.blocked");
+ });
+
+ function Second(e) {
+ var deleterq = indexedDB.deleteDatabase('db');
+
+ deleterq.onsuccess = function(e) { t.done(); }
+
+ deleterq.onerror = fail(t, "delete.error");
+ deleterq.onblocked = fail(t, "delete.blocked");
+ deleterq.onupgradeneeded = fail(t, "delete.upgradeneeded");
+ }
+
+ async_test("Delete a nonexistant database").step(function(e) {
+ var deleterq = indexedDB.deleteDatabase('nonexistant');
+
+ deleterq.onsuccess = this.step_func(function(e) { this.done(); });
+
+ deleterq.onerror = fail(this, "delete.error");
+ deleterq.onblocked = fail(this, "delete.blocked");
+ deleterq.onupgradeneeded = fail(this, "delete.upgradeneeded");
+ });
+
+</script>
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/idbfactory_open.htm b/testing/web-platform/tests/IndexedDB/idbfactory_open.htm
new file mode 100644
index 000000000..bca2cfdc8
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbfactory_open.htm
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<title>IDBFactory.open() - request has no source</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var open_rq = createdb(async_test(), undefined, 9);
+
+ open_rq.onupgradeneeded = function(e) {};
+ open_rq.onsuccess = function(e) {
+ assert_equals(e.target.source, null, "source")
+ this.done();
+ }
+</script>
+
+<div id="log"> </div>
diff --git a/testing/web-platform/tests/IndexedDB/idbfactory_open10.htm b/testing/web-platform/tests/IndexedDB/idbfactory_open10.htm
new file mode 100644
index 000000000..598046ff9
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbfactory_open10.htm
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<title>IDBFactory.open() - error in upgradeneeded resets db</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db, db2;
+ var open_rq = createdb(async_test(document.title, {timeout: 10000}), undefined, 9);
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var st = db.createObjectStore("store");
+ st.createIndex("index", "i");
+
+ assert_equals(db.version, 9, "first db.version");
+ assert_true(db.objectStoreNames.contains("store"), "objectStoreNames contains store");
+ assert_true(st.indexNames.contains("index"), "indexNames contains index");
+
+ st.add({i: "Joshua"}, 1);
+ st.add({i: "Jonas"}, 2);
+ };
+ open_rq.onsuccess = function(e) {
+ db.close();
+ var open_rq2 = window.indexedDB.open(db.name, 10);
+ open_rq2.onupgradeneeded = this.step_func(function(e) {
+ db2 = e.target.result;
+
+ db2.createObjectStore("store2");
+
+ var store = open_rq2.transaction.objectStore("store")
+ store.createIndex("index2", "i");
+
+ assert_equals(db2.version, 10, "db2.version");
+
+ assert_true(db2.objectStoreNames.contains("store"), "second objectStoreNames contains store");
+ assert_true(db2.objectStoreNames.contains("store2"), "second objectStoreNames contains store2");
+ assert_true(store.indexNames.contains("index"), "second indexNames contains index");
+ assert_true(store.indexNames.contains("index2"), "second indexNames contains index2");
+
+ store.add({i: "Odin"}, 3);
+ store.put({i: "Sicking"}, 2);
+
+ open_rq2.transaction.abort();
+ });
+ open_rq2.onerror = this.step_func(function(e) {
+ assert_equals(db2.version, 9, "db2.version after error");
+ assert_true(db2.objectStoreNames.contains("store"), "objectStoreNames contains store after error");
+ assert_false(db2.objectStoreNames.contains("store2"), "objectStoreNames not contains store2 after error");
+
+ var open_rq3 = window.indexedDB.open(db.name);
+ open_rq3.onsuccess = this.step_func(function(e) {
+ var db3 = e.target.result;
+
+ assert_true(db3.objectStoreNames.contains("store"), "third objectStoreNames contains store");
+ assert_false(db3.objectStoreNames.contains("store2"), "third objectStoreNames contains store2");
+
+ var st = db3.transaction("store").objectStore("store");
+
+ assert_equals(db3.version, 9, "db3.version");
+
+ assert_true(st.indexNames.contains("index"), "third indexNames contains index");
+ assert_false(st.indexNames.contains("index2"), "third indexNames contains index2");
+
+ st.openCursor(null, "prev").onsuccess = this.step_func(function(e) {
+ assert_equals(e.target.result.key, 2, "opencursor(prev) key");
+ assert_equals(e.target.result.value.i, "Jonas", "opencursor(prev) value");
+ });
+ st.get(3).onsuccess = this.step_func(function(e) {
+ assert_equals(e.target.result, undefined, "get(3)");
+ });
+
+ var idx = st.index("index");
+ idx.getKey("Jonas").onsuccess = this.step_func(function(e) {
+ assert_equals(e.target.result, 2, "getKey(Jonas)");
+ });
+ idx.getKey("Odin").onsuccess = this.step_func(function(e) {
+ assert_equals(e.target.result, undefined, "getKey(Odin)");
+ });
+ idx.getKey("Sicking").onsuccess = this.step_func(function(e) {
+ assert_equals(e.target.result, undefined, "getKey(Sicking)");
+ this.done();
+ });
+ });
+ });
+ };
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbfactory_open11.htm b/testing/web-platform/tests/IndexedDB/idbfactory_open11.htm
new file mode 100644
index 000000000..66ea9d525
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbfactory_open11.htm
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<title>IDBFactory.open() - second open's transaction is available to get objectStores</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db;
+ var count_done = 0;
+ var open_rq = createdb(async_test(document.title, {timeout: 10000}));
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ db.createObjectStore("store");
+ assert_true(db.objectStoreNames.contains("store"), "objectStoreNames contains store");
+
+ var store = e.target.transaction.objectStore("store");
+ assert_equals(store.name, "store", "store.name");
+
+ store.add("data", 1);
+
+ store.count().onsuccess = this.step_func(function(e) {
+ assert_equals(e.target.result, 1, "count()");
+ count_done++;
+ });
+
+ store.add("data2", 2);
+ };
+ open_rq.onsuccess = function(e) {
+ var store = db.transaction("store").objectStore("store");
+ assert_equals(store.name, "store", "store.name");
+ store.count().onsuccess = this.step_func(function(e) {
+ assert_equals(e.target.result, 2, "count()");
+ count_done++;
+ });
+ db.close();
+
+ var open_rq2 = window.indexedDB.open(db.name, 10);
+ open_rq2.onupgradeneeded = this.step_func(function(e) {
+ var db2 = e.target.result;
+ assert_true(db2.objectStoreNames.contains("store"), "objectStoreNames contains store");
+ var store = open_rq2.transaction.objectStore("store");
+ assert_equals(store.name, "store", "store.name");
+
+ store.add("data3", 3);
+
+ store.count().onsuccess = this.step_func(function(e) {
+ assert_equals(e.target.result, 3, "count()");
+ count_done++;
+
+ assert_equals(count_done, 3, "count_done");
+ this.done();
+ });
+ });
+ };
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbfactory_open12.htm b/testing/web-platform/tests/IndexedDB/idbfactory_open12.htm
new file mode 100644
index 000000000..763c48051
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbfactory_open12.htm
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<title>IDBFactory.open() - upgradeneeded gets VersionChangeEvent</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db;
+ var open_rq = createdb(async_test(document.title, {timeout: 10000}), undefined, 9);
+ var open2_t = async_test(document.title + " - second upgrade");
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ assert_true(e instanceof IDBVersionChangeEvent, "e instanceof IDBVersionChangeEvent");
+ assert_equals(e.oldVersion, 0, "oldVersion");
+ assert_equals(e.newVersion, 9, "newVersion");
+ assert_equals(e.type, "upgradeneeded", "event type");
+
+ assert_equals(db.version, 9, "db.version");
+ };
+ open_rq.onsuccess = function(e) {
+ assert_true(e instanceof Event, "e instanceof Event");
+ assert_false(e instanceof IDBVersionChangeEvent, "e not instanceof IDBVersionChangeEvent");
+ assert_equals(e.type, "success", "event type");
+ this.done();
+
+
+ /**
+ * Second test
+ */
+ db.onversionchange = function() { db.close(); };
+
+ var open_rq2 = createdb(open2_t, db.name, 10);
+ open_rq2.onupgradeneeded = function(e) {
+ var db2 = e.target.result;
+ assert_true(e instanceof IDBVersionChangeEvent, "e instanceof IDBVersionChangeEvent");
+ assert_equals(e.oldVersion, 9, "oldVersion");
+ assert_equals(e.newVersion, 10, "newVersion");
+ assert_equals(e.type, "upgradeneeded", "event type");
+
+ assert_equals(db2.version, 10, "new db.version");
+
+ this.done();
+ };
+ };
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbfactory_open2.htm b/testing/web-platform/tests/IndexedDB/idbfactory_open2.htm
new file mode 100644
index 000000000..e4d54ee0a
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbfactory_open2.htm
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<title>IDBFactory.open() - database 'name' and 'version' are correctly set</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var open_rq = createdb(async_test(), 'database_name', 13);
+
+ open_rq.onupgradeneeded = function(e) {};
+ open_rq.onsuccess = function(e) {
+ var db = e.target.result;
+ assert_equals(db.name, 'database_name', 'db.name');
+ assert_equals(db.version, 13, 'db.version');
+ this.done();
+ }
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbfactory_open3.htm b/testing/web-platform/tests/IndexedDB/idbfactory_open3.htm
new file mode 100644
index 000000000..9ec6db5ab
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbfactory_open3.htm
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>IDBFactory.open() - no version opens current database</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var open_rq = createdb(async_test(), undefined, 13);
+ var did_upgrade = false;
+
+ open_rq.onupgradeneeded = function() {};
+ open_rq.onsuccess = function(e) {
+ var db = e.target.result;
+ db.close();
+
+ var open_rq2 = window.indexedDB.open(db.name);
+ open_rq2.onsuccess = this.step_func(function(e) {
+ assert_equals(e.target.result.version, 13, "db.version")
+ this.done();
+ });
+ open_rq2.onupgradeneeded = fail(this, 'Unexpected upgradeneeded')
+ open_rq2.onerror = fail(this, 'Unexpected error')
+ }
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbfactory_open4.htm b/testing/web-platform/tests/IndexedDB/idbfactory_open4.htm
new file mode 100644
index 000000000..15ca666b8
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbfactory_open4.htm
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<title>IDBFactory.open() - new database has default version</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var open_rq = createdb(async_test(), 'database_name');
+
+ open_rq.onupgradeneeded = function(e) {
+ assert_equals(e.target.result.version, 1, "db.version");
+ };
+ open_rq.onsuccess = function(e) {
+ assert_equals(e.target.result.version, 1, "db.version");
+ this.done();
+ };
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbfactory_open5.htm b/testing/web-platform/tests/IndexedDB/idbfactory_open5.htm
new file mode 100644
index 000000000..d9460bb7e
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbfactory_open5.htm
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<title>IDBFactory.open() - new database is empty</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var open_rq = createdb(async_test(), 'database_name');
+
+ open_rq.onupgradeneeded = function() {};
+ open_rq.onsuccess = function(e) {
+ assert_equals(e.target.result.objectStoreNames.length, 0, "objectStoreNames.length");
+ this.done();
+ };
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbfactory_open6.htm b/testing/web-platform/tests/IndexedDB/idbfactory_open6.htm
new file mode 100644
index 000000000..bbb8ac02d
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbfactory_open6.htm
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<title>IDBFactory.open() - open database with a lower version than current</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var open_rq = createdb(async_test(), undefined, 13);
+ var did_upgrade = false;
+
+ open_rq.onupgradeneeded = function() {};
+ open_rq.onsuccess = function(e) {
+ var db = e.target.result;
+ db.close();
+
+ var open_rq2 = window.indexedDB.open(db.name, 14);
+ open_rq2.onupgradeneeded = function() {};
+ open_rq2.onsuccess = this.step_func(open_previous_db);
+ open_rq2.onerror = fail(this, 'Unexpected error')
+ }
+
+ function open_previous_db(e) {
+ var open_rq3 = window.indexedDB.open(e.target.result.name, 13);
+ open_rq3.onerror = this.step_func(function(e) {
+ assert_equals(e.target.error.name, 'VersionError', 'e.target.error.name')
+ this.done();
+ });
+ open_rq3.onupgradeneeded = fail(this, 'Unexpected upgradeneeded')
+ open_rq3.onsuccess = fail(this, 'Unexpected success')
+ }
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbfactory_open7.htm b/testing/web-platform/tests/IndexedDB/idbfactory_open7.htm
new file mode 100644
index 000000000..bd168f755
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbfactory_open7.htm
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<title>IDBFactory.open() - open database with a higher version than current</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var open_rq = createdb(async_test(), undefined, 13);
+ var did_upgrade = false;
+
+ open_rq.onupgradeneeded = function() {};
+ open_rq.onsuccess = function(e) {
+ var db = e.target.result;
+ db.close();
+
+ var open_rq2 = window.indexedDB.open(db.name, 14);
+ open_rq2.onupgradeneeded = function() {
+ did_upgrade = true;
+ };
+ open_rq2.onsuccess = this.step_func(open_current_db);
+ open_rq2.onerror = fail(this, 'Unexpected error')
+ }
+
+ function open_current_db(e) {
+ var open_rq3 = window.indexedDB.open(e.target.result.name);
+ open_rq3.onsuccess = this.step_func(function(e) {
+ assert_equals(e.target.result.version, 14, "db.version")
+ this.done();
+ });
+ open_rq3.onupgradeneeded = fail(this, 'Unexpected upgradeneeded')
+ open_rq3.onerror = fail(this, 'Unexpected error')
+
+ assert_true(did_upgrade, 'did upgrade');
+ }
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbfactory_open8.htm b/testing/web-platform/tests/IndexedDB/idbfactory_open8.htm
new file mode 100644
index 000000000..7e2ac93ec
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbfactory_open8.htm
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>IDBFactory.open() - error in version change transaction aborts open</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var open_rq = createdb(async_test(), undefined, 13);
+ var did_upgrade = false;
+ var did_db_abort = false;
+
+ open_rq.onupgradeneeded = function(e) {
+ did_upgrade = true;
+ e.target.result.onabort = function() {
+ did_db_abort = true;
+ }
+ e.target.transaction.abort();
+ };
+ open_rq.onerror = function(e) {
+ assert_true(did_upgrade);
+ assert_equals(e.target.error.name, 'AbortError', 'target.error');
+ this.done()
+ };
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbfactory_open9.htm b/testing/web-platform/tests/IndexedDB/idbfactory_open9.htm
new file mode 100644
index 000000000..98b1ddeef
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbfactory_open9.htm
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<title>IDBFactory.open() - errors in version argument</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+
+<script>
+function should_throw(val, name) {
+ if (!name) {
+ name = ((typeof val == "object" && val) ? "object" : format_value(val))
+ }
+ test(function() {
+ assert_throws(new TypeError(), function() {
+ window.indexedDB.open('test', val);
+ });
+ }, "Calling open() with version argument " + name + " should throw TypeError.")
+}
+
+should_throw(-1)
+should_throw(-0.5)
+should_throw(0)
+should_throw(0.5)
+should_throw(0.8)
+should_throw(0x20000000000000) // Number.MAX_SAFE_INTEGER + 1
+should_throw(NaN)
+should_throw(Infinity)
+should_throw(-Infinity)
+should_throw("foo")
+should_throw(null)
+should_throw(false)
+
+should_throw({
+ toString: function() { assert_unreached("toString should not be called for ToPrimitive [Number]"); },
+ valueOf: function() { return 0; }
+})
+should_throw({
+ toString: function() { return 0; },
+ valueOf: function() { return {}; }
+}, 'object (second)')
+should_throw({
+ toString: function() { return {}; },
+ valueOf: function() { return {}; },
+}, 'object (third)')
+
+
+/* Valid */
+
+function should_work(val, expected_version) {
+ var name = format_value(val);
+ var dbname = 'test-db-does-not-exist';
+ async_test(function(t) {
+ window.indexedDB.deleteDatabase(dbname);
+ var rq = window.indexedDB.open(dbname, val);
+ rq.onupgradeneeded = t.step_func(function() {
+ var db = rq.result;
+ assert_equals(db.version, expected_version, 'version');
+ rq.transaction.abort();
+ });
+ rq.onsuccess = t.unreached_func("open should fail");
+ rq.onerror = t.step_func(function() {
+ t.done()
+ });
+ }, "Calling open() with version argument " + name + " should not throw.")
+}
+
+should_work(1.5, 1)
+should_work(Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER) // 0x20000000000000 - 1
+should_work(undefined, 1)
+
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbindex-multientry-arraykeypath.htm b/testing/web-platform/tests/IndexedDB/idbindex-multientry-arraykeypath.htm
new file mode 100644
index 000000000..3e584a6c4
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbindex-multientry-arraykeypath.htm
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.multiEntry: array keyPath with multiEntry</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#key-construct">
+<link rel=assert title="XXX">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ createdb(async_test(document.title, {timeout: 10000})).onupgradeneeded = function(e) {
+ var store = e.target.result.createObjectStore("store");
+
+ assert_throws('InvalidAccessError', function() {
+ store.createIndex('actors', ['name'], { multiEntry: true })
+ });
+
+ this.done();
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbindex-multientry-big.htm b/testing/web-platform/tests/IndexedDB/idbindex-multientry-big.htm
new file mode 100644
index 000000000..4f9df36e2
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbindex-multientry-big.htm
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.multiEntry - a 1000 entry multiEntry array</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#key-construct">
+<link rel=assert title="XXX">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t_add = async_test("Adding one item with 1000 multiEntry keys", { timeout: 10000 }),
+ t_get = async_test("Getting the one item by 1000 indeced keys ", { timeout: 10000 });
+
+ var open_rq = createdb(t_add);
+ var obj = { test: 'yo', idxkeys: [] };
+
+ for (var i = 0; i < 1000; i++)
+ obj.idxkeys.push('index_no_' + i);
+
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ db.createObjectStore('store')
+ .createIndex('index', 'idxkeys', { multiEntry: true });
+ };
+ open_rq.onsuccess = function(e) {
+ var tx = db.transaction('store', 'readwrite');
+ tx.objectStore('store')
+ .put(obj, 1)
+ .onsuccess = t_add.step_func(function(e)
+ {
+ assert_equals(e.target.result, 1, "put'd key");
+ this.done();
+ });
+
+ tx.oncomplete = t_get.step_func(function() {
+ var idx = db.transaction('store').objectStore('store').index('index')
+
+ for (var i = 0; i < 1000; i++)
+ {
+ idx.get('index_no_' + i).onsuccess = t_get.step_func(function(e) {
+ assert_equals(e.target.result.test, "yo");
+ });
+ }
+
+ idx.get('index_no_999').onsuccess = t_get.step_func(function(e) {
+ assert_equals(e.target.result.test, "yo");
+ assert_equals(e.target.result.idxkeys.length, 1000);
+ this.done();
+ });
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbindex-multientry.htm b/testing/web-platform/tests/IndexedDB/idbindex-multientry.htm
new file mode 100644
index 000000000..5077f4846
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbindex-multientry.htm
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.multiEntry - adding keys</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#key-construct">
+<link rel=assert title="XXX">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ expected_keys = [1, 2, 2, 3, 3];
+
+ var open_rq = createdb(async_test(document.title, {timeout: 10000}))
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var store = db.createObjectStore("store")
+
+ store.createIndex('actors', 'name', { multiEntry: true })
+
+ store.add({name: 'Odin'}, 1);
+ store.add({name: ['Rita', 'Scheeta', {Bobby:'Bobby'}]}, 2);
+ store.add({name: [ {s: 'Robert'}, 'Neil', 'Bobby']}, 3);
+ };
+ open_rq.onsuccess = function(e) {
+ var gotten_keys = [];
+ var idx = db.transaction('store').objectStore('store').index('actors');
+
+ idx.getKey('Odin').onsuccess = this.step_func(function(e) {
+ gotten_keys.push(e.target.result)
+ });
+ idx.getKey('Rita').onsuccess = this.step_func(function(e) {
+ gotten_keys.push(e.target.result)
+ });
+ idx.getKey('Scheeta').onsuccess = this.step_func(function(e) {
+ gotten_keys.push(e.target.result)
+ });
+ idx.getKey('Neil').onsuccess = this.step_func(function(e) {
+ gotten_keys.push(e.target.result)
+ });
+ idx.getKey('Bobby').onsuccess = this.step_func(function(e) {
+ gotten_keys.push(e.target.result)
+
+ assert_array_equals(gotten_keys, expected_keys);
+ this.done();
+ });
+ }
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbindex-rename-abort.html b/testing/web-platform/tests/IndexedDB/idbindex-rename-abort.html
new file mode 100644
index 000000000..f8dca5202
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbindex-rename-abort.html
@@ -0,0 +1,110 @@
+<!DOCTYPE html>
+<title>IndexedDB: index renaming support in aborted transactions</title>
+<link rel="help"
+ href="https://w3c.github.io/IndexedDB/#dom-idbindex-name">
+<link rel="author" href="pwnall@chromium.org" title="Victor Costan">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support-promises.js"></script>
+<script>
+
+promise_test(testCase => {
+ const dbName = databaseName(testCase);
+ let authorIndex = null, authorIndex2 = null;
+ return createDatabase(testCase, (database, transaction) => {
+ createBooksStore(testCase, database);
+ }).then(database => {
+ database.close();
+ }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
+ const store = transaction.objectStore('books');
+ authorIndex = store.index('by_author');
+ authorIndex.name = 'renamed_by_author';
+
+ transaction.abort();
+
+ assert_equals(
+ authorIndex.name, 'by_author',
+ 'IDBIndex.name should not reflect the rename any more ' +
+ 'immediately after transaction.abort() returns');
+ assert_array_equals(
+ store.indexNames, ['by_author', 'by_title'],
+ 'IDBObjectStore.indexNames should not reflect the rename any ' +
+ 'more immediately after transaction.abort() returns');
+ })).then(event => {
+ assert_equals(
+ authorIndex.name, 'by_author',
+ 'IDBIndex.name should not reflect the rename any more after the ' +
+ 'versionchange transaction is aborted');
+
+ const request = indexedDB.open(dbName, 1);
+ return requestWatcher(testCase, request).wait_for('success');
+ }).then(event => {
+ const database = event.target.result;
+ const transaction = database.transaction('books', 'readonly');
+ const store = transaction.objectStore('books');
+ assert_array_equals(
+ store.indexNames, ['by_author', 'by_title'],
+ 'IDBDatabase.objectStoreNames should not reflect the rename ' +
+ 'after the versionchange transaction is aborted');
+
+ authorIndex2 = store.index('by_author');
+ return checkAuthorIndexContents(
+ testCase, authorIndex2,
+ 'Aborting an index rename transaction should not change the ' +
+ "index's records").then(() => database.close());
+ }).then(() => {
+ assert_equals(
+ authorIndex.name, 'by_author',
+ 'IDBIndex used in aborted rename transaction should not reflect ' +
+ 'the rename after the transaction is aborted');
+ assert_equals(authorIndex2.name, 'by_author',
+ 'IDBIndex obtained after an aborted rename transaction should ' +
+ 'not reflect the rename');
+ });
+}, 'IndexedDB index rename in aborted transaction');
+
+promise_test(testCase => {
+ const dbName = databaseName(testCase);
+ let authorIndex = null;
+ return createDatabase(testCase, (database, transaction) => {
+ createNotBooksStore(testCase, database);
+ }).then(database => {
+ database.close();
+ }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
+ const store = transaction.objectStore('not_books');
+ authorIndex = store.createIndex('by_author', 'author');
+ authorIndex.name = 'by_author_renamed';
+ authorIndex.name = 'by_author_renamed_again';
+
+ transaction.abort();
+
+ assert_equals(
+ authorIndex.name, 'by_author_renamed_again',
+ 'IDBIndex.name should reflect the last rename immediately after ' +
+ 'transaction.abort() returns');
+ assert_array_equals(
+ store.indexNames, ['not_by_author', 'not_by_title'],
+ 'IDBObjectStore.indexNames should not reflect the creation or ' +
+ 'the rename immediately after transaction.abort() returns');
+ })).then(event => {
+ assert_equals(
+ authorIndex.name, 'by_author_renamed_again',
+ 'IDBIndex.name should reflect the last rename after the ' +
+ 'versionchange transaction is aborted');
+
+ const request = indexedDB.open(dbName, 1);
+ return requestWatcher(testCase, request).wait_for('success');
+ }).then(event => {
+ const database = event.target.result;
+ const transaction = database.transaction('not_books', 'readonly');
+ const store = transaction.objectStore('not_books');
+ assert_array_equals(
+ store.indexNames, ['not_by_author', 'not_by_title'],
+ 'IDBDatabase.objectStoreNames should not reflect the creation or ' +
+ 'the rename after the versionchange transaction is aborted');
+
+ database.close();
+ });
+}, 'IndexedDB index creation and rename in an aborted transaction');
+
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/idbindex-rename-errors.html b/testing/web-platform/tests/IndexedDB/idbindex-rename-errors.html
new file mode 100644
index 000000000..1f50f36c6
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbindex-rename-errors.html
@@ -0,0 +1,130 @@
+<!DOCTYPE html>
+<title>IndexedDB: index renaming error handling</title>
+<link rel="help"
+ href="https://w3c.github.io/IndexedDB/#dom-idbindex-name">
+<link rel="author" href="pwnall@chromium.org" title="Victor Costan">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support-promises.js"></script>
+<script>
+
+promise_test(testCase => {
+ return createDatabase(testCase, (database, transaction) => {
+ createBooksStore(testCase, database);
+ }).then(database => {
+ database.close();
+ }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
+ const store = transaction.objectStore('books');
+ const index = store.index('by_author');
+ store.deleteIndex('by_author');
+ assert_throws(
+ 'InvalidStateError', () => index.name = 'renamed_by_author');
+ })).then(database => database.close());
+}, 'IndexedDB deleted index rename throws');
+
+promise_test(testCase => {
+ return createDatabase(testCase, (database, transaction) => {
+ createBooksStore(testCase, database);
+ }).then(database => {
+ const transaction = database.transaction('books', 'readonly');
+ const store = transaction.objectStore('books');
+ const index = store.index('by_author');
+
+ assert_throws(
+ 'InvalidStateError', () => index.name = 'renamed_by_author');
+ database.close();
+ });
+}, 'IndexedDB index rename throws in a readonly transaction');
+
+promise_test(testCase => {
+ return createDatabase(testCase, (database, transaction) => {
+ createBooksStore(testCase, database);
+ }).then(database => {
+ const transaction = database.transaction('books', 'readwrite');
+ const store = transaction.objectStore('books');
+ const index = store.index('by_author');
+
+ assert_throws(
+ 'InvalidStateError', () => index.name = 'renamed_by_author');
+ database.close();
+ });
+}, 'IndexedDB index rename throws in a readwrite transaction');
+
+promise_test(testCase => {
+ let authorIndex = null;
+ return createDatabase(testCase, (database, transaction) => {
+ const store = createBooksStore(testCase, database);
+ authorIndex = store.index('by_author');
+ }).then(database => {
+ assert_throws(
+ 'TransactionInactiveError',
+ () => authorIndex.name = 'renamed_by_author');
+ database.close();
+ });
+}, 'IndexedDB index rename throws in an inactive transaction');
+
+promise_test(testCase => {
+ return createDatabase(testCase, (database, transaction) => {
+ createBooksStore(testCase, database);
+ }).then(database => {
+ database.close();
+ }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
+ const store = transaction.objectStore('books');
+ const index = store.index('by_author');
+
+ assert_throws('ConstraintError', () => index.name = 'by_title');
+ assert_array_equals(
+ store.indexNames, ['by_author', 'by_title'],
+ 'An index rename that throws an exception should not change the ' +
+ "index's IDBObjectStore.indexNames");
+ })).then(database => {
+ const transaction = database.transaction('books', 'readonly');
+ const store = transaction.objectStore('books');
+ assert_array_equals(
+ store.indexNames, ['by_author', 'by_title'],
+ 'Committing a transaction with a failed store rename attempt ' +
+ "should not change the index's IDBObjectStore.indexNames");
+ const index = store.index('by_author');
+ return checkAuthorIndexContents(
+ testCase, index,
+ 'Committing a transaction with a failed rename attempt should ' +
+ "not change the index's contents").then(() => database.close());
+ });
+}, 'IndexedDB index rename to the name of another index throws');
+
+promise_test(testCase => {
+ return createDatabase(testCase, (database, transaction) => {
+ createBooksStore(testCase, database);
+ }).then(database => {
+ database.close();
+ }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
+ const store = transaction.objectStore('books');
+ const index = store.index('by_author');
+
+ assert_throws(
+ { name: 'Custom stringifying error' },
+ () => {
+ index.name = {
+ toString: () => { throw { name: 'Custom stringifying error'}; }
+ };
+ }, 'IDBObjectStore rename should re-raise toString() exception');
+ assert_array_equals(
+ store.indexNames, ['by_author', 'by_title'],
+ 'An index rename that throws an exception should not change the ' +
+ "index's IDBObjectStore.indexNames");
+ })).then(database => {
+ const transaction = database.transaction('books', 'readonly');
+ const store = transaction.objectStore('books');
+ assert_array_equals(
+ store.indexNames, ['by_author', 'by_title'],
+ 'Committing a transaction with a failed store rename attempt ' +
+ "should not change the index's IDBObjectStore.indexNames");
+ const index = store.index('by_author');
+ return checkAuthorIndexContents(
+ testCase, index,
+ 'Committing a transaction with a failed rename attempt should ' +
+ "not change the index's contents").then(() => database.close());
+ });
+}, 'IndexedDB index rename handles exceptions when stringifying names');
+
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/idbindex-rename.html b/testing/web-platform/tests/IndexedDB/idbindex-rename.html
new file mode 100644
index 000000000..370b83e53
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbindex-rename.html
@@ -0,0 +1,299 @@
+<!DOCTYPE html>
+<meta name="timeout" content="long">
+<title>IndexedDB: index renaming support</title>
+<link rel="help"
+ href="https://w3c.github.io/IndexedDB/#dom-idbindex-name">
+<link rel="author" href="pwnall@chromium.org" title="Victor Costan">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support-promises.js"></script>
+<script>
+
+promise_test(testCase => {
+ let authorIndex = null, authorIndex2 = null;
+ let renamedAuthorIndex = null, renamedAuthorIndex2 = null;
+ return createDatabase(testCase, (database, transaction) => {
+ const store = createBooksStore(testCase, database);
+ authorIndex = store.index('by_author');
+ }).then(database => {
+ const transaction = database.transaction('books', 'readonly');
+ const store = transaction.objectStore('books');
+ assert_array_equals(
+ store.indexNames, ['by_author', 'by_title'],
+ 'Test setup should have created two indexes');
+ authorIndex2 = store.index('by_author');
+ return checkAuthorIndexContents(
+ testCase, authorIndex2,
+ 'The index should have the expected contents before any renaming').
+ then(() => database.close());
+ }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
+ const store = transaction.objectStore('books');
+ renamedAuthorIndex = store.index('by_author');
+ renamedAuthorIndex.name = 'renamed_by_author';
+
+ assert_equals(
+ renamedAuthorIndex.name, 'renamed_by_author',
+ 'IDBIndex name should change immediately after a rename');
+ assert_array_equals(
+ store.indexNames, ['by_title', 'renamed_by_author'],
+ 'IDBObjectStore.indexNames should immediately reflect the rename');
+ assert_equals(
+ store.index('renamed_by_author'), renamedAuthorIndex,
+ 'IDBObjectStore.index should return the renamed index store when ' +
+ 'queried using the new name immediately after the rename');
+ assert_throws(
+ 'NotFoundError', () => store.index('by_author'),
+ 'IDBObjectStore.index should throw when queried using the ' +
+ "renamed index's old name immediately after the rename");
+ })).then(database => {
+ const transaction = database.transaction('books', 'readonly');
+ const store = transaction.objectStore('books');
+ assert_array_equals(
+ store.indexNames, ['by_title', 'renamed_by_author'],
+ 'IDBObjectStore.indexNames should still reflect the rename after ' +
+ 'the versionchange transaction commits');
+ renamedAuthorIndex2 = store.index('renamed_by_author');
+ return checkAuthorIndexContents(
+ testCase, renamedAuthorIndex2,
+ 'Renaming an index should not change its contents').then(
+ () => database.close());
+ }).then(() => {
+ assert_equals(
+ authorIndex.name, 'by_author',
+ 'IDBIndex obtained before the rename transaction should not ' +
+ 'reflect the rename');
+ assert_equals(
+ authorIndex2.name, 'by_author',
+ 'IDBIndex obtained before the rename transaction should not ' +
+ 'reflect the rename');
+ assert_equals(
+ renamedAuthorIndex.name, 'renamed_by_author',
+ 'IDBIndex used in the rename transaction should keep reflecting ' +
+ 'the new name after the transaction is committed');
+ assert_equals(
+ renamedAuthorIndex2.name, 'renamed_by_author',
+ 'IDBIndex obtained after the rename transaction should reflect ' +
+ 'the new name');
+ });
+}, 'IndexedDB index rename in new transaction');
+
+promise_test(testCase => {
+ let renamedAuthorIndex = null, renamedAuthorIndex2 = null;
+ return createDatabase(testCase, (database, transaction) => {
+ const store = createBooksStore(testCase, database);
+ renamedAuthorIndex = store.index('by_author');
+ renamedAuthorIndex.name = 'renamed_by_author';
+
+ assert_equals(
+ renamedAuthorIndex.name, 'renamed_by_author',
+ 'IDBIndex name should change immediately after a rename');
+ assert_array_equals(
+ store.indexNames, ['by_title', 'renamed_by_author'],
+ 'IDBObjectStore.indexNames should immediately reflect the rename');
+ assert_equals(
+ store.index('renamed_by_author'), renamedAuthorIndex,
+ 'IDBObjectStore.index should return the renamed index store when ' +
+ 'queried using the new name immediately after the rename');
+ assert_throws(
+ 'NotFoundError', () => store.index('by_author'),
+ 'IDBObjectStore.index should throw when queried using the ' +
+ "renamed index's old name immediately after the rename");
+ }).then(database => {
+ const transaction = database.transaction('books', 'readonly');
+ const store = transaction.objectStore('books');
+ assert_array_equals(
+ store.indexNames, ['by_title', 'renamed_by_author'],
+ 'IDBObjectStore.indexNames should still reflect the rename after ' +
+ 'the versionchange transaction commits');
+ renamedAuthorIndex2 = store.index('renamed_by_author');
+ return checkAuthorIndexContents(
+ testCase, renamedAuthorIndex2,
+ 'Renaming an index should not change its contents').then(
+ () => database.close());
+ }).then(() => {
+ assert_equals(
+ renamedAuthorIndex.name, 'renamed_by_author',
+ 'IDBIndex used in the rename transaction should keep reflecting ' +
+ 'the new name after the transaction is committed');
+ assert_equals(
+ renamedAuthorIndex2.name, 'renamed_by_author',
+ 'IDBIndex obtained after the rename transaction should reflect ' +
+ 'the new name');
+ });
+}, 'IndexedDB index rename in the transaction where it is created');
+
+promise_test(testCase => {
+ return createDatabase(testCase, (database, transaction) => {
+ createBooksStore(testCase, database);
+ }).then(database => {
+ database.close();
+ }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
+ const store = transaction.objectStore('books');
+ const index = store.index('by_author');
+ index.name = 'by_author';
+ assert_array_equals(
+ store.indexNames, ['by_author', 'by_title'],
+ 'Renaming an index to the same name should not change the ' +
+ "index's IDBObjectStore.indexNames");
+ })).then(database => {
+ const transaction = database.transaction('books', 'readonly');
+ const store = transaction.objectStore('books');
+ assert_array_equals(
+ store.indexNames, ['by_author', 'by_title'],
+ 'Committing a transaction that renames a store to the same name ' +
+ "should not change the index's IDBObjectStore.indexNames");
+ const index = store.index('by_author');
+ return checkAuthorIndexContents(
+ testCase, index,
+ 'Committing a transaction that renames an index to the same name ' +
+ "should not change the index's contents").then(
+ () => database.close());
+ });
+}, 'IndexedDB index rename to the same name succeeds');
+
+promise_test(testCase => {
+ return createDatabase(testCase, (database, transaction) => {
+ createBooksStore(testCase, database);
+ }).then(database => {
+ database.close();
+ }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
+ const store = transaction.objectStore('books');
+ const index = store.index('by_author');
+ store.deleteIndex('by_title');
+ index.name = 'by_title';
+ assert_array_equals(
+ store.indexNames, ['by_title'],
+ 'IDBObjectStore.indexNames should immediately reflect the rename');
+ })).then(database => {
+ const transaction = database.transaction('books', 'readonly');
+ const store = transaction.objectStore('books');
+ assert_array_equals(
+ store.indexNames, ['by_title'],
+ 'IDBObjectStore.indexNames should still reflect the rename after ' +
+ 'the versionchange transaction commits');
+ const index = store.index('by_title');
+ return checkAuthorIndexContents(
+ testCase, index,
+ 'Renaming an index should not change its contents').then(
+ () => database.close());
+ });
+}, 'IndexedDB index rename to the name of a deleted index succeeds');
+
+promise_test(testCase => {
+ return createDatabase(testCase, (database, transaction) => {
+ createBooksStore(testCase, database);
+ }).then(database => {
+ database.close();
+ }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
+ const store = transaction.objectStore('books');
+ store.index('by_author').name = 'tmp';
+ store.index('by_title').name = 'by_author';
+ store.index('tmp').name = 'by_title';
+ assert_array_equals(
+ store.indexNames, ['by_author', 'by_title'],
+ 'IDBObjectStore.indexNames should reflect the swap immediately ' +
+ 'after the renames');
+ return checkTitleIndexContents(
+ testCase, store.index('by_author'),
+ 'Renaming an index should not change its contents');
+ })).then(database => {
+ const transaction = database.transaction('books', 'readonly');
+ const store = transaction.objectStore('books');
+ assert_array_equals(
+ store.indexNames, ['by_author', 'by_title'],
+ 'IDBObjectStore.indexNames should still reflect the swap after ' +
+ 'the versionchange transaction commits');
+ const index = store.index('by_title');
+ return checkAuthorIndexContents(
+ testCase, index,
+ 'Renaming an index should not change its contents').then(
+ () => database.close());
+ });
+}, 'IndexedDB index swapping via renames succeeds');
+
+promise_test(testCase => {
+ return createDatabase(testCase, (database, transaction) => {
+ createBooksStore(testCase, database);
+ }).then(database => {
+ database.close();
+ }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
+ const store = transaction.objectStore('books');
+ const index = store.index('by_author');
+
+ index.name = 42;
+ assert_equals(index.name, '42',
+ 'IDBIndex name should change immediately after a rename to a ' +
+ 'number');
+ assert_array_equals(
+ store.indexNames, ['42', 'by_title'],
+ 'IDBObjectStore.indexNames should immediately reflect the ' +
+ 'stringifying rename');
+
+ index.name = true;
+ assert_equals(index.name, 'true',
+ 'IDBIndex name should change immediately after a rename to a ' +
+ 'boolean');
+
+ index.name = {};
+ assert_equals(index.name, '[object Object]',
+ 'IDBIndex name should change immediately after a rename to an ' +
+ 'object');
+
+ index.name = () => null;
+ assert_equals(index.name, '() => null',
+ 'IDBIndex name should change immediately after a rename to a ' +
+ 'function');
+
+ index.name = undefined;
+ assert_equals(index.name, 'undefined',
+ 'IDBIndex name should change immediately after a rename to ' +
+ 'undefined');
+ })).then(database => {
+ const transaction = database.transaction('books', 'readonly');
+ const store = transaction.objectStore('books');
+ assert_array_equals(
+ store.indexNames, ['by_title', 'undefined'],
+ 'IDBObjectStore.indexNames should reflect the last rename ' +
+ 'after the versionchange transaction commits');
+ const index = store.index('undefined');
+ return checkAuthorIndexContents(
+ testCase, index,
+ 'Renaming an index should not change its contents').then(
+ () => database.close());
+ });
+}, 'IndexedDB index rename stringifies non-string names');
+
+for (let escapedName of ['', '\\u0000', '\\uDC00\\uD800']) ((escapedName) => {
+ const name = JSON.parse('"' + escapedName + '"');
+ promise_test(testCase => {
+ return createDatabase(testCase, (database, transaction) => {
+ createBooksStore(testCase, database);
+ }).then(database => {
+ database.close();
+ }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
+ const store = transaction.objectStore('books');
+ const index = store.index('by_author');
+
+ index.name = name;
+ assert_equals(index.name, name,
+ 'IDBIndex name should change immediately after the rename');
+ assert_array_equals(
+ store.indexNames, [name, 'by_title'].sort(),
+ 'IDBObjectStore.indexNames should immediately reflect the rename');
+ })).then(database => {
+ const transaction = database.transaction('books', 'readonly');
+ const store = transaction.objectStore('books');
+ assert_array_equals(
+ store.indexNames, [name, 'by_title'].sort(),
+ 'IDBObjectStore.indexNames should reflect the rename ' +
+ 'after the versionchange transaction commits');
+ const index = store.index(name);
+ return checkAuthorIndexContents(
+ testCase, index,
+ 'Renaming an index should not change its contents').then(
+ () => database.close());
+ });
+ }, 'IndexedDB index can be renamed to "' + escapedName + '"');
+})(escapedName);
+
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/idbindex_count.htm b/testing/web-platform/tests/IndexedDB/idbindex_count.htm
new file mode 100644
index 000000000..1b84ef9b7
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbindex_count.htm
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>IDBIndex.count() - returns the number of records in the index </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db, t = async_test();
+
+ var open_rq = createdb(t);
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var store = db.createObjectStore("store", { autoIncrement: true });
+ store.createIndex("index", "indexedProperty");
+
+ for(var i = 0; i < 10; i++) {
+ store.add({ indexedProperty: "data" + i });
+ }
+ }
+
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("store")
+ .objectStore("store")
+ .index("index")
+ .count();
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, 10);
+ t.done();
+ });
+ }
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbindex_count2.htm b/testing/web-platform/tests/IndexedDB/idbindex_count2.htm
new file mode 100644
index 000000000..1494fe116
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbindex_count2.htm
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>IDBIndex.count() - returns the number of records that have keys within the range </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db, t = async_test();
+
+ var open_rq = createdb(t);
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var store = db.createObjectStore("store", { autoIncrement: true });
+ store.createIndex("index", "indexedProperty");
+
+ for(var i = 0; i < 10; i++) {
+ store.add({ indexedProperty: "data" + i });
+ }
+ }
+
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("store")
+ .objectStore("store")
+ .index("index")
+ .count(IDBKeyRange.bound('data0', 'data4'));
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, 5);
+ t.done();
+ });
+ }
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbindex_count3.htm b/testing/web-platform/tests/IndexedDB/idbindex_count3.htm
new file mode 100644
index 000000000..7fb34347c
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbindex_count3.htm
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>IDBIndex.count() - returns the number of records that have keys with the key</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db
+
+ createdb(async_test()).onupgradeneeded = function(e) {
+ db = e.target.result
+
+ var store = db.createObjectStore("store", { autoIncrement: true })
+ store.createIndex("myindex", "idx")
+
+ for (var i = 0; i < 10; i++)
+ store.add({ idx: "data_" + (i%2) });
+
+ store.index("myindex").count("data_0").onsuccess = this.step_func(function(e) {
+ assert_equals(e.target.result, 5, "count(data_0)")
+ this.done()
+ })
+ }
+
+</script>
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbindex_count4.htm b/testing/web-platform/tests/IndexedDB/idbindex_count4.htm
new file mode 100644
index 000000000..addd99260
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbindex_count4.htm
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.count() - throw DataError when using invalid key</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBIndex-count-IDBRequest-any-key">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db, t = async_test();
+
+ var open_rq = createdb(t);
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var store = db.createObjectStore("store", { autoIncrement: true });
+ store.createIndex("index", "indexedProperty");
+
+ for(var i = 0; i < 10; i++) {
+ store.add({ indexedProperty: "data" + i });
+ }
+ }
+
+ open_rq.onsuccess = function(e) {
+ var index = db.transaction("store")
+ .objectStore("store")
+ .index("index");
+
+ assert_throws("DataError", function() {
+ index.count(NaN);
+ });
+
+ t.done();
+ }
+</script>
+
diff --git a/testing/web-platform/tests/IndexedDB/idbindex_get.htm b/testing/web-platform/tests/IndexedDB/idbindex_get.htm
new file mode 100644
index 000000000..835cbefd2
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbindex_get.htm
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.get() - returns the record </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { key: 1, indexedProperty: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { keyPath: "key" });
+ index = objStore.createIndex("index", "indexedProperty");
+
+ objStore.add(record);
+ }
+
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("store")
+ .objectStore("store")
+ .index("index")
+ .get(record.indexedProperty);
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result.key, record.key);
+ t.done();
+ });
+ }
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbindex_get2.htm b/testing/web-platform/tests/IndexedDB/idbindex_get2.htm
new file mode 100644
index 000000000..52b1d371e
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbindex_get2.htm
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.get() - returns the record where the index contains duplicate values </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ records = [ { key:1, indexedProperty:"data" },
+ { key:2, indexedProperty:"data" },
+ { key:3, indexedProperty:"data" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", { keyPath: "key" });
+ objStore.createIndex("index", "indexedProperty");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("test")
+ .objectStore("test")
+ .index("index")
+ .get("data");
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result.key, records[0].key);
+ t.done();
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbindex_get3.htm b/testing/web-platform/tests/IndexedDB/idbindex_get3.htm
new file mode 100644
index 000000000..d0f900789
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbindex_get3.htm
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.get() - attempt to retrieve a record that doesn't exist </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var rq = db.createObjectStore("test", { keyPath: "key" })
+ .createIndex("index", "indexedProperty")
+ .get(1);
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, undefined);
+ t.done();
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbindex_get4.htm b/testing/web-platform/tests/IndexedDB/idbindex_get4.htm
new file mode 100644
index 000000000..bd0cc5ec8
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbindex_get4.htm
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>IDBIndex.get() - returns the record with the first key in the range </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db, t = async_test();
+
+ var open_rq = createdb(t);
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var store = db.createObjectStore("store", { keyPath: "key" });
+ store.createIndex("index", "indexedProperty");
+
+ for(var i = 0; i < 10; i++) {
+ store.add({ key: i, indexedProperty: "data" + i });
+ }
+ }
+
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("store")
+ .objectStore("store")
+ .index("index")
+ .get(IDBKeyRange.bound('data4', 'data7'));
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result.key, 4);
+ assert_equals(e.target.result.indexedProperty, 'data4');
+
+ setTimeout(function() { t.done(); }, 4)
+ });
+ }
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbindex_get5.htm b/testing/web-platform/tests/IndexedDB/idbindex_get5.htm
new file mode 100644
index 000000000..65e2623cd
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbindex_get5.htm
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.get() - throw DataError when using invalid key </title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBIndex-get-IDBRequest-any-key">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var index = db.createObjectStore("test", { keyPath: "key" })
+ .createIndex("index", "indexedProperty");
+ assert_throws("DataError",function(){
+ index.get(NaN);
+ });
+ t.done();
+ };
+</script>
+
diff --git a/testing/web-platform/tests/IndexedDB/idbindex_get6.htm b/testing/web-platform/tests/IndexedDB/idbindex_get6.htm
new file mode 100644
index 000000000..c7f6b92fe
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbindex_get6.htm
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.get() - throw InvalidStateError when the index is deleted</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBIndex-get-IDBRequest-any-key">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var store = db.createObjectStore("store", { keyPath: "key" });
+ var index = store.createIndex("index", "indexedProperty");
+
+ store.add({ key: 1, indexedProperty: "data" });
+ store.deleteIndex("index");
+
+ assert_throws("InvalidStateError", function(){
+ index.get("data");
+ });
+ t.done();
+ }
+</script>
+
diff --git a/testing/web-platform/tests/IndexedDB/idbindex_get7.htm b/testing/web-platform/tests/IndexedDB/idbindex_get7.htm
new file mode 100644
index 000000000..e28fed4c5
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbindex_get7.htm
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.get() - throw TransactionInactiveError on aborted transaction</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBIndex-get-IDBRequest-any-key">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var store = db.createObjectStore("store", { keyPath: "key" });
+ var index = store.createIndex("index", "indexedProperty");
+ store.add({ key: 1, indexedProperty: "data" });
+ }
+ open_rq.onsuccess = function(e) {
+ db = e.target.result;
+ var tx = db.transaction('store');
+ var index = tx.objectStore('store').index('index');
+ tx.abort();
+
+ assert_throws("TransactionInactiveError", function(){
+ index.get("data");
+ });
+ t.done();
+ }
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/idbindex_get8.htm b/testing/web-platform/tests/IndexedDB/idbindex_get8.htm
new file mode 100644
index 000000000..ef67c6d6d
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbindex_get8.htm
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.get() - throw InvalidStateError on index deleted by aborted upgrade</title>
+<link rel="help" href="https://w3c.github.io/IndexedDB/#dom-idb">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var store = db.createObjectStore("store", { keyPath: "key" });
+ var index = store.createIndex("index", "indexedProperty");
+ store.add({ key: 1, indexedProperty: "data" });
+
+ e.target.transaction.abort();
+
+ assert_throws("InvalidStateError", function(){
+ index.get("data");
+ });
+ t.done();
+ }
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/idbindex_getAll.html b/testing/web-platform/tests/IndexedDB/idbindex_getAll.html
new file mode 100644
index 000000000..507b6c9f8
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbindex_getAll.html
@@ -0,0 +1,232 @@
+<!DOCTYPE html>
+<title>IndexedDB: Test IDBIndex.getAll.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+setup({explicit_done: true});
+
+var alphabet = 'abcdefghijklmnopqrstuvwxyz'.split('');
+var ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
+
+function doSetup(dbName, dbVersion, onsuccess) {
+ var delete_request = indexedDB.deleteDatabase(dbName);
+ delete_request.onerror = function() {
+ assert_unreached('deleteDatabase should not fail');
+ };
+ delete_request.onsuccess = function(e) {
+ var req = indexedDB.open(dbName, dbVersion);
+ req.onsuccess = onsuccess;
+ req.onerror = function() {
+ assert_unreached('open should not fail');
+ };
+ req.onupgradeneeded = function(evt) {
+ var connection = evt.target.result;
+
+ var store = connection.createObjectStore('generated',
+ {autoIncrement: true, keyPath: 'id'});
+ var index = store.createIndex('test_idx', 'upper');
+ alphabet.forEach(function(letter) {
+ store.put({ch: letter, upper: letter.toUpperCase()});
+ });
+
+ store = connection.createObjectStore('out-of-line', null);
+ index = store.createIndex('test_idx', 'upper');
+ alphabet.forEach(function(letter) {
+ store.put({ch: letter, upper: letter.toUpperCase()}, letter);
+ });
+
+ store = connection.createObjectStore('out-of-line-not-unique', null);
+ index = store.createIndex('test_idx', 'half');
+ alphabet.forEach(function(letter) {
+ if (letter <= 'm')
+ store.put({ch: letter, half: 'first'}, letter);
+ else
+ store.put({ch: letter, half: 'second'}, letter);
+ });
+
+ store = connection.createObjectStore('out-of-line-multi', null);
+ index = store.createIndex('test_idx', 'attribs', {multiEntry: true});
+ alphabet.forEach(function(letter) {
+ attrs = [];
+ if (['a', 'e', 'i', 'o', 'u'].indexOf(letter) != -1)
+ attrs.push('vowel');
+ else
+ attrs.push('consonant');
+ if (letter == 'a')
+ attrs.push('first');
+ if (letter == 'z')
+ attrs.push('last');
+ store.put({ch: letter, attribs: attrs}, letter);
+ });
+
+ store = connection.createObjectStore('empty', null);
+ index = store.createIndex('test_idx', 'upper');
+ };
+ };
+}
+
+function createGetAllRequest(t, storeName, connection, range, maxCount) {
+ var transaction = connection.transaction(storeName, 'readonly');
+ var store = transaction.objectStore(storeName);
+ var index = store.index('test_idx');
+ var req = index.getAll(range, maxCount);
+ req.onerror = t.unreached_func('getAll request should succeed');
+ return req;
+}
+
+doSetup(location.pathname + '-IDBIndex.getAll', 1, function(evt) {
+ var connection = evt.target.result;
+ async_test(function(t) {
+ var req = createGetAllRequest(t, 'out-of-line', connection, 'C');
+ req.onsuccess = t.step_func(function(evt) {
+ var data = evt.target.result;
+ assert_class_string(data, 'Array', 'result should be an array');
+ assert_array_equals(data.map(function(e) { return e.ch; }), ['c']);
+ assert_array_equals(data.map(function(e) { return e.upper; }), ['C']);
+ t.done();
+ });
+ }, 'Single item get');
+
+ async_test(function(t) {
+ var req = createGetAllRequest(t, 'empty', connection);
+ req.onsuccess = t.step_func(function(evt) {
+ assert_array_equals(evt.target.result, [],
+ 'getAll() on empty object store should return an empty array');
+ t.done();
+ });
+ }, 'Empty object store');
+
+ async_test(function(t) {
+ var req = createGetAllRequest(t, 'out-of-line', connection);
+ req.onsuccess = t.step_func(function(evt) {
+ var data = evt.target.result;
+ assert_class_string(data, 'Array', 'result should be an array');
+ assert_array_equals(data.map(function(e) { return e.ch; }), alphabet);
+ assert_array_equals(data.map(function(e) { return e.upper; }), ALPHABET);
+ t.done();
+ });
+ }, 'Get all keys');
+
+ async_test(function(t) {
+ var req = createGetAllRequest(t, 'out-of-line', connection, undefined,
+ 10);
+ req.onsuccess = t.step_func(function(evt) {
+ var data = evt.target.result;
+ assert_class_string(data, 'Array', 'result should be an array');
+ assert_array_equals(data.map(function(e) { return e.ch; }), 'abcdefghij'.split(''));
+ assert_array_equals(data.map(function(e) { return e.upper; }), 'ABCDEFGHIJ'.split(''));
+ t.done();
+ });
+ }, 'maxCount=10');
+
+ async_test(function(t) {
+ var req = createGetAllRequest(t, 'out-of-line', connection,
+ IDBKeyRange.bound('G', 'M'));
+ req.onsuccess = t.step_func(function(evt) {
+ var data = evt.target.result;
+ assert_array_equals(data.map(function(e) { return e.ch; }), 'ghijklm'.split(''));
+ assert_array_equals(data.map(function(e) { return e.upper; }), 'GHIJKLM'.split(''));
+ t.done();
+ });
+ }, 'Get bound range');
+
+ async_test(function(t) {
+ var req = createGetAllRequest(t, 'out-of-line', connection,
+ IDBKeyRange.bound('G', 'M'), 3);
+ req.onsuccess = t.step_func(function(evt) {
+ var data = evt.target.result;
+ assert_class_string(data, 'Array', 'result should be an array');
+ assert_array_equals(data.map(function(e) { return e.ch; }), 'ghi'.split(''));
+ assert_array_equals(data.map(function(e) { return e.upper; }), 'GHI'.split(''));
+ t.done();
+ });
+ }, 'Get bound range with maxCount');
+
+ async_test(function(t) {
+ var req = createGetAllRequest(t, 'out-of-line', connection,
+ IDBKeyRange.bound('G', 'K', false, true));
+ req.onsuccess = t.step_func(function(evt) {
+ var data = evt.target.result;
+ assert_class_string(data, 'Array', 'result should be an array');
+ assert_array_equals(data.map(function(e) { return e.ch; }), 'ghij'.split(''));
+ assert_array_equals(data.map(function(e) { return e.upper; }), 'GHIJ'.split(''));
+ t.done();
+ });
+ }, 'Get upper excluded');
+
+ async_test(function(t) {
+ var req = createGetAllRequest(t, 'out-of-line', connection,
+ IDBKeyRange.bound('G', 'K', true, false));
+ req.onsuccess = t.step_func(function(evt) {
+ var data = evt.target.result;
+ assert_class_string(data, 'Array', 'result should be an array');
+ assert_array_equals(data.map(function(e) { return e.ch; }), 'hijk'.split(''));
+ assert_array_equals(data.map(function(e) { return e.upper; }), 'HIJK'.split(''));
+ t.done();
+ });
+ }, 'Get lower excluded');
+
+ async_test(function(t) {
+ var req = createGetAllRequest(t, 'generated',
+ connection, IDBKeyRange.bound(4, 15), 3);
+ req.onsuccess = t.step_func(function(evt) {
+ var data = evt.target.result;
+ assert_true(Array.isArray(data));
+ assert_equals(data.length, 0);
+ t.done();
+ });
+ }, 'Get bound range (generated) with maxCount');
+
+ async_test(function(t) {
+ var req = createGetAllRequest(t, 'out-of-line',
+ connection, "Doesn't exist");
+ req.onsuccess = t.step_func(function(evt) {
+ assert_array_equals(evt.target.result, [],
+ 'getAll() using a nonexistent key should return an empty array');
+ t.done();
+ req.onerror = t.unreached_func('getAll request should succeed');
+ });
+ }, 'Non existent key');
+
+ async_test(function(t) {
+ var req = createGetAllRequest(t, 'out-of-line', connection,
+ undefined, 0);
+ req.onsuccess = t.step_func(function(evt) {
+ var data = evt.target.result;
+ assert_class_string(data, 'Array', 'result should be an array');
+ assert_array_equals(data.map(function(e) { return e.ch; }), alphabet);
+ assert_array_equals(data.map(function(e) { return e.upper; }), ALPHABET);
+ t.done();
+ });
+ }, 'maxCount=0');
+
+ async_test(function(t) {
+ var req = createGetAllRequest(t, 'out-of-line-not-unique', connection,
+ 'first');
+ req.onsuccess = t.step_func(function(evt) {
+ var data = evt.target.result;
+ assert_class_string(data, 'Array', 'result should be an array');
+ assert_array_equals(data.map(function(e) { return e.ch; }), 'abcdefghijklm'.split(''));
+ assert_true(data.every(function(e) { return e.half === 'first'; }));
+ t.done();
+ });
+ }, 'Retrieve multiEntry key');
+
+ async_test(function(t) {
+ var req = createGetAllRequest(t, 'out-of-line-multi', connection,
+ 'vowel');
+ req.onsuccess = t.step_func(function(evt) {
+ var data = evt.target.result;
+ assert_class_string(data, 'Array', 'result should be an array');
+ assert_array_equals(data.map(function(e) { return e.ch; }), ['a', 'e', 'i', 'o', 'u']);
+ assert_array_equals(data[0].attribs, ['vowel', 'first']);
+ assert_true(data.every(function(e) { return e.attribs[0] === 'vowel'; }));
+ t.done();
+ });
+ }, 'Retrieve one key multiple values');
+
+ // Explicit done needed in case async_test body fails synchronously.
+ done();
+});
+
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/idbindex_getAllKeys.html b/testing/web-platform/tests/IndexedDB/idbindex_getAllKeys.html
new file mode 100644
index 000000000..7653a5152
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbindex_getAllKeys.html
@@ -0,0 +1,207 @@
+<!DOCTYPE html>
+<title>IndexedDB: Test IDBIndex.getAllKeys.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+setup({explicit_done: true});
+
+var alphabet = 'abcdefghijklmnopqrstuvwxyz'.split('');
+
+function doSetup(dbName, dbVersion, onsuccess) {
+ var delete_request = indexedDB.deleteDatabase(dbName);
+ delete_request.onerror = function() {
+ assert_unreached('deleteDatabase should not fail');
+ };
+ delete_request.onsuccess = function(e) {
+ var req = indexedDB.open(dbName, dbVersion);
+ req.onsuccess = onsuccess;
+ req.onerror = function() {
+ assert_unreached('open should not fail');
+ };
+ req.onupgradeneeded = function(evt) {
+ var connection = evt.target.result;
+
+ var store = connection.createObjectStore('generated',
+ {autoIncrement: true, keyPath: 'id'});
+ var index = store.createIndex('test_idx', 'upper');
+ alphabet.forEach(function(letter) {
+ store.put({ch: letter, upper: letter.toUpperCase()});
+ });
+
+ store = connection.createObjectStore('out-of-line', null);
+ index = store.createIndex('test_idx', 'upper');
+ alphabet.forEach(function(letter) {
+ store.put({ch: letter, upper: letter.toUpperCase()}, letter);
+ });
+
+ store = connection.createObjectStore('out-of-line-multi', null);
+ index = store.createIndex('test_idx', 'attribs', {multiEntry: true});
+ alphabet.forEach(function(letter) {
+ attrs = [];
+ if (['a', 'e', 'i', 'o', 'u'].indexOf(letter) != -1)
+ attrs.push('vowel');
+ else
+ attrs.push('consonant');
+ if (letter == 'a')
+ attrs.push('first');
+ if (letter == 'z')
+ attrs.push('last');
+ store.put({ch: letter, attribs: attrs}, letter.toUpperCase());
+ });
+
+ store = connection.createObjectStore('empty', null);
+ index = store.createIndex('test_idx', 'upper');
+ };
+ };
+}
+
+function createGetAllKeysRequest(t, storeName, connection, range, maxCount) {
+ var transaction = connection.transaction(storeName, 'readonly');
+ var store = transaction.objectStore(storeName);
+ var index = store.index('test_idx');
+ var req = index.getAllKeys(range, maxCount);
+ req.onerror = t.unreached_func('getAllKeys request should succeed');
+ return req;
+}
+
+doSetup(location.pathname + '-IDBIndex.getAllKeys', 1, function(evt) {
+ var connection = evt.target.result;
+ async_test(function(t) {
+ var req = createGetAllKeysRequest(t, 'out-of-line', connection, 'C');
+ req.onsuccess = t.step_func(function(evt) {
+ var data = evt.target.result;
+ assert_array_equals(evt.target.result, ['c']);
+ t.done();
+ });
+ }, 'Single item get');
+
+ async_test(function(t) {
+ var req = createGetAllKeysRequest(t, 'empty', connection);
+ req.onsuccess = t.step_func(function(evt) {
+ assert_array_equals(evt.target.result, [],
+ 'getAllKeys() on empty object store should return empty array');
+ t.done();
+ });
+ }, 'Empty object store');
+
+ async_test(function(t) {
+ var req = createGetAllKeysRequest(t, 'out-of-line', connection);
+ req.onsuccess = t.step_func(function(evt) {
+ assert_array_equals(evt.target.result, alphabet,
+ 'getAllKeys() should return a..z');
+ t.done();
+ });
+ }, 'Get all keys');
+
+ async_test(function(t) {
+ var req = createGetAllKeysRequest(t, 'generated', connection);
+ req.onsuccess = t.step_func(function(evt) {
+ assert_array_equals(evt.target.result,
+ [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 24, 25, 26],
+ 'getAllKeys() should return 1..26');
+ t.done();
+ });
+ }, 'Get all generated keys');
+
+ async_test(function(t) {
+ var req = createGetAllKeysRequest(t, 'out-of-line', connection, undefined,
+ 10);
+ req.onsuccess = t.step_func(function(evt) {
+ assert_array_equals(evt.target.result,
+ 'abcdefghij'.split(''),
+ 'getAllKeys() should return a..j');
+ t.done();
+ });
+ }, 'maxCount=10');
+
+ async_test(function(t) {
+ var req = createGetAllKeysRequest(t, 'out-of-line', connection,
+ IDBKeyRange.bound('G', 'M'));
+ req.onsuccess = t.step_func(function(evt) {
+ assert_array_equals(evt.target.result,
+ 'ghijklm'.split(''),
+ 'getAllKeys() should return g..m');
+ t.done();
+ });
+ }, 'Get bound range');
+
+ async_test(function(t) {
+ var req = createGetAllKeysRequest(t, 'out-of-line', connection,
+ IDBKeyRange.bound('G', 'M'), 3);
+ req.onsuccess = t.step_func(function(evt) {
+ assert_array_equals(evt.target.result,
+ ['g', 'h', 'i'],
+ 'getAllKeys() should return g..i');
+ t.done();
+ });
+ }, 'Get bound range with maxCount');
+
+ async_test(function(t) {
+ var req = createGetAllKeysRequest(t, 'out-of-line', connection,
+ IDBKeyRange.bound('G', 'K', false, true));
+ req.onsuccess = t.step_func(function(evt) {
+ assert_array_equals(evt.target.result,
+ ['g', 'h', 'i', 'j'],
+ 'getAllKeys() should return g..j');
+ t.done();
+ });
+ }, 'Get upper excluded');
+
+ async_test(function(t) {
+ var req = createGetAllKeysRequest(t, 'out-of-line', connection,
+ IDBKeyRange.bound('G', 'K', true, false));
+ req.onsuccess = t.step_func(function(evt) {
+ assert_array_equals(evt.target.result,
+ ['h', 'i', 'j', 'k'],
+ 'getAllKeys() should return h..k');
+ t.done();
+ });
+ }, 'Get lower excluded');
+
+ async_test(function(t) {
+ var req = createGetAllKeysRequest(t, 'generated',
+ connection, IDBKeyRange.bound(4, 15), 3);
+ req.onsuccess = t.step_func(function(evt) {
+ assert_array_equals(evt.target.result, [],
+ 'getAllKeys() should return []');
+ t.done();
+ });
+ }, 'Get bound range (generated) with maxCount');
+
+ async_test(function(t) {
+ var req = createGetAllKeysRequest(t, 'out-of-line',
+ connection, "Doesn't exist");
+ req.onsuccess = t.step_func(function(evt) {
+ assert_array_equals(evt.target.result, [],
+ 'getAllKeys() using a nonexistent key should return empty array');
+ t.done();
+ req.onerror = t.unreached_func('getAllKeys request should succeed');
+ });
+ }, 'Non existent key');
+
+ async_test(function(t) {
+ var req = createGetAllKeysRequest(t, 'out-of-line', connection,
+ undefined, 0);
+ req.onsuccess = t.step_func(function(evt) {
+ assert_array_equals(evt.target.result, alphabet,
+ 'getAllKeys() should return a..z');
+ t.done();
+ });
+ }, 'maxCount=0');
+
+ async_test(function(t) {
+ var req = createGetAllKeysRequest(t, 'out-of-line-multi', connection,
+ 'vowel');
+ req.onsuccess = t.step_func(function(evt) {
+ assert_array_equals(evt.target.result, ['A','E','I','O','U'])
+ t.done();
+ });
+ req.onerror = t.unreached_func('getAllKeys request should succeed');
+ }, 'Retrieve multiEntry keys');
+
+ // Explicit done needed in case async_test body fails synchronously.
+ done();
+});
+
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/idbindex_getKey.htm b/testing/web-platform/tests/IndexedDB/idbindex_getKey.htm
new file mode 100644
index 000000000..536f2fd39
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbindex_getKey.htm
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.getKey() - returns the record's primary key </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { key:1, indexedProperty:"data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", { keyPath: "key" });
+ objStore.createIndex("index", "indexedProperty");
+
+ objStore.add(record);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("test")
+ .objectStore("test");
+
+ rq = rq.index("index");
+
+ rq = rq.getKey("data");
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, record.key);
+ t.done();
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbindex_getKey2.htm b/testing/web-platform/tests/IndexedDB/idbindex_getKey2.htm
new file mode 100644
index 000000000..9e8673242
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbindex_getKey2.htm
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.getKey() - returns the record's primary key where the index contains duplicate values </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ records = [ { key:1, indexedProperty:"data" },
+ { key:2, indexedProperty:"data" },
+ { key:3, indexedProperty:"data" } ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", { keyPath: "key" });
+ objStore.createIndex("index", "indexedProperty");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("test")
+ .objectStore("test")
+ .index("index")
+ .getKey("data");
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, records[0].key);
+ t.done();
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbindex_getKey3.htm b/testing/web-platform/tests/IndexedDB/idbindex_getKey3.htm
new file mode 100644
index 000000000..238107ccc
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbindex_getKey3.htm
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.getKey() - attempt to retrieve the primary key of a record that doesn't exist</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test();
+
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var rq = db.createObjectStore("test", { keyPath: "key" })
+ .createIndex("index", "indexedProperty")
+ .getKey(1);
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, undefined);
+ t.done();
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbindex_getKey4.htm b/testing/web-platform/tests/IndexedDB/idbindex_getKey4.htm
new file mode 100644
index 000000000..2002a5fe1
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbindex_getKey4.htm
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>IDBIndex.getKey() - returns the key of the first record within the range </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db, t = async_test();
+
+ var open_rq = createdb(t);
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var store = db.createObjectStore("store", { keyPath: "key" });
+ store.createIndex("index", "indexedProperty");
+
+ for(var i = 0; i < 10; i++) {
+ store.add({ key: i, indexedProperty: "data" + i });
+ }
+ }
+
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("store")
+ .objectStore("store")
+ .index("index")
+ .getKey(IDBKeyRange.bound('data4', 'data7'));
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, 4);
+
+ setTimeout(function() { t.done(); }, 4)
+ });
+ }
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbindex_getKey5.htm b/testing/web-platform/tests/IndexedDB/idbindex_getKey5.htm
new file mode 100644
index 000000000..96af868be
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbindex_getKey5.htm
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.getKey() - throw DataError when using invalid key </title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBIndex-getKey-IDBRequest-any-key">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var index = db.createObjectStore("test", { keyPath: "key" })
+ .createIndex("index", "indexedProperty");
+ assert_throws("DataError",function(){
+ index.getKey(NaN);
+ });
+ t.done();
+ };
+</script>
+
diff --git a/testing/web-platform/tests/IndexedDB/idbindex_getKey6.htm b/testing/web-platform/tests/IndexedDB/idbindex_getKey6.htm
new file mode 100644
index 000000000..6e9680da9
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbindex_getKey6.htm
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.getKey() - throw InvalidStateError when the index is deleted</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBIndex-getKey-IDBRequest-any-key">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var store = db.createObjectStore("store", { keyPath: "key" });
+ var index = store.createIndex("index", "indexedProperty");
+
+ store.add({ key: 1, indexedProperty: "data" });
+ store.deleteIndex("index");
+
+ assert_throws("InvalidStateError", function(){
+ index.getKey("data");
+ });
+ t.done();
+ }
+</script>
+
diff --git a/testing/web-platform/tests/IndexedDB/idbindex_getKey7.htm b/testing/web-platform/tests/IndexedDB/idbindex_getKey7.htm
new file mode 100644
index 000000000..c949d39b3
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbindex_getKey7.htm
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.getKey() - throw TransactionInactiveError on aborted transaction</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBIndex-getKey-IDBRequest-any-key">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var store = db.createObjectStore("store", { keyPath: "key" });
+ var index = store.createIndex("index", "indexedProperty");
+ store.add({ key: 1, indexedProperty: "data" });
+ }
+ open_rq.onsuccess = function(e) {
+ db = e.target.result;
+ var tx = db.transaction('store');
+ var index = tx.objectStore('store').index('index');
+ tx.abort();
+
+ assert_throws("TransactionInactiveError", function(){
+ index.getKey("data");
+ });
+ t.done();
+ }
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/idbindex_getKey8.htm b/testing/web-platform/tests/IndexedDB/idbindex_getKey8.htm
new file mode 100644
index 000000000..e46f7bc36
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbindex_getKey8.htm
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.getKey() - throw InvalidStateError on index deleted by aborted upgrade</title>
+<link rel="help" href="https://w3c.github.io/IndexedDB/#dom-idbindex-getkey">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var store = db.createObjectStore("store", { keyPath: "key" });
+ var index = store.createIndex("index", "indexedProperty");
+ store.add({ key: 1, indexedProperty: "data" });
+
+ e.target.transaction.abort();
+
+ assert_throws("InvalidStateError", function(){
+ index.getKey("data");
+ });
+ t.done();
+ }
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/idbindex_indexNames.htm b/testing/web-platform/tests/IndexedDB/idbindex_indexNames.htm
new file mode 100644
index 000000000..3099b45e9
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbindex_indexNames.htm
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.getKey() - returns the record's primary key</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(document.title, {timeout: 10000});
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test", { keyPath: "key" });
+ objStore.createIndex("index", "data");
+
+ assert_equals(objStore.indexNames[0], "index", "indexNames");
+ assert_equals(objStore.indexNames.length, 1, "indexNames.length");
+ };
+
+ open_rq.onsuccess = function(e) {
+ var objStore = db.transaction("test")
+ .objectStore("test");
+
+ assert_equals(objStore.indexNames[0], "index", "indexNames (second)");
+ assert_equals(objStore.indexNames.length, 1, "indexNames.length (second)");
+
+ t.done();
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbindex_openCursor.htm b/testing/web-platform/tests/IndexedDB/idbindex_openCursor.htm
new file mode 100644
index 000000000..0efff9325
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbindex_openCursor.htm
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.openCursor() - throw InvalidStateError when the index is deleted</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBIndex-openCursor-IDBRequest-any-range-IDBCursorDirection-direction">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var store = db.createObjectStore("store", { keyPath: "key" });
+ var index = store.createIndex("index", "indexedProperty");
+
+ store.add({ key: 1, indexedProperty: "data" });
+ store.deleteIndex("index");
+
+ assert_throws("InvalidStateError", function(){
+ index.openCursor();
+ });
+ t.done();
+ }
+</script>
+
diff --git a/testing/web-platform/tests/IndexedDB/idbindex_openCursor2.htm b/testing/web-platform/tests/IndexedDB/idbindex_openCursor2.htm
new file mode 100644
index 000000000..7ce967e0b
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbindex_openCursor2.htm
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.openCursor() - throw TransactionInactiveError on aborted transaction</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBIndex-openCursor-IDBRequest-any-range-IDBCursorDirection-direction">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var store = db.createObjectStore("store", { keyPath: "key" });
+ var index = store.createIndex("index", "indexedProperty");
+ store.add({ key: 1, indexedProperty: "data" });
+ }
+ open_rq.onsuccess = function(e) {
+ db = e.target.result;
+ var tx = db.transaction('store');
+ var index = tx.objectStore('store').index('index');
+ tx.abort();
+
+ assert_throws("TransactionInactiveError", function(){
+ index.openCursor();
+ });
+ t.done();
+ }
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/idbindex_openCursor3.htm b/testing/web-platform/tests/IndexedDB/idbindex_openCursor3.htm
new file mode 100644
index 000000000..fea479e9c
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbindex_openCursor3.htm
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.openCursor() - throw InvalidStateError on index deleted by aborted upgrade</title>
+<link rel="help" href="https://w3c.github.io/IndexedDB/#dom-idbindex-opencursor">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var store = db.createObjectStore("store", { keyPath: "key" });
+ var index = store.createIndex("index", "indexedProperty");
+ store.add({ key: 1, indexedProperty: "data" });
+
+ e.target.transaction.abort();
+
+ assert_throws("InvalidStateError", function(){
+ index.openCursor();
+ });
+ t.done();
+ }
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/idbindex_openKeyCursor.htm b/testing/web-platform/tests/IndexedDB/idbindex_openKeyCursor.htm
new file mode 100644
index 000000000..e15880291
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbindex_openKeyCursor.htm
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.openKeyCursor() - throw DataError when using a invalid key</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBIndex-openKeyCursor-IDBRequest-any-range-IDBCursorDirection-direction">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var store = db.createObjectStore("store", { keyPath: "key" });
+ var index = store.createIndex("index", "indexedProperty");
+
+ store.add({ key: 1, indexedProperty: "data" });
+
+ assert_throws("DataError", function(){
+ index.openKeyCursor(NaN);
+ });
+ t.done();
+ }
+</script>
+
diff --git a/testing/web-platform/tests/IndexedDB/idbindex_openKeyCursor2.htm b/testing/web-platform/tests/IndexedDB/idbindex_openKeyCursor2.htm
new file mode 100644
index 000000000..d8354c2fd
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbindex_openKeyCursor2.htm
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.openKeyCursor() - throw InvalidStateError when the index is deleted</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBIndex-openKeyCursor-IDBRequest-any-range-IDBCursorDirection-direction">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var store = db.createObjectStore("store", { keyPath: "key" });
+ var index = store.createIndex("index", "indexedProperty");
+
+ store.add({ key: 1, indexedProperty: "data" });
+ store.deleteIndex("index");
+
+ assert_throws("InvalidStateError", function(){
+ index.openKeyCursor();
+ });
+ t.done();
+ }
+</script>
+
diff --git a/testing/web-platform/tests/IndexedDB/idbindex_openKeyCursor3.htm b/testing/web-platform/tests/IndexedDB/idbindex_openKeyCursor3.htm
new file mode 100644
index 000000000..f009cef49
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbindex_openKeyCursor3.htm
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.openKeyCursor() - throw TransactionInactiveError on aborted transaction</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBIndex-openKeyCursor-IDBRequest-any-range-IDBCursorDirection-direction">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var store = db.createObjectStore("store", { keyPath: "key" });
+ var index = store.createIndex("index", "indexedProperty");
+ store.add({ key: 1, indexedProperty: "data" });
+ }
+ open_rq.onsuccess = function(e) {
+ db = e.target.result;
+ var tx = db.transaction('store');
+ var index = tx.objectStore('store').index('index');
+ tx.abort();
+
+ assert_throws("TransactionInactiveError", function(){
+ index.openKeyCursor();
+ });
+ t.done();
+ }
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/idbindex_openKeyCursor4.htm b/testing/web-platform/tests/IndexedDB/idbindex_openKeyCursor4.htm
new file mode 100644
index 000000000..bf134dff1
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbindex_openKeyCursor4.htm
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBIndex.openKeyCursor() - throw InvalidStateError on index deleted by aborted upgrade</title>
+<link rel="help" href="https://w3c.github.io/IndexedDB/#dom-idbindex-openkeycursor">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var store = db.createObjectStore("store", { keyPath: "key" });
+ var index = store.createIndex("index", "indexedProperty");
+ store.add({ key: 1, indexedProperty: "data" });
+
+ e.target.transaction.abort();
+
+ assert_throws("InvalidStateError", function(){
+ index.openKeyCursor();
+ });
+ t.done();
+ }
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/idbkeyrange-includes.htm b/testing/web-platform/tests/IndexedDB/idbkeyrange-includes.htm
new file mode 100644
index 000000000..6a0562746
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbkeyrange-includes.htm
@@ -0,0 +1,61 @@
+<!doctype html>
+<meta charset=utf-8>
+<title></title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+
+ test(function() {
+ var closedRange = IDBKeyRange.bound(5, 20);
+ assert_true(!!closedRange.includes, "IDBKeyRange has a .includes");
+ assert_true(closedRange.includes(7), "in range");
+ assert_false(closedRange.includes(1), "below range");
+ assert_false(closedRange.includes(42), "above range");
+ assert_true(closedRange.includes(5) && closedRange.includes(20),
+ "boundary points");
+ assert_throws("DataError", function() { closedRange.includes({}) },
+ "invalid key");
+ }, "IDBKeyRange.includes() with a closed range");
+
+ test(function() {
+ var openRange = IDBKeyRange.bound(5, 20, true, true);
+ assert_false(openRange.includes(5) || openRange.includes(20),
+ "boundary points");
+ }, "IDBKeyRange.includes() with an open range");
+
+ test(function() {
+ var range = IDBKeyRange.only(42);
+ assert_true(range.includes(42), "in range");
+ assert_false(range.includes(1), "below range");
+ assert_false(range.includes(9000), "above range");
+ }, "IDBKeyRange.includes() with an only range");
+
+ test(function() {
+ var range = IDBKeyRange.lowerBound(5);
+ assert_false(range.includes(4), 'value before closed lower bound');
+ assert_true(range.includes(5), 'value at closed lower bound');
+ assert_true(range.includes(6), 'value after closed lower bound');
+ }, "IDBKeyRange.includes() with an closed lower-bounded range");
+
+ test(function() {
+ var range = IDBKeyRange.lowerBound(5, true);
+ assert_false(range.includes(4), 'value before open lower bound');
+ assert_false(range.includes(5), 'value at open lower bound');
+ assert_true(range.includes(6), 'value after open lower bound');
+ }, "IDBKeyRange.includes() with an open lower-bounded range");
+
+ test(function() {
+ var range = IDBKeyRange.upperBound(5);
+ assert_true(range.includes(4), 'value before closed upper bound');
+ assert_true(range.includes(5), 'value at closed upper bound');
+ assert_false(range.includes(6), 'value after closed upper bound');
+ }, "IDBKeyRange.includes() with an closed upper-bounded range");
+
+ test(function() {
+ var range = IDBKeyRange.upperBound(5, true);
+ assert_true(range.includes(4), 'value before open upper bound');
+ assert_false(range.includes(5), 'value at open upper bound');
+ assert_false(range.includes(6), 'value after open upper bound');
+ }, "IDBKeyRange.includes() with an open upper-bounded range");
+
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/idbkeyrange.htm b/testing/web-platform/tests/IndexedDB/idbkeyrange.htm
new file mode 100644
index 000000000..dd6e5f7e5
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbkeyrange.htm
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>IDBKeyRange Tests</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ // only
+ test( function() {
+ var keyRange = IDBKeyRange.only(1);
+ assert_true(keyRange instanceof IDBKeyRange, "keyRange instanceof IDBKeyRange");
+ assert_equals(keyRange.lower, 1, "keyRange");
+ assert_equals(keyRange.upper, 1, "keyRange");
+ assert_false(keyRange.lowerOpen, "keyRange.lowerOpen");
+ assert_false(keyRange.upperOpen, "keyRange.upperOpen");
+ }, "IDBKeyRange.only() - returns an IDBKeyRange and the properties are set correctly");
+
+ // lowerBound
+ test( function() {
+ var keyRange = IDBKeyRange.lowerBound(1, true)
+ assert_true(keyRange instanceof IDBKeyRange, "keyRange instanceof IDBKeyRange");
+ assert_equals(keyRange.lower, 1, "keyRange.lower");
+ assert_equals(keyRange.upper, undefined, "keyRange.upper");
+ assert_true(keyRange.lowerOpen, "keyRange.lowerOpen");
+ assert_true(keyRange.upperOpen, "keyRange.upperOpen");
+ }, "IDBKeyRange.lowerBound() - returns an IDBKeyRange and the properties are set correctly");
+
+ test( function() {
+ var keyRange = IDBKeyRange.lowerBound(1);
+ assert_false(keyRange.lowerOpen, "keyRange.lowerOpen");
+ }, "IDBKeyRange.lowerBound() - 'open' parameter has correct default set");
+
+ // upperBound
+ test( function() {
+ var keyRange = IDBKeyRange.upperBound(1, true);
+ assert_true(keyRange instanceof IDBKeyRange, "keyRange instanceof IDBKeyRange");
+ assert_equals(keyRange.lower, undefined, "keyRange.lower");
+ assert_equals(keyRange.upper, 1, "keyRange.upper");
+ assert_true(keyRange.lowerOpen, "keyRange.lowerOpen");
+ assert_true(keyRange.upperOpen, "keyRange.upperOpen");
+ }, "IDBKeyRange.upperBound() - returns an IDBKeyRange and the properties are set correctly");
+
+ test( function() {
+ var keyRange = IDBKeyRange.upperBound(1);
+ assert_false(keyRange.upperOpen, "keyRange.upperOpen");
+ }, "IDBKeyRange.upperBound() - 'open' parameter has correct default set");
+
+ // bound
+ test( function() {
+ var keyRange = IDBKeyRange.bound(1, 2, true, true);
+ assert_true(keyRange instanceof IDBKeyRange, "keyRange instanceof IDBKeyRange");
+ assert_equals(keyRange.lower, 1, "keyRange");
+ assert_equals(keyRange.upper, 2, "keyRange");
+ assert_true(keyRange.lowerOpen, "keyRange.lowerOpen");
+ assert_true(keyRange.upperOpen, "keyRange.upperOpen");
+ }, "IDBKeyRange.bound() - returns an IDBKeyRange and the properties are set correctly");
+
+ test( function() {
+ var keyRange = IDBKeyRange.bound(1, 2);
+ assert_false(keyRange.lowerOpen, "keyRange.lowerOpen");
+ assert_false(keyRange.upperOpen, "keyRange.upperOpen");
+ }, "IDBKeyRange.bound() - 'lowerOpen' and 'upperOpen' parameters have correct defaults set");
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbkeyrange_incorrect.htm b/testing/web-platform/tests/IndexedDB/idbkeyrange_incorrect.htm
new file mode 100644
index 000000000..0449ca807
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbkeyrange_incorrect.htm
@@ -0,0 +1,92 @@
+<!DOCTYPE html>
+<!-- Submitted from TestTWF Paris -->
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title id='desc'>IDBKeyRange Tests - Incorrect</title>
+ <link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#range-concept">
+ <link rel=assert title="If the lower key is greater than the upper key, then a DOMException of type DataError must be thrown.">
+ <link rel=author href="mailto:chrcharles67@gmail.com" title="Christophe CHARLES">
+
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="support.js"></script>
+
+ <script type="text/javascript">
+
+ // TypeError: bound requires more than 0 arguments
+ test( function() {
+ assert_throws(new TypeError(), function() {
+ IDBKeyRange.bound();
+ });
+ }, "IDBKeyRange.bound() - bound requires more than 0 arguments.");
+
+ // Null parameters
+ test( function() {
+ assert_throws("DataError", function() {
+ IDBKeyRange.bound(null, null);
+ });
+ }, "IDBKeyRange.bound(null, null) - null parameters are incorrect.");
+
+ // // Null parameter
+ test( function() {
+ assert_throws("DataError", function() {
+ IDBKeyRange.bound(1, null);
+ });
+ assert_throws("DataError", function() {
+ IDBKeyRange.bound(null, 1);
+ });
+ }, "IDBKeyRange.bound(1, null / null, 1) - null parameter is incorrect.");
+
+ // bound incorrect
+ test( function() {
+ var lowerBad = Math.floor(Math.random()*31) + 5;
+ var upper = lowerBad - 1;
+ assert_throws("DataError", function() {
+ IDBKeyRange.bound(lowerBad, upper);
+ });
+ assert_throws("DataError", function() {
+ IDBKeyRange.bound('b', 'a');
+ });
+ }, "IDBKeyRange.bound(lower, upper / lower > upper) - 'lower' is greater than 'upper'."
+ );
+
+ test( function() {
+ assert_throws("DataError", function() {
+ IDBKeyRange.bound('a', 1);
+ });
+ assert_throws("DataError", function() {
+ IDBKeyRange.bound(new Date(), 1);
+ });
+ assert_throws("DataError", function() {
+ IDBKeyRange.bound([1, 2], 1);
+ });
+ }, "IDBKeyRange.bound(DOMString/Date/Array, 1) - A DOMString, Date and Array are greater than a float.");
+
+
+ // ReferenceError: the variable is not defined
+ test( function() {
+ var goodVariable = 1;
+ assert_throws(new ReferenceError(), function() {
+ IDBKeyRange.bound(noExistingVariable, 1);
+ });
+ assert_throws(new ReferenceError(), function() {
+ IDBKeyRange.bound(goodVariable, noExistingVariable);
+ });
+ }, "IDBKeyRange.bound(noExistingVariable, 1 / goodVariable, noExistingVariable) - noExistingVariable is not defined.");
+
+ // Valid type key error
+ test( function() {
+ assert_throws("DataError", function() {
+ IDBKeyRange.bound(true, 1);
+ });
+ }, "IDBKeyRange.bound(true, 1) - boolean is not a valid key type.");
+
+
+ </script>
+ </head>
+
+ <body>
+ <div id="log"></div>
+ </body>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore-rename-abort.html b/testing/web-platform/tests/IndexedDB/idbobjectstore-rename-abort.html
new file mode 100644
index 000000000..b59117a80
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore-rename-abort.html
@@ -0,0 +1,120 @@
+<!DOCTYPE html>
+<title>IndexedDB: object store renaming support in aborted transactions</title>
+<link rel="help"
+ href="https://w3c.github.io/IndexedDB/#dom-idbobjectstore-name">
+<link rel="author" href="pwnall@chromium.org" title="Victor Costan">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support-promises.js"></script>
+<script>
+
+promise_test(testCase => {
+ const dbName = databaseName(testCase);
+ let bookStore = null, bookStore2 = null;
+ return createDatabase(testCase, (database, transaction) => {
+ createBooksStore(testCase, database);
+ }).then(database => {
+ database.close();
+ }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
+ bookStore = transaction.objectStore('books');
+ bookStore.name = 'renamed_books';
+
+ transaction.abort();
+
+ assert_equals(
+ bookStore.name, 'books',
+ 'IDBObjectStore.name should not reflect the rename any more ' +
+ 'immediately after transaction.abort() returns');
+ assert_array_equals(
+ database.objectStoreNames, ['books'],
+ 'IDBDatabase.objectStoreNames should not reflect the rename ' +
+ 'any more immediately after transaction.abort() returns');
+ assert_array_equals(
+ transaction.objectStoreNames, ['books'],
+ 'IDBTransaction.objectStoreNames should not reflect the ' +
+ 'rename any more immediately after transaction.abort() returns');
+ })).then(event => {
+ assert_equals(bookStore.name, 'books',
+ 'IDBObjectStore.name should not reflect the rename any more ' +
+ 'after the versionchange transaction is aborted');
+ const request = indexedDB.open(dbName, 1);
+ return requestWatcher(testCase, request).wait_for('success');
+ }).then(event => {
+ const database = event.target.result;
+ assert_array_equals(
+ database.objectStoreNames, ['books'],
+ 'IDBDatabase.objectStoreNames should not reflect the rename ' +
+ 'after the versionchange transaction is aborted');
+
+ const transaction = database.transaction('books', 'readonly');
+ bookStore2 = transaction.objectStore('books');
+ return checkStoreContents(
+ testCase, bookStore2,
+ 'Aborting an object store rename transaction should not change ' +
+ "the store's records").then(() => database.close());
+ }).then(() => {
+ assert_equals(
+ bookStore.name, 'books',
+ 'IDBObjectStore used in aborted rename transaction should not ' +
+ 'reflect the rename after the transaction is aborted');
+ assert_equals(
+ bookStore2.name, 'books',
+ 'IDBObjectStore obtained after an aborted rename transaction ' +
+ 'should not reflect the rename');
+ });
+}, 'IndexedDB object store rename in aborted transaction');
+
+promise_test(testCase => {
+ const dbName = databaseName(testCase);
+ let notBookStore = null;
+ return createDatabase(testCase, (database, transaction) => {
+ }).then(database => {
+ database.close();
+ }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
+ notBookStore = createNotBooksStore(testCase, database);
+ notBookStore.name = 'not_books_renamed';
+ notBookStore.name = 'not_books_renamed_again';
+
+ transaction.abort();
+
+ assert_equals(
+ notBookStore.name, 'not_books_renamed_again',
+ 'IDBObjectStore.name should reflect the last rename ' +
+ 'immediately after transaction.abort() returns');
+ assert_array_equals(
+ database.objectStoreNames, [],
+ 'IDBDatabase.objectStoreNames should not reflect the creation ' +
+ 'or the rename any more immediately after transaction.abort() ' +
+ 'returns');
+ assert_array_equals(
+ transaction.objectStoreNames, [],
+ 'IDBTransaction.objectStoreNames should not reflect the ' +
+ 'creation or the rename any more immediately after ' +
+ 'transaction.abort() returns');
+ assert_array_equals(notBookStore.indexNames, [],
+ 'IDBObjectStore.indexNames for the newly created store ' +
+ 'should be empty immediately after transaction.abort() ' +
+ 'returns');
+ })).then(event => {
+ assert_equals(
+ notBookStore.name, 'not_books_renamed_again',
+ 'IDBObjectStore.name should reflect the last rename after the ' +
+ 'versionchange transaction is aborted');
+ assert_array_equals(notBookStore.indexNames, [],
+ 'IDBObjectStore.indexNames for the newly created store ' +
+ 'should be empty after the versionchange transaction is aborted ' +
+ 'returns');
+ const request = indexedDB.open(dbName, 1);
+ return requestWatcher(testCase, request).wait_for('success');
+ }).then(event => {
+ const database = event.target.result;
+ assert_array_equals(
+ database.objectStoreNames, [],
+ 'IDBDatabase.objectStoreNames should not reflect the creation or ' +
+ 'the rename after the versionchange transaction is aborted');
+
+ database.close();
+ });
+}, 'IndexedDB object store creation and rename in an aborted transaction');
+
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore-rename-errors.html b/testing/web-platform/tests/IndexedDB/idbobjectstore-rename-errors.html
new file mode 100644
index 000000000..8e603baec
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore-rename-errors.html
@@ -0,0 +1,118 @@
+<!DOCTYPE html>
+<title>IndexedDB: object store renaming error handling</title>
+<link rel="help"
+ href="https://w3c.github.io/IndexedDB/#dom-idbobjectstore-name">
+<link rel="author" href="pwnall@chromium.org" title="Victor Costan">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support-promises.js"></script>
+<script>
+
+promise_test(testCase => {
+ return createDatabase(testCase, (database, transaction) => {
+ createBooksStore(testCase, database);
+ }).then(database => {
+ database.close();
+ }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
+ const store = transaction.objectStore('books');
+ database.deleteObjectStore('books');
+ assert_throws('InvalidStateError', () => store.name = 'renamed_books');
+ })).then(database => {
+ database.close();
+ });
+}, 'IndexedDB deleted object store rename throws');
+
+promise_test(testCase => {
+ return createDatabase(testCase, (database, transaction) => {
+ createBooksStore(testCase, database);
+ }).then(database => {
+ const transaction = database.transaction('books', 'readonly');
+ const store = transaction.objectStore('books');
+ assert_throws('InvalidStateError', () => store.name = 'renamed_books');
+ database.close();
+ });
+}, 'IndexedDB object store rename throws in a readonly transaction');
+
+promise_test(testCase => {
+ return createDatabase(testCase, (database, transaction) => {
+ createBooksStore(testCase, database);
+ }).then(database => {
+ const transaction = database.transaction('books', 'readwrite');
+ const store = transaction.objectStore('books');
+
+ assert_throws('InvalidStateError', () => store.name = 'renamed_books');
+ database.close();
+ });
+}, 'IndexedDB object store rename throws in a readwrite transaction');
+
+promise_test(testCase => {
+ let bookStore = null;
+ return createDatabase(testCase, (database, transaction) => {
+ bookStore = createBooksStore(testCase, database);
+ }).then(database => {
+ assert_throws('TransactionInactiveError',
+ () => { bookStore.name = 'renamed_books'; });
+ database.close();
+ });
+}, 'IndexedDB object store rename throws in an inactive transaction');
+
+promise_test(testCase => {
+ return createDatabase(testCase, (database, transaction) => {
+ createBooksStore(testCase, database);
+ createNotBooksStore(testCase, database);
+ }).then(database => {
+ database.close();
+ }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
+ const store = transaction.objectStore('books');
+ assert_throws('ConstraintError', () => store.name = 'not_books');
+ assert_array_equals(
+ database.objectStoreNames, ['books', 'not_books'],
+ 'A store rename that throws an exception should not change the ' +
+ "store's IDBDatabase.objectStoreNames");
+ })).then(database => {
+ assert_array_equals(
+ database.objectStoreNames, ['books', 'not_books'],
+ 'Committing a transaction with a failed store rename attempt ' +
+ "should not change the store's IDBDatabase.objectStoreNames");
+ const transaction = database.transaction('books', 'readonly');
+ const store = transaction.objectStore('books');
+ return checkStoreContents(
+ testCase, store,
+ 'Committing a transaction with a failed rename attempt should ' +
+ "not change the store's contents").then(() => database.close());
+ });
+}, 'IndexedDB object store rename to the name of another store throws');
+
+promise_test(testCase => {
+ return createDatabase(testCase, (database, transaction) => {
+ createBooksStore(testCase, database);
+ }).then(database => {
+ database.close();
+ }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
+ const store = transaction.objectStore('books');
+ assert_throws(
+ { name: 'Custom stringifying error' },
+ () => {
+ store.name = {
+ toString: () => { throw { name: 'Custom stringifying error'}; }
+ };
+ }, 'IDBObjectStore rename should re-raise toString() exception');
+ assert_array_equals(
+ database.objectStoreNames, ['books'],
+ 'A store rename that throws an exception should not change the ' +
+ "store's IDBDatabase.objectStoreNames");
+ })).then(database => {
+ assert_array_equals(
+ database.objectStoreNames, ['books'],
+ 'Committing a transaction with a failed store rename attempt ' +
+ "should not change the store's IDBDatabase.objectStoreNames");
+ const transaction = database.transaction('books', 'readonly');
+ const store = transaction.objectStore('books');
+ return checkStoreContents(
+ testCase, store,
+ 'Committing a transaction with a failed rename attempt should ' +
+ "not change the store's contents").then(() => database.close());
+ });
+}, 'IndexedDB object store rename handles exceptions when stringifying names');
+
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore-rename-store.html b/testing/web-platform/tests/IndexedDB/idbobjectstore-rename-store.html
new file mode 100644
index 000000000..d07a46487
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore-rename-store.html
@@ -0,0 +1,367 @@
+<!DOCTYPE html>
+<meta name="timeout" content="long">
+<title>IndexedDB: object store renaming support</title>
+<link rel="help"
+ href="https://w3c.github.io/IndexedDB/#dom-idbobjectstore-name">
+<link rel="author" href="pwnall@chromium.org" title="Victor Costan">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support-promises.js"></script>
+<script>
+
+// Renames the 'books' store to 'renamed_books'.
+//
+// Returns a promise that resolves to an IndexedDB database. The caller must
+// close the database.
+const renameBooksStore = (testCase) => {
+ return migrateDatabase(testCase, 2, (database, transaction) => {
+ const store = transaction.objectStore('books');
+ store.name = 'renamed_books';
+ });
+};
+
+promise_test(testCase => {
+ let bookStore = null, bookStore2 = null;
+ let renamedBookStore = null, renamedBookStore2 = null;
+ return createDatabase(testCase, (database, transaction) => {
+ bookStore = createBooksStore(testCase, database);
+ }).then(database => {
+ assert_array_equals(
+ database.objectStoreNames, ['books'],
+ 'Test setup should have created a "books" object store');
+ const transaction = database.transaction('books', 'readonly');
+ bookStore2 = transaction.objectStore('books');
+ return checkStoreContents(
+ testCase, bookStore2,
+ 'The store should have the expected contents before any renaming').
+ then(() => database.close());
+ }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
+ renamedBookStore = transaction.objectStore('books');
+ renamedBookStore.name = 'renamed_books';
+
+ assert_equals(
+ renamedBookStore.name, 'renamed_books',
+ 'IDBObjectStore name should change immediately after a rename');
+ assert_array_equals(
+ database.objectStoreNames, ['renamed_books'],
+ 'IDBDatabase.objectStoreNames should immediately reflect the ' +
+ 'rename');
+ assert_array_equals(
+ transaction.objectStoreNames, ['renamed_books'],
+ 'IDBTransaction.objectStoreNames should immediately reflect the ' +
+ 'rename');
+ assert_equals(
+ transaction.objectStore('renamed_books'), renamedBookStore,
+ 'IDBTransaction.objectStore should return the renamed object ' +
+ 'store when queried using the new name immediately after the ' +
+ 'rename');
+ assert_throws(
+ 'NotFoundError', () => transaction.objectStore('books'),
+ 'IDBTransaction.objectStore should throw when queried using the ' +
+ "renamed object store's old name immediately after the rename");
+ })).then(database => {
+ assert_array_equals(
+ database.objectStoreNames, ['renamed_books'],
+ 'IDBDatabase.objectStoreNames should still reflect the rename ' +
+ 'after the versionchange transaction commits');
+ const transaction = database.transaction('renamed_books', 'readonly');
+ renamedBookStore2 = transaction.objectStore('renamed_books');
+ return checkStoreContents(
+ testCase, renamedBookStore2,
+ 'Renaming an object store should not change its records').then(
+ () => database.close());
+ }).then(() => {
+ assert_equals(
+ bookStore.name, 'books',
+ 'IDBObjectStore obtained before the rename transaction should ' +
+ 'not reflect the rename');
+ assert_equals(
+ bookStore2.name, 'books',
+ 'IDBObjectStore obtained before the rename transaction should ' +
+ 'not reflect the rename');
+ assert_equals(
+ renamedBookStore.name, 'renamed_books',
+ 'IDBObjectStore used in the rename transaction should keep ' +
+ 'reflecting the new name after the transaction is committed');
+ assert_equals(
+ renamedBookStore2.name, 'renamed_books',
+ 'IDBObjectStore obtained after the rename transaction should ' +
+ 'reflect the new name');
+ });
+}, 'IndexedDB object store rename in new transaction');
+
+promise_test(testCase => {
+ let renamedBookStore = null, renamedBookStore2 = null;
+ return createDatabase(testCase, (database, transaction) => {
+ renamedBookStore = createBooksStore(testCase, database);
+ renamedBookStore.name = 'renamed_books';
+
+ assert_equals(
+ renamedBookStore.name, 'renamed_books',
+ 'IDBObjectStore name should change immediately after a rename');
+ assert_array_equals(
+ database.objectStoreNames, ['renamed_books'],
+ 'IDBDatabase.objectStoreNames should immediately reflect the ' +
+ 'rename');
+ assert_array_equals(
+ transaction.objectStoreNames, ['renamed_books'],
+ 'IDBTransaction.objectStoreNames should immediately reflect the ' +
+ 'rename');
+ assert_equals(
+ transaction.objectStore('renamed_books'), renamedBookStore,
+ 'IDBTransaction.objectStore should return the renamed object ' +
+ 'store when queried using the new name immediately after the ' +
+ 'rename');
+ assert_throws(
+ 'NotFoundError', () => transaction.objectStore('books'),
+ 'IDBTransaction.objectStore should throw when queried using the ' +
+ "renamed object store's old name immediately after the rename");
+ }).then(database => {
+ assert_array_equals(
+ database.objectStoreNames, ['renamed_books'],
+ 'IDBDatabase.objectStoreNames should still reflect the rename ' +
+ 'after the versionchange transaction commits');
+ const transaction = database.transaction('renamed_books', 'readonly');
+ renamedBookStore2 = transaction.objectStore('renamed_books');
+ return checkStoreContents(
+ testCase, renamedBookStore2,
+ 'Renaming an object store should not change its records').then(
+ () => database.close());
+ }).then(() => {
+ assert_equals(
+ renamedBookStore.name, 'renamed_books',
+ 'IDBObjectStore used in the rename transaction should keep ' +
+ 'reflecting the new name after the transaction is committed');
+ assert_equals(
+ renamedBookStore2.name, 'renamed_books',
+ 'IDBObjectStore obtained after the rename transaction should ' +
+ 'reflect the new name');
+ });
+}, 'IndexedDB object store rename in the transaction where it is created');
+
+promise_test(testCase => {
+ return createDatabase(testCase, (database, transaction) => {
+ createBooksStore(testCase, database);
+ }).then(database => {
+ const transaction = database.transaction('books', 'readonly');
+ const store = transaction.objectStore('books');
+ return checkStoreIndexes(
+ testCase, store,
+ 'The object store index should have the expected contens before ' +
+ 'any renaming').then(
+ () => database.close());
+ }).then(() => renameBooksStore(testCase)
+ ).then(database => {
+ const transaction = database.transaction('renamed_books', 'readonly');
+ const store = transaction.objectStore('renamed_books');
+ return checkStoreIndexes(
+ testCase, store,
+ 'Renaming an object store should not change its indexes').then(
+ () => database.close());
+ });
+}, 'IndexedDB object store rename covers index');
+
+promise_test(testCase => {
+ return createDatabase(testCase, (database, transaction) => {
+ createBooksStore(testCase, database);
+ }).then(database => {
+ const transaction = database.transaction('books', 'readwrite');
+ const store = transaction.objectStore('books');
+ return checkStoreGenerator(
+ testCase, store, 345679,
+ 'The object store key generator should have the expected state ' +
+ 'before any renaming').then(() => database.close());
+ }).then(() => renameBooksStore(testCase)
+ ).then(database => {
+ const transaction = database.transaction('renamed_books', 'readwrite');
+ const store = transaction.objectStore('renamed_books');
+ return checkStoreGenerator(
+ testCase, store, 345680,
+ 'Renaming an object store should not change the state of its key ' +
+ 'generator').then(() => database.close());
+ });
+}, 'IndexedDB object store rename covers key generator');
+
+promise_test(testCase => {
+ return createDatabase(testCase, (database, transaction) => {
+ createBooksStore(testCase, database);
+ }).then(database => {
+ database.close();
+ }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
+ const store = transaction.objectStore('books');
+ store.name = 'books';
+ assert_array_equals(
+ database.objectStoreNames, ['books'],
+ 'Renaming a store to the same name should not change ' +
+ "the store's IDBDatabase.objectStoreNames");
+ })).then(database => {
+ assert_array_equals(
+ database.objectStoreNames, ['books'],
+ 'Committing a transaction that renames a store to the same name ' +
+ "should not change the store's IDBDatabase.objectStoreNames");
+ const transaction = database.transaction('books', 'readonly');
+ const store = transaction.objectStore('books');
+ return checkStoreContents(
+ testCase, store,
+ 'Committing a transaction that renames a store to the same name ' +
+ "should not change the store's contents").then(
+ () => database.close());
+ });
+}, 'IndexedDB object store rename to the same name succeeds');
+
+promise_test(testCase => {
+ return createDatabase(testCase, (database, transaction) => {
+ createBooksStore(testCase, database);
+ createNotBooksStore(testCase, database);
+ }).then(database => {
+ database.close();
+ }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
+ const store = transaction.objectStore('books');
+ database.deleteObjectStore('not_books');
+ store.name = 'not_books';
+ assert_array_equals(
+ database.objectStoreNames, ['not_books'],
+ 'IDBDatabase.objectStoreNames should immediately reflect the ' +
+ 'rename');
+ })).then(database => {
+ assert_array_equals(
+ database.objectStoreNames, ['not_books'],
+ 'IDBDatabase.objectStoreNames should still reflect the rename ' +
+ 'after the versionchange transaction commits');
+ const transaction = database.transaction('not_books', 'readonly');
+ const store = transaction.objectStore('not_books');
+ return checkStoreContents(
+ testCase, store,
+ 'Renaming an object store should not change its records').then(
+ () => database.close());
+ });
+}, 'IndexedDB object store rename to the name of a deleted store succeeds');
+
+promise_test(testCase => {
+ return createDatabase(testCase, (database, transaction) => {
+ createBooksStore(testCase, database);
+ createNotBooksStore(testCase, database);
+ }).then(database => {
+ database.close();
+ }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
+ const bookStore = transaction.objectStore('books');
+ const notBookStore = transaction.objectStore('not_books');
+
+ transaction.objectStore('books').name = 'tmp';
+ transaction.objectStore('not_books').name = 'books';
+ transaction.objectStore('tmp').name = 'not_books';
+
+ assert_array_equals(
+ database.objectStoreNames, ['books', 'not_books'],
+ 'IDBDatabase.objectStoreNames should immediately reflect the swap');
+
+ assert_equals(
+ transaction.objectStore('books'), notBookStore,
+ 'IDBTransaction.objectStore should return the original "books" ' +
+ 'store when queried with "not_books" after the swap');
+ assert_equals(
+ transaction.objectStore('not_books'), bookStore,
+ 'IDBTransaction.objectStore should return the original ' +
+ '"not_books" store when queried with "books" after the swap');
+ })).then(database => {
+ assert_array_equals(
+ database.objectStoreNames, ['books', 'not_books'],
+ 'IDBDatabase.objectStoreNames should still reflect the swap ' +
+ 'after the versionchange transaction commits');
+ const transaction = database.transaction('not_books', 'readonly');
+ const store = transaction.objectStore('not_books');
+ assert_array_equals(
+ store.indexNames, ['by_author', 'by_title'],
+ '"not_books" index names should still reflect the swap after the ' +
+ 'versionchange transaction commits');
+ return checkStoreContents(
+ testCase, store,
+ 'Swapping two object stores should not change their records').then(
+ () => database.close());
+ });
+}, 'IndexedDB object store swapping via renames succeeds');
+
+promise_test(testCase => {
+ return createDatabase(testCase, (database, transaction) => {
+ createBooksStore(testCase, database);
+ }).then(database => {
+ database.close();
+ }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
+ const store = transaction.objectStore('books');
+
+ store.name = 42;
+ assert_equals(store.name, '42',
+ 'IDBObjectStore name should change immediately after a ' +
+ 'rename to a number');
+ assert_array_equals(
+ database.objectStoreNames, ['42'],
+ 'IDBDatabase.objectStoreNames should immediately reflect the ' +
+ 'stringifying rename');
+
+ store.name = true;
+ assert_equals(store.name, 'true',
+ 'IDBObjectStore name should change immediately after a ' +
+ 'rename to a boolean');
+
+ store.name = {};
+ assert_equals(store.name, '[object Object]',
+ 'IDBObjectStore name should change immediately after a ' +
+ 'rename to an object');
+
+ store.name = () => null;
+ assert_equals(store.name, '() => null',
+ 'IDBObjectStore name should change immediately after a ' +
+ 'rename to a function');
+
+ store.name = undefined;
+ assert_equals(store.name, 'undefined',
+ 'IDBObjectStore name should change immediately after a ' +
+ 'rename to undefined');
+ })).then(database => {
+ assert_array_equals(
+ database.objectStoreNames, ['undefined'],
+ 'IDBDatabase.objectStoreNames should reflect the last rename ' +
+ 'after the versionchange transaction commits');
+ const transaction = database.transaction('undefined', 'readonly');
+ const store = transaction.objectStore('undefined');
+ return checkStoreContents(
+ testCase, store,
+ 'Renaming an object store should not change its records').then(
+ () => database.close());
+ });
+}, 'IndexedDB object store rename stringifies non-string names');
+
+for (let escapedName of ['', '\\u0000', '\\uDC00\\uD800']) ((escapedName) => {
+ const name = JSON.parse('"' + escapedName + '"');
+ promise_test(testCase => {
+ return createDatabase(testCase, (database, transaction) => {
+ createBooksStore(testCase, database);
+ }).then(database => {
+ database.close();
+ }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
+ const store = transaction.objectStore('books');
+
+ store.name = name;
+ assert_equals(store.name, name,
+ 'IDBObjectStore name should change immediately after the ' +
+ 'rename');
+ assert_array_equals(
+ database.objectStoreNames, [name],
+ 'IDBDatabase.objectStoreNames should immediately reflect the ' +
+ 'rename');
+ })).then(database => {
+ assert_array_equals(
+ database.objectStoreNames, [name],
+ 'IDBDatabase.objectStoreNames should reflect the rename ' +
+ 'after the versionchange transaction commits');
+ const transaction = database.transaction(name, 'readonly');
+ const store = transaction.objectStore(name);
+ return checkStoreContents(
+ testCase, store,
+ 'Renaming an object store should not change its records').then(
+ () => database.close());
+ });
+ }, 'IndexedDB object store can be renamed to "' + escapedName + '"');
+})(escapedName);
+
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_add.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_add.htm
new file mode 100644
index 000000000..f091d1faf
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_add.htm
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.add() - add with an inline key </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { key: 1, property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { keyPath: "key" });
+
+ objStore.add(record);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("store")
+ .objectStore("store")
+ .get(record.key);
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result.property, record.property);
+ assert_equals(e.target.result.key, record.key);
+ t.done();
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_add10.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_add10.htm
new file mode 100644
index 000000000..f2bf44750
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_add10.htm
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.add() - Attempt to call 'add' without an key parameter when the object store uses out-of-line keys </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var rq,
+ objStore = db.createObjectStore("store");
+
+ assert_throws("DataError",
+ function() { rq = objStore.add(record); });
+
+ assert_equals(rq, undefined);
+ t.done();
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_add11.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_add11.htm
new file mode 100644
index 000000000..99ff14c31
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_add11.htm
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.add() - Attempt to add a record where the record's key does not meet the constraints of a valid key </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { key: { value: 1 }, property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var rq,
+ objStore = db.createObjectStore("store", { keyPath: "key" });
+
+ assert_throws("DataError",
+ function() { rq = objStore.add(record); });
+
+ assert_equals(rq, undefined);
+ t.done();
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_add12.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_add12.htm
new file mode 100644
index 000000000..d679af08b
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_add12.htm
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.add() - Attempt to add a record where the record's in-line key is not defined </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var rq,
+ objStore = db.createObjectStore("store", { keyPath: "key" });
+
+ assert_throws("DataError",
+ function() { rq = objStore.add(record); });
+
+ assert_equals(rq, undefined);
+ t.done();
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_add13.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_add13.htm
new file mode 100644
index 000000000..943a6cf9b
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_add13.htm
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.add() - Attempt to add a record where the out of line key provided does not meet the constraints of a valid key </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var rq,
+ objStore = db.createObjectStore("store");
+
+ assert_throws("DataError",
+ function() { rq = objStore.add(record, { value: 1 }); });
+
+ assert_equals(rq, undefined);
+ t.done();
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_add14.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_add14.htm
new file mode 100644
index 000000000..5bac57cb7
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_add14.htm
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.add() - Add a record where a value being indexed does not meet the constraints of a valid key </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { key: 1, indexedProperty: { property: "data" } };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var rq,
+ objStore = db.createObjectStore("store", { keyPath: "key" });
+
+ objStore.createIndex("index", "indexedProperty");
+
+ rq = objStore.add(record);
+
+ assert_true(rq instanceof IDBRequest);
+ rq.onsuccess = function() {
+ t.done();
+ }
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_add15.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_add15.htm
new file mode 100644
index 000000000..268ed72e9
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_add15.htm
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.add() - If the transaction this IDBObjectStore belongs to has its mode set to readonly, throw ReadOnlyError </title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBObjectStore-add-IDBRequest-any-value-any-key">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ db.createObjectStore("store", {keyPath:"pKey"});
+ }
+
+ open_rq.onsuccess = function (event) {
+ var txn = db.transaction("store");
+ var ostore = txn.objectStore("store");
+ t.step(function(){
+ assert_throws("ReadOnlyError", function(){
+ ostore.add({ pKey: "primaryKey_0"});
+ });
+ });
+ t.done();
+ }
+</script>
+
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_add16.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_add16.htm
new file mode 100644
index 000000000..391b94458
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_add16.htm
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.add() - If the object store has been deleted, the implementation must throw a DOMException of type InvalidStateError </title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBObjectStore-add-IDBRequest-any-value-any-key">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ ostore,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ ostore = db.createObjectStore("store", {keyPath:"pKey"});
+ db.deleteObjectStore("store");
+ assert_throws("InvalidStateError", function(){
+ ostore.add({ pKey: "primaryKey_0"});
+ });
+ t.done();
+ }
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_add2.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_add2.htm
new file mode 100644
index 000000000..70c055445
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_add2.htm
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.add() - add with an out-of-line key </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ key = 1,
+ record = { property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store");
+
+ objStore.add(record, key);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("store")
+ .objectStore("store")
+ .get(key);
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result.property, record.property);
+
+ t.done();
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_add3.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_add3.htm
new file mode 100644
index 000000000..ac397372d
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_add3.htm
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.add() - record with same key already exists </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { key: 1, property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { keyPath: "key" });
+ objStore.add(record);
+
+ var rq = objStore.add(record);
+ rq.onsuccess = fail(t, "success on adding duplicate record")
+
+ rq.onerror = t.step_func(function(e) {
+ assert_equals(e.target.error.name, "ConstraintError");
+ assert_equals(rq.error.name, "ConstraintError");
+ assert_equals(e.type, "error");
+
+ e.preventDefault();
+ e.stopPropagation();
+ });
+ };
+
+ // Defer done, giving rq.onsuccess a chance to run
+ open_rq.onsuccess = function(e) {
+ t.done();
+ }
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_add4.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_add4.htm
new file mode 100644
index 000000000..c4b875cd4
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_add4.htm
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.add() - add where an index has unique:true specified </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { key: 1, property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { autoIncrement: true });
+ objStore.createIndex("i1", "property", { unique: true });
+ objStore.add(record);
+
+ var rq = objStore.add(record);
+ rq.onsuccess = fail(t, "success on adding duplicate indexed record")
+
+ rq.onerror = t.step_func(function(e) {
+ assert_equals(rq.error.name, "ConstraintError");
+ assert_equals(e.target.error.name, "ConstraintError");
+ assert_equals(e.type, "error");
+
+ e.preventDefault();
+ e.stopPropagation();
+ });
+ };
+
+ // Defer done, giving a spurious rq.onsuccess a chance to run
+ open_rq.onsuccess = function(e) {
+ t.done();
+ }
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_add5.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_add5.htm
new file mode 100644
index 000000000..1c1cd1fb2
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_add5.htm
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.add() - object store's key path is an object attribute </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { test: { obj: { key: 1 } }, property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { keyPath: "test.obj.key" });
+ objStore.add(record);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("store")
+ .objectStore("store")
+ .get(record.test.obj.key);
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result.property, record.property);
+
+ t.done();
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_add6.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_add6.htm
new file mode 100644
index 000000000..c6f1910a3
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_add6.htm
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.add() - autoIncrement and inline keys </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { property: "data" },
+ expected_keys = [ 1, 2, 3, 4 ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { keyPath: "key", autoIncrement: true });
+
+ objStore.add(record);
+ objStore.add(record);
+ objStore.add(record);
+ objStore.add(record);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var actual_keys = [],
+ rq = db.transaction("store")
+ .objectStore("store")
+ .openCursor();
+
+ rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ if (cursor) {
+ actual_keys.push(cursor.value.key);
+ cursor.continue();
+ }
+ else {
+ assert_array_equals(actual_keys, expected_keys);
+ t.done();
+ }
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_add7.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_add7.htm
new file mode 100644
index 000000000..1b2a6dac3
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_add7.htm
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.add() - autoIncrement and out-of-line keys </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { property: "data" },
+ expected_keys = [ 1, 2, 3, 4 ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { autoIncrement: true });
+
+ objStore.add(record);
+ objStore.add(record);
+ objStore.add(record);
+ objStore.add(record);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var actual_keys = [],
+ rq = db.transaction("store")
+ .objectStore("store")
+ .openCursor();
+
+ rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ if (cursor) {
+ actual_keys.push(cursor.key);
+ cursor.continue();
+ }
+ else {
+ assert_array_equals(actual_keys, expected_keys);
+ t.done();
+ }
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_add8.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_add8.htm
new file mode 100644
index 000000000..b3266fdc0
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_add8.htm
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.add() - object store has autoIncrement:true and the key path is an object attribute </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { property: "data" },
+ expected_keys = [ 1, 2, 3, 4 ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { keyPath: "test.obj.key", autoIncrement: true });
+
+ objStore.add(record);
+ objStore.add(record);
+ objStore.add(record);
+ objStore.add(record);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var actual_keys = [],
+ rq = db.transaction("store")
+ .objectStore("store")
+ .openCursor();
+
+ rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ if (cursor) {
+ actual_keys.push(cursor.value.test.obj.key);
+ cursor.continue();
+ }
+ else {
+ assert_array_equals(actual_keys, expected_keys);
+ t.done();
+ }
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_add9.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_add9.htm
new file mode 100644
index 000000000..6e027a11d
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_add9.htm
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.add() - Attempt to add a record that does not meet the constraints of an object store's inline key requirements </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var t = async_test(),
+ record = { key: 1, property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ var rq,
+ db = e.target.result,
+ objStore = db.createObjectStore("store", { keyPath: "key" });
+
+ assert_throws("DataError",
+ function() { rq = objStore.add(record, 1); });
+
+ assert_equals(rq, undefined);
+ t.done();
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_clear.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_clear.htm
new file mode 100644
index 000000000..d9c3fb2a1
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_clear.htm
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.clear() - Verify clear removes all records </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { autoIncrement: true });
+
+ objStore.add({ property: "data" });
+ objStore.add({ something_different: "Yup, totally different" });
+ objStore.add(1234);
+ objStore.add([1, 2, 1234]);
+
+ objStore.clear().onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, undefined);
+ });
+ };
+
+
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("store")
+ .objectStore("store")
+ .openCursor();
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, null, 'cursor');
+ t.done();
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_clear2.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_clear2.htm
new file mode 100644
index 000000000..ac1fdff4c
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_clear2.htm
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.clear() - clear removes all records from an index </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { autoIncrement: true });
+ objStore.createIndex("index", "indexedProperty");
+
+ objStore.add({ indexedProperty: "data" });
+ objStore.add({ indexedProperty: "yo, man", something_different: "Yup, totally different" });
+ objStore.add({ indexedProperty: 1234 });
+ objStore.add({ indexedProperty: [1, 2, 1234] });
+ objStore.add(1234);
+
+ objStore.clear().onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, undefined);
+ });
+ };
+
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("store")
+ .objectStore("store")
+ .index("index")
+ .openCursor();
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, null, 'cursor');
+ t.done();
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_clear3.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_clear3.htm
new file mode 100644
index 000000000..fc0fa4d8d
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_clear3.htm
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.clear() - If the transaction this IDBObjectStore belongs to has its mode set to readonly, throw ReadOnlyError </title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBObjectStore-clear-IDBRequest">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test(),
+ records = [{ pKey: "primaryKey_0"},
+ { pKey: "primaryKey_1"}];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ var objStore = db.createObjectStore("store", {keyPath:"pKey"});
+ for (var i = 0; i < records.length; i++) {
+ objStore.add(records[i]);
+ }
+ }
+
+ open_rq.onsuccess = function (event) {
+ var txn = db.transaction("store");
+ var ostore = txn.objectStore("store");
+ t.step(function(){
+ assert_throws("ReadOnlyError", function(){
+ ostore.clear();
+ });
+ });
+ t.done();
+ }
+</script>
+
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_clear4.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_clear4.htm
new file mode 100644
index 000000000..4e08f6738
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_clear4.htm
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.clear() - If the object store has been deleted, the implementation must throw a DOMException of type InvalidStateError </title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBObjectStore-clear-IDBRequest">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ ostore,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ ostore = db.createObjectStore("store", {keyPath:"pKey"});
+ db.deleteObjectStore("store");
+ assert_throws("InvalidStateError", function(){
+ ostore.clear();
+ });
+ t.done();
+ }
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_count.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_count.htm
new file mode 100644
index 000000000..a54d16e43
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_count.htm
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>IDBObjectStore.count() - returns the number of records in the object store </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db, t = async_test();
+
+ var open_rq = createdb(t);
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var store = db.createObjectStore("store");
+
+ for(var i = 0; i < 10; i++) {
+ store.add({ data: "data" + i }, i);
+ }
+ }
+
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("store")
+ .objectStore("store")
+ .count();
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, 10);
+ t.done();
+ });
+ }
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_count2.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_count2.htm
new file mode 100644
index 000000000..b92715a2d
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_count2.htm
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>IDBObjectStore.count() - returns the number of records that have keys within the range </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db, t = async_test();
+
+ var open_rq = createdb(t);
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var store = db.createObjectStore("store");
+
+ for(var i = 0; i < 10; i++) {
+ store.add({ data: "data" + i }, i);
+ }
+ }
+
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("store")
+ .objectStore("store")
+ .count(IDBKeyRange.bound(5,20));
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, 5);
+ t.done();
+ });
+ }
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_count3.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_count3.htm
new file mode 100644
index 000000000..970b87a3d
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_count3.htm
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>IDBObjectStore.count() - returns the number of records that have keys with the key</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db
+
+ createdb(async_test()).onupgradeneeded = function(e) {
+ db = e.target.result
+
+ var store = db.createObjectStore("store", { keyPath: "k" })
+
+ for (var i = 0; i < 5; i++)
+ store.add({ k: "key_" + i });
+
+ store.count("key_2").onsuccess = this.step_func(function(e) {
+ assert_equals(e.target.result, 1, "count(key_2)")
+
+ store.count("key_").onsuccess = this.step_func(function(e) {
+ assert_equals(e.target.result, 0, "count(key_)")
+ this.done()
+ })
+ })
+ }
+
+</script>
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_count4.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_count4.htm
new file mode 100644
index 000000000..50dd6fe54
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_count4.htm
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.count() - If the object store has been deleted, the implementation must throw a DOMException of type InvalidStateError </title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBObjectStore-count-IDBRequest-any-key">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ ostore,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ ostore = db.createObjectStore("store", {keyPath:"pKey"});
+ db.deleteObjectStore("store");
+ assert_throws("InvalidStateError", function(){
+ ostore.count();
+ });
+ t.done();
+ }
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex.htm
new file mode 100644
index 000000000..8f0327c1a
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex.htm
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.createIndex() - returns an IDBIndex and the properties are set correctly</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store");
+ var index = objStore.createIndex("index", "indexedProperty", { unique: true });
+
+ assert_true(index instanceof IDBIndex, "IDBIndex");
+ assert_equals(index.name, "index", "name");
+ assert_equals(index.objectStore, objStore, "objectStore");
+ assert_equals(index.keyPath, "indexedProperty", "keyPath");
+ assert_true(index.unique, "unique");
+ assert_false(index.multiEntry, "multiEntry");
+
+ t.done();
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex10.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex10.htm
new file mode 100644
index 000000000..757296253
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex10.htm
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBDatabase.createIndex() - If an index with the name name already exists in this object store, the implementation must throw a DOMException of type ConstraintError </title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBObjectStore-createIndex-IDBIndex-DOMString-name-DOMString-sequence-DOMString--keyPath-IDBIndexParameters-optionalParameters">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test(),
+ open_rq = createdb(t);
+
+open_rq.onupgradeneeded = function (e) {
+ var db = e.target.result;
+ var ostore = db.createObjectStore("store");
+ ostore.createIndex("a", "a");
+ assert_throws("ConstraintError", function(){
+ ostore.createIndex("a", "a");
+ });
+ t.done();
+}
+</script>
+
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex11.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex11.htm
new file mode 100644
index 000000000..7da1169e4
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex11.htm
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBDatabase.createIndex() - If keyPath is not a valid key path, the implementation must throw a DOMException of type SyntaxError </title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBObjectStore-createIndex-IDBIndex-DOMString-name-DOMString-sequence-DOMString--keyPath-IDBIndexParameters-optionalParameters">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test(),
+ open_rq = createdb(t);
+
+open_rq.onupgradeneeded = function (e) {
+ var db = e.target.result;
+ var ostore = db.createObjectStore("store");
+ assert_throws("SyntaxError", function(){
+ ostore.createIndex("ab", ".");
+ });
+ t.done();
+}
+</script>
+
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex12.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex12.htm
new file mode 100644
index 000000000..18296b4ad
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex12.htm
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBDatabase.createIndex() - If the object store has been deleted, the implementation must throw a DOMException of type InvalidStateError </title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBObjectStore-createIndex-IDBIndex-DOMString-name-DOMString-sequence-DOMString--keyPath-IDBIndexParameters-optionalParameters">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ ostore,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ ostore = db.createObjectStore("store");
+ db.deleteObjectStore("store");
+ }
+
+ open_rq.onsuccess = function (event) {
+ t.step(function(){
+ assert_throws("InvalidStateError", function(){
+ ostore.createIndex("index", "indexedProperty");
+ });
+ });
+ t.done();
+ }
+</script>
+
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex13.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex13.htm
new file mode 100644
index 000000000..fb70cc72b
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex13.htm
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBDatabase.createIndex() - Operate out versionchange throw InvalidStateError </title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBObjectStore-createIndex-IDBIndex-DOMString-name-DOMString-sequence-DOMString--keyPath-IDBIndexParameters-optionalParameters">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ db.createObjectStore("store");
+ }
+
+ open_rq.onsuccess = function (event) {
+ var txn = db.transaction("store", "readwrite");
+ ostore = txn.objectStore("store");
+ t.step(function(){
+ assert_throws("InvalidStateError", function(){
+ ostore.createIndex("index", "indexedProperty");
+ });
+ });
+ t.done();
+ }
+</script>
+
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex14-exception_order.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex14-exception_order.htm
new file mode 100644
index 000000000..a0ec288cb
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex14-exception_order.htm
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<title>IndexedDB: Exception Order of IDBObjectStore.createIndex()</title>
+<link rel="author" title="Mozilla" href="https://www.mozilla.org">
+<link rel="help" href="http://w3c.github.io/IndexedDB/#dom-idbobjectstore-createindex">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<script>
+
+indexeddb_test(
+ function(t, db, txn) {
+ var store = db.createObjectStore("s");
+ },
+ function(t, db) {
+ var txn = db.transaction("s");
+ var store = txn.objectStore("s");
+ txn.oncomplete = function() {
+ assert_throws("InvalidStateError", function() {
+ store.createIndex("index", "foo");
+ }, "Mode check should precede state check of the transaction");
+ t.done();
+ };
+ },
+ "InvalidStateError(Incorrect mode) vs. TransactionInactiveError"
+);
+
+var gDeletedObjectStore;
+indexeddb_test(
+ function(t, db, txn) {
+ gDeletedObjectStore = db.createObjectStore("s");
+ db.deleteObjectStore("s");
+ txn.oncomplete = function() {
+ assert_throws("InvalidStateError", function() {
+ gDeletedObjectStore.createIndex("index", "foo");
+ }, "Deletion check should precede transaction-state check");
+ t.done();
+ };
+ },
+ null,
+ "InvalidStateError(Deleted ObjectStore) vs. TransactionInactiveError"
+);
+
+indexeddb_test(
+ function(t, db, txn) {
+ var store = db.createObjectStore("s");
+ store.createIndex("index", "foo");
+ txn.oncomplete = function() {
+ assert_throws("TransactionInactiveError", function() {
+ store.createIndex("index", "foo");
+ }, "Transaction-state check should precede index name check");
+ t.done();
+ };
+ },
+ null,
+ "TransactionInactiveError vs. ConstraintError"
+);
+
+indexeddb_test(
+ function(t, db) {
+ var store = db.createObjectStore("s");
+ store.createIndex("index", "foo");
+ assert_throws("ConstraintError", function() {
+ store.createIndex("index", "invalid key path");
+ }, "Index name check should precede syntax check of the key path");
+ assert_throws("ConstraintError", function() {
+ store.createIndex("index",
+ ["invalid key path 1", "invalid key path 2"]);
+ }, "Index name check should precede syntax check of the key path");
+ t.done();
+ },
+ null,
+ "ConstraintError vs. SyntaxError"
+);
+
+indexeddb_test(
+ function(t, db) {
+ var store = db.createObjectStore("s");
+ assert_throws("SyntaxError", function() {
+ store.createIndex("index",
+ ["invalid key path 1", "invalid key path 2"],
+ { multiEntry: true });
+ }, "Syntax check should precede multiEntry check of the key path");
+ t.done();
+ },
+ null,
+ "SyntaxError vs. InvalidAccessError"
+);
+
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex2.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex2.htm
new file mode 100644
index 000000000..9dc1686b1
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex2.htm
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.createIndex() - attempt to create an index that requires unique values on an object store already contains duplicates </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db, aborted,
+ t = async_test(),
+ record = { indexedProperty: "bar" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var txn = e.target.transaction,
+ objStore = db.createObjectStore("store");
+
+ objStore.add(record, 1);
+ objStore.add(record, 2);
+ var index = objStore.createIndex("index", "indexedProperty", { unique: true });
+
+ assert_true(index instanceof IDBIndex, "IDBIndex");
+
+ e.target.transaction.onabort = t.step_func(function(e) {
+ aborted = true;
+ assert_equals(e.type, "abort", "event type");
+ });
+
+ db.onabort = function(e) {
+ assert_true(aborted, "transaction.abort event has fired");
+ t.done();
+ };
+
+ e.target.transaction.oncomplete = fail(t, "got complete, expected abort");
+ };
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex3-usable-right-away.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex3-usable-right-away.htm
new file mode 100644
index 000000000..f4b9b984f
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex3-usable-right-away.htm
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.createIndex() - the index is usable right after being made</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<meta name=timeout content=long>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db, aborted,
+ t = async_test(document.title, {timeout:19000})
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var txn = e.target.transaction,
+ objStore = db.createObjectStore("store", { keyPath: 'key' });
+
+ for (var i = 0; i < 100; i++)
+ objStore.add({ key: "key_" + i, indexedProperty: "indexed_" + i });
+
+ var idx = objStore.createIndex("index", "indexedProperty")
+
+ idx.get('indexed_99').onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result.key, 'key_99', 'key');
+ });
+ idx.get('indexed_9').onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result.key, 'key_9', 'key');
+ });
+ }
+
+ open_rq.onsuccess = function() {
+ t.done();
+ }
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex4-deleteIndex-event_order.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex4-deleteIndex-event_order.htm
new file mode 100644
index 000000000..228dfc457
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex4-deleteIndex-event_order.htm
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.createIndex() - Event ordering for a later deleted index</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ events = [],
+ t = async_test(document.title, {timeout: 10000})
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ e.target.transaction.oncomplete = log("transaction.complete");
+
+ var txn = e.target.transaction,
+ objStore = db.createObjectStore("store");
+
+ var rq_add1 = objStore.add({ animal: "Unicorn" }, 1);
+ rq_add1.onsuccess = log("rq_add1.success");
+ rq_add1.onerror = log("rq_add1.error");
+
+ objStore.createIndex("index", "animal", { unique: true });
+
+ var rq_add2 = objStore.add({ animal: "Unicorn" }, 2);
+ rq_add2.onsuccess = log("rq_add2.success");
+ rq_add2.onerror = function(e) {
+ log("rq_add2.error")(e);
+ e.preventDefault();
+ e.stopPropagation();
+ }
+
+ objStore.deleteIndex("index");
+
+ var rq_add3 = objStore.add({ animal: "Unicorn" }, 3);
+ rq_add3.onsuccess = log("rq_add3.success");
+ rq_add3.onerror = log("rq_add3.error");
+ }
+
+ open_rq.onsuccess = function(e) {
+ log("open_rq.success")(e);
+ assert_array_equals(events, [ "rq_add1.success",
+ "rq_add2.error: ConstraintError",
+ "rq_add3.success",
+
+ "transaction.complete",
+
+ "open_rq.success" ],
+ "events");
+ t.done();
+ }
+
+ function log(msg) {
+ return function(e) {
+ if(e && e.target && e.target.error)
+ events.push(msg + ": " + e.target.error.name);
+ else
+ events.push(msg);
+ };
+ }
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex5-emptykeypath.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex5-emptykeypath.htm
new file mode 100644
index 000000000..29fadc00e
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex5-emptykeypath.htm
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.createIndex() - empty keyPath</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db, aborted,
+ t = async_test(document.title, {timeout: 10000})
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var txn = e.target.transaction,
+ objStore = db.createObjectStore("store");
+
+ for (var i = 0; i < 5; i++)
+ objStore.add("object_" + i, i);
+
+ var rq = objStore.createIndex("index", "")
+ rq.onerror = function() { assert_unreached("error: " + rq.error.name); }
+ rq.onsuccess = function() { }
+
+ objStore.index("index")
+ .get('object_4')
+ .onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, 'object_4', 'result');
+ });
+ }
+
+ open_rq.onsuccess = function() {
+ t.done();
+ }
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex6-event_order.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex6-event_order.htm
new file mode 100644
index 000000000..3dcb7330a
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex6-event_order.htm
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>IDBObjectStore.createIndex() - event order when unique constraint is triggered</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<meta rel=help href=http://odinho.html5.org/IndexedDB/spec/Overview.html#widl-IDBObjectStore-createIndex-IDBIndex-DOMString-name-any-keyPath-IDBIndexParameters-optionalParameters>
+<meta rel=assert title="The index that is requested to be created can contain constraints on the data allowed in the index's referenced object store, such as requiring uniqueness of the values referenced by the index's keyPath. If the referenced object store already contains data which violates these constraints, this must not cause the implementation of createIndex to throw an exception or affect what it returns. The implementation must still create and return an IDBIndex object. Instead the implementation must queue up an operation to abort the 'versionchange' transaction which was used for the createIndex call.">
+<meta rel=assert title="In some implementations it's possible for the implementation to asynchronously run into problems creating the index after the createIndex function has returned. For example in implementations where metadata about the newly created index is queued up to be inserted into the database asynchronously, or where the implementation might need to ask the user for permission for quota reasons. Such implementations must still create and return an IDBIndex object. Instead, once the implementation realizes that creating the index has failed, it must abort the transaction using the steps for aborting a transaction using the appropriate error as error parameter.">
+<meta rel=assert title="if the index can't be created due to unique constraints, ConstraintError must be used as error">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ // Transaction may fire window.onerror in some implementations.
+ setup({allow_uncaught_exception:true});
+
+ var db,
+ events = [],
+ t = async_test(document.title, {timeout: 10000})
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ db.onerror = log("db.error");
+ db.onabort = log("db.abort");
+ e.target.transaction.onabort = log("transaction.abort")
+ e.target.transaction.onerror = log("transaction.error")
+ e.target.transaction.oncomplete = log("transaction.complete")
+
+ var txn = e.target.transaction,
+ objStore = db.createObjectStore("store");
+
+ var rq_add1 = objStore.add({ animal: "Unicorn" }, 1);
+ rq_add1.onsuccess = log("rq_add1.success");
+ rq_add1.onerror = log("rq_add1.error");
+
+ var rq_add2 = objStore.add({ animal: "Unicorn" }, 2);
+ rq_add2.onsuccess = log("rq_add2.success");
+ rq_add2.onerror = log("rq_add2.error");
+
+ objStore.createIndex("index", "animal", { unique: true })
+
+ var rq_add3 = objStore.add({ animal: "Unicorn" }, 3);
+ rq_add3.onsuccess = log("rq_add3.success");
+ rq_add3.onerror = log("rq_add3.error");
+ }
+
+ open_rq.onerror = function(e) {
+ log("open_rq.error")(e);
+ assert_array_equals(events, [ "rq_add1.success",
+ "rq_add2.success",
+
+ "rq_add3.error: AbortError",
+ "transaction.error: AbortError",
+ "db.error: AbortError",
+
+ "transaction.abort: ConstraintError",
+ "db.abort: ConstraintError",
+
+ "open_rq.error: AbortError" ],
+ "events");
+ t.done();
+ }
+
+ function log(msg) {
+ return function(e) {
+ if(e && e.target && e.target.error)
+ events.push(msg + ": " + e.target.error.name);
+ else
+ events.push(msg);
+ };
+ }
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex7-event_order.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex7-event_order.htm
new file mode 100644
index 000000000..f564f6611
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex7-event_order.htm
@@ -0,0 +1,80 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.createIndex() - Event ordering for ConstraintError on request</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<meta rel=help href=http://odinho.html5.org/IndexedDB/spec/Overview.html#dfn-steps-for-aborting-a-transaction>
+<meta rel=assert title="Unless error was set to null, create a DOMError object and set its name to error. Set transaction's error property to this newly created DOMError.">
+<meta rel=assert title="If the transaction's request list contain any requests whose done flag is still false, abort the steps for asynchronously executing a request for each such request and queue a task to perform the following steps:">
+<meta rel=assert title="set the request's error attribute to a DOMError with a type of AbortError.">
+<meta rel=assert title="Dispatch an event at request. The event must use the Event interface and have its type set to 'error'. The event bubbles and is cancelable. The propagation path for the event is transaction's connection, then transaction and finally the request. There is no default action for the event.">
+<meta rel=assert title="Queue up an operation to dispatch an event at transaction. The event must use the Event interface and have its type set to 'abort'. The event does bubble but is not cancelable. The propagation path for the event is transaction's connection and then transaction.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ // Transaction may fire window.onerror in some implementations.
+ setup({allow_uncaught_exception:true});
+
+ var db,
+ events = [],
+ t = async_test(document.title, {timeout: 10000})
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var txn = e.target.transaction;
+ db.onerror = log("db.error");
+ db.onabort = log("db.abort");
+ txn.onabort = log("transaction.abort")
+ txn.onerror = log("transaction.error")
+ txn.oncomplete = log("transaction.complete")
+
+ var objStore = db.createObjectStore("store");
+
+ var rq_add1 = objStore.add({ animal: "Unicorn" }, 1);
+ rq_add1.onsuccess = log("rq_add1.success");
+ rq_add1.onerror = log("rq_add1.error");
+
+ objStore.createIndex("index", "animal", { unique: true })
+
+ var rq_add2 = objStore.add({ animal: "Unicorn" }, 2);
+ rq_add2.onsuccess = log("rq_add2.success");
+ rq_add2.onerror = log("rq_add2.error");
+
+ var rq_add3 = objStore.add({ animal: "Horse" }, 3);
+ rq_add3.onsuccess = log("rq_add3.success");
+ rq_add3.onerror = log("rq_add3.error");
+ }
+
+ open_rq.onerror = function(e) {
+ log("open_rq.error")(e);
+ assert_array_equals(events, [ "rq_add1.success",
+
+ "rq_add2.error: ConstraintError",
+ "transaction.error: ConstraintError",
+ "db.error: ConstraintError",
+
+ "rq_add3.error: AbortError",
+ "transaction.error: AbortError",
+ "db.error: AbortError",
+
+ "transaction.abort: ConstraintError",
+ "db.abort: ConstraintError",
+
+ "open_rq.error: AbortError" ],
+ "events");
+ t.done();
+ }
+
+ function log(msg) {
+ return function(e) {
+ if(e && e.target && e.target.error)
+ events.push(msg + ": " + e.target.error.name);
+ else
+ events.push(msg);
+ };
+ }
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex8-valid_keys.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex8-valid_keys.htm
new file mode 100644
index 000000000..6174523e4
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex8-valid_keys.htm
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.createIndex() - index can be valid keys</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<meta name=timeout content=long>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(document.title, {timeout:19000}),
+ now = new Date(),
+ mar18 = new Date(1111111111111),
+ ar = ["Yay", 2, -Infinity],
+ num = 1337
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var txn = e.target.transaction,
+ objStore = db.createObjectStore("store", { keyPath: 'key' });
+
+ objStore.add({ key: "now", i: now });
+ objStore.add({ key: "mar18", i: mar18 });
+ objStore.add({ key: "array", i: ar });
+ objStore.add({ key: "number", i: num });
+
+ var idx = objStore.createIndex("index", "i")
+
+ idx.get(now).onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result.key, 'now', 'key');
+ assert_equals(e.target.result.i.getTime(), now.getTime(), 'getTime');
+ });
+ idx.get(mar18).onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result.key, 'mar18', 'key');
+ assert_equals(e.target.result.i.getTime(), mar18.getTime(), 'getTime');
+ });
+ idx.get(ar).onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result.key, 'array', 'key');
+ assert_array_equals(e.target.result.i, ar, 'array is the same');
+ });
+ idx.get(num).onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result.key, 'number', 'key');
+ assert_equals(e.target.result.i, num, 'number is the same');
+ });
+ }
+
+ open_rq.onsuccess = function() {
+ t.done();
+ }
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex9-emptyname.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex9-emptyname.htm
new file mode 100644
index 000000000..3d04357c9
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_createIndex9-emptyname.htm
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>IDBObjectStore.createIndex() - empty name</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db
+
+ var open_rq = createdb(async_test())
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result
+ var store = db.createObjectStore("store")
+
+ for (var i = 0; i < 5; i++)
+ store.add({ idx: "object_" + i }, i)
+
+ store.createIndex("", "idx")
+
+ store.index("")
+ .get('object_4')
+ .onsuccess = this.step_func(function(e) {
+ assert_equals(e.target.result.idx, 'object_4', 'result')
+ })
+ assert_equals(store.indexNames[0], "", "indexNames[0]")
+ assert_equals(store.indexNames.length, 1, "indexNames.length")
+ }
+
+ open_rq.onsuccess = function() {
+ var store = db.transaction("store").objectStore("store")
+
+ assert_equals(store.indexNames[0], "", "indexNames[0]")
+ assert_equals(store.indexNames.length, 1, "indexNames.length")
+
+ this.done()
+ }
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_delete.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_delete.htm
new file mode 100644
index 000000000..337289296
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_delete.htm
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.delete() - delete removes record (inline keys)</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { key: 1, property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var objStore = db.createObjectStore("test", { keyPath: "key" });
+ objStore.add(record);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var delete_rq = db.transaction("test", "readwrite")
+ .objectStore("test")
+ .delete(record.key);
+
+ delete_rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, undefined);
+
+ e.target.transaction.oncomplete = t.step_func(VerifyRecordRemoved);
+ });
+ };
+
+ function VerifyRecordRemoved() {
+ var rq = db.transaction("test")
+ .objectStore("test")
+ .get(record.key);
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, undefined);
+ t.done();
+ });
+ }
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_delete2.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_delete2.htm
new file mode 100644
index 000000000..f7e468460
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_delete2.htm
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.delete() - key doesn't match any records </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var delete_rq = db.createObjectStore("test")
+ .delete(1);
+
+ delete_rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, undefined);
+ t.done();
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_delete3.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_delete3.htm
new file mode 100644
index 000000000..b72b1072d
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_delete3.htm
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.delete() - object store's key path is an object attribute </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { test: { obj: { key: 1 } }, property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var objStore = db.createObjectStore("test", { keyPath: "test.obj.key" });
+ objStore.add(record);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var delete_rq = db.transaction("test", "readwrite")
+ .objectStore("test")
+ .delete(record.test.obj.key);
+
+ delete_rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, undefined);
+
+ e.target.transaction.oncomplete = t.step_func(VerifyRecordRemoved);
+ });
+ };
+
+ function VerifyRecordRemoved() {
+ var rq = db.transaction("test")
+ .objectStore("test")
+ .get(record.test.obj.key);
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, undefined);
+ t.done();
+ });
+ }
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_delete4.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_delete4.htm
new file mode 100644
index 000000000..3d36b7962
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_delete4.htm
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.delete() - delete removes record (out-of-line keys) </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ key = 1,
+ record = { property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var objStore = db.createObjectStore("test");
+ objStore.add(record, key);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var delete_rq = db.transaction("test", "readwrite")
+ .objectStore("test")
+ .delete(key);
+
+ delete_rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, undefined);
+
+ e.target.transaction.oncomplete = t.step_func(VerifyRecordRemoved);
+ });
+ };
+
+ function VerifyRecordRemoved() {
+ var rq = db.transaction("test")
+ .objectStore("test")
+ .get(key);
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, undefined);
+ t.done();
+ });
+ }
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_delete5.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_delete5.htm
new file mode 100644
index 000000000..9e8ac80a1
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_delete5.htm
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<title>IDBObjectStore.delete() - removes all of the records in the range</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+<script>
+ var db
+ var open_rq = createdb(async_test())
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result
+ var os = db.createObjectStore("store")
+
+ for(var i = 0; i < 10; i++)
+ os.add("data" + i, i)
+ }
+
+ open_rq.onsuccess = function (e) {
+ var os = db.transaction("store", "readwrite")
+ .objectStore("store")
+
+ os.delete( IDBKeyRange.bound(3, 6) )
+ os.count().onsuccess = this.step_func(function(e)
+ {
+ assert_equals(e.target.result, 6, "Count after deleting 3-6 from 10");
+ this.done();
+ })
+ }
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_delete6.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_delete6.htm
new file mode 100644
index 000000000..01d54dee9
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_delete6.htm
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.delete() - If the transaction this IDBObjectStore belongs to has its mode set to readonly, throw ReadOnlyError</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBObjectStore-delete-IDBRequest-any-key">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test(),
+ records = [{ pKey: "primaryKey_0"},
+ { pKey: "primaryKey_1"}];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ var objStore = db.createObjectStore("store", {keyPath:"pKey"});
+ for (var i = 0; i < records.length; i++) {
+ objStore.add(records[i]);
+ }
+ }
+
+ open_rq.onsuccess = function (event) {
+ var txn = db.transaction("store");
+ var ostore = txn.objectStore("store");
+ t.step(function(){
+ assert_throws("ReadOnlyError", function(){
+ ostore.delete("primaryKey_0");
+ });
+ });
+ t.done();
+ }
+</script>
+
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_delete7.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_delete7.htm
new file mode 100644
index 000000000..98831c5da
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_delete7.htm
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.delete() - If the object store has been deleted, the implementation must throw a DOMException of type InvalidStateError</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBObjectStore-delete-IDBRequest-any-key">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ ostore,
+ t = async_test(),
+ records = [{ pKey: "primaryKey_0"},
+ { pKey: "primaryKey_1"}];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ ostore = db.createObjectStore("store", {keyPath:"pKey"});
+ db.deleteObjectStore("store");
+ assert_throws("InvalidStateError", function(){
+ ostore.delete("primaryKey_0");
+ });
+ t.done();
+ }
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_deleteIndex.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_deleteIndex.htm
new file mode 100644
index 000000000..1e0fb2976
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_deleteIndex.htm
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.deleteIndex() - removes the index </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ key = 1,
+ record = { property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ db.createObjectStore("test")
+ .createIndex("index", "indexedProperty")
+ };
+
+ open_rq.onsuccess = function(e) {
+ db.close();
+ var new_version = createdb(t, db.name, 2);
+ new_version.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = e.target.transaction.objectStore("test")
+ objStore.deleteIndex("index");
+ }
+ new_version.onsuccess = function(e) {
+ var index,
+ objStore = db.transaction("test")
+ .objectStore("test");
+
+ assert_throws('NotFoundError',
+ function() { index = objStore.index("index") });
+ assert_equals(index, undefined);
+ t.done();
+ }
+ }
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_deleted.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_deleted.htm
new file mode 100644
index 000000000..1d9421ce0
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_deleted.htm
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Attempting to use deleted IDBObjectStore</title>
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#object-store">
+<link rel=assert title="InvalidStateError Occurs if a request is made on a source object that has been deleted or removed.">
+<link rel=author href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db,
+ add_success = false,
+ t = async_test(document.title, {timeout: 10000})
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var objStore = db.createObjectStore("store", { autoIncrement: true });
+ assert_equals(db.objectStoreNames[0], "store", "objectStoreNames");
+
+ var rq_add = objStore.add(1);
+ rq_add.onsuccess = function() { add_success = true; };
+ rq_add.onerror = fail(t, 'rq_add.error');
+
+ objStore.createIndex("idx", "a");
+ db.deleteObjectStore("store");
+ assert_equals(db.objectStoreNames.length, 0, "objectStoreNames.length after delete");
+
+ assert_throws(null, function() { objStore.add(2); });
+ assert_throws(null, function() { objStore.put(3); });
+ assert_throws(null, function() { objStore.get(1); });
+ assert_throws(null, function() { objStore.clear(); });
+ assert_throws(null, function() { objStore.count(); });
+ assert_throws(null, function() { objStore.delete(1); });
+ assert_throws(null, function() { objStore.openCursor(); });
+ assert_throws(null, function() { objStore.index("idx"); });
+ assert_throws(null, function() { objStore.deleteIndex("idx"); });
+ assert_throws(null, function() { objStore.createIndex("idx2", "a"); });
+ }
+
+ open_rq.onsuccess = function() {
+ assert_true(add_success, "First add was successful");
+ t.done();
+ }
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_get.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_get.htm
new file mode 100644
index 000000000..99aff78d5
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_get.htm
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.get() - key is a number </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { key: 3.14159265, property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ db.createObjectStore("store", { keyPath: "key" })
+ .add(record);
+ }
+
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("store")
+ .objectStore("store")
+ .get(record.key);
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result.key, record.key);
+ assert_equals(e.target.result.property, record.property);
+ t.done();
+ });
+ }
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_get2.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_get2.htm
new file mode 100644
index 000000000..dfbfea17c
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_get2.htm
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.get() - key is a string </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { key: "this is a key that's a string", property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ db.createObjectStore("store", { keyPath: "key" })
+ .add(record);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("store")
+ .objectStore("store")
+ .get(record.key);
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result.key, record.key);
+ assert_equals(e.target.result.property, record.property);
+ t.done();
+ });
+ };
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_get3.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_get3.htm
new file mode 100644
index 000000000..b093e5357
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_get3.htm
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.get() - key is a Date </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { key: new Date(), property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ db.createObjectStore("store", { keyPath: "key" })
+ .add(record);
+ }
+
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("store")
+ .objectStore("store")
+ .get(record.key);
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result.key.valueOf(), record.key.valueOf());
+ assert_equals(e.target.result.property, record.property);
+ t.done();
+ });
+ }
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_get4.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_get4.htm
new file mode 100644
index 000000000..7853697a1
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_get4.htm
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.get() - attempt to retrieve a record that doesn't exist </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var rq = db.createObjectStore("store", { keyPath: "key" })
+ .get(1);
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.results, undefined);
+ setTimeout(function() { t.done(); }, 10);
+ });
+ };
+
+ open_rq.onsuccess = function() {};
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_get5.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_get5.htm
new file mode 100644
index 000000000..59b0ede64
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_get5.htm
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<title>IDBObjectStore.get() - returns the record with the first key in the range </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+<script>
+ var db
+ var open_rq = createdb(async_test())
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result
+ var os = db.createObjectStore("store")
+
+ for(var i = 0; i < 10; i++)
+ os.add("data" + i, i)
+ }
+
+ open_rq.onsuccess = function (e) {
+ db.transaction("store")
+ .objectStore("store")
+ .get( IDBKeyRange.bound(3, 6) )
+ .onsuccess = this.step_func(function(e)
+ {
+ assert_equals(e.target.result, "data3", "get(3-6)");
+ this.done();
+ })
+ }
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_get6.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_get6.htm
new file mode 100644
index 000000000..33381a684
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_get6.htm
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.get() - throw TransactionInactiveError on aborted transaction </title>
+<link rel="author" title="YuichiNukiyama" href="https://github.com/YuichiNukiyama">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ db.createObjectStore("store", { keyPath: "key" })
+ }
+
+ open_rq.onsuccess = function (e) {
+ var store = db.transaction("store")
+ .objectStore("store");
+ store.transaction.abort();
+ assert_throws("TransactionInactiveError", function () {
+ store.get(1);
+ }, "throw TransactionInactiveError on aborted transaction.");
+ t.done();
+ }
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_get7.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_get7.htm
new file mode 100644
index 000000000..570441b66
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_get7.htm
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.get() - throw DataError when using invalid key </title>
+<link rel="author" title="YuichiNukiyama" href="https://github.com/YuichiNukiyama">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ db.createObjectStore("store", { keyPath: "key" })
+ }
+
+ open_rq.onsuccess = function(e) {
+ var store = db.transaction("store")
+ .objectStore("store")
+ assert_throws("DataError", function () {
+ store.get(null)
+ }, "throw DataError when using invalid key.");
+ t.done();
+ }
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_getAll.html b/testing/web-platform/tests/IndexedDB/idbobjectstore_getAll.html
new file mode 100644
index 000000000..f81e4caf3
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_getAll.html
@@ -0,0 +1,174 @@
+<!DOCTYPE html>
+<title>IndexedDB: Test IDBObjectStore.getAll.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+setup({explicit_done: true});
+
+var alphabet = 'abcdefghijklmnopqrstuvwxyz'.split('');
+
+function doSetup(dbName, dbVersion, onsuccess) {
+ var delete_request = indexedDB.deleteDatabase(dbName);
+ delete_request.onerror = function() {
+ assert_unreached('deleteDatabase should not fail');
+ };
+ delete_request.onsuccess = function(e) {
+ var req = indexedDB.open(dbName, dbVersion);
+ req.onsuccess = onsuccess;
+ req.onerror = function() {
+ assert_unreached('open should not fail');
+ };
+ req.onupgradeneeded = function(evt) {
+ var connection = evt.target.result;
+
+ var store = connection.createObjectStore('generated',
+ {autoIncrement: true, keyPath: 'id'});
+ alphabet.forEach(function(letter) {
+ store.put({ch: letter});
+ });
+
+ store = connection.createObjectStore('out-of-line', null);
+ alphabet.forEach(function(letter) {
+ store.put('value-' + letter, letter);
+ });
+
+ store = connection.createObjectStore('empty', null);
+ };
+ };
+}
+
+function createGetAllRequest(t, storeName, connection, range, maxCount) {
+ var transaction = connection.transaction(storeName, 'readonly');
+ var store = transaction.objectStore(storeName);
+ var req = store.getAll(range, maxCount);
+ req.onerror = t.unreached_func('getAll request should succeed');
+ return req;
+}
+
+doSetup(location.pathname + '-IDBObjectStore.getAll', 1, function(evt) {
+ var connection = evt.target.result;
+ async_test(function(t) {
+ var req = createGetAllRequest(t, 'out-of-line', connection, 'c');
+ req.onsuccess = t.step_func(function(evt) {
+ assert_array_equals(evt.target.result, ['value-c']);
+ t.done();
+ });
+ }, 'Single item get');
+
+ async_test(function(t) {
+ var req = createGetAllRequest(t, 'generated', connection, 3);
+ req.onsuccess = t.step_func(function(evt) {
+ var data = evt.target.result;
+ assert_true(Array.isArray(data));
+ assert_equals(data.length, 1);
+ assert_equals(data[0].id, 3);
+ assert_equals(data[0].ch, 'c');
+ t.done();
+ });
+ }, 'Single item get (generated key)');
+
+ async_test(function(t) {
+ var req = createGetAllRequest(t, 'empty', connection);
+ req.onsuccess = t.step_func(function(evt) {
+ assert_array_equals(evt.target.result, [],
+ 'getAll() on empty object store should return an empty array');
+ t.done();
+ });
+ }, 'getAll on empty object store');
+
+ async_test(function(t) {
+ var req = createGetAllRequest(t, 'out-of-line', connection);
+ req.onsuccess = t.step_func(function(evt) {
+ assert_array_equals(evt.target.result,
+ alphabet.map(function(c) { return 'value-' + c; }));
+ t.done();
+ });
+ }, 'Get all values');
+
+ async_test(function(t) {
+ var req = createGetAllRequest(t, 'out-of-line', connection, undefined,
+ 10);
+ req.onsuccess = t.step_func(function(evt) {
+ assert_array_equals(evt.target.result,
+ 'abcdefghij'.split('').map(function(c) { return 'value-' + c; }));
+ t.done();
+ });
+ }, 'Test maxCount');
+
+ async_test(function(t) {
+ var req = createGetAllRequest(t, 'out-of-line', connection,
+ IDBKeyRange.bound('g', 'm'));
+ req.onsuccess = t.step_func(function(evt) {
+ assert_array_equals(evt.target.result,
+ 'ghijklm'.split('').map(function(c) { return 'value-' + c; }));
+ t.done();
+ });
+ }, 'Get bound range');
+
+ async_test(function(t) {
+ var req = createGetAllRequest(t, 'out-of-line', connection,
+ IDBKeyRange.bound('g', 'm'), 3);
+ req.onsuccess = t.step_func(function(evt) {
+ assert_array_equals(evt.target.result, ['g', 'h', 'i']
+ .map(function(c) { return 'value-' + c; }));
+ t.done();
+ });
+ }, 'Get bound range with maxCount');
+
+ async_test(function(t) {
+ var req = createGetAllRequest(t, 'out-of-line', connection,
+ IDBKeyRange.bound('g', 'k', false, true));
+ req.onsuccess = t.step_func(function(evt) {
+ assert_array_equals(evt.target.result, ['g', 'h', 'i', 'j']
+ .map(function(c) { return 'value-' + c; }));
+ t.done();
+ });
+ }, 'Get upper excluded');
+
+ async_test(function(t) {
+ var req = createGetAllRequest(t, 'out-of-line', connection,
+ IDBKeyRange.bound('g', 'k', true, false));
+ req.onsuccess = t.step_func(function(evt) {
+ assert_array_equals(evt.target.result, ['h', 'i', 'j', 'k']
+ .map(function(c) { return 'value-' + c; }));
+ t.done();
+ });
+ }, 'Get lower excluded');
+
+ async_test(function(t) {
+ var req = createGetAllRequest(t, 'generated', connection,
+ IDBKeyRange.bound(4, 15), 3);
+ req.onsuccess = t.step_func(function(evt) {
+ var data = evt.target.result;
+ assert_true(Array.isArray(data));
+ assert_array_equals(data.map(function(e) { return e.ch; }), ['d', 'e', 'f']);
+ assert_array_equals(data.map(function(e) { return e.id; }), [4, 5, 6]);
+ t.done();
+ });
+ }, 'Get bound range (generated) with maxCount');
+
+ async_test(function(t) {
+ var req = createGetAllRequest(t, 'out-of-line', connection,
+ "Doesn't exist");
+ req.onsuccess = t.step_func(function(evt) {
+ assert_array_equals(evt.target.result, [],
+ 'getAll() using a nonexistent key should return an empty array');
+ t.done();
+ });
+ req.onerror = t.unreached_func('getAll request should succeed');
+ }, 'Non existent key');
+
+ async_test(function(t) {
+ var req = createGetAllRequest(t, 'out-of-line', connection, undefined, 0);
+ req.onsuccess = t.step_func(function(evt) {
+ assert_array_equals(evt.target.result,
+ alphabet.map(function(c) { return 'value-' + c; }));
+ t.done();
+ });
+ }, 'zero maxCount');
+
+ // Explicit done needed in case async_test body fails synchronously.
+ done();
+});
+
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_getAllKeys.html b/testing/web-platform/tests/IndexedDB/idbobjectstore_getAllKeys.html
new file mode 100644
index 000000000..f4d317d43
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_getAllKeys.html
@@ -0,0 +1,167 @@
+<!DOCTYPE html>
+<title>IndexedDB: Test IDBObjectStore.getAllKeys.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+setup({explicit_done: true});
+
+var alphabet = 'abcdefghijklmnopqrstuvwxyz'.split('');
+
+function doSetup(dbName, dbVersion, onsuccess) {
+ var delete_request = indexedDB.deleteDatabase(dbName);
+ delete_request.onerror = function() {
+ assert_unreached('deleteDatabase should not fail');
+ };
+ delete_request.onsuccess = function(e) {
+ var req = indexedDB.open(dbName, dbVersion);
+ req.onsuccess = onsuccess;
+ req.onerror = function() {
+ assert_unreached('open should not fail');
+ };
+ req.onupgradeneeded = function(evt) {
+ var connection = evt.target.result;
+
+ var store = connection.createObjectStore('generated',
+ {autoIncrement: true, keyPath: 'id'});
+ alphabet.forEach(function(letter) {
+ store.put({ch: letter});
+ });
+
+ store = connection.createObjectStore('out-of-line', null);
+ alphabet.forEach(function(letter) {
+ store.put('value-' + letter, letter);
+ });
+
+ store = connection.createObjectStore('empty', null);
+ };
+ };
+}
+
+function createGetAllKeysRequest(t, storeName, connection, range, maxCount) {
+ var transaction = connection.transaction(storeName, 'readonly');
+ var store = transaction.objectStore(storeName);
+ var req = store.getAllKeys(range, maxCount);
+ req.onerror = t.unreached_func('getAllKeys request should succeed');
+ return req;
+}
+
+doSetup(location.pathname + '-IDBObjectStore.getAllKeys', 1, function(evt) {
+ var connection = evt.target.result;
+ async_test(function(t) {
+ var req = createGetAllKeysRequest(t, 'out-of-line', connection, 'c');
+ req.onsuccess = t.step_func(function(evt) {
+ assert_array_equals(evt.target.result, ['c']);
+ t.done();
+ });
+ }, 'Single item get');
+
+ async_test(function(t) {
+ var req = createGetAllKeysRequest(t, 'generated', connection, 3);
+ req.onsuccess = t.step_func(function(evt) {
+ var data = evt.target.result;
+ assert_true(Array.isArray(data));
+ assert_array_equals(data, [3]);
+ t.done();
+ });
+ }, 'Single item get (generated key)');
+
+ async_test(function(t) {
+ var req = createGetAllKeysRequest(t, 'empty', connection);
+ req.onsuccess = t.step_func(function(evt) {
+ assert_array_equals(evt.target.result, [],
+ 'getAllKeys() on empty object store should return an empty ' +
+ 'array');
+ t.done();
+ });
+ }, 'getAllKeys on empty object store');
+
+ async_test(function(t) {
+ var req = createGetAllKeysRequest(t, 'out-of-line', connection);
+ req.onsuccess = t.step_func(function(evt) {
+ assert_array_equals(evt.target.result, alphabet);
+ t.done();
+ });
+ }, 'Get all values');
+
+ async_test(function(t) {
+ var req = createGetAllKeysRequest(t, 'out-of-line', connection, undefined,
+ 10);
+ req.onsuccess = t.step_func(function(evt) {
+ assert_array_equals(evt.target.result, 'abcdefghij'.split(''));
+ t.done();
+ });
+ }, 'Test maxCount');
+
+ async_test(function(t) {
+ var req = createGetAllKeysRequest(t, 'out-of-line', connection,
+ IDBKeyRange.bound('g', 'm'));
+ req.onsuccess = t.step_func(function(evt) {
+ assert_array_equals(evt.target.result, 'ghijklm'.split(''));
+ t.done();
+ });
+ }, 'Get bound range');
+
+ async_test(function(t) {
+ var req = createGetAllKeysRequest(t, 'out-of-line', connection,
+ IDBKeyRange.bound('g', 'm'), 3);
+ req.onsuccess = t.step_func(function(evt) {
+ assert_array_equals(evt.target.result, ['g', 'h', 'i']);
+ t.done();
+ });
+ }, 'Get bound range with maxCount');
+
+ async_test(function(t) {
+ var req = createGetAllKeysRequest(t, 'out-of-line', connection,
+ IDBKeyRange.bound('g', 'k', false, true));
+ req.onsuccess = t.step_func(function(evt) {
+ assert_array_equals(evt.target.result, ['g', 'h', 'i', 'j']);
+ t.done();
+ });
+ }, 'Get upper excluded');
+
+ async_test(function(t) {
+ var req = createGetAllKeysRequest(t, 'out-of-line', connection,
+ IDBKeyRange.bound('g', 'k', true, false));
+ req.onsuccess = t.step_func(function(evt) {
+ assert_array_equals(evt.target.result, ['h', 'i', 'j', 'k']);
+ t.done();
+ });
+ }, 'Get lower excluded');
+
+ async_test(function(t) {
+ var req = createGetAllKeysRequest(t, 'generated', connection,
+ IDBKeyRange.bound(4, 15), 3);
+ req.onsuccess = t.step_func(function(evt) {
+ var data = evt.target.result;
+ assert_true(Array.isArray(data));
+ assert_array_equals(data, [4, 5, 6]);
+ t.done();
+ });
+ }, 'Get bound range (generated) with maxCount');
+
+ async_test(function(t) {
+ var req = createGetAllKeysRequest(t, 'out-of-line', connection,
+ "Doesn't exist");
+ req.onsuccess = t.step_func(function(evt) {
+ assert_array_equals(evt.target.result, [],
+ 'getAllKeys() using a nonexistent key should return an ' +
+ 'empty array');
+ t.done();
+ });
+ req.onerror = t.unreached_func('getAllKeys request should succeed');
+ }, 'Non existent key');
+
+ async_test(function(t) {
+ var req = createGetAllKeysRequest(t, 'out-of-line', connection, undefined,
+ 0);
+ req.onsuccess = t.step_func(function(evt) {
+ assert_array_equals(evt.target.result, alphabet);
+ t.done();
+ });
+ }, 'zero maxCount');
+
+ // Explicit done needed in case async_test body fails synchronously.
+ done();
+});
+
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_index.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_index.htm
new file mode 100644
index 000000000..5da58ecc3
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_index.htm
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.index() - returns an index </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ db.createObjectStore("store")
+ .createIndex("index", "indexedProperty");
+ };
+
+ open_rq.onsuccess = function(e) {
+ var index = db.transaction("store")
+ .objectStore("store")
+ .index("index");
+
+ assert_true(index instanceof IDBIndex, 'instanceof IDBIndex');
+ t.done();
+ };
+
+</script>
+
+
+<div id="log"></div>
+
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_openCursor.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_openCursor.htm
new file mode 100644
index 000000000..c54760a7c
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_openCursor.htm
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<title>IDBObjectStore.openCursor() - iterate through 100 objects</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db
+ var open_rq = createdb(async_test())
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var store = db.createObjectStore("store");
+
+ for (var i=0; i < 100; i++)
+ store.add("record_" + i, i);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var count = 0
+ var txn = db.transaction("store")
+
+ txn.objectStore("store")
+ .openCursor().onsuccess = this.step_func(function(e)
+ {
+ if (e.target.result) {
+ count += 1;
+ e.target.result.continue()
+ }
+ })
+
+ txn.oncomplete = this.step_func(function() {
+ assert_equals(count, 100);
+ this.done()
+ })
+ }
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_openCursor_invalid.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_openCursor_invalid.htm
new file mode 100644
index 000000000..698e7998b
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_openCursor_invalid.htm
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<title>IDBObjectStore.openCursor() - invalid</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db, open;
+
+ setup(function() {
+ open = indexedDB.open('testdb-' + new Date().getTime());
+ open.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("test");
+ objStore.createIndex("index", "");
+
+ objStore.add("data", 1);
+ objStore.add("data2", 2);
+ };
+ },
+ { explicit_done: true });
+
+
+ open.onsuccess = function() {
+
+ async_test(document.title + " - pass something other than number").step(function(e) {
+ var idx = db.transaction("test").objectStore("test").index("index");
+
+ assert_throws("DataError",
+ function() { idx.openCursor({ lower: "a" }); });
+
+ assert_throws("DataError",
+ function() { idx.openCursor({ lower: "a", lowerOpen: false }); });
+
+ assert_throws("DataError",
+ function() { idx.openCursor({ lower: "a", lowerOpen: false, upper: null, upperOpen: false }); });
+
+ this.done();
+ });
+
+
+ // Stop blocking the testing system from hereon
+ done();
+ }
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_openKeyCursor.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_openKeyCursor.htm
new file mode 100644
index 000000000..9dc547c3f
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_openKeyCursor.htm
@@ -0,0 +1,139 @@
+<!DOCTYPE html>
+<title>IDBObjectStore.openKeyCursor()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+function store_test(func, name) {
+ async_test(function(t) {
+ var del = indexedDB.deleteDatabase(name);
+ del.onerror = t.unreached_func("deleteDatabase failed");
+ var open = indexedDB.open(name);
+ open.onupgradeneeded = t.step_func(function() {
+ var db = open.result;
+ var store = db.createObjectStore("store");
+ for (var i = 0; i < 10; ++i) {
+ store.put("value: " + i, i);
+ }
+ });
+
+ open.onsuccess = t.step_func(function() {
+ var db = open.result;
+ var tx = db.transaction("store");
+ var store = tx.objectStore("store");
+ func(t, db, tx, store);
+ });
+ }, name);
+}
+
+store_test(function(t, db, tx, store) {
+ var expected = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
+ var actual = [];
+ var request = store.openKeyCursor();
+ request.onsuccess = t.step_func(function() {
+ var cursor = request.result;
+ if (!cursor)
+ return;
+ assert_equals(cursor.direction, "next");
+ assert_false("value" in cursor);
+ assert_equals(indexedDB.cmp(cursor.key, cursor.primaryKey), 0);
+ actual.push(cursor.key);
+ cursor.continue();
+ });
+
+ tx.onabort = t.unreached_func("transaction aborted");
+ tx.oncomplete = t.step_func(function() {
+ assert_array_equals(expected, actual, "keys should match");
+ t.done();
+ });
+
+}, "IDBObjectStore.openKeyCursor() - forward iteration");
+
+store_test(function(t, db, tx, store) {
+ var expected = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0];
+ var actual = [];
+ var request = store.openKeyCursor(null, "prev");
+ request.onsuccess = t.step_func(function() {
+ var cursor = request.result;
+ if (!cursor)
+ return;
+ assert_equals(cursor.direction, "prev");
+ assert_false("value" in cursor);
+ assert_equals(indexedDB.cmp(cursor.key, cursor.primaryKey), 0);
+ actual.push(cursor.key);
+ cursor.continue();
+ });
+
+ tx.onabort = t.unreached_func("transaction aborted");
+ tx.oncomplete = t.step_func(function() {
+ assert_array_equals(expected, actual, "keys should match");
+ t.done();
+ });
+
+}, "IDBObjectStore.openKeyCursor() - reverse iteration");
+
+store_test(function(t, db, tx, store) {
+ var expected = [4, 5, 6];
+ var actual = [];
+ var request = store.openKeyCursor(IDBKeyRange.bound(4, 6));
+ request.onsuccess = t.step_func(function() {
+ var cursor = request.result;
+ if (!cursor)
+ return;
+ assert_equals(cursor.direction, "next");
+ assert_false("value" in cursor);
+ assert_equals(indexedDB.cmp(cursor.key, cursor.primaryKey), 0);
+ actual.push(cursor.key);
+ cursor.continue();
+ });
+
+ tx.onabort = t.unreached_func("transaction aborted");
+ tx.oncomplete = t.step_func(function() {
+ assert_array_equals(expected, actual, "keys should match");
+ t.done();
+ });
+
+}, "IDBObjectStore.openKeyCursor() - forward iteration with range");
+
+store_test(function(t, db, tx, store) {
+ var expected = [6, 5, 4];
+ var actual = [];
+ var request = store.openKeyCursor(IDBKeyRange.bound(4, 6), "prev");
+ request.onsuccess = t.step_func(function() {
+ var cursor = request.result;
+ if (!cursor)
+ return;
+ assert_equals(cursor.direction, "prev");
+ assert_false("value" in cursor);
+ assert_equals(indexedDB.cmp(cursor.key, cursor.primaryKey), 0);
+ actual.push(cursor.key);
+ cursor.continue();
+ });
+
+ tx.onabort = t.unreached_func("transaction aborted");
+ tx.oncomplete = t.step_func(function() {
+ assert_array_equals(expected, actual, "keys should match");
+ t.done();
+ });
+
+}, "IDBObjectStore.openKeyCursor() - reverse iteration with range");
+
+store_test(function(t, db, tx, store) {
+ assert_throws("DataError", function() { store.openKeyCursor(NaN); },
+ "openKeyCursor should throw on invalid number key");
+ assert_throws("DataError", function() { store.openKeyCursor(new Date(NaN)); },
+ "openKeyCursor should throw on invalid date key");
+ assert_throws("DataError", function() {
+ var cycle = [];
+ cycle.push(cycle);
+ store.openKeyCursor(cycle);
+ }, "openKeyCursor should throw on invalid array key");
+ assert_throws("DataError", function() { store.openKeyCursor({}); },
+ "openKeyCursor should throw on invalid key type");
+ setTimeout(t.step_func(function() {
+ assert_throws("TransactionInactiveError", function() { store.openKeyCursor(); },
+ "openKeyCursor should throw if transaction is inactive");
+ t.done();
+ }), 0);
+
+}, "IDBObjectStore.openKeyCursor() - invalid inputs");
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_put.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_put.htm
new file mode 100644
index 000000000..6a0fed4b7
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_put.htm
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.put() - put with an inline key </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { key: 1, property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { keyPath: "key" });
+
+ objStore.put(record);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("store")
+ .objectStore("store")
+ .get(record.key);
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result.property, record.property);
+ assert_equals(e.target.result.key, record.key);
+ t.done();
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_put10.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_put10.htm
new file mode 100644
index 000000000..d0de11c3e
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_put10.htm
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.put() - Attempt to call 'put' without an key parameter when the object store uses out-of-line keys </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var rq,
+ objStore = db.createObjectStore("store", { keyPath: "key" });
+
+ assert_throws("DataError",
+ function() { rq = objStore.put(record); });
+
+ assert_equals(rq, undefined);
+ t.done();
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_put11.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_put11.htm
new file mode 100644
index 000000000..9a13757ef
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_put11.htm
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.put() - Attempt to put a record where the record's key does not meet the constraints of a valid key </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { key: { value: 1 }, property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var rq,
+ objStore = db.createObjectStore("store", { keyPath: "key" });
+
+ assert_throws("DataError",
+ function() { rq = objStore.put(record); });
+
+ assert_equals(rq, undefined);
+ t.done();
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_put12.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_put12.htm
new file mode 100644
index 000000000..24970dff0
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_put12.htm
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.put() - Attempt to put a record where the record's in-line key is not defined </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var rq,
+ objStore = db.createObjectStore("store", { keyPath: "key" });
+
+ assert_throws("DataError",
+ function() { rq = objStore.put(record); });
+
+ assert_equals(rq, undefined);
+ t.done();
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_put13.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_put13.htm
new file mode 100644
index 000000000..870c8e4a7
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_put13.htm
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.put() - Attempt to put a record where the out of line key provided does not meet the constraints of a valid key </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var rq,
+ objStore = db.createObjectStore("store");
+
+ assert_throws("DataError",
+ function() { rq = objStore.put(record, { value: 1 }); });
+
+ assert_equals(rq, undefined);
+ t.done();
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_put14.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_put14.htm
new file mode 100644
index 000000000..c68969645
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_put14.htm
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.put() - Put a record where a value being indexed does not meet the constraints of a valid key </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { key: 1, indexedProperty: { property: "data" } };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ var rq,
+ objStore = db.createObjectStore("store", { keyPath: "key" });
+
+ objStore.createIndex("index", "indexedProperty");
+
+ rq = objStore.put(record);
+
+ assert_true(rq instanceof IDBRequest);
+ rq.onsuccess = function() {
+ t.done();
+ }
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_put15.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_put15.htm
new file mode 100644
index 000000000..cf2c35435
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_put15.htm
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.put() - If the transaction this IDBObjectStore belongs to has its mode set to readonly, throw ReadOnlyError</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBObjectStore-put-IDBRequest-any-value-any-key">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ db.createObjectStore("store", {keyPath:"pKey"});
+ }
+
+ open_rq.onsuccess = function (event) {
+ var txn = db.transaction("store");
+ var ostore = txn.objectStore("store");
+ t.step(function(){
+ assert_throws("ReadOnlyError", function(){
+ ostore.put({pKey: "primaryKey_0"});
+ });
+ });
+ t.done();
+ }
+</script>
+
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_put16.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_put16.htm
new file mode 100644
index 000000000..4818dd25d
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_put16.htm
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.put() - If the object store has been deleted, the implementation must throw a DOMException of type InvalidStateError</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<link rel="help" href="https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBObjectStore-put-IDBRequest-any-value-any-key">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<div id="log"></div>
+<script>
+ var db,
+ ostore,
+ t = async_test();
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function (event) {
+ db = event.target.result;
+ ostore = db.createObjectStore("store", {keyPath:"pKey"});
+ db.deleteObjectStore("store");
+ assert_throws("InvalidStateError", function(){
+ ostore.put({pKey: "primaryKey_0"});
+ });
+ t.done();
+ }
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_put2.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_put2.htm
new file mode 100644
index 000000000..3b9fc30a8
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_put2.htm
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.put() - put with an out-of-line key </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ key = 1,
+ record = { property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store");
+
+ objStore.put(record, key);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("store")
+ .objectStore("store")
+ .get(key);
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result.property, record.property);
+
+ t.done();
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_put3.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_put3.htm
new file mode 100644
index 000000000..79097a283
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_put3.htm
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.put() - record with same key already exists </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db, success_event,
+ t = async_test(),
+ record = { key: 1, property: "data" },
+ record_put = { key: 1, property: "changed", more: ["stuff", 2] };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { keyPath: "key" });
+ objStore.put(record);
+
+ var rq = objStore.put(record_put);
+ rq.onerror = fail(t, "error on put");
+
+ rq.onsuccess = t.step_func(function(e) {
+ success_event = true;
+ });
+ };
+
+ open_rq.onsuccess = function(e) {
+ assert_true(success_event);
+
+ var rq = db.transaction("store")
+ .objectStore("store")
+ .get(1);
+
+ rq.onsuccess = t.step_func(function(e) {
+ var rec = e.target.result;
+
+ assert_equals(rec.key, record_put.key);
+ assert_equals(rec.property, record_put.property);
+ assert_array_equals(rec.more, record_put.more);
+
+ t.done();
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_put4.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_put4.htm
new file mode 100644
index 000000000..c1335b27d
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_put4.htm
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.put() - put where an index has unique:true specified </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ record = { key: 1, property: "data" };
+
+ var open_rq = createdb(async_test());
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { autoIncrement: true });
+ objStore.createIndex("i1", "property", { unique: true });
+ objStore.put(record);
+
+ var rq = objStore.put(record);
+ rq.onsuccess = fail(this, "success on putting duplicate indexed record")
+
+ rq.onerror = this.step_func(function(e) {
+ assert_equals(rq.error.name, "ConstraintError");
+ assert_equals(e.target.error.name, "ConstraintError");
+
+ assert_equals(e.type, "error");
+
+ e.preventDefault();
+ e.stopPropagation();
+ });
+ };
+
+ // Defer done, giving a spurious rq.onsuccess a chance to run
+ open_rq.onsuccess = function(e) {
+ this.done();
+ }
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_put5.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_put5.htm
new file mode 100644
index 000000000..a4d9abeff
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_put5.htm
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.put() - object store's key path is an object attribute </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { test: { obj: { key: 1 } }, property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { keyPath: "test.obj.key" });
+ objStore.put(record);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("store")
+ .objectStore("store")
+ .get(record.test.obj.key);
+
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result.property, record.property);
+
+ t.done();
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_put6.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_put6.htm
new file mode 100644
index 000000000..bcf7e7d19
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_put6.htm
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.put() - autoIncrement and inline keys </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { property: "data" },
+ expected_keys = [ 1, 2, 3, 4 ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { keyPath: "key", autoIncrement: true });
+
+ objStore.put(record);
+ objStore.put(record);
+ objStore.put(record);
+ objStore.put(record);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var actual_keys = [],
+ rq = db.transaction("store")
+ .objectStore("store")
+ .openCursor();
+
+ rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ if (cursor) {
+ actual_keys.push(cursor.value.key);
+ cursor.continue();
+ }
+ else {
+ assert_array_equals(actual_keys, expected_keys);
+ t.done();
+ }
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_put7.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_put7.htm
new file mode 100644
index 000000000..6765b0a84
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_put7.htm
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.put() - autoIncrement and out-of-line keys </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { property: "data" },
+ expected_keys = [ 1, 2, 3, 4 ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { autoIncrement: true });
+
+ objStore.put(record);
+ objStore.put(record);
+ objStore.put(record);
+ objStore.put(record);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var actual_keys = [],
+ rq = db.transaction("store")
+ .objectStore("store")
+ .openCursor();
+
+ rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ if (cursor) {
+ actual_keys.push(cursor.key);
+ cursor.continue();
+ }
+ else {
+ assert_array_equals(actual_keys, expected_keys);
+ t.done();
+ }
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_put8.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_put8.htm
new file mode 100644
index 000000000..3bf284eac
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_put8.htm
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.put() - object store has autoIncrement:true and the key path is an object attribute </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(),
+ record = { property: "data" },
+ expected_keys = [ 1, 2, 3, 4 ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { keyPath: "test.obj.key", autoIncrement: true });
+
+ objStore.put(record);
+ objStore.put(record);
+ objStore.put(record);
+ objStore.put(record);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var actual_keys = [],
+ rq = db.transaction("store")
+ .objectStore("store")
+ .openCursor();
+
+ rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ if (cursor) {
+ actual_keys.push(cursor.value.test.obj.key);
+ cursor.continue();
+ }
+ else {
+ assert_array_equals(actual_keys, expected_keys);
+ t.done();
+ }
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbobjectstore_put9.htm b/testing/web-platform/tests/IndexedDB/idbobjectstore_put9.htm
new file mode 100644
index 000000000..6e50a0b29
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbobjectstore_put9.htm
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IDBObjectStore.put() - Attempt to put a record that does not meet the constraints of an object store's inline key requirements </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var t = async_test(),
+ record = { key: 1, property: "data" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ var rq,
+ db = e.target.result,
+ objStore = db.createObjectStore("store", { keyPath: "key" });
+
+ assert_throws("DataError",
+ function() { rq = objStore.put(record, 1); });
+
+ assert_equals(rq, undefined);
+ t.done();
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbtransaction-oncomplete.htm b/testing/web-platform/tests/IndexedDB/idbtransaction-oncomplete.htm
new file mode 100644
index 000000000..7c295c7c1
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbtransaction-oncomplete.htm
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<title>IDBTransaction - complete event</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db, store,
+ t = async_test(document.title, {timeout: 10000}),
+ open_rq = createdb(t),
+ stages = [];
+
+ open_rq.onupgradeneeded = function(e) {
+ stages.push("upgradeneeded");
+
+ db = e.target.result;
+ store = db.createObjectStore('store');
+
+ e.target.transaction.oncomplete = function() {
+ stages.push("complete");
+ };
+ };
+
+ open_rq.onsuccess = function(e) {
+ stages.push("success");
+
+ // Making a totally new transaction to check
+ db.transaction('store').objectStore('store').count().onsuccess = t.step_func(function(e) {
+ assert_array_equals(stages, [ "upgradeneeded",
+ "complete",
+ "success" ]);
+ t.done();
+ });
+ // XXX: Make one with real transactions, not only open() versionchange one
+
+ /*db.transaction.objectStore('store').openCursor().onsuccess = function(e) {
+ stages.push("opencursor1");
+ }
+
+ store.openCursor().onsuccess = function(e) {
+ stages.push("opencursor2");
+ }
+
+ e.target.transaction.objectStore('store').openCursor().onsuccess = function(e) {
+ stages.push("opencursor3");
+ }
+ */
+ }
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbtransaction.htm b/testing/web-platform/tests/IndexedDB/idbtransaction.htm
new file mode 100644
index 000000000..8a3484511
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbtransaction.htm
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<title>IDBTransaction</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ t = async_test(document.title + " - request gotten by the handler"),
+ open_t = async_test(document.title + " - request returned by open()"),
+
+ open_rq = indexedDB.open("idbtransaction-" + new Date().getTime() + Math.random());
+
+ open_t.step(function() {
+ assert_equals(open_rq.transaction, null, "IDBOpenDBRequest.transaction");
+ assert_equals(open_rq.source, null, "IDBOpenDBRequest.source");
+ assert_equals(open_rq.readyState, "pending", "IDBOpenDBRequest.readyState");
+
+ assert_true(open_rq instanceof IDBOpenDBRequest, "open_rq instanceof IDBOpenDBRequest");
+ assert_equals(open_rq + "", "[object IDBOpenDBRequest]", "IDBOpenDBRequest (open_rq)");
+
+ open_t.done();
+ });
+
+ open_rq.onupgradeneeded = t.step_func(function(e) {
+ assert_equals(e.target, open_rq, "e.target is reusing the same IDBOpenDBRequest");
+ assert_equals(e.target.transaction, open_rq.transaction, "IDBOpenDBRequest.transaction");
+
+ assert_true(e.target.transaction instanceof IDBTransaction, "transaction instanceof IDBTransaction");
+ t.done();
+ });
+
+
+ // Not plausible conditions...
+ function fail_helper(name) {
+ return function() {
+ t.step(function() { assert_unreached(name); });
+ open_t.step(function() { assert_unreached(name); });
+ };
+ }
+ open_rq.onblocked = fail_helper('open_rq.onblocked');
+ open_rq.onerror = fail_helper('open_rq.onerror');
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbtransaction_abort.htm b/testing/web-platform/tests/IndexedDB/idbtransaction_abort.htm
new file mode 100644
index 000000000..1f37bb401
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbtransaction_abort.htm
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>IDBTransaction - abort</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db, aborted,
+ t = async_test(document.title, {timeout: 10000}),
+ record = { indexedProperty: "bar" };
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var txn = e.target.transaction,
+ objStore = db.createObjectStore("store");
+
+ objStore.add(record, 1);
+ objStore.add(record, 2);
+ var index = objStore.createIndex("index", "indexedProperty", { unique: true });
+
+ assert_true(index instanceof IDBIndex, "IDBIndex");
+
+ e.target.transaction.onabort = t.step_func(function(e) {
+ aborted = true;
+ assert_equals(e.type, "abort", "event type");
+ });
+
+ db.onabort = function(e) {
+ assert_true(aborted, "transaction.abort event has fired");
+ t.done();
+ };
+
+ e.target.transaction.oncomplete = fail(t, "got complete, expected abort");
+ };
+
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/idbtransaction_objectStoreNames.html b/testing/web-platform/tests/IndexedDB/idbtransaction_objectStoreNames.html
new file mode 100644
index 000000000..7f6aa3518
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbtransaction_objectStoreNames.html
@@ -0,0 +1,164 @@
+<!DOCTYPE html>
+<title>IndexedDB: IDBTransaction.objectStoreNames attribute</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<script>
+
+function with_stores_test(store_names, open_func, description) {
+ indexeddb_test(function(t, db, tx) {
+ store_names.forEach(function(name) {
+ db.createObjectStore(name);
+ });
+ }, open_func, description);
+}
+
+indexeddb_test(function(t, db, tx) {
+ assert_array_equals(tx.objectStoreNames, [],
+ 'transaction objectStoreNames should be empty');
+ assert_array_equals(db.objectStoreNames, tx.objectStoreNames,
+ 'connection and transacton objectStoreNames should match');
+
+ db.createObjectStore('s1');
+ assert_array_equals(tx.objectStoreNames, ['s1'],
+ 'transaction objectStoreNames should have new store');
+ assert_array_equals(db.objectStoreNames, tx.objectStoreNames,
+ 'connection and transacton objectStoreNames should match');
+
+ db.createObjectStore('s3');
+ assert_array_equals(tx.objectStoreNames, ['s1', 's3'],
+ 'transaction objectStoreNames should have new store');
+ assert_array_equals(db.objectStoreNames, tx.objectStoreNames,
+ 'connection and transacton objectStoreNames should match');
+
+ db.createObjectStore('s2');
+ assert_array_equals(tx.objectStoreNames, ['s1', 's2', 's3'],
+ 'transaction objectStoreNames should be sorted');
+ assert_array_equals(db.objectStoreNames, tx.objectStoreNames,
+ 'connection and transacton objectStoreNames should match');
+
+ db.deleteObjectStore('s1');
+ assert_array_equals(tx.objectStoreNames, ['s2', 's3'],
+ 'transaction objectStoreNames should be updated after delete');
+ assert_array_equals(db.objectStoreNames, tx.objectStoreNames,
+ 'connection and transacton objectStoreNames should match');
+}, function(t, db) {
+ t.done();
+}, 'IDBTransaction.objectStoreNames - during upgrade transaction');
+
+(function() {
+ var saved_tx;
+ indexeddb_test(function(t, db, tx) {
+ saved_tx = tx;
+ db.createObjectStore('s2');
+ db.createObjectStore('s3');
+ }, function(t, db) {
+ db.close();
+ var open2 = indexedDB.open(db.name, db.version + 1);
+ open2.onerror = t.unreached_func('open should succeed');
+ open2.onupgradeneeded = t.step_func(function() {
+ var db2 = open2.result;
+ var tx2 = open2.transaction;
+ assert_array_equals(tx2.objectStoreNames, ['s2', 's3'],
+ 'transaction should have previous stores in scope');
+ assert_array_equals(db2.objectStoreNames, tx2.objectStoreNames,
+ 'connection and transacton objectStoreNames should match');
+
+ db2.createObjectStore('s4');
+ assert_array_equals(tx2.objectStoreNames, ['s2', 's3', 's4'],
+ 'transaction should have new store in scope');
+ assert_array_equals(db2.objectStoreNames, tx2.objectStoreNames,
+ 'connection and transacton objectStoreNames should match');
+
+ assert_array_equals(saved_tx.objectStoreNames, ['s2', 's3'],
+ 'previous transaction objectStoreNames should be unchanged');
+ assert_array_equals(db.objectStoreNames, saved_tx.objectStoreNames,
+ 'connection and transaction objectStoreNames should match');
+ t.done();
+ });
+ }, 'IDBTransaction.objectStoreNames - value after close');
+}());
+
+with_stores_test(['s1', 's2'], function(t, db) {
+ assert_array_equals(db.transaction('s1').objectStoreNames, ['s1'],
+ 'transaction should have one store in scope');
+ assert_array_equals(db.transaction(['s1', 's2']).objectStoreNames,
+ ['s1', 's2'],
+ 'transaction should have two stores in scope');
+ t.done();
+}, 'IDBTransaction.objectStoreNames - transaction scope');
+
+with_stores_test(['s1', 's2'], function(t, db) {
+ var tx = db.transaction(['s1', 's2'], 'readwrite');
+ tx.objectStore('s1').put(0, 0);
+ tx.onabort = t.unreached_func('transaction should complete');
+ tx.oncomplete = t.step_func(function() {
+ assert_array_equals(tx.objectStoreNames, ['s1', 's2'],
+ 'objectStoreNames should return scope after transaction commits');
+ t.done();
+ });
+}, 'IDBTransaction.objectStoreNames - value after commit');
+
+with_stores_test(['s1', 's2'], function(t, db) {
+ var tx = db.transaction(['s1', 's2'], 'readwrite');
+ tx.objectStore('s1').put(0, 0);
+ tx.objectStore('s1').add(0, 0);
+ tx.oncomplete = t.unreached_func('transaction should abort');
+ tx.onabort = t.step_func(function() {
+ assert_array_equals(tx.objectStoreNames, ['s1', 's2'],
+ 'objectStoreNames should return scope after transaction aborts');
+ t.done();
+ });
+}, 'IDBTransaction.objectStoreNames - value after abort');
+
+with_stores_test(['s1', 's2', 's3'], function(t, db) {
+ assert_array_equals(db.transaction(['s3', 's2', 's1']).objectStoreNames,
+ ['s1', 's2', 's3'],
+ 'transaction objectStoreNames should be sorted');
+ t.done();
+}, 'IDBTransaction.objectStoreNames - sorting');
+
+with_stores_test(['s1', 's2'], function(t, db) {
+ assert_array_equals(
+ db.transaction(['s2', 's1', 's2']).objectStoreNames,
+ ['s1', 's2'],
+ 'transaction objectStoreNames should not have duplicates');
+ t.done();
+}, 'IDBTransaction.objectStoreNames - no duplicates');
+
+var unusual_names = [
+ '', // empty string
+
+ '\x00', // U+0000 NULL
+ '\xFF', // U+00FF LATIN SMALL LETTER Y WITH DIAERESIS
+
+ '1', // basic ASCII
+ '12', // basic ASCII
+ '123', // basic ASCII
+ 'abc', // basic ASCII
+ 'ABC', // basic ASCII
+
+ '\xA2', // U+00A2 CENT SIGN
+ '\u6C34', // U+6C34 CJK UNIFIED IDEOGRAPH (water)
+ '\uD834\uDD1E', // U+1D11E MUSICAL SYMBOL G-CLEF (UTF-16 surrogate pair)
+ '\uFFFD', // U+FFFD REPLACEMENT CHARACTER
+
+ '\uD800', // UTF-16 surrogate lead
+ '\uDC00', // UTF-16 surrogate trail
+];
+unusual_names.sort();
+
+indexeddb_test(function(t, db, tx) {
+ unusual_names.slice().reverse().forEach(function(name) {
+ db.createObjectStore(name);
+ });
+ assert_array_equals(tx.objectStoreNames, unusual_names,
+ 'transaction should have names sorted');
+}, function(t, db) {
+ var tx = db.transaction(unusual_names.slice().reverse().concat(unusual_names));
+ assert_array_equals(tx.objectStoreNames, unusual_names,
+ 'transaction should have names sorted with no duplicates');
+ t.done();
+}, 'IDBTransaction.objectStoreNames - unusual names');
+
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/idbversionchangeevent.htm b/testing/web-platform/tests/IndexedDB/idbversionchangeevent.htm
new file mode 100644
index 000000000..866a8b2eb
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbversionchangeevent.htm
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<title>IDBVersionChangeEvent fired in upgradeneeded, versionchange and deleteDatabase</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#versionchange--transaction-steps">
+<link rel=assert title="Fire a versionchange event at each object in openDatabases that is open. The event must not be fired on objects which has the closePending flag set. The event must use the IDBVersionChangeEvent interface and have the oldVersion property set to db's version and have the newVersion property set to version.">
+<link rel=assert title="Fire a upgradeneeded event targeted at request. The event must use the IDBVersionChangeEvent interface and have the oldVersion property set to old version and have the newVersion property set to version.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<div id="log"></div>
+
+<script>
+
+ var db,
+ t = async_test(document.title, {timeout: 10000});
+
+ t.step(function() {
+ var openrq = indexedDB.open('db', 3);
+
+ openrq.onupgradeneeded = t.step_func(function(e) {
+ assert_equals(e.oldVersion, 0, "old version (upgradeneeded)");
+ assert_equals(e.newVersion, 3, "new version (upgradeneeded)");
+ assert_true(e instanceof IDBVersionChangeEvent, "upgradeneeded instanceof IDBVersionChangeEvent");
+ });
+
+ openrq.onsuccess = t.step_func(function(e) {
+ db = e.target.result;
+
+ db.onversionchange = t.step_func(function(e) {
+ assert_equals(e.oldVersion, 3, "old version (versionchange)");
+ assert_equals(e.newVersion, null, "new version (versionchange)");
+ assert_true(e instanceof IDBVersionChangeEvent, "versionchange instanceof IDBVersionChangeEvent");
+ db.close();
+ });
+
+ // Errors
+ db.onerror = fail(t, "db.error");
+ db.onabort = fail(t, "db.abort");
+
+ setTimeout(t.step_func(deleteDB), 10);
+ });
+
+ // Errors
+ openrq.onerror = fail(t, "open.error");
+ openrq.onblocked = fail(t, "open.blocked");
+
+ });
+
+ function deleteDB (e) {
+ var deleterq = indexedDB.deleteDatabase('db');
+
+ deleterq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.oldVersion, 3, "old version (delete.success)");
+ assert_equals(e.newVersion, null, "new version (delete.success)");
+ assert_true(e instanceof IDBVersionChangeEvent, "delete.success instanceof IDBVersionChangeEvent");
+
+ setTimeout(function() { t.done(); }, 10);
+ });
+
+ // Errors
+ deleterq.onerror = fail(t, "delete.error");
+ deleterq.onblocked = fail(t, "delete.blocked");
+ }
+
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/idbworker.js b/testing/web-platform/tests/IndexedDB/idbworker.js
new file mode 100644
index 000000000..359f6fb69
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/idbworker.js
@@ -0,0 +1,34 @@
+var db
+
+self.addEventListener('message', MessageHandler, false)
+
+function MessageHandler(e)
+{
+ var open_rq, idb = self.indexedDB || self.msIndexedDB || self.webkitIndexedDB || self.mozIndexedDB
+
+ if (!idb)
+ {
+ self.postMessage(false)
+ return
+ }
+ else
+ self.postMessage(true)
+
+ open_rq = idb.open("webworker101", 1)
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result
+ db.createObjectStore("store")
+ .add("test", 1)
+ }
+ open_rq.onsuccess = function(e) {
+ db = e.target.result
+ db.onerror = function() { self.postMessage("db.error") }
+ db.transaction("store").objectStore("store").get(1).onsuccess = function(e) {
+ self.postMessage(e.target.result)
+ db.close()
+ }
+ }
+ open_rq.onerror = function() { self.postMessage("open.error") }
+ open_rq.onblocked = function() { self.postMessage("open.blocked") }
+}
diff --git a/testing/web-platform/tests/IndexedDB/index_sort_order.htm b/testing/web-platform/tests/IndexedDB/index_sort_order.htm
new file mode 100644
index 000000000..6249c4204
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/index_sort_order.htm
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Verify key sort order in an index is 'number &lt; Date &lt; DOMString' </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ d = new Date(),
+ t = async_test(),
+ records = [ { foo: d },
+ { foo: "test" },
+ { foo: 1 },
+ { foo: 2.55 } ],
+ expectedKeyOrder = [ 1, 2.55, d.valueOf(), "test" ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { autoIncrement: true });
+ objStore.createIndex("index", "foo");
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var actual_keys = [],
+ rq = db.transaction("store")
+ .objectStore("store")
+ .index("index")
+ .openCursor();
+
+ rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ if (cursor) {
+ actual_keys.push(cursor.key.valueOf());
+ cursor.continue();
+ }
+ else {
+ assert_array_equals(actual_keys, expectedKeyOrder);
+ t.done();
+ }
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/interfaces.html b/testing/web-platform/tests/IndexedDB/interfaces.html
new file mode 100644
index 000000000..9c2919094
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/interfaces.html
@@ -0,0 +1,50 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>IndexedDB IDL tests</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/resources/WebIDLParser.js></script>
+<script src=/resources/idlharness.js></script>
+
+<h1>IndexedDB IDL tests</h1>
+<div id=log></div>
+
+<script>
+"use strict";
+setup(function() {
+ var idlArray = new IdlArray();
+
+ var request = new XMLHttpRequest();
+ request.open("GET", "interfaces.idl");
+ request.send();
+ request.onload = function() {
+ var idls = request.responseText;
+
+ idlArray.add_untested_idls("[PrimaryGlobal] interface Window { };");
+ idlArray.add_untested_idls("[Exposed=(Window,Worker)] interface Event { };");
+ idlArray.add_untested_idls("[Exposed=(Window,Worker)] interface EventTarget { };");
+ idlArray.add_untested_idls("[NoInterfaceObject, Exposed=(Window,Worker)] interface WindowOrWorkerGlobalScope { };");
+
+ // From Indexed DB:
+ idlArray.add_idls(idls);
+ idlArray.add_idls("Window implements WindowOrWorkerGlobalScope;");
+
+ idlArray.add_objects({
+ IDBCursor: [],
+ IDBCursorWithValue: [],
+ IDBDatabase: [],
+ IDBFactory: ["window.indexedDB"],
+ IDBIndex: [],
+ IDBKeyRange: ["IDBKeyRange.only(0)"],
+ IDBObjectStore: [],
+ IDBOpenDBRequest: [],
+ IDBRequest: [],
+ IDBTransaction: [],
+ IDBVersionChangeEvent: ["new IDBVersionChangeEvent('foo')"],
+ });
+
+ idlArray.test();
+ done();
+ };
+}, {explicit_done: true});
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/interfaces.idl b/testing/web-platform/tests/IndexedDB/interfaces.idl
new file mode 100644
index 000000000..f1682965c
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/interfaces.idl
@@ -0,0 +1,156 @@
+enum IDBTransactionMode {
+ "readonly",
+ "readwrite",
+ "versionchange"
+};
+
+enum IDBRequestReadyState {
+ "pending",
+ "done"
+};
+
+[Exposed=(Window,Worker)]
+interface IDBKeyRange {
+ readonly attribute any lower;
+ readonly attribute any upper;
+ readonly attribute boolean lowerOpen;
+ readonly attribute boolean upperOpen;
+ static IDBKeyRange only (any value);
+ static IDBKeyRange lowerBound (any lower, optional boolean open = false);
+ static IDBKeyRange upperBound (any upper, optional boolean open = false);
+ static IDBKeyRange bound (any lower, any upper, optional boolean lowerOpen = false, optional boolean upperOpen = false);
+};
+
+enum IDBCursorDirection {
+ "next",
+ "nextunique",
+ "prev",
+ "prevunique"
+};
+
+dictionary IDBObjectStoreParameters {
+ (DOMString or sequence<DOMString>)? keyPath = null;
+ boolean autoIncrement = false;
+};
+
+dictionary IDBIndexParameters {
+ boolean unique = false;
+ boolean multiEntry = false;
+};
+
+dictionary IDBVersionChangeEventInit : EventInit {
+ unsigned long long oldVersion = 0;
+ unsigned long long? newVersion = null;
+};
+
+[Exposed=(Window,Worker)]
+interface IDBRequest : EventTarget {
+ readonly attribute any result;
+ readonly attribute DOMError error;
+ readonly attribute (IDBObjectStore or IDBIndex or IDBCursor)? source;
+ readonly attribute IDBTransaction transaction;
+ readonly attribute IDBRequestReadyState readyState;
+ attribute EventHandler onsuccess;
+ attribute EventHandler onerror;
+};
+
+[Exposed=(Window,Worker)]
+interface IDBOpenDBRequest : IDBRequest {
+ attribute EventHandler onblocked;
+ attribute EventHandler onupgradeneeded;
+};
+
+[Exposed=(Window,Worker),
+ Constructor(DOMString type, optional IDBVersionChangeEventInit eventInitDict)]
+interface IDBVersionChangeEvent : Event {
+ readonly attribute unsigned long long oldVersion;
+ readonly attribute unsigned long long? newVersion;
+};
+
+partial interface WindowOrWorkerGlobalScope {
+ readonly attribute IDBFactory indexedDB;
+};
+
+[Exposed=(Window,Worker)]
+interface IDBFactory {
+ IDBOpenDBRequest open (DOMString name, [EnforceRange] optional unsigned long long version);
+ IDBOpenDBRequest deleteDatabase (DOMString name);
+ short cmp (any first, any second);
+};
+
+[Exposed=(Window,Worker)]
+interface IDBDatabase : EventTarget {
+ readonly attribute DOMString name;
+ readonly attribute unsigned long long version;
+ readonly attribute DOMStringList objectStoreNames;
+ IDBObjectStore createObjectStore (DOMString name, optional IDBObjectStoreParameters optionalParameters);
+ void deleteObjectStore (DOMString name);
+ IDBTransaction transaction ((DOMString or sequence<DOMString>) storeNames, optional IDBTransactionMode mode = "readonly");
+ void close ();
+ attribute EventHandler onabort;
+ attribute EventHandler onclose;
+ attribute EventHandler onerror;
+ attribute EventHandler onversionchange;
+};
+
+[Exposed=(Window,Worker)]
+interface IDBObjectStore {
+ attribute DOMString name;
+ readonly attribute any keyPath;
+ readonly attribute DOMStringList indexNames;
+ readonly attribute IDBTransaction transaction;
+ readonly attribute boolean autoIncrement;
+ IDBRequest put (any value, optional any key);
+ IDBRequest add (any value, optional any key);
+ IDBRequest delete (any key);
+ IDBRequest get (any key);
+ IDBRequest clear ();
+ IDBRequest openCursor (optional any range, optional IDBCursorDirection direction = "next");
+ IDBIndex createIndex (DOMString name, (DOMString or sequence<DOMString>) keyPath, optional IDBIndexParameters optionalParameters);
+ IDBIndex index (DOMString name);
+ void deleteIndex (DOMString indexName);
+ IDBRequest count (optional any key);
+};
+
+[Exposed=(Window,Worker)]
+interface IDBIndex {
+ attribute DOMString name;
+ readonly attribute IDBObjectStore objectStore;
+ readonly attribute any keyPath;
+ readonly attribute boolean multiEntry;
+ readonly attribute boolean unique;
+ IDBRequest openCursor (optional any range, optional IDBCursorDirection direction = "next");
+ IDBRequest openKeyCursor (optional any range, optional IDBCursorDirection direction = "next");
+ IDBRequest get (any key);
+ IDBRequest getKey (any key);
+ IDBRequest count (optional any key);
+};
+
+[Exposed=(Window,Worker)]
+interface IDBCursor {
+ readonly attribute (IDBObjectStore or IDBIndex) source;
+ readonly attribute IDBCursorDirection direction;
+ readonly attribute any key;
+ readonly attribute any primaryKey;
+ IDBRequest update (any value);
+ void advance ([EnforceRange] unsigned long count);
+ void continue (optional any key);
+ IDBRequest delete ();
+};
+
+[Exposed=(Window,Worker)]
+interface IDBCursorWithValue : IDBCursor {
+ readonly attribute any value;
+};
+
+[Exposed=(Window,Worker)]
+interface IDBTransaction : EventTarget {
+ readonly attribute IDBTransactionMode mode;
+ readonly attribute IDBDatabase db;
+ readonly attribute DOMError error;
+ IDBObjectStore objectStore (DOMString name);
+ void abort ();
+ attribute EventHandler onabort;
+ attribute EventHandler oncomplete;
+ attribute EventHandler onerror;
+};
diff --git a/testing/web-platform/tests/IndexedDB/interfaces.worker.js b/testing/web-platform/tests/IndexedDB/interfaces.worker.js
new file mode 100644
index 000000000..8616159b3
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/interfaces.worker.js
@@ -0,0 +1,37 @@
+"use strict";
+
+importScripts("/resources/testharness.js");
+importScripts("/resources/WebIDLParser.js", "/resources/idlharness.js");
+
+var request = new XMLHttpRequest();
+request.open("GET", "interfaces.idl");
+request.send();
+request.onload = function() {
+ var idlArray = new IdlArray();
+ var idls = request.responseText;
+
+ idlArray.add_untested_idls("[Exposed=Worker] interface WorkerGlobalScope {};");
+ idlArray.add_untested_idls("[Exposed=(Window,Worker)] interface Event { };");
+ idlArray.add_untested_idls("[Exposed=(Window,Worker)] interface EventTarget { };");
+ idlArray.add_untested_idls("[NoInterfaceObject, Exposed=(Window,Worker)] interface WindowOrWorkerGlobalScope {};");
+
+ // From Indexed DB:
+ idlArray.add_idls("WorkerGlobalScope implements WindowOrWorkerGlobalScope;");
+ idlArray.add_idls(idls);
+
+ idlArray.add_objects({
+ IDBCursor: [],
+ IDBCursorWithValue: [],
+ IDBDatabase: [],
+ IDBFactory: ["self.indexedDB"],
+ IDBIndex: [],
+ IDBKeyRange: ["IDBKeyRange.only(0)"],
+ IDBObjectStore: [],
+ IDBOpenDBRequest: [],
+ IDBRequest: [],
+ IDBTransaction: [],
+ IDBVersionChangeEvent: ["new IDBVersionChangeEvent('foo')"],
+ });
+ idlArray.test();
+ done();
+};
diff --git a/testing/web-platform/tests/IndexedDB/key_invalid.htm b/testing/web-platform/tests/IndexedDB/key_invalid.htm
new file mode 100644
index 000000000..30759d5ef
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/key_invalid.htm
@@ -0,0 +1,129 @@
+<!DOCTYPE html>
+<!-- Submitted from TestTWF Paris -->
+<meta charset=utf-8">
+<title>Invalid key</title>
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#key-construct">
+<link rel=assert title="A value is said to be a valid key if it is one of the following types: Array JavaScript objects [ECMA-262], DOMString [WEBIDL], Date [ECMA-262] or float [WEBIDL]. However Arrays are only valid keys if every item in the array is defined and is a valid key (i.e. sparse arrays can not be valid keys) and if the Array doesn't directly or indirectly contain itself. Any non-numeric properties are ignored, and thus does not affect whether the Array is a valid key. Additionally, if the value is of type float, it is only a valid key if it is not NaN, and if the value is of type Date it is only a valid key if its [[PrimitiveValue]] internal property, as defined by [ECMA-262], is not NaN. Conforming user agents must support all valid keys as keys.">
+<!-- original author -->
+<link rel=author href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<!-- some additions by Baptiste Fontaine (batifon@yahoo.fr) -->
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db = createdb_for_multiple_tests(),
+ // cache for ObjectStores
+ objStore = null,
+ objStore2 = null;
+
+ function is_cloneable(o) {
+ try {
+ self.postMessage(o, '*');
+ return true;
+ } catch (ex) {
+ return false;
+ }
+ }
+
+ function invalid_key(desc, key) {
+ var t = async_test(document.title + " - " + desc);
+
+ // set the current test, and run it
+ db.setTest(t).onupgradeneeded = function(e) {
+ objStore = objStore || e.target.result.createObjectStore("store");
+ assert_throws('DataError', function() {
+ objStore.add("value", key);
+ });
+
+ if (is_cloneable(key)) {
+ objStore2 = objStore2 || e.target.result.createObjectStore("store2", { keyPath: ["x", "keypath"] });
+ assert_throws('DataError', function() {
+ objStore2.add({ x: "value", keypath: key });
+ });
+ }
+ this.done();
+ };
+ }
+
+ var fake_array = {
+ length : 0,
+ constructor : Array
+ };
+
+ var ArrayClone = function(){};
+ ArrayClone.prototype = Array;
+ var ArrayClone_instance = new ArrayClone();
+
+ // booleans
+ invalid_key( 'true' , true );
+ invalid_key( 'false' , false );
+
+ // null/NaN/undefined
+ invalid_key( 'null' , null );
+ invalid_key( 'NaN' , NaN );
+ invalid_key( 'undefined' , undefined );
+ invalid_key( 'undefined2');
+
+ // functions
+ invalid_key( 'function() {}', function(){} );
+
+ // objects
+ invalid_key( '{}' , {} );
+ invalid_key( '{ obj: 1 }' , { obj: 1 });
+ invalid_key( 'Math' , Math );
+ invalid_key( 'window' , window );
+ invalid_key( '{length:0,constructor:Array}' , fake_array );
+ invalid_key( 'Array clone’s instance' , ArrayClone_instance );
+ invalid_key( 'Array (object)' , Array );
+ invalid_key( 'String (object)' , String );
+ invalid_key( 'new String()' , new String() );
+ invalid_key( 'new Number()' , new Number() );
+ invalid_key( 'new Boolean()' , new Boolean() );
+
+ // arrays
+ invalid_key( '[{}]' , [{}] );
+ invalid_key( '[[], [], [], [[ Date ]]]' , [ [], [], [], [[ Date ]] ] );
+ invalid_key( '[undefined]' , [undefined] );
+ invalid_key( '[,1]' , [,1] );
+
+ invalid_key( 'document.getElements'
+ +'ByTagName("script")' , document.getElementsByTagName("script") );
+
+ // dates
+ invalid_key( 'new Date(NaN)' , new Date(NaN) );
+ invalid_key( 'new Date(Infinity)' , new Date(Infinity) );
+
+ // regexes
+ invalid_key( '/foo/' , /foo/ );
+ invalid_key( 'new RegExp()' , new RegExp() );
+
+ var sparse = [];
+ sparse[10] = "hei";
+ invalid_key('sparse array', sparse);
+
+ var sparse2 = [];
+ sparse2[0] = 1;
+ sparse2[""] = 2;
+ sparse2[2] = 3;
+ invalid_key('sparse array 2', sparse2);
+
+ invalid_key('[[1], [3], [7], [[ sparse array ]]]', [ [1], [3], [7], [[ sparse2 ]] ]);
+
+ // sparse3
+ invalid_key( '[1,2,3,,]', [1,2,3,,] );
+
+ var recursive = [];
+ recursive.push(recursive);
+ invalid_key('array directly contains self', recursive);
+
+ var recursive2 = [];
+ recursive2.push([recursive2]);
+ invalid_key('array indirectly contains self', recursive2);
+
+ var recursive3 = [recursive];
+ invalid_key('array member contains self', recursive3);
+
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/key_valid.html b/testing/web-platform/tests/IndexedDB/key_valid.html
new file mode 100644
index 000000000..3bac0732c
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/key_valid.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<!-- Submitted from TestTWF Paris -->
+<meta charset=utf-8">
+<meta name="timeout" content="long">
+<title>Valid key</title>
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#key-construct">
+<link rel=assert title="A value is said to be a valid key if it is one of the following types: Array JavaScript objects [ECMA-262], DOMString [WEBIDL], Date [ECMA-262] or float [WEBIDL]. However Arrays are only valid keys if every item in the array is defined and is a valid key (i.e. sparse arrays can not be valid keys) and if the Array doesn't directly or indirectly contain itself. Any non-numeric properties are ignored, and thus does not affect whether the Array is a valid key. Additionally, if the value is of type float, it is only a valid key if it is not NaN, and if the value is of type Date it is only a valid key if its [[PrimitiveValue]] internal property, as defined by [ECMA-262], is not NaN. Conforming user agents must support all valid keys as keys.">
+<link rel=author href="mailto:batifon@yahoo.fr" title="Baptiste Fontaine">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ function valid_key(desc, key) {
+ var db;
+ var t = async_test(document.title + " - " + desc);
+ var open_rq = createdb(t);
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ store = db.createObjectStore("store");
+ assert_true(store.add('value', key) instanceof IDBRequest);
+
+ store2 = db.createObjectStore("store2", { keyPath: ["x", "keypath"] });
+ assert_true(store2.add({ x: 'v', keypath: key }) instanceof IDBRequest);
+ };
+ open_rq.onsuccess = function(e) {
+ var rq = db.transaction("store")
+ .objectStore("store")
+ .get(key)
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result, 'value')
+ var rq = db.transaction("store2")
+ .objectStore("store2")
+ .get(['v', key])
+ rq.onsuccess = t.step_func(function(e) {
+ assert_equals(e.target.result.x, 'v');
+ assert_key_equals(e.target.result.keypath, key);
+ t.done()
+ })
+ })
+ }
+ }
+
+ // Date
+ valid_key( 'new Date()' , new Date() );
+ valid_key( 'new Date(0)' , new Date(0) );
+
+ // Array
+ valid_key( '[]' , [] );
+ valid_key( 'new Array()' , new Array() );
+
+ valid_key( '["undefined"]' , ['undefined'] );
+
+ // Float
+ valid_key( 'Infinity' , Infinity );
+ valid_key( '-Infinity' , -Infinity );
+ valid_key( '0' , 0 );
+ valid_key( '1.5' , 1.5 );
+ valid_key( '3e38' , 3e38 );
+ valid_key( '3e-38' , 3e38 );
+
+ // String
+ valid_key( '"foo"' , "foo" );
+ valid_key( '"\\n"' , "\n" );
+ valid_key( '""' , "" );
+ valid_key( '"\\""' , "\"" );
+ valid_key( '"\\u1234"' , "\u1234" );
+ valid_key( '"\\u0000"' , "\u0000" );
+ valid_key( '"NaN"' , "NaN" );
+
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/keygenerator-constrainterror.htm b/testing/web-platform/tests/IndexedDB/keygenerator-constrainterror.htm
new file mode 100644
index 000000000..ee2e24799
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/keygenerator-constrainterror.htm
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Keygenerator ConstraintError when using same id as already generated</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db,
+ t = async_test(document.title, {timeout: 10000}),
+ objects = [1, null, {id: 2}, null, 2.00001, 5, null, {id: 6} ],
+ expected = [1, 2, 2.00001, 3, 5, 6],
+ errors = 0;
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { keyPath: "id", autoIncrement: true });
+
+ for (var i = 0; i < objects.length; i++)
+ {
+ if (objects[i] === null)
+ {
+ objStore.add({});
+ }
+ else if (typeof objects[i] === "object")
+ {
+ var rq = objStore.add(objects[i])
+ rq.yeh = objects[i];
+ rq.onerror = t.step_func(function(e) {
+ errors++;
+
+ assert_equals(e.target.error.name, "ConstraintError");
+ assert_equals(e.type, "error");
+
+ e.stopPropagation();
+ e.preventDefault();
+ });
+ rq.onsuccess = t.step_func(function(e) {
+ assert_unreached("Got rq.success when adding duplicate id " + objects[i]);
+ });
+ }
+ else
+ objStore.add({ id: objects[i] });
+ }
+ };
+
+ open_rq.onsuccess = function(e) {
+ var actual_keys = [],
+ rq = db.transaction("store")
+ .objectStore("store")
+ .openCursor();
+
+ rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ if (cursor) {
+ actual_keys.push(cursor.key.valueOf());
+ cursor.continue();
+ }
+ else {
+ assert_equals(errors, 2, "expected ConstraintError's");
+ assert_array_equals(actual_keys, expected, "keygenerator array");
+ t.done();
+ }
+ });
+ };
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/keygenerator-overflow.htm b/testing/web-platform/tests/IndexedDB/keygenerator-overflow.htm
new file mode 100644
index 000000000..d069f0a2b
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/keygenerator-overflow.htm
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Keygenerator overflow</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#key-generator-concept">
+<link rel=assert title="When the current number of a key generator reaches above the value 2^53 (9007199254740992) any attempts to use the key generator to generate a new key will result in an error. It's still possible to insert records into the object store by specifying an explicit key, however the only way to use a key generator again for the object store is to delete the object store and create a new one.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var db,
+ t = async_test(document.title, {timeout: 10000}),
+ overflow_error_fired = false,
+ objects = [9007199254740991, null, "error", 2, "error" ],
+ expected_keys = [2, 9007199254740991, 9007199254740992];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { keyPath: "id", autoIncrement: true });
+
+ for (var i = 0; i < objects.length; i++)
+ {
+ if (objects[i] === null)
+ {
+ objStore.add({});
+ }
+ else if (objects[i] === "error")
+ {
+ var rq = objStore.add({});
+ rq.onsuccess = fail(t, 'When "current number" overflows, error event is expected');
+ rq.onerror = t.step_func(function(e) {
+ overflow_error_fired = true;
+ assert_equals(e.target.error.name, "ConstraintError", "error name");
+ e.preventDefault();
+ e.stopPropagation();
+ });
+ }
+ else
+ objStore.add({ id: objects[i] });
+ }
+ };
+
+ open_rq.onsuccess = function(e) {
+ var actual_keys = [],
+ rq = db.transaction("store")
+ .objectStore("store")
+ .openCursor();
+
+ rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ if (cursor) {
+ actual_keys.push(cursor.key.valueOf());
+ cursor.continue();
+ }
+ else {
+ assert_true(overflow_error_fired, "error fired on 'current number' overflow");
+ assert_array_equals(actual_keys, expected_keys, "keygenerator array");
+
+ t.done();
+ }
+ });
+ };
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/keygenerator.htm b/testing/web-platform/tests/IndexedDB/keygenerator.htm
new file mode 100644
index 000000000..7e5961382
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/keygenerator.htm
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Keygenerator</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#key-generator-concept">
+<link rel=assert title="The current number of a key generator is always set to 1 when the object store for that key generator is first created.">
+<link rel=assert title="When a key generator is used to generate a new key for a object store, the key generator's current number is used as the new key value and then the key generator's current number is increased by 1.">
+<link rel=assert title="When a record is stored in a object store which uses a key generator, and an explicit key is defined, if the key's value is a float greater than or equal to the key generator's current number, then the key generator's current number is set to the smallest integer number larger than the explicit key. Only explicit keys which are float values affect the current number of the key generator.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ function keygenerator(objects, expected_keys, desc, func) {
+ var db,
+ t = async_test(document.title + " - " + desc);
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { keyPath: "id", autoIncrement: true });
+
+ for (var i = 0; i < objects.length; i++)
+ {
+ if (objects[i] === null)
+ objStore.add({});
+ else
+ objStore.add({ id: objects[i] });
+ }
+ };
+
+ open_rq.onsuccess = function(e) {
+ var actual_keys = [],
+ rq = db.transaction("store")
+ .objectStore("store")
+ .openCursor();
+
+ rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ if (cursor) {
+ actual_keys.push(cursor.key.valueOf());
+ cursor.continue();
+ }
+ else {
+ assert_key_equals(actual_keys, expected_keys, "keygenerator array");
+ t.done();
+ }
+ });
+ };
+ }
+
+
+ keygenerator([null, null, null, null], [1, 2, 3, 4],
+ "starts at one, and increments by one");
+
+ keygenerator([2, null, 5, null, 6.66, 7], [2, 3, 5, 6, 6.66, 7],
+ "increments by one from last set key");
+
+ keygenerator([-10, null, "6", 6.3, [10], -2, 4, null], [-10, -2, 1, 4, 6.3, 7, "6", [10]],
+ "don't increment when new key is not bigger than current");
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/keyorder.htm b/testing/web-platform/tests/IndexedDB/keyorder.htm
new file mode 100644
index 000000000..1896333f9
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/keyorder.htm
@@ -0,0 +1,175 @@
+<!DOCTYPE html>
+<!-- Submitted from TestTWF Paris -->
+<meta charset="utf-8">
+<title>Key sort order</title>
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#key-construct">
+<link rel=assert title="For purposes of comparison, all Arrays are greater than all DOMString, Date and float values; all DOMString values are greater than all Date and float values; and all Date values are greater than all float values. Values of type float are compared to other float values numerically. Values of type Date are compared to other Date values chronologically. Values of type DOMString are compared to other values of type DOMString by using the algorithm defined by step 4 of section 11.8.5, The Abstract Relational Comparison Algorithm, of the ECMAScript Language Specification [ECMA-262]. Values of type Array are compared to other values of type Array as follows:
+
+1. Let A be the first Array value and B be the second Array value.
+2. Let length be the lesser of A's length and B's length.
+3. Let i be 0.
+4. If the ith value of A is less than the ith value of B, then A is less than B. Skip the remaining steps.
+5. If the ith value of A is greater than the ith value of B, then A is greater than B. Skip the remaining steps.
+6. Increase i by 1.
+7. If i is not equal to length, go back to step 4. Otherwise continue to next step.
+8. If A's length is less than B's length, then A is less than B. If A's length is greater than B's length, then A is greater than B. Otherwise A and B are equal.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var global_db = createdb_for_multiple_tests();
+
+ function keysort(desc, unsorted, expected) {
+ var db,
+ t = async_test("Database readback sort - " + desc, { timeout: 10000 }),
+ store_name = 'store-' + Date.now() + Math.random();
+
+ // The database test
+ var open_rq = global_db.setTest(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore(store_name);
+
+ for (var i = 0; i < unsorted.length; i++)
+ objStore.add("value", unsorted[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var actual_keys = [],
+ rq = db.transaction(store_name)
+ .objectStore(store_name)
+ .openCursor();
+
+ rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ if (cursor) {
+ actual_keys.push(cursor.key);
+ cursor.continue();
+ }
+ else {
+ assert_key_equals(actual_keys, expected, "keyorder array");
+ assert_equals(actual_keys.length, expected.length, "array length");
+
+ t.done();
+ }
+ });
+ };
+
+ // The IDBKey.cmp test
+ test(function () {
+ var sorted = unsorted.slice(0).sort(function(a, b) { return indexedDB.cmp(a, b)});
+ assert_key_equals(sorted, expected, "sorted array");
+
+ }, "IDBKey.cmp sorted - " + desc);
+ }
+
+ var now = new Date(),
+ one_sec_ago = new Date(now - 1000),
+ one_min_future = new Date(now.getTime() + (1000*60));
+
+ keysort('String < Array',
+ [ [0], "yo", "", [] ],
+ [ "", "yo", [], [0] ]);
+
+ keysort('float < String',
+ [ Infinity, "yo", 0, "", 100 ],
+ [ 0, 100, Infinity, "", "yo" ]);
+
+ keysort('float < Date',
+ [ now, 0, 9999999999999, -0.22 ],
+ [ -0.22, 0, 9999999999999, now ]);
+
+ keysort('float < Date < String < Array',
+ [ [], "", now, [0], "-1", 0, 9999999999999, ],
+ [ 0, 9999999999999, now, "", "-1", [], [0] ]);
+
+
+ keysort('Date(1 sec ago) < Date(now) < Date(1 minute in future)',
+ [ now, one_sec_ago, one_min_future ],
+ [ one_sec_ago, now, one_min_future ]);
+
+ keysort('-1.1 < 1 < 1.01337 < 1.013373 < 2',
+ [ 1.013373, 2, 1.01337, -1.1, 1 ],
+ [ -1.1, 1, 1.01337, 1.013373, 2 ]);
+
+ keysort('-Infinity < -0.01 < 0 < Infinity',
+ [ 0, -0.01, -Infinity, Infinity ],
+ [ -Infinity, -0.01, 0, Infinity ]);
+
+ keysort('"" < "a" < "ab" < "b" < "ba"',
+ [ "a", "ba", "", "b", "ab" ],
+ [ "", "a", "ab", "b", "ba" ]);
+
+ keysort('Arrays',
+ [ [[0]], [0], [], [0, 0], [0, [0]] ],
+ [ [], [0], [0, 0], [0, [0]], [[0]] ]);
+
+ var big_array = [], bigger_array = [];
+ for (var i=0; i < 10000; i++) {
+ big_array.push(i);
+ bigger_array.push(i);
+ }
+ bigger_array.push(0);
+
+ keysort('Array.length: 10,000 < Array.length: 10,001',
+ [ bigger_array, [0, 2, 3], [0], [9], big_array ],
+ [ [0], big_array, bigger_array, [0, 2, 3], [9] ]);
+
+ keysort('Infinity inside arrays',
+ [ [Infinity, 1], [Infinity, Infinity], [1, 1],
+ [1, Infinity], [1, -Infinity], [-Infinity, Infinity] ],
+ [ [-Infinity, Infinity], [1, -Infinity], [1, 1],
+ [1, Infinity], [Infinity, 1], [Infinity, Infinity] ]);
+
+
+ keysort('Test different stuff at once',
+ [
+ now,
+ [0, []],
+ "test",
+ 1,
+ ["a", [1, [-1]]],
+ ["b", "a"],
+ [ 0, 2, "c"],
+ ["a", [1, 2]],
+ [],
+ [0, [], 3],
+ ["a", "b"],
+ [ 1, 2 ],
+ ["a", "b", "c"],
+ one_sec_ago,
+ [ 0, "b", "c"],
+ Infinity,
+ -Infinity,
+ 2.55,
+ [ 0, now ],
+ [1]
+ ],
+ [
+ -Infinity,
+ 1,
+ 2.55,
+ Infinity,
+ one_sec_ago,
+ now,
+ "test",
+ [],
+ [0 ,2, "c"],
+ [0, now],
+ [0, "b", "c"],
+ [0, []],
+ [0, [], 3],
+ [1],
+ [1, 2],
+ ["a", "b"],
+ ["a", "b", "c"],
+ ["a", [1, 2]],
+ ["a", [1, [-1]]],
+ ["b", "a"]
+ ]);
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/keypath.htm b/testing/web-platform/tests/IndexedDB/keypath.htm
new file mode 100644
index 000000000..b59d614e8
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/keypath.htm
@@ -0,0 +1,146 @@
+<!DOCTYPE html>
+<!-- Submitted from TestTWF Paris -->
+<meta charset="utf-8">
+<title>Keypath</title>
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#key-path-construct">
+<link rel=assert title="A key path is a DOMString that defines how to extract a key from a value. A valid key path is either the empty string, a JavaScript identifier, or multiple Javascript identifiers separated by periods (ASCII character code 46) [ECMA-262].">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var global_db = createdb_for_multiple_tests();
+
+ function keypath(keypath, objects, expected_keys, desc) {
+ var db,
+ t = async_test(document.title + " - " + (desc ? desc : keypath)),
+
+ store_name = "store-"+(Date.now())+Math.random();
+
+ var open_rq = global_db.setTest(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore(store_name, { keyPath: keypath });
+
+ for (var i = 0; i < objects.length; i++)
+ objStore.add(objects[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var actual_keys = [],
+ rq = db.transaction(store_name)
+ .objectStore(store_name)
+ .openCursor();
+
+ rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ if (cursor) {
+ actual_keys.push(cursor.key.valueOf());
+ cursor.continue();
+ }
+ else {
+ assert_key_equals(actual_keys, expected_keys, "keyorder array");
+ t.done();
+ }
+ });
+ };
+ }
+
+ keypath('my.key',
+ [ { my: { key: 10 } } ],
+ [ 10 ]);
+
+ keypath('my.køi',
+ [ { my: { køi: 5 } } ],
+ [ 5 ]);
+
+ keypath('my.key_ya',
+ [ { my: { key_ya: 10 } } ],
+ [ 10 ]);
+
+ keypath('public.key$ya',
+ [ { public: { key$ya: 10 } } ],
+ [ 10 ]);
+
+ keypath('true.$',
+ [ { true: { $: 10 } } ],
+ [ 10 ]);
+
+ keypath('my._',
+ [ { my: { _: 10 } } ],
+ [ 10 ]);
+
+ keypath('delete.a7',
+ [ { delete: { a7: 10 } } ],
+ [ 10 ]);
+
+ keypath('p.p.p.p.p.p.p.p.p.p.p.p.p.p',
+ [ {p:{p:{p:{p:{p:{p:{p:{p:{p:{p:{p:{p:{p:{p:10}}}}}}}}}}}}}} ],
+ [ 10 ]);
+
+ keypath('str.length',
+ [ { str: "pony" }, { str: "my" }, { str: "little" }, { str: "" } ],
+ [ 0, 2, 4, 6 ]);
+
+ keypath('arr.length',
+ [ {arr: [0, 0, 0, 0]}, {arr: [{}, 0, "hei", "length", Infinity, []]}, {arr: [10, 10]}, { arr: []} ],
+ [ 0, 2, 4, 6 ]);
+
+ keypath('length',
+ [ [10, 10], "123", { length: 20 } ],
+ [ 2, 3, 20 ]);
+
+ keypath('',
+ [ ["bags"], "bean", 10 ],
+ [ 10, "bean", ["bags"] ],
+ "'' uses value as key");
+
+ keypath([''],
+ [ ["bags"], "bean", 10 ],
+ [ [10], ["bean"] , [["bags"]] ],
+ "[''] uses value as [key]");
+
+ keypath(['x', 'y'],
+ [ {x:10, y:20}, {y:1.337, x:100} ],
+ [ [10, 20], [100, 1.337] ],
+ "['x', 'y']");
+
+ keypath([['x'], ['y']],
+ [ {x:10, y:20}, {y:1.337, x:100} ],
+ [ [10, 20], [100, 1.337] ],
+ "[['x'], 'y'] (stringifies)");
+
+ keypath(['x', {toString:function(){return 'y'}}],
+ [ {x:10, y:20}, {y:1.337, x:100} ],
+ [ [10, 20], [100, 1.337] ],
+ "['x', {toString->'y'}] (stringifies)");
+
+ if (false) {
+ var myblob = Blob(["Yoda"], {type:'suprawsum'});
+ keypath(['length', 'type'],
+ [ myblob ],
+ [ 4, 'suprawsum' ],
+ "[Blob.length, Blob.type]");
+ }
+
+ // File.name and File.lastModifiedDate is not testable automatically
+
+ keypath(['name', 'type'],
+ [ { name: "orange", type: "fruit" }, { name: "orange", type: ["telecom", "french"] } ],
+ [ ["orange", "fruit"], ["orange", ["telecom", "french"]] ]);
+
+ keypath(['name', 'type.name'],
+ [ { name: "orange", type: { name: "fruit" }}, { name: "orange", type: { name: "telecom" }} ],
+ [ ["orange", "fruit"], ["orange", "telecom" ] ]);
+
+ loop_array = [];
+ loop_array.push(loop_array);
+ keypath(loop_array,
+ [ "a", 1, ["k"] ],
+ [ [1], ["a"], [["k"]] ],
+ "array loop -> stringify becomes ['']");
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/keypath_invalid.htm b/testing/web-platform/tests/IndexedDB/keypath_invalid.htm
new file mode 100644
index 000000000..9c5bd6c2f
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/keypath_invalid.htm
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<!-- Submitted from TestTWF Paris -->
+<meta charset="utf-8">
+<title>Invalid keypath</title>
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#key-path-construct">
+<link rel=assert title="A key path is a DOMString that defines how to extract a key from a value. A valid key path is either the empty string, a JavaScript identifier, or multiple Javascript identifiers separated by periods (ASCII character code 46) [ECMA-262].">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+
+ var global_db = createdb_for_multiple_tests();
+
+ function invalid_keypath(keypath, desc) {
+ var t = async_test("Invalid keyPath - " + (desc ? desc : format_value(keypath)), undefined, 2);
+
+ var openrq = global_db.setTest(t),
+ store_name = "store-" + Date.now() + Math.random();
+
+ openrq.onupgradeneeded = function(e) {
+ var db = e.target.result;
+ assert_throws('SyntaxError', function() {
+ db.createObjectStore(store_name, { keyPath: keypath })
+ }, "createObjectStore with keyPath");
+
+ store = db.createObjectStore(store_name);
+ assert_throws('SyntaxError', function() {
+ store.createIndex('index', keypath);
+ }, "createIndex with keyPath");
+
+ db.close();
+
+ this.done();
+ };
+ }
+
+ invalid_keypath('j a');
+ invalid_keypath('.yo');
+ invalid_keypath('yo,lo');
+ invalid_keypath([]);
+ invalid_keypath(['array with space']);
+ invalid_keypath(['multi_array', ['a', 'b']], "multidimensional array (invalid toString)"); // => ['multi_array', 'a,b']
+ invalid_keypath('3m');
+ invalid_keypath({toString:function(){return '3m'}}, '{toString->3m}');
+ invalid_keypath('my.1337');
+ invalid_keypath('..yo');
+ invalid_keypath('y..o');
+ invalid_keypath('y.o.');
+ invalid_keypath('y.o..');
+ invalid_keypath('m.*');
+ invalid_keypath('"m"');
+ invalid_keypath('m%');
+ invalid_keypath('m/');
+ invalid_keypath('m/a');
+ invalid_keypath('m&');
+ invalid_keypath('m!');
+ invalid_keypath('*');
+ invalid_keypath('*.*');
+ invalid_keypath('^m');
+ invalid_keypath('/m/');
+
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/keypath_maxsize.htm b/testing/web-platform/tests/IndexedDB/keypath_maxsize.htm
new file mode 100644
index 000000000..835b7a33b
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/keypath_maxsize.htm
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Keypath</title>
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#key-path-construct">
+<link rel=assert title="A key path is a DOMString that defines how to extract a key from a value. A valid key path is either the empty string, a JavaScript identifier, or multiple Javascript identifiers separated by periods (ASCII character code 46) [ECMA-262].">
+<meta name=timeout content=long>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ function keypath(keypath, objects, expected_keys, desc) {
+ var db,
+ t = async_test(document.title + " - " + (desc ? desc : keypath), { timeout: 10000 }),
+ open_rq = createdb(t);
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { keyPath: keypath });
+
+ for (var i = 0; i < objects.length; i++)
+ objStore.add(objects[i]);
+ };
+
+ open_rq.onerror = function(e) {
+ assert_unreached(e.target.error.name);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var actual_keys = [],
+ rq = db.transaction("store")
+ .objectStore("store")
+ .openCursor();
+
+ rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ if (cursor) {
+ actual_keys.push(cursor.key.valueOf());
+ cursor.continue();
+ } else {
+ assert_array_equals(actual_keys, expected_keys, "keyorder array");
+ t.done();
+ }
+ });
+ };
+ }
+
+ keypath('maaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaai.keeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeey',
+ [ { maaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaai: { keeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeey: 10 } } ],
+ [ 10 ], '~260 chars');
+
+ keypath('maaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaai_maaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaai.keeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeey_keeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeey',
+ [ { maaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaai_maaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaai: { keeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeey_keeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeey: 10 } } ],
+ [ 10 ], '~530 chars');
+
+ keypath('maaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaai_maaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaai_maaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaai_maaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaai.keeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeey_keeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeey_keeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeey_keeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeey',
+ [ { maaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaai_maaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaai_maaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaai_maaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaai: { keeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeey_keeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeey_keeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeey_keeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeey: 10 } } ],
+ [ 10 ], '~1050 chars');
+
+</script>
+
+<div id=log></log>
diff --git a/testing/web-platform/tests/IndexedDB/list_ordering.htm b/testing/web-platform/tests/IndexedDB/list_ordering.htm
new file mode 100644
index 000000000..8349dbae7
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/list_ordering.htm
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>objectStoreNames and indexNames order</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBDatabase-objectStoreNames">
+<link rel=assert title="The list must be sorted in ascending order using the algorithm defined by step 4 of section 11.8.5, The Abstract Relational Comparison Algorithm of the ECMAScript Language Specification [ECMA-262].">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ function list_order(desc, unsorted, expected) {
+ var objStore, db,
+ t = async_test(document.title + " - " + desc);
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ for (var i = 0; i < unsorted.length; i++)
+ objStore = db.createObjectStore(unsorted[i]);
+
+ assert_equals(db.objectStoreNames.length, expected.length, "objectStoreNames length");
+ for (var i = 0; i < expected.length; i++)
+ assert_equals(db.objectStoreNames[i], expected[i], "objectStoreNames["+i+"]");
+
+ for (var i = 0; i < unsorted.length; i++)
+ objStore.createIndex(unsorted[i], "length");
+
+ assert_equals(objStore.indexNames.length, expected.length, "indexNames length");
+ for (var i = 0; i < expected.length; i++)
+ assert_equals(objStore.indexNames[i], expected[i], "indexNames["+i+"]");
+ };
+
+ open_rq.onsuccess = function(e) {
+ assert_equals(db.objectStoreNames.length, expected.length, "objectStoreNames length");
+ for (var i = 0; i < expected.length; i++)
+ assert_equals(db.objectStoreNames[i], expected[i], "objectStoreNames["+i+"]");
+
+ assert_equals(objStore.indexNames.length, expected.length, "indexNames length");
+ for (var i = 0; i < expected.length; i++)
+ assert_equals(objStore.indexNames[i], expected[i], "indexNames["+i+"]");
+
+ t.done();
+ };
+ }
+
+ list_order("numbers",
+ [123456, -12345, -123, 123, 1234, -1234, 0, 12345, -123456],
+ ["-123", "-1234", "-12345", "-123456", "0", "123", "1234", "12345", "123456"]);
+
+ list_order("numbers 'overflow'",
+ [9, 1, 1000000000, 200000000000000000],
+ ["1", "1000000000", "200000000000000000", "9"]);
+
+ list_order("lexigraphical string sort",
+ [ "cc", "c", "aa", "a", "bb", "b", "ab", "", "ac" ],
+ [ "", "a", "aa", "ab", "ac", "b", "bb", "c", "cc" ]);
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/objectstore_keyorder.htm b/testing/web-platform/tests/IndexedDB/objectstore_keyorder.htm
new file mode 100644
index 000000000..69c281fd0
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/objectstore_keyorder.htm
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Verify key sort order in an object store is 'number &lt; Date &lt; DOMString' </title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+ var db,
+ d = new Date(),
+ t = async_test(),
+ records = [ { key: d },
+ { key: "test" },
+ { key: 1 },
+ { key: 2.55 } ],
+ expectedKeyOrder = [ 1, 2.55, d.valueOf(), "test" ];
+
+ var open_rq = createdb(t);
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objStore = db.createObjectStore("store", { keyPath: "key" });
+
+ for (var i = 0; i < records.length; i++)
+ objStore.add(records[i]);
+ };
+
+ open_rq.onsuccess = function(e) {
+ var actual_keys = [],
+ rq = db.transaction("store")
+ .objectStore("store")
+ .openCursor();
+
+ rq.onsuccess = t.step_func(function(e) {
+ var cursor = e.target.result;
+
+ if (cursor) {
+ actual_keys.push(cursor.key.valueOf());
+ cursor.continue();
+ }
+ else {
+ assert_array_equals(actual_keys, expectedKeyOrder);
+ t.done();
+ }
+ });
+ };
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/request_bubble-and-capture.htm b/testing/web-platform/tests/IndexedDB/request_bubble-and-capture.htm
new file mode 100644
index 000000000..319f228c8
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/request_bubble-and-capture.htm
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Bubbling and capturing of request events</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var events = [];
+
+ var open_rq = createdb(async_test(document.title, {timeout: 10000}));
+ open_rq.onupgradeneeded = function(e) {
+ var db = e.target.result;
+ var txn = e.target.transaction;
+ var store = db.createObjectStore("s");
+ var rq1 = store.add("", 1);
+ var rq2 = store.add("", 1);
+ db.onerror = function(){};
+
+ log_request(' db', db);
+ log_request('txn', txn);
+ log_request('rq1', rq1);
+ log_request('rq2', rq2);
+
+ // Don't let it get to abort
+ db.addEventListener('error', function(e) { e.preventDefault() }, false);
+ }
+
+ open_rq.onsuccess = function(e) {
+ log("open_rq.success")(e);
+ assert_array_equals(events, [
+ "capture db.success",
+ "capture txn.success",
+ "capture rq1.success",
+ "bubble rq1.success",
+
+ "capture db.error: ConstraintError",
+ "capture txn.error: ConstraintError",
+ "capture rq2.error: ConstraintError",
+ "bubble rq2.error: ConstraintError",
+ "bubble txn.error: ConstraintError",
+ "bubble db.error: ConstraintError",
+
+ "open_rq.success"
+ ],
+ "events");
+ this.done();
+ }
+
+
+ function log_request(type, obj) {
+ obj.addEventListener('success', log('capture ' + type + '.success'), true);
+ obj.addEventListener('success', log('bubble ' + type + '.success'), false);
+ obj.addEventListener('error', log('capture ' + type + '.error'), true);
+ obj.addEventListener('error', log('bubble ' + type + '.error'), false);
+ }
+
+ function log(msg) {
+ return function(e) {
+ if(e && e.target && e.target.error)
+ events.push(msg + ": " + e.target.error.name);
+ else
+ events.push(msg);
+ };
+ }
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/string-list-ordering.htm b/testing/web-platform/tests/IndexedDB/string-list-ordering.htm
new file mode 100644
index 000000000..cc905e56e
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/string-list-ordering.htm
@@ -0,0 +1,85 @@
+<!--
+Test converted from WebKit:
+http://trac.webkit.org/browser/trunk/LayoutTests/storage/indexeddb/resources/list-ordering.js
+-->
+
+<!DOCTYPE html>
+<!-- Submitted from TestTWF Paris -->
+<meta charset=utf-8>
+<title>Test string list ordering in IndexedDB</title>
+<link rel=help href="http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#widl-IDBDatabase-objectStoreNames">
+<link rel=assert title="The list must be sorted in ascending order using the algorithm defined by step 4 of section 11.8.5, The Abstract Relational Comparison Algorithm of the ECMAScript Language Specification [ECMA-262].">
+<link rel=author href="mailto:romain.huet@gmail.com" title="Romain Huet">
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+
+ var expectedOrder = [
+ "",
+ "\x00", // 'NULL' (U+0000)
+ "0",
+ "1",
+ "A",
+ "B",
+ "a",
+ "b",
+ "\x7F", // 'DELETE' (U+007F)
+ "\xC0", // 'LATIN CAPITAL LETTER A WITH GRAVE' (U+00C0)
+ "\xC1", // 'LATIN CAPITAL LETTER A WITH ACUTE' (U+00C1)
+ "\xE0", // 'LATIN SMALL LETTER A WITH GRAVE' (U+00E0)
+ "\xE1", // 'LATIN SMALL LETTER A WITH ACUTE' (U+00E1)
+ "\xFF", // 'LATIN SMALL LETTER Y WITH DIAERESIS' (U+00FF)
+ "\u0100", // 'LATIN CAPITAL LETTER A WITH MACRON' (U+0100)
+ "\u1000", // 'MYANMAR LETTER KA' (U+1000)
+ "\uD834\uDD1E", // 'MUSICAL SYMBOL G-CLEF' (U+1D11E), UTF-16 surrogate pairs
+ "\uFFFD" // 'REPLACEMENT CHARACTER' (U+FFFD)
+ ];
+
+ var i, tmp, permutedOrder = expectedOrder.slice();
+ permutedOrder.reverse();
+ for (i = 0; i < permutedOrder.length - 2; i += 2) {
+ tmp = permutedOrder[i];
+ permutedOrder[i] = permutedOrder[i + 1];
+ permutedOrder[i + 1] = tmp;
+ }
+
+ var objStore, db;
+ var t = async_test();
+
+ // Check that the expected order is the canonical JS sort order.
+ var sortedOrder = expectedOrder.slice();
+ sortedOrder.sort();
+ assert_array_equals(sortedOrder, expectedOrder);
+
+ var request = createdb(t);
+
+ request.onupgradeneeded = function(e) {
+ db = e.target.result;
+
+ // Object stores.
+ for (var i = 0; i < permutedOrder.length; i++) {
+ objStore = db.createObjectStore(permutedOrder[i]);
+ }
+ assert_array_equals(db.objectStoreNames, expectedOrder);
+
+ // Indexes.
+ for (var i = 0; i < permutedOrder.length; i++) {
+ objStore.createIndex(permutedOrder[i], "keyPath");
+ }
+ assert_array_equals(objStore.indexNames, expectedOrder);
+ };
+
+ request.onsuccess = function(e) {
+ // Object stores.
+ assert_array_equals(db.objectStoreNames, expectedOrder);
+ // Indexes.
+ assert_array_equals(objStore.indexNames, expectedOrder);
+ t.done();
+ };
+
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/support-promises.js b/testing/web-platform/tests/IndexedDB/support-promises.js
new file mode 100644
index 000000000..c24a9fb92
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/support-promises.js
@@ -0,0 +1,200 @@
+// Returns an IndexedDB database name likely to be unique to the test case.
+const databaseName = (testCase) => {
+ return 'db' + self.location.pathname + '-' + testCase.name;
+};
+
+// Creates an EventWatcher covering all the events that can be issued by
+// IndexedDB requests and transactions.
+const requestWatcher = (testCase, request) => {
+ return new EventWatcher(testCase, request,
+ ['error', 'success', 'upgradeneeded']);
+};
+
+// Migrates an IndexedDB database whose name is unique for the test case.
+//
+// newVersion must be greater than the database's current version.
+//
+// migrationCallback will be called during a versionchange transaction and will
+// be given the created database and the versionchange transaction.
+//
+// Returns a promise. If the versionchange transaction goes through, the promise
+// resolves to an IndexedDB database that must be closed by the caller. If the
+// versionchange transaction is aborted, the promise resolves to an error.
+const migrateDatabase = (testCase, newVersion, migrationCallback) => {
+ // We cannot use eventWatcher.wait_for('upgradeneeded') here, because
+ // the versionchange transaction auto-commits before the Promise's then
+ // callback gets called.
+ return new Promise((resolve, reject) => {
+ const request = indexedDB.open(databaseName(testCase), newVersion);
+ request.onupgradeneeded = testCase.step_func(event => {
+ const database = event.target.result;
+ const transaction = event.target.transaction;
+ let abortCalled = false;
+
+ // We wrap IDBTransaction.abort so we can set up the correct event
+ // listeners and expectations if the test chooses to abort the
+ // versionchange transaction.
+ const transactionAbort = transaction.abort.bind(transaction);
+ transaction.abort = () => {
+ request.onerror = event => {
+ event.preventDefault();
+ resolve(event);
+ };
+ request.onsuccess = () => reject(new Error(
+ 'indexedDB.open should not succeed after the ' +
+ 'versionchange transaction is aborted'));
+ transactionAbort();
+ abortCalled = true;
+ }
+
+ migrationCallback(database, transaction);
+ if (!abortCalled) {
+ request.onsuccess = null;
+ resolve(requestWatcher(testCase, request).wait_for('success'));
+ }
+ });
+ request.onerror = event => reject(event.target.error);
+ request.onsuccess = () => reject(new Error(
+ 'indexedDB.open should not succeed without creating a ' +
+ 'versionchange transaction'));
+ }).then(event => event.target.result || event.target.error);
+};
+
+// Creates an IndexedDB database whose name is unique for the test case.
+//
+// setupCallback will be called during a versionchange transaction, and will be
+// given the created database and the versionchange transaction.
+//
+// Returns a promise that resolves to an IndexedDB database. The caller must
+// close the database.
+const createDatabase = (testCase, setupCallback) => {
+ const request = indexedDB.deleteDatabase(databaseName(testCase));
+ const eventWatcher = requestWatcher(testCase, request);
+
+ return eventWatcher.wait_for('success').then(event =>
+ migrateDatabase(testCase, 1, setupCallback));
+};
+
+// Opens an IndexedDB database without performing schema changes.
+//
+// The given version number must match the database's current version.
+//
+// Returns a promise that resolves to an IndexedDB database. The caller must
+// close the database.
+const openDatabase = (testCase, version) => {
+ const request = indexedDB.open(databaseName(testCase), version);
+ const eventWatcher = requestWatcher(testCase, request);
+ return eventWatcher.wait_for('success').then(
+ event => event.target.result);
+}
+
+// The data in the 'books' object store records in the first example of the
+// IndexedDB specification.
+const BOOKS_RECORD_DATA = [
+ { title: 'Quarry Memories', author: 'Fred', isbn: 123456 },
+ { title: 'Water Buffaloes', author: 'Fred', isbn: 234567 },
+ { title: 'Bedrock Nights', author: 'Barney', isbn: 345678 },
+];
+
+// Creates a 'books' object store whose contents closely resembles the first
+// example in the IndexedDB specification.
+const createBooksStore = (testCase, database) => {
+ const store = database.createObjectStore('books',
+ { keyPath: 'isbn', autoIncrement: true });
+ store.createIndex('by_author', 'author');
+ store.createIndex('by_title', 'title', { unique: true });
+ for (let record of BOOKS_RECORD_DATA)
+ store.put(record);
+ return store;
+};
+
+// Creates a 'not_books' object store used to test renaming into existing or
+// deleted store names.
+const createNotBooksStore = (testCase, database) => {
+ const store = database.createObjectStore('not_books');
+ store.createIndex('not_by_author', 'author');
+ store.createIndex('not_by_title', 'title', { unique: true });
+ return store;
+};
+
+// Verifies that an object store's indexes match the indexes used to create the
+// books store in the test database's version 1.
+//
+// The errorMessage is used if the assertions fail. It can state that the
+// IndexedDB implementation being tested is incorrect, or that the testing code
+// is using it incorrectly.
+const checkStoreIndexes = (testCase, store, errorMessage) => {
+ assert_array_equals(
+ store.indexNames, ['by_author', 'by_title'], errorMessage);
+ const authorIndex = store.index('by_author');
+ const titleIndex = store.index('by_title');
+ return Promise.all([
+ checkAuthorIndexContents(testCase, authorIndex, errorMessage),
+ checkTitleIndexContents(testCase, titleIndex, errorMessage),
+ ]);
+};
+
+// Verifies that an object store's key generator is in the same state as the
+// key generator created for the books store in the test database's version 1.
+//
+// The errorMessage is used if the assertions fail. It can state that the
+// IndexedDB implementation being tested is incorrect, or that the testing code
+// is using it incorrectly.
+const checkStoreGenerator = (testCase, store, expectedKey, errorMessage) => {
+ const request = store.put(
+ { title: 'Bedrock Nights ' + expectedKey, author: 'Barney' });
+ const eventWatcher = requestWatcher(testCase, request);
+ return eventWatcher.wait_for('success').then(() => {
+ const result = request.result;
+ assert_equals(result, expectedKey, errorMessage);
+ });
+};
+
+// Verifies that an object store's contents matches the contents used to create
+// the books store in the test database's version 1.
+//
+// The errorMessage is used if the assertions fail. It can state that the
+// IndexedDB implementation being tested is incorrect, or that the testing code
+// is using it incorrectly.
+const checkStoreContents = (testCase, store, errorMessage) => {
+ const request = store.get(123456);
+ const eventWatcher = requestWatcher(testCase, request);
+ return eventWatcher.wait_for('success').then(() => {
+ const result = request.result;
+ assert_equals(result.isbn, BOOKS_RECORD_DATA[0].isbn, errorMessage);
+ assert_equals(result.author, BOOKS_RECORD_DATA[0].author, errorMessage);
+ assert_equals(result.title, BOOKS_RECORD_DATA[0].title, errorMessage);
+ });
+};
+
+// Verifies that index matches the 'by_author' index used to create the
+// by_author books store in the test database's version 1.
+//
+// The errorMessage is used if the assertions fail. It can state that the
+// IndexedDB implementation being tested is incorrect, or that the testing code
+// is using it incorrectly.
+const checkAuthorIndexContents = (testCase, index, errorMessage) => {
+ const request = index.get(BOOKS_RECORD_DATA[2].author);
+ const eventWatcher = requestWatcher(testCase, request);
+ return eventWatcher.wait_for('success').then(() => {
+ const result = request.result;
+ assert_equals(result.isbn, BOOKS_RECORD_DATA[2].isbn, errorMessage);
+ assert_equals(result.title, BOOKS_RECORD_DATA[2].title, errorMessage);
+ });
+};
+
+// Verifies that an index matches the 'by_title' index used to create the books
+// store in the test database's version 1.
+//
+// The errorMessage is used if the assertions fail. It can state that the
+// IndexedDB implementation being tested is incorrect, or that the testing code
+// is using it incorrectly.
+const checkTitleIndexContents = (testCase, index, errorMessage) => {
+ const request = index.get(BOOKS_RECORD_DATA[2].title);
+ const eventWatcher = requestWatcher(testCase, request);
+ return eventWatcher.wait_for('success').then(() => {
+ const result = request.result;
+ assert_equals(result.isbn, BOOKS_RECORD_DATA[2].isbn, errorMessage);
+ assert_equals(result.author, BOOKS_RECORD_DATA[2].author, errorMessage);
+ });
+};
diff --git a/testing/web-platform/tests/IndexedDB/support.js b/testing/web-platform/tests/IndexedDB/support.js
new file mode 100644
index 000000000..814987393
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/support.js
@@ -0,0 +1,123 @@
+var databaseName = "database";
+var databaseVersion = 1;
+
+/* Delete created databases
+ *
+ * Go through each finished test, see if it has an associated database. Close
+ * that and delete the database. */
+add_completion_callback(function(tests)
+{
+ for (var i in tests)
+ {
+ if(tests[i].db)
+ {
+ tests[i].db.close();
+ window.indexedDB.deleteDatabase(tests[i].db.name);
+ }
+ }
+});
+
+function fail(test, desc) {
+ return test.step_func(function(e) {
+ if (e && e.message && e.target.error)
+ assert_unreached(desc + " (" + e.target.error.name + ": " + e.message + ")");
+ else if (e && e.message)
+ assert_unreached(desc + " (" + e.message + ")");
+ else if (e && e.target.readyState === 'done' && e.target.error)
+ assert_unreached(desc + " (" + e.target.error.name + ")");
+ else
+ assert_unreached(desc);
+ });
+}
+
+function createdb(test, dbname, version)
+{
+ var rq_open = createdb_for_multiple_tests(dbname, version);
+ return rq_open.setTest(test);
+}
+
+function createdb_for_multiple_tests(dbname, version) {
+ var rq_open,
+ fake_open = {},
+ test = null,
+ dbname = (dbname ? dbname : "testdb-" + new Date().getTime() + Math.random() );
+
+ if (version)
+ rq_open = window.indexedDB.open(dbname, version);
+ else
+ rq_open = window.indexedDB.open(dbname);
+
+ function auto_fail(evt, current_test) {
+ /* Fail handlers, if we haven't set on/whatever/, don't
+ * expect to get event whatever. */
+ rq_open.manually_handled = {}
+
+ rq_open.addEventListener(evt, function(e) {
+ if (current_test !== test) {
+ return;
+ }
+
+ test.step(function() {
+ if (!rq_open.manually_handled[evt]) {
+ assert_unreached("unexpected open." + evt + " event");
+ }
+
+ if (e.target.result + "" == "[object IDBDatabase]" && !this.db) {
+ this.db = e.target.result;
+
+ this.db.onerror = fail(test, "unexpected db.error");
+ this.db.onabort = fail(test, "unexpected db.abort");
+ this.db.onversionchange = fail(test, "unexpected db.versionchange");
+ }
+ })
+ })
+ rq_open.__defineSetter__("on" + evt, function(h) {
+ rq_open.manually_handled[evt] = true;
+ if (!h)
+ rq_open.addEventListener(evt, function() {});
+ else
+ rq_open.addEventListener(evt, test.step_func(h));
+ })
+ }
+
+ // add a .setTest method to the DB object
+ Object.defineProperty(rq_open, 'setTest', {
+ enumerable: false,
+ value: function(t) {
+ test = t;
+
+ auto_fail("upgradeneeded", test);
+ auto_fail("success", test);
+ auto_fail("blocked", test);
+ auto_fail("error", test);
+
+ return this;
+ }
+ });
+
+ return rq_open;
+}
+
+function assert_key_equals(actual, expected, description) {
+ assert_equals(indexedDB.cmp(actual, expected), 0, description);
+}
+
+function indexeddb_test(upgrade_func, open_func, description) {
+ async_test(function(t) {
+ var dbname = document.location + '-' + t.name;
+ var del = indexedDB.deleteDatabase(dbname);
+ del.onerror = t.unreached_func('deleteDatabase should succeed');
+ var open = indexedDB.open(dbname, 1);
+ open.onerror = t.unreached_func('open should succeed');
+ open.onupgradeneeded = t.step_func(function() {
+ var db = open.result;
+ var tx = open.transaction;
+ upgrade_func(t, db, tx);
+ });
+ open.onsuccess = t.step_func(function() {
+ var db = open.result;
+ if (open_func)
+ open_func(t, db);
+ });
+ }, description);
+}
diff --git a/testing/web-platform/tests/IndexedDB/transaction-abort-generator-revert.html b/testing/web-platform/tests/IndexedDB/transaction-abort-generator-revert.html
new file mode 100644
index 000000000..770d623f7
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/transaction-abort-generator-revert.html
@@ -0,0 +1,108 @@
+<!DOCTYPE html>
+<title>IndexedDB: aborting transactions reverts an object store's key generator state</title>
+<link rel="help" href="https://w3c.github.io/IndexedDB/#abort-transaction">
+<link rel="author" href="pwnall@chromium.org" title="Victor Costan">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support-promises.js"></script>
+<script>
+
+promise_test(testCase => {
+ return createDatabase(testCase, (database, transaction) => {
+ createBooksStore(testCase, database);
+ }).then(database => {
+ database.close();
+ }).then(() => {
+ return new Promise((resolve, reject) => {
+ const request = indexedDB.open(databaseName(testCase), 2);
+ request.onupgradeneeded = testCase.step_func(event => {
+ const database = event.target.result;
+ const transaction = event.target.transaction;
+ const store = transaction.objectStore('books');
+ const request2 = store.put(
+ { title: 'Bedrock Nights II', author: 'Barney' });
+ request2.onerror = testCase.unreached_func(
+ 'IDBObjectStore.put() should not receive an error request');
+ request2.onsuccess = testCase.step_func(event => {
+ assert_equals(
+ event.target.result, 345679,
+ "The key generator's current number should be set by " +
+ 'the last put operation in the database creation ' +
+ 'transaction');
+
+ request.onerror = event => {
+ event.preventDefault();
+ resolve(event);
+ };
+ request.onsuccess = () => reject(new Error(
+ 'indexedDB.open should not succeed after the ' +
+ 'versionchange transaction is aborted'));
+
+ transaction.abort();
+ });
+ });
+ request.onerror = event => reject(event.target.error);
+ request.onsuccess = () => reject(new Error(
+ 'indexedDB.open should not succeed without creating a ' +
+ 'versionchange transaction'));
+ });
+ }).then(() => {
+ return openDatabase(testCase, 1);
+ }).then(database => {
+ const transaction = database.transaction(['books'], 'readwrite');
+ const store = transaction.objectStore('books');
+
+ return checkStoreGenerator(
+ testCase, store, 345679,
+ "The key generator's current number should be reverted after the " +
+ 'transaction modifying it is aborted').then(() => database.close());
+ });
+}, 'The current number of a key generator is reverted when a versionchange ' +
+ 'transaction aborts');
+
+promise_test(testCase => {
+ return createDatabase(testCase, (database, transaction) => {
+ createBooksStore(testCase, database);
+ }).then(database => {
+ return new Promise((resolve, reject) => {
+ const transaction = database.transaction(['books'], 'readwrite');
+ const store = transaction.objectStore('books');
+ const request = store.put(
+ { title: 'Bedrock Nights II', author: 'Barney' });
+ request.onerror = testCase.unreached_func(
+ 'IDBObjectStore.put() should not receive an error request');
+ request.onsuccess = testCase.step_func(event => {
+ assert_equals(
+ event.target.result, 345679,
+ "The key generator's current number should be set by the " +
+ 'last put operation in the database creation transaction');
+
+ transaction.onabort = event => {
+ event.preventDefault();
+ resolve(event);
+ }
+ transaction.abort();
+ });
+ transaction.onabort = () => reject(new Error(
+ 'The aborted readwrite transaction should not receive an ' +
+ 'abort event before IDBTransaction.abort() is called'));
+ transaction.oncomplete = () => reject(new Error(
+ 'The aborted readwrite transaction should not receive a ' +
+ 'completed event'));
+ transaction.onerror = () => reject(new Error(
+ 'The aborted readwrite transaction should not receive an ' +
+ 'error event'));
+ }).then(() => database);
+ }).then(database => {
+ const transaction = database.transaction(['books'], 'readwrite');
+ const store = transaction.objectStore('books');
+
+ return checkStoreGenerator(
+ testCase, store, 345679,
+ "The key generator's current number should be reverted after the " +
+ 'transaction modifying it is aborted').then(() => database.close());
+ });
+}, 'The current number of a key generator is reverted when a readwrite ' +
+ 'transaction aborts');
+
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/transaction-abort-index-metadata-revert.html b/testing/web-platform/tests/IndexedDB/transaction-abort-index-metadata-revert.html
new file mode 100644
index 000000000..88ea28e22
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/transaction-abort-index-metadata-revert.html
@@ -0,0 +1,276 @@
+<!DOCTYPE html>
+<title>IndexedDB: aborting transactions reverts index metadata</title>
+<link rel="help" href="https://w3c.github.io/IndexedDB/#abort-transaction">
+<link rel="author" href="pwnall@chromium.org" title="Victor Costan">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support-promises.js"></script>
+<script>
+
+promise_test(testCase => {
+ let store = null, index = null;
+ return createDatabase(testCase, (database, transaction) => {
+ createBooksStore(testCase, database);
+ }).then(database => {
+ database.close();
+ }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
+ store = createNotBooksStore(testCase, database);
+ index = store.index('not_by_author');
+ assert_array_equals(
+ store.indexNames, ['not_by_author', 'not_by_title'],
+ 'IDBObjectStore.indexNames should include newly created indexes ' +
+ 'before the transaction is aborted');
+
+ transaction.abort();
+ assert_throws(
+ 'InvalidStateError', () => index.get('query'),
+ 'IDBIndex.get should throw InvalidStateError, indicating that ' +
+ 'the index is marked for deletion, immediately after ' +
+ 'IDBTransaction.abort() returns');
+ assert_array_equals(
+ store.indexNames, [],
+ 'IDBObjectStore.indexNames should stop including the newly ' +
+ 'created indexes immediately after IDBTransaction.abort() returns');
+ })).then(() => {
+ assert_throws(
+ 'InvalidStateError', () => index.get('query'),
+ 'IDBIndex.get should throw InvalidStateError, indicating that ' +
+ 'the index is marked for deletion, after the transaction is ' +
+ 'aborted');
+ assert_array_equals(
+ store.indexNames, [],
+ 'IDBObjectStore.indexNames should stop including the newly ' +
+ 'created indexes after the transaction is aborted');
+ });
+}, 'Created stores get their indexes marked as deleted after the transaction ' +
+ 'that created them aborts');
+
+promise_test(testCase => {
+ let store = null, index = null;
+ return createDatabase(testCase, (database, transaction) => {
+ createBooksStore(testCase, database);
+ createNotBooksStore(testCase, database);
+ }).then(database => {
+ database.close();
+ }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
+ store = transaction.objectStore('not_books');
+ index = store.index('not_by_author');
+
+ database.deleteObjectStore('not_books');
+ assert_throws(
+ 'InvalidStateError', () => index.get('query'),
+ 'IDBIndex.get should throw InvalidStateError, indicating that ' +
+ 'the index is marked for deletion, immediately after ' +
+ 'IDBDatabase.deleteObjectStore() returns');
+ assert_array_equals(
+ store.indexNames, [],
+ 'IDBObjectStore.indexNames should be empty immediately after ' +
+ 'IDBDatabase.deleteObjectStore() returns');
+
+ transaction.abort();
+ assert_throws(
+ 'TransactionInactiveError', () => index.get('query'),
+ 'IDBIndex.get should throw TransactionInactiveError, indicating ' +
+ 'that the index is no longer marked for deletion, immediately ' +
+ 'after IDBTransaction.abort() returns');
+ assert_array_equals(
+ store.indexNames, ['not_by_author', 'not_by_title'],
+ 'IDBObjectStore.indexNames should include the deleted indexes ' +
+ 'immediately after IDBTransaction.abort() returns');
+ })).then(() => {
+ assert_throws(
+ 'TransactionInactiveError', () => index.get('query'),
+ 'IDBIndex.get should throw TransactionInactiveError, indicating ' +
+ 'that the index is no longer marked for deletion, after the ' +
+ 'transaction is aborted');
+ assert_array_equals(
+ store.indexNames, ['not_by_author', 'not_by_title'],
+ 'IDBObjectStore.indexNames should include the deleted indexes ' +
+ 'after the transaction is aborted');
+ });
+}, 'Deleted stores get their indexes marked as not-deleted after the ' +
+ 'transaction that deleted them aborts');
+
+promise_test(testCase => {
+ let store = null, index = null;
+ return createDatabase(testCase, (database, transaction) => {
+ createBooksStore(testCase, database);
+ }).then(database => {
+ database.close();
+ }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
+ store = createNotBooksStore(testCase, database);
+ index = store.index('not_by_author');
+ assert_array_equals(
+ store.indexNames, ['not_by_author', 'not_by_title'],
+ 'IDBObjectStore.indexNames should include newly created indexes ' +
+ 'before the transaction is aborted');
+
+ database.deleteObjectStore('not_books');
+ assert_throws(
+ 'InvalidStateError', () => index.get('query'),
+ 'IDBIndex.get should throw InvalidStateError, indicating that ' +
+ 'the index is marked for deletion, immediately after ' +
+ 'IDBDatabase.deleteObjectStore() returns');
+ assert_array_equals(
+ store.indexNames, [],
+ 'IDBObjectStore.indexNames should be empty immediately after ' +
+ 'IDBDatabase.deleteObjectStore() returns');
+
+ transaction.abort();
+ assert_throws(
+ 'InvalidStateError', () => index.get('query'),
+ 'IDBIndex.get should throw InvalidStateError, indicating that ' +
+ 'the index is still marked for deletion, immediately after ' +
+ 'IDBTransaction.abort() returns');
+ assert_array_equals(
+ store.indexNames, [],
+ 'IDBObjectStore.indexNames should not include the newly ' +
+ 'created indexes immediately after IDBTransaction.abort() returns');
+ })).then(() => {
+ assert_throws(
+ 'InvalidStateError', () => index.get('query'),
+ 'IDBIndex.get should throw InvalidStateError, indicating that ' +
+ 'the index is still marked for deletion, after the transaction ' +
+ 'is aborted');
+ assert_array_equals(
+ store.indexNames, [],
+ 'IDBObjectStore.indexNames should not include the newly ' +
+ 'created indexes after the transaction is aborted');
+ });
+}, 'Created+deleted stores still have their indexes marked as deleted after ' +
+ 'the transaction aborts');
+
+promise_test(testCase => {
+ let store = null, index = null;
+ return createDatabase(testCase, (database, transaction) => {
+ createBooksStore(testCase, database);
+ createNotBooksStore(testCase, database);
+ }).then(database => {
+ database.close();
+ }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
+ store = transaction.objectStore('not_books');
+ index = store.createIndex('not_by_isbn', 'isbn');
+ assert_array_equals(
+ store.indexNames, ['not_by_author', 'not_by_isbn', 'not_by_title'],
+ 'IDBObjectStore.indexNames should include newly created indexes ' +
+ 'before the transaction is aborted');
+
+ transaction.abort();
+ assert_throws(
+ 'InvalidStateError', () => index.get('query'),
+ 'IDBIndex.get should throw InvalidStateError, indicating that ' +
+ 'the index is marked for deletion, immediately after ' +
+ 'IDBTransaction.abort() returns');
+ assert_array_equals(
+ store.indexNames, ['not_by_author', 'not_by_title'],
+ 'IDBObjectStore.indexNames should stop including the newly ' +
+ 'created index immediately after IDBTransaction.abort() returns');
+ })).then(() => {
+ assert_throws(
+ 'InvalidStateError', () => index.get('query'),
+ 'IDBIndex.get should throw InvalidStateError, indicating that ' +
+ 'the index is marked for deletion, after the transaction is ' +
+ 'aborted');
+ assert_array_equals(
+ store.indexNames, ['not_by_author', 'not_by_title'],
+ 'IDBObjectStore.indexNames should stop including the newly ' +
+ 'created index after the transaction is aborted');
+ });
+}, 'Created indexes get marked as deleted after their transaction aborts');
+
+promise_test(testCase => {
+ let store = null, index = null;
+ return createDatabase(testCase, (database, transaction) => {
+ createBooksStore(testCase, database);
+ createNotBooksStore(testCase, database);
+ }).then(database => {
+ database.close();
+ }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
+ store = transaction.objectStore('not_books');
+ index = store.index('not_by_author');
+
+ store.deleteIndex('not_by_author');
+ assert_throws(
+ 'InvalidStateError', () => index.get('query'),
+ 'IDBIndex.get should throw InvalidStateError, indicating that ' +
+ 'the index is marked for deletion, immediately after ' +
+ 'IDBObjectStore.deleteIndex() returns');
+ assert_array_equals(
+ store.indexNames, ['not_by_title'],
+ 'IDBObjectStore.indexNames should not include the deleted index ' +
+ 'immediately after IDBObjectStore.deleteIndex() returns');
+
+ transaction.abort();
+ assert_throws(
+ 'TransactionInactiveError', () => index.get('query'),
+ 'IDBIndex.get should throw TransactionInactiveError, indicating ' +
+ 'that the index is no longer marked for deletion, immediately ' +
+ 'after IDBTransaction.abort() returns');
+ assert_array_equals(
+ store.indexNames, ['not_by_author', 'not_by_title'],
+ 'IDBObjectStore.indexNames should include the deleted indexes ' +
+ 'immediately after IDBTransaction.abort() returns');
+ })).then(() => {
+ assert_throws(
+ 'TransactionInactiveError', () => index.get('query'),
+ 'IDBIndex.get should throw TransactionInactiveError, indicating ' +
+ 'that the index is no longer marked for deletion, after the ' +
+ 'transaction is aborted');
+ assert_array_equals(
+ store.indexNames, ['not_by_author', 'not_by_title'],
+ 'IDBObjectStore.indexNames should include the deleted indexes ' +
+ 'after the transaction is aborted');
+ });
+}, 'Deleted indexes get marked as not-deleted after the transaction aborts');
+
+promise_test(testCase => {
+ let store = null, index = null;
+ return createDatabase(testCase, (database, transaction) => {
+ createBooksStore(testCase, database);
+ createNotBooksStore(testCase, database);
+ }).then(database => {
+ database.close();
+ }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
+ store = transaction.objectStore('not_books');
+ index = store.createIndex('not_by_isbn', 'isbn');
+ assert_array_equals(
+ store.indexNames, ['not_by_author', 'not_by_isbn', 'not_by_title'],
+ 'IDBObjectStore.indexNames should include newly created indexes ' +
+ 'before the transaction is aborted');
+
+ store.deleteIndex('not_by_isbn');
+ assert_throws(
+ 'InvalidStateError', () => index.get('query'),
+ 'IDBIndex.get should throw InvalidStateError, indicating that ' +
+ 'the index is marked for deletion, immediately after ' +
+ 'IDBObjectStore.deleteIndex() returns');
+ assert_array_equals(
+ store.indexNames, ['not_by_author', 'not_by_title'],
+ 'IDBObjectStore.indexNames should not include the deleted index ' +
+ 'immediately after IDBObjectStore.deleteIndex() returns');
+
+ transaction.abort();
+ assert_throws(
+ 'InvalidStateError', () => index.get('query'),
+ 'IDBIndex.get should throw InvalidStateError, indicating that ' +
+ 'the index is still marked for deletion, immediately after ' +
+ 'IDBTransaction.abort() returns');
+ assert_array_equals(
+ store.indexNames, ['not_by_author', 'not_by_title'],
+ 'IDBObjectStore.indexNames should stop including the newly ' +
+ 'created index immediately after IDBTransaction.abort() returns');
+ })).then(() => {
+ assert_throws(
+ 'InvalidStateError', () => index.get('query'),
+ 'IDBIndex.get should throw InvalidStateError, indicating that ' +
+ 'the index is marked for deletion, after the transaction is ' +
+ 'aborted');
+ assert_array_equals(
+ store.indexNames, ['not_by_author', 'not_by_title'],
+ 'IDBObjectStore.indexNames should stop including the newly ' +
+ 'created index after the transaction is aborted');
+ });
+}, 'Created+deleted indexes are still marked as deleted after their ' +
+ 'transaction aborts');
+
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/transaction-abort-multiple-metadata-revert.html b/testing/web-platform/tests/IndexedDB/transaction-abort-multiple-metadata-revert.html
new file mode 100644
index 000000000..4a00d4113
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/transaction-abort-multiple-metadata-revert.html
@@ -0,0 +1,291 @@
+<!DOCTYPE html>
+<title>IndexedDB: aborting transactions reverts multiple operations on the same metadata</title>
+<link rel="help" href="https://w3c.github.io/IndexedDB/#abort-transaction">
+<link rel="author" href="pwnall@chromium.org" title="Victor Costan">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support-promises.js"></script>
+<script>
+
+promise_test(testCase => {
+ let store = null, index = null;
+ let migrationTransaction = null, migrationDatabase = null;
+ return createDatabase(testCase, (database, transaction) => {
+ createBooksStore(testCase, database);
+ }).then(database => {
+ database.close();
+ }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
+ store = createNotBooksStore(testCase, database);
+ migrationDatabase = database;
+ migrationTransaction = transaction;
+ assert_array_equals(
+ database.objectStoreNames, ['books', 'not_books'],
+ 'IDBDatabase.objectStoreNames should include a newly created ' +
+ 'store before the transaction is aborted');
+ assert_array_equals(
+ transaction.objectStoreNames, ['books', 'not_books'],
+ 'IDBTransaction.objectStoreNames should include a newly created ' +
+ 'store before the transaction is aborted');
+
+ index = store.index('not_by_author');
+ store.deleteIndex('not_by_author');
+ assert_throws(
+ 'InvalidStateError', () => index.get('query'),
+ 'IDBIndex.get should throw InvalidStateError, indicating that ' +
+ 'the index is marked for deletion, immediately after ' +
+ 'IDBObjectStore.deleteIndex() returns');
+ assert_array_equals(
+ store.indexNames, ['not_by_title'],
+ 'IDBObjectStore.indexNames should not include the deleted index ' +
+ 'immediately after IDBObjectStore.deleteIndex() returns');
+
+ transaction.abort();
+ assert_throws(
+ 'InvalidStateError', () => store.get('query'),
+ 'IDBObjectStore.get should throw InvalidStateError, indicating ' +
+ 'that the store is marked for deletion, immediately after ' +
+ 'IDBTransaction.abort() returns');
+ assert_throws(
+ 'InvalidStateError', () => index.get('query'),
+ 'IDBIndex.get should throw InvalidStateError, indicating that ' +
+ 'the index is still marked for deletion, immediately after ' +
+ 'IDBTransaction.abort() returns');
+ assert_array_equals(
+ transaction.objectStoreNames, ['books'],
+ 'IDBTransaction.objectStoreNames should stop including the newly ' +
+ 'created store immediately after IDBTransaction.abort() returns');
+ assert_array_equals(
+ database.objectStoreNames, ['books'],
+ 'IDBDatabase.objectStoreNames should stop including the newly ' +
+ 'created store immediately after IDBTransaction.abort() returns');
+ assert_array_equals(
+ store.indexNames, [],
+ 'IDBObjectStore.indexNames for the newly created store should be ' +
+ 'empty immediately after IDBTransaction.abort() returns');
+ })).then(() => {
+ assert_throws(
+ 'InvalidStateError', () => store.get('query'),
+ 'IDBObjectStore.get should throw InvalidStateError, indicating ' +
+ 'that the store is marked for deletion, after the transaction is ' +
+ 'aborted');
+ assert_throws(
+ 'InvalidStateError', () => index.get('query'),
+ 'IDBIndex.get should throw InvalidStateError, indicating that ' +
+ 'the index is still marked for deletion, after the transaction ' +
+ 'is aborted');
+ assert_array_equals(
+ migrationDatabase.objectStoreNames, ['books'],
+ 'IDBDatabase.objectStoreNames should stop including the newly ' +
+ 'created store after the transaction is aborted');
+ assert_array_equals(
+ migrationTransaction.objectStoreNames, ['books'],
+ 'IDBTransaction.objectStoreNames should stop including the newly ' +
+ 'created store after the transaction is aborted');
+ assert_array_equals(
+ store.indexNames, [],
+ 'IDBObjectStore.indexNames for the newly created store should be ' +
+ 'empty after the transaction is aborted');
+ });
+}, 'Deleted indexes in newly created stores are still marked as deleted ' +
+ 'after the transaction aborts');
+
+promise_test(testCase => {
+ let store = null, index = null;
+ let migrationTransaction = null, migrationDatabase = null;
+ return createDatabase(testCase, (database, transaction) => {
+ createBooksStore(testCase, database);
+ createNotBooksStore(testCase, database);
+ }).then(database => {
+ database.close();
+ }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
+ migrationDatabase = database;
+ migrationTransaction = transaction;
+ store = transaction.objectStore('not_books');
+ index = store.index('not_by_author');
+ store.deleteIndex('not_by_author');
+ assert_throws(
+ 'InvalidStateError', () => index.get('query'),
+ 'IDBIndex.get should throw InvalidStateError, indicating that ' +
+ 'the index is marked for deletion, immediately after ' +
+ 'IDBObjectStore.deleteIndex() returns');
+ assert_array_equals(
+ store.indexNames, ['not_by_title'],
+ 'IDBObjectStore.indexNames should not include the deleted index ' +
+ 'immediately after IDBObjectStore.deleteIndex() returns');
+
+ database.deleteObjectStore('not_books');
+ assert_throws(
+ 'InvalidStateError', () => store.get('query'),
+ 'IDBObjectStore.get should throw InvalidStateError, indicating ' +
+ 'that the store is marked for deletion, immediately after ' +
+ 'IDBDatabase.deleteObjectStore() returns');
+ assert_throws(
+ 'InvalidStateError', () => index.get('query'),
+ 'IDBIndex.get should throw InvalidStateError, indicating that ' +
+ 'the index is still marked for deletion, immediately after ' +
+ 'IDBObjectStore.deleteIndex() returns');
+ assert_array_equals(
+ transaction.objectStoreNames, ['books'],
+ 'IDBTransaction.objectStoreNames should stop including the ' +
+ 'deleted store immediately after IDBDatabase.deleteObjectStore() ' +
+ 'returns');
+ assert_array_equals(
+ database.objectStoreNames, ['books'],
+ 'IDBDatabase.objectStoreNames should stop including the newly ' +
+ 'created store immediately after IDBDatabase.deleteObjectStore() ' +
+ 'returns');
+ assert_array_equals(
+ store.indexNames, [],
+ 'IDBObjectStore.indexNames for the deleted store should be empty ' +
+ 'immediately after IDBDatabase.deleteObjectStore() returns');
+
+ transaction.abort();
+ assert_throws(
+ 'TransactionInactiveError', () => store.get('query'),
+ 'IDBObjectStore.get should throw TransactionInactiveError, ' +
+ 'indicating that the store is no longer marked for deletion, ' +
+ 'immediately after IDBTransaction.abort() returns');
+ assert_throws(
+ 'TransactionInactiveError', () => index.get('query'),
+ 'IDBIndex.get should throw TransactionInactiveError, indicating ' +
+ 'that the index is no longer marked for deletion, immediately ' +
+ 'after IDBObjectStore.deleteIndex() returns');
+ assert_array_equals(
+ database.objectStoreNames, ['books', 'not_books'],
+ 'IDBDatabase.objectStoreNames should include the deleted store ' +
+ 'store immediately after IDBTransaction.abort() returns');
+ assert_array_equals(
+ transaction.objectStoreNames, ['books', 'not_books'],
+ 'IDBTransaction.objectStoreNames should include the deleted ' +
+ 'store immediately after IDBTransaction.abort() returns');
+ assert_array_equals(
+ store.indexNames, ['not_by_author', 'not_by_title'],
+ 'IDBObjectStore.indexNames for the deleted store should not be ' +
+ 'empty any more immediately after IDBTransaction.abort() returns');
+ })).then(() => {
+ assert_throws(
+ 'TransactionInactiveError', () => store.get('query'),
+ 'IDBObjectStore.get should throw TransactionInactiveError, ' +
+ 'indicating that the store is no longer marked for deletion, ' +
+ 'after the transaction is aborted');
+ assert_throws(
+ 'TransactionInactiveError', () => index.get('query'),
+ 'IDBIndex.get should throw TransactionInactiveError, indicating ' +
+ 'that the index is no longer marked for deletion, after the ' +
+ 'transaction is aborted');
+ assert_array_equals(
+ migrationDatabase.objectStoreNames, ['books', 'not_books'],
+ 'IDBDatabase.objectStoreNames should include the previously ' +
+ 'deleted store after the transaction is aborted');
+ assert_array_equals(
+ migrationTransaction.objectStoreNames, ['books', 'not_books'],
+ 'IDBTransaction.objectStoreNames should include the previously ' +
+ 'deleted store after the transaction is aborted');
+ assert_array_equals(
+ store.indexNames, ['not_by_author', 'not_by_title'],
+ 'IDBObjectStore.indexNames for the deleted store should not be ' +
+ 'empty after the transaction is aborted');
+ });
+}, 'Deleted indexes in deleted stores are still marked as not-deleted after ' +
+ 'the transaction aborts');
+
+promise_test(testCase => {
+ let store = null, index = null;
+ let migrationTransaction = null, migrationDatabase = null;
+ return createDatabase(testCase, (database, transaction) => {
+ createBooksStore(testCase, database);
+ }).then(database => {
+ database.close();
+ }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
+ store = createNotBooksStore(testCase, database);
+ migrationDatabase = database;
+ migrationTransaction = transaction;
+ index = store.index('not_by_author');
+ store.deleteIndex('not_by_author');
+ assert_throws(
+ 'InvalidStateError', () => index.get('query'),
+ 'IDBIndex.get should throw InvalidStateError, indicating that ' +
+ 'the index is marked for deletion, immediately after ' +
+ 'IDBObjectStore.deleteIndex() returns');
+ assert_array_equals(
+ store.indexNames, ['not_by_title'],
+ 'IDBObjectStore.indexNames should not include the deleted index ' +
+ 'immediately after IDBObjectStore.deleteIndex() returns');
+
+ database.deleteObjectStore('not_books');
+ assert_throws(
+ 'InvalidStateError', () => store.get('query'),
+ 'IDBObjectStore.get should throw InvalidStateError, indicating ' +
+ 'that the store is marked for deletion, immediately after ' +
+ 'IDBDatabase.deleteObjectStore() returns');
+ assert_throws(
+ 'InvalidStateError', () => index.get('query'),
+ 'IDBIndex.get should throw InvalidStateError, indicating that ' +
+ 'the index is still marked for deletion, immediately after ' +
+ 'IDBDatabase.deleteObjectStore() returns');
+ assert_array_equals(
+ transaction.objectStoreNames, ['books'],
+ 'IDBTransaction.objectStoreNames should stop including the ' +
+ 'deleted store immediately after IDBDatabase.deleteObjectStore() ' +
+ 'returns');
+ assert_array_equals(
+ database.objectStoreNames, ['books'],
+ 'IDBDatabase.objectStoreNames should stop including the newly ' +
+ 'created store immediately after IDBDatabase.deleteObjectStore() ' +
+ 'returns');
+ assert_array_equals(
+ store.indexNames, [],
+ 'IDBObjectStore.indexNames should be empty immediately after ' +
+ 'IDBDatabase.deleteObjectStore() returns');
+
+ transaction.abort();
+ assert_throws(
+ 'InvalidStateError', () => store.get('query'),
+ 'IDBObjectStore.get should throw InvalidStateError, indicating ' +
+ 'that the store is still marked for deletion, immediately after ' +
+ 'IDBTransaction.abort() returns');
+ assert_throws(
+ 'InvalidStateError', () => index.get('query'),
+ 'IDBIndex.get should throw InvalidStateError, indicating that ' +
+ 'the index is still marked for deletion, immediately after ' +
+ 'IDBTransaction.abort() returns');
+ assert_array_equals(
+ transaction.objectStoreNames, ['books'],
+ 'IDBTransaction.objectStoreNames should not include the newly ' +
+ 'created store immediately after IDBTransaction.abort() returns');
+ assert_array_equals(
+ database.objectStoreNames, ['books'],
+ 'IDBDatabase.objectStoreNames should not include the newly ' +
+ 'created store immediately after IDBTransaction.abort() returns');
+ assert_array_equals(
+ store.indexNames, [],
+ 'IDBObjectStore.indexNames should be empty immediately after ' +
+ 'IDBTransaction.abort() returns');
+ })).then(() => {
+ assert_throws(
+ 'InvalidStateError', () => store.get('query'),
+ 'IDBObjectStore.get should throw InvalidStateError, indicating ' +
+ 'that the store is still marked for deletion, after the ' +
+ 'transaction is aborted');
+ assert_throws(
+ 'InvalidStateError', () => index.get('query'),
+ 'IDBIndex.get should throw InvalidStateError, indicating that ' +
+ 'the index is still marked for deletion, after the transaction ' +
+ 'is aborted');
+ assert_array_equals(
+ migrationDatabase.objectStoreNames, ['books'],
+ 'IDBDatabase.objectStoreNames should not include the newly ' +
+ 'created store after the transaction is aborted');
+ assert_array_equals(
+ migrationTransaction.objectStoreNames, ['books'],
+ 'IDBTransaction.objectStoreNames should not include the newly ' +
+ 'created store after the transaction is aborted');
+ assert_array_equals(
+ store.indexNames, [],
+ 'IDBObjectStore.indexNames should be empty after the transaction ' +
+ 'is aborted');
+ });
+}, 'Deleted indexes in created+deleted stores are still marked as deleted ' +
+ 'after their transaction aborts');
+
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/transaction-abort-object-store-metadata-revert.html b/testing/web-platform/tests/IndexedDB/transaction-abort-object-store-metadata-revert.html
new file mode 100644
index 000000000..52982b8a3
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/transaction-abort-object-store-metadata-revert.html
@@ -0,0 +1,188 @@
+<!DOCTYPE html>
+<title>IndexedDB: aborting transactions reverts object store metadata</title>
+<link rel="help" href="https://w3c.github.io/IndexedDB/#abort-transaction">
+<link rel="author" href="pwnall@chromium.org" title="Victor Costan">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support-promises.js"></script>
+<script>
+
+promise_test(testCase => {
+ let store = null, migrationTransaction = null, migrationDatabase = null;
+ return createDatabase(testCase, (database, transaction) => {
+ createBooksStore(testCase, database);
+ }).then(database => {
+ database.close();
+ }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
+ store = createNotBooksStore(testCase, database);
+ migrationDatabase = database;
+ migrationTransaction = transaction;
+ assert_array_equals(
+ database.objectStoreNames, ['books', 'not_books'],
+ 'IDBDatabase.objectStoreNames should include a newly created ' +
+ 'store before the transaction is aborted');
+ assert_array_equals(
+ transaction.objectStoreNames, ['books', 'not_books'],
+ 'IDBTransaction.objectStoreNames should include a newly created ' +
+ 'store before the transaction is aborted');
+
+ transaction.abort();
+ assert_throws(
+ 'InvalidStateError', () => store.get('query'),
+ 'IDBObjectStore.get should throw InvalidStateError, indicating ' +
+ 'that the store is marked for deletion, immediately after ' +
+ 'IDBTransaction.abort() returns');
+ assert_array_equals(
+ transaction.objectStoreNames, ['books'],
+ 'IDBTransaction.objectStoreNames should stop including the newly ' +
+ 'created store immediately after IDBTransaction.abort() returns');
+ assert_array_equals(
+ database.objectStoreNames, ['books'],
+ 'IDBDatabase.objectStoreNames should stop including the newly ' +
+ 'created store immediately after IDBTransaction.abort() returns');
+ })).then(() => {
+ assert_throws(
+ 'InvalidStateError', () => store.get('query'),
+ 'IDBObjectStore.get should throw InvalidStateError, indicating ' +
+ 'that the store is marked for deletion, after the transaction is ' +
+ 'aborted');
+ assert_array_equals(
+ migrationDatabase.objectStoreNames, ['books'],
+ 'IDBDatabase.objectStoreNames should stop including the newly ' +
+ 'created store after the transaction is aborted');
+ assert_array_equals(
+ migrationTransaction.objectStoreNames, ['books'],
+ 'IDBTransaction.objectStoreNames should stop including the newly ' +
+ 'created store after the transaction is aborted');
+ });
+}, 'Created stores get marked as deleted after their transaction aborts');
+
+promise_test(testCase => {
+ let store = null, migrationTransaction = null, migrationDatabase = null;
+ return createDatabase(testCase, (database, transaction) => {
+ createBooksStore(testCase, database);
+ createNotBooksStore(testCase, database);
+ }).then(database => {
+ database.close();
+ }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
+ migrationDatabase = database;
+ migrationTransaction = transaction;
+ store = transaction.objectStore('not_books');
+
+ database.deleteObjectStore('not_books');
+ assert_throws(
+ 'InvalidStateError', () => store.get('query'),
+ 'IDBObjectStore.get should throw InvalidStateError, indicating ' +
+ 'that the store is marked for deletion, immediately after ' +
+ 'IDBDatabase.deleteObjectStore() returns');
+ assert_array_equals(
+ transaction.objectStoreNames, ['books'],
+ 'IDBTransaction.objectStoreNames should stop including the ' +
+ 'deleted store immediately after IDBDatabase.deleteObjectStore() ' +
+ 'returns');
+ assert_array_equals(
+ database.objectStoreNames, ['books'],
+ 'IDBDatabase.objectStoreNames should stop including the newly ' +
+ 'created store immediately after IDBDatabase.deleteObjectStore() ' +
+ 'returns');
+
+ transaction.abort();
+ assert_throws(
+ 'TransactionInactiveError', () => store.get('query'),
+ 'IDBObjectStore.get should throw TransactionInactiveError, ' +
+ 'indicating that the store is no longer marked for deletion, ' +
+ 'immediately after IDBTransaction.abort() returns');
+ assert_array_equals(
+ database.objectStoreNames, ['books', 'not_books'],
+ 'IDBDatabase.objectStoreNames should include the deleted store ' +
+ 'store immediately after IDBTransaction.abort() returns');
+ assert_array_equals(
+ transaction.objectStoreNames, ['books', 'not_books'],
+ 'IDBTransaction.objectStoreNames should include the deleted ' +
+ 'store immediately after IDBTransaction.abort() returns');
+ })).then(() => {
+ assert_throws(
+ 'TransactionInactiveError', () => store.get('query'),
+ 'IDBObjectStore.get should throw TransactionInactiveError, ' +
+ 'indicating that the store is no longer marked for deletion, ' +
+ 'after the transaction is aborted');
+ assert_array_equals(
+ migrationDatabase.objectStoreNames, ['books', 'not_books'],
+ 'IDBDatabase.objectStoreNames should include the previously ' +
+ 'deleted store after the transaction is aborted');
+ assert_array_equals(
+ migrationTransaction.objectStoreNames, ['books', 'not_books'],
+ 'IDBTransaction.objectStoreNames should include the previously ' +
+ 'deleted store after the transaction is aborted');
+ });
+}, 'Deleted stores get marked as not-deleted after the transaction aborts');
+
+promise_test(testCase => {
+ let store = null, migrationTransaction = null, migrationDatabase = null;
+ return createDatabase(testCase, (database, transaction) => {
+ createBooksStore(testCase, database);
+ }).then(database => {
+ database.close();
+ }).then(() => migrateDatabase(testCase, 2, (database, transaction) => {
+ store = createNotBooksStore(testCase, database);
+ migrationDatabase = database;
+ migrationTransaction = transaction;
+ assert_array_equals(
+ database.objectStoreNames, ['books', 'not_books'],
+ 'IDBDatabase.objectStoreNames should include a newly created ' +
+ 'store before the transaction is aborted');
+ assert_array_equals(
+ transaction.objectStoreNames, ['books', 'not_books'],
+ 'IDBTransaction.objectStoreNames should include a newly created ' +
+ 'store before the transaction is aborted');
+
+ database.deleteObjectStore('not_books');
+ assert_throws(
+ 'InvalidStateError', () => store.get('query'),
+ 'IDBObjectStore.get should throw InvalidStateError, indicating ' +
+ 'that the store is marked for deletion, immediately after ' +
+ 'IDBDatabase.deleteObjectStore() returns');
+ assert_array_equals(
+ transaction.objectStoreNames, ['books'],
+ 'IDBTransaction.objectStoreNames should stop including the ' +
+ 'deleted store immediately after IDBDatabase.deleteObjectStore() ' +
+ 'returns');
+ assert_array_equals(
+ database.objectStoreNames, ['books'],
+ 'IDBDatabase.objectStoreNames should stop including the newly ' +
+ 'created store immediately after IDBDatabase.deleteObjectStore() ' +
+ 'returns');
+
+ transaction.abort();
+ assert_throws(
+ 'InvalidStateError', () => store.get('query'),
+ 'IDBObjectStore.get should throw InvalidStateError, indicating ' +
+ 'that the store is still marked for deletion, immediately after ' +
+ 'IDBTransaction.abort() returns');
+ assert_array_equals(
+ transaction.objectStoreNames, ['books'],
+ 'IDBTransaction.objectStoreNames should not include the newly ' +
+ 'created store immediately after IDBTransaction.abort() returns');
+ assert_array_equals(
+ database.objectStoreNames, ['books'],
+ 'IDBDatabase.objectStoreNames should not include the newly ' +
+ 'created store immediately after IDBTransaction.abort() returns');
+ })).then(() => {
+ assert_throws(
+ 'InvalidStateError', () => store.get('query'),
+ 'IDBObjectStore.get should throw InvalidStateError, indicating ' +
+ 'that the store is still marked for deletion, after the ' +
+ 'transaction is aborted');
+ assert_array_equals(
+ migrationDatabase.objectStoreNames, ['books'],
+ 'IDBDatabase.objectStoreNames should not include the newly ' +
+ 'created store after the transaction is aborted');
+ assert_array_equals(
+ migrationTransaction.objectStoreNames, ['books'],
+ 'IDBTransaction.objectStoreNames should not include the newly ' +
+ 'created store after the transaction is aborted');
+ });
+}, 'Created+deleted stores are still marked as deleted after their ' +
+ 'transaction aborts');
+
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/transaction-create_in_versionchange.htm b/testing/web-platform/tests/IndexedDB/transaction-create_in_versionchange.htm
new file mode 100644
index 000000000..4d98c0004
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/transaction-create_in_versionchange.htm
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Attempt to create new transactions inside a versionchange transaction</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db, events = [],
+ open_rq = createdb(async_test())
+
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result
+
+ db.createObjectStore("store")
+ .add("versionchange1", 1)
+ .addEventListener("success", log("versionchange_add.success"))
+
+ assert_throws('InvalidStateError', function() { db.transaction("store") })
+
+ e.target.transaction
+ .objectStore("store")
+ .count(2)
+ .addEventListener("success", log("versionchange_count.success"))
+
+ assert_throws('InvalidStateError', function() { db.transaction("store", "readwrite") })
+
+ open_rq.transaction
+ .objectStore("store")
+ .add("versionchange2", 2)
+ .addEventListener("success", log("versionchange_add2.success"))
+
+ open_rq.transaction.oncomplete = function(e) {
+ log("versionchange_txn.complete")(e)
+
+ db.transaction("store")
+ .objectStore("store")
+ .count()
+ .addEventListener("success", log("complete_count.success"))
+ }
+ }
+
+ open_rq.onsuccess = function(e) {
+ log("open_rq.success")(e)
+
+ var txn = db.transaction("store", "readwrite")
+ txn.objectStore("store")
+ .put("woo", 1)
+ .addEventListener("success", log("complete2_get.success"))
+
+ txn.oncomplete = this.step_func(function(e) {
+ assert_array_equals(events, [
+ "versionchange_add.success: 1",
+ "versionchange_count.success: 0",
+ "versionchange_add2.success: 2",
+ "versionchange_txn.complete",
+
+ "open_rq.success: [object IDBDatabase]",
+
+ "complete_count.success: 2",
+ "complete2_get.success: 1",
+ ],
+ "events")
+ this.done()
+ })
+ }
+
+
+ function log(msg) {
+ return function(e) {
+ if(e && e.target && e.target.error)
+ events.push(msg + ": " + e.target.error.name)
+ else if(e && e.target && e.target.result !== undefined)
+ events.push(msg + ": " + e.target.result)
+ else
+ events.push(msg)
+ };
+ }
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/transaction-lifetime-blocked.htm b/testing/web-platform/tests/IndexedDB/transaction-lifetime-blocked.htm
new file mode 100644
index 000000000..3288506c5
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/transaction-lifetime-blocked.htm
@@ -0,0 +1,108 @@
+<!DOCTYPE html>
+<title>Blocked event</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<div id="log"></div>
+
+<script>
+
+ var db, db_got_versionchange, db2,
+ events = [],
+ t = async_test(document.title, {timeout: 10000});
+
+ t.step(function() {
+ var openrq = indexedDB.open('db', 3);
+
+ // 1
+ openrq.onupgradeneeded = t.step_func(function(e) {
+ events.push("open." + e.type);
+ e.target.result.createObjectStore('store');
+ });
+
+ // 2
+ openrq.onsuccess = t.step_func(function(e) {
+ db = e.target.result;
+
+ events.push("open." + e.type);
+
+ // 3
+ db.onversionchange = t.step_func(function(e) {
+ events.push("db." + e.type);
+
+ assert_equals(e.oldVersion, 3, "old version");
+ assert_equals(e.newVersion, 4, "new version");
+ // Do not close db here (as we should)
+ });
+
+ // Errors
+ db.onerror = fail(t, "db.error");
+ db.abort = fail(t, "db.abort");
+
+ setTimeout(t.step_func(OpenSecond), 10);
+ });
+
+ // Errors
+ openrq.onerror = fail(t, "open.error");
+ openrq.onblocked = fail(t, "open.blocked");
+
+ });
+
+ function OpenSecond (e) {
+ assert_equals(db2, undefined);
+ assert_equals(db + "", "[object IDBDatabase]");
+ assert_array_equals(db.objectStoreNames, [ "store" ]);
+
+ var openrq2 = indexedDB.open('db', 4);
+
+ // 4
+ openrq2.onblocked = t.step_func(function(e) {
+ events.push("open2." + e.type);
+ // We're closing connection from the other open()
+ db.close();
+ });
+
+ // 5
+ openrq2.onupgradeneeded = t.step_func(function(e) {
+ db2 = e.target.result;
+
+ events.push("open2." + e.type);
+
+ assert_equals(db2 + "", "[object IDBDatabase]");
+
+ // Errors
+ db2.onversionchange = fail(t, "db2.versionchange");
+ db2.onerror = fail(t, "db2.error");
+ db2.abort = fail(t, "db2.abort");
+ });
+
+ // 6
+ openrq2.onsuccess = t.step_func(function(e) {
+ events.push("open2." + e.type);
+
+ assert_array_equals(events,
+ [ "open.upgradeneeded",
+ "open.success",
+ "db.versionchange",
+ "open2.blocked",
+ "open2.upgradeneeded",
+ "open2.success",
+ ]);
+
+ setTimeout(function() { t.done(); }, 10);
+ });
+
+ // Errors
+ openrq2.onerror = fail(t, "open2.error");
+ }
+
+
+ // Cleanup
+ add_completion_callback(function(tests) {
+ if (db2) db2.close();
+ indexedDB.deleteDatabase('db');
+ })
+
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/transaction-lifetime-empty.html b/testing/web-platform/tests/IndexedDB/transaction-lifetime-empty.html
new file mode 100644
index 000000000..7d4b0d7f7
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/transaction-lifetime-empty.html
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<title>IndexedDB: Commit ordering of empty transactions</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+<script>
+
+// Call with a test object and array of expected values. Returns a
+// function to call with each actual value. Once the expected number
+// of values is seen, asserts that the value orders match and completes
+// the test.
+function expect(t, expected) {
+ var results = [];
+ return result => {
+ results.push(result);
+ if (results.length === expected.length) {
+ assert_array_equals(results, expected);
+ t.done();
+ }
+ };
+}
+
+indexeddb_test(
+ (t, db) => {
+ db.createObjectStore('store');
+ },
+ (t, db) => {
+ var saw = expect(t, ['rq1.onsuccess',
+ 'rq2.onsuccess',
+ 'tx1.oncomplete',
+ 'tx2.oncomplete']);
+
+ var tx1 = db.transaction('store', 'readwrite');
+ tx1.onabort = t.unreached_func('transaction should commit');
+ tx1.oncomplete = t.step_func(() => saw('tx1.oncomplete'));
+
+ var store = tx1.objectStore('store');
+ var rq1 = store.put('a', 1);
+ rq1.onerror = t.unreached_func('put should succeed');
+ rq1.onsuccess = t.step_func(() => {
+ saw('rq1.onsuccess');
+
+ var tx2 = db.transaction('store', 'readonly');
+ tx2.onabort = t.unreached_func('transaction should commit');
+ tx2.oncomplete = t.step_func(() => saw('tx2.oncomplete'));
+
+ var rq2 = store.put('b', 2);
+ rq2.onsuccess = t.step_func(() => saw('rq2.onsuccess'));
+ rq2.onerror = t.unreached_func('request should succeed');
+ });
+
+ },
+ 'Transactions without requests complete in the expected order');
+
+indexeddb_test(
+ (t, db) => {
+ db.createObjectStore('store');
+ },
+ (t, db) => {
+ var saw = expect(t, ['rq1.onsuccess',
+ 'rq2.onsuccess',
+ 'tx1.oncomplete',
+ 'tx2.oncomplete',
+ 'tx3.oncomplete']);
+ var tx1 = db.transaction('store', 'readwrite');
+ tx1.onabort = t.unreached_func('transaction should commit');
+ tx1.oncomplete = t.step_func(() => saw('tx1.oncomplete'));
+
+ var store = tx1.objectStore('store');
+ var rq1 = store.put('a', 1);
+ rq1.onerror = t.unreached_func('put should succeed');
+ rq1.onsuccess = t.step_func(() => {
+ saw('rq1.onsuccess');
+
+ var tx2 = db.transaction('store', 'readonly');
+ tx2.onabort = t.unreached_func('transaction should commit');
+ tx2.oncomplete = t.step_func(() => saw('tx2.oncomplete'));
+
+ var tx3 = db.transaction('store', 'readonly');
+ tx3.onabort = t.unreached_func('transaction should commit');
+ tx3.oncomplete = t.step_func(() => saw('tx3.oncomplete'));
+
+ var rq2 = store.put('b', 2);
+ rq2.onsuccess = t.step_func(() => saw('rq2.onsuccess'));
+ rq2.onerror = t.unreached_func('request should succeed');
+ });
+ },
+ 'Multiple transactions without requests complete in the expected order');
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/transaction-lifetime.htm b/testing/web-platform/tests/IndexedDB/transaction-lifetime.htm
new file mode 100644
index 000000000..2412424fd
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/transaction-lifetime.htm
@@ -0,0 +1,101 @@
+<!DOCTYPE html>
+<title>Test events opening a second database when one connection is open already</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<div id="log"></div>
+
+<script>
+
+ var db, db_got_versionchange, db2,
+ events = [],
+ t = async_test(document.title, {timeout: 10000});
+
+ t.step(function() {
+ var openrq = indexedDB.open('db', 3);
+
+ // 1
+ openrq.onupgradeneeded = t.step_func(function(e) {
+ events.push("open." + e.type);
+ e.target.result.createObjectStore('store');
+ });
+
+ // 2
+ openrq.onsuccess = t.step_func(function(e) {
+ db = e.target.result;
+
+ events.push("open." + e.type);
+
+ // 3
+ db.onversionchange = t.step_func(function(e) {
+ events.push("db." + e.type);
+
+ assert_equals(e.oldVersion, 3, "old version");
+ assert_equals(e.newVersion, 4, "new version");
+ db.close();
+ });
+
+ // Errors
+ db.onerror = fail(t, "db.error");
+ db.abort = fail(t, "db.abort");
+
+ setTimeout(t.step_func(OpenSecond), 10);
+ });
+
+ // Errors
+ openrq.onerror = fail(t, "open.error");
+ openrq.onblocked = fail(t, "open.blocked");
+
+ });
+
+ function OpenSecond (e) {
+ assert_equals(db2, undefined);
+ assert_equals(db + "", "[object IDBDatabase]");
+ assert_array_equals(db.objectStoreNames, [ "store" ]);
+
+ var openrq2 = indexedDB.open('db', 4);
+
+ // 4
+ openrq2.onupgradeneeded = t.step_func(function(e) {
+ db2 = e.target.result;
+
+ events.push("open2." + e.type);
+
+ assert_equals(db2 + "", "[object IDBDatabase]");
+
+ // Errors
+ db2.onversionchange = fail(t, "db2.versionchange");
+ db2.onerror = fail(t, "db2.error");
+ db2.abort = fail(t, "db2.abort");
+ });
+
+ // 5
+ openrq2.onsuccess = t.step_func(function(e) {
+ events.push("open2." + e.type);
+
+ assert_array_equals(events,
+ [ "open.upgradeneeded",
+ "open.success",
+ "db.versionchange",
+ "open2.upgradeneeded",
+ "open2.success",
+ ]);
+
+ setTimeout(function() { t.done(); }, 10);
+ });
+
+ // Errors
+ openrq2.onerror = fail(t, "open2.error");
+ openrq2.onblocked = fail(t, "open2.blocked");
+ }
+
+
+ // Cleanup
+ add_completion_callback(function(tests) {
+ if (db2) db2.close();
+ indexedDB.deleteDatabase('db');
+ })
+
+</script>
diff --git a/testing/web-platform/tests/IndexedDB/transaction-requestqueue.htm b/testing/web-platform/tests/IndexedDB/transaction-requestqueue.htm
new file mode 100644
index 000000000..b5706fe81
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/transaction-requestqueue.htm
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Transactions have a request queue</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+
+var db, t = async_test(document.title, {timeout: 10000}),
+ keys = { txn: [], txn2: [] },
+ open_rq = createdb(t)
+
+open_rq.onupgradeneeded = function(e) {
+ var i, os;
+ db = e.target.result;
+
+ for (i = 1; i < 6; i++)
+ {
+ os = db.createObjectStore("os" + i, { autoIncrement: true, keyPath: "k" });
+ os.add({ os: "os" + i });
+ os.put({ os: "os" + i, k: i});
+ os.add({ os: "os" + i });
+ }
+}
+
+open_rq.onsuccess = function(e) {
+ var txn = db.transaction(["os2", "os1", "os3", "os5"])
+ txn.objectStore("os1").openCursor().onsuccess = reg("txn")
+ txn.objectStore("os3").openCursor().onsuccess = reg("txn")
+ txn.objectStore("os1").get(2).onsuccess = reg("txn")
+ txn.objectStore("os2").get(3).onsuccess = reg("txn")
+
+ var txn2 = db.transaction(["os4", "os3", "os1", "os5"])
+ var os4 = txn2.objectStore("os4")
+
+ for (var i=0; i < 3; i++) {
+ os4.openCursor().onsuccess = reg("txn2")
+ os4.get(5).onsuccess = reg("txn2")
+ os4.get(4).onsuccess = reg("txn2")
+ txn.objectStore("os2").get(1).onsuccess = reg("txn")
+ txn2.objectStore("os3").get(1).onsuccess = reg("txn2")
+ }
+
+ txn2.objectStore("os1").get(2).onsuccess = reg("txn2")
+ txn.objectStore("os1").openCursor(null, "prev").onsuccess = reg("txn")
+ os4.openCursor(null, "prev").onsuccess = reg("txn2")
+
+ txn.oncomplete = t.step_func(finish);
+ txn2.oncomplete = t.step_func(finish);
+}
+
+
+function reg(n) {
+ return t.step_func(function (e) {
+ var v = e.target.result;
+ if (v.value) v = v.value;
+ keys[n].push(v.os + ": " + v.k);
+ });
+}
+
+var finish_to_go = 2;
+function finish() {
+ if (--finish_to_go)
+ return;
+
+ assert_array_equals(keys['txn'], [
+ "os1: 1",
+ "os3: 1",
+ "os1: 2",
+ "os2: 3",
+ "os2: 1", "os2: 1", "os2: 1",
+ "os1: 2",
+ ], 'transaction keys');
+
+ assert_array_equals(keys['txn2'], [
+ "os4: 1", "os4: 5", "os4: 4", "os3: 1",
+ "os4: 1", "os4: 5", "os4: 4", "os3: 1",
+ "os4: 1", "os4: 5", "os4: 4", "os3: 1",
+ "os1: 2",
+ "os4: 5",
+ ], 'transaction 2 keys');
+
+ t.done();
+}
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/transaction_bubble-and-capture.htm b/testing/web-platform/tests/IndexedDB/transaction_bubble-and-capture.htm
new file mode 100644
index 000000000..f4b5ec0ae
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/transaction_bubble-and-capture.htm
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Capture and bubble</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var events = [];
+
+ var open_rq = createdb(async_test(document.title, {timeout: 10000}));
+ open_rq.onupgradeneeded = function(e) {
+ var db = e.target.result;
+ var txn = e.target.transaction;
+ var store = db.createObjectStore("store");
+ var rq1 = store.add("", 1);
+ var rq2 = store.add("", 1);
+
+ db.onerror = undefined; // We will run db.error, but don't let that fail the test
+
+ log_events('db', db, 'success');
+ log_events('db', db, 'error');
+
+ log_events('txn', txn, 'success');
+ log_events('txn', txn, 'error');
+
+ log_events('rq1', rq1, 'success');
+ log_events('rq1', rq1, 'error');
+
+ log_events('rq2', rq2, 'success');
+ log_events('rq2', rq2, 'error');
+
+ // Don't let it get to abort
+ db.addEventListener('error', function(e) { e.preventDefault(); }, false);
+ }
+
+ open_rq.onsuccess = function(e) {
+ log("open_rq.success")(e);
+ assert_array_equals(events, [
+ "capture db.success",
+ "capture txn.success",
+ "capture rq1.success",
+ "bubble rq1.success",
+
+ "capture db.error: ConstraintError",
+ "capture txn.error: ConstraintError",
+ "capture rq2.error: ConstraintError",
+ "bubble rq2.error: ConstraintError",
+ "bubble txn.error: ConstraintError",
+ "bubble db.error: ConstraintError",
+
+ "open_rq.success",
+ ],
+ "events");
+ this.done();
+ }
+
+
+ function log_events(type, obj, evt) {
+ obj.addEventListener(evt, log('capture ' + type + '.' + evt), true);
+ obj.addEventListener(evt, log('bubble ' + type + '.' + evt), false);
+ }
+
+ function log(msg) {
+ return function(e) {
+ if(e && e.target && e.target.error)
+ events.push(msg + ": " + e.target.error.name);
+ else
+ events.push(msg);
+ };
+ }
+</script>
+
+<div id=log></div>
diff --git a/testing/web-platform/tests/IndexedDB/value.htm b/testing/web-platform/tests/IndexedDB/value.htm
new file mode 100644
index 000000000..36e833952
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/value.htm
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Values</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+function value(value, _instanceof) {
+ var t = async_test(document.title + " - " + _instanceof.name);
+ t.step(function() {
+ assert_true(value instanceof _instanceof, "TEST ERROR, instanceof");
+ });
+
+ createdb(t).onupgradeneeded = function(e) {
+ e.target.result
+ .createObjectStore("store")
+ .add(value, 1);
+
+ e.target.onsuccess = t.step_func(function(e) {
+ e.target.result
+ .transaction("store")
+ .objectStore("store")
+ .get(1)
+ .onsuccess = t.step_func(function(e)
+ {
+ assert_true(e.target.result instanceof _instanceof, "instanceof")
+ t.done();
+ });
+ });
+ };
+}
+
+value(new Date(), Date);
+value(new Array(), Array);
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/value_recursive.htm b/testing/web-platform/tests/IndexedDB/value_recursive.htm
new file mode 100644
index 000000000..f49a1ccbc
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/value_recursive.htm
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Recursive value</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support.js"></script>
+
+<script>
+function recursive_value(desc, value) {
+ var db, t = async_test(document.title + " - " + desc);
+
+ createdb(t).onupgradeneeded = function(e) {
+ db = e.target.result
+ db.createObjectStore("store")
+ .add(value, 1);
+
+ e.target.onsuccess = t.step_func(function(e) {
+ db.transaction('store')
+ .objectStore('store')
+ .get(1)
+ .onsuccess = t.step_func(function(e)
+ {
+
+ try
+ {
+ var fresh_value = JSON.stringify(value);
+ assert_unreached("Testcase is written wrongly, must supply something recursive (that JSON won't stringify).");
+ }
+ catch (e)
+ {
+ if (e.name == 'TypeError')
+ {
+ try
+ {
+ JSON.stringify(e.target.result);
+ assert_unreached("Expected a non-JSON-serializable value back, didn't get that.");
+ }
+ catch (e)
+ {
+ t.done();
+ return;
+ }
+ }
+ else
+ throw e;
+ }
+ });
+ });
+ };
+}
+
+var recursive = [];
+recursive.push(recursive);
+recursive_value('array directly contains self', recursive);
+
+var recursive2 = [];
+recursive2.push([recursive2]);
+recursive_value('array indirectly contains self', recursive2);
+
+var recursive3 = [recursive];
+recursive_value('array member contains self', recursive3);
+
+</script>
+
+<div id="log"></div>
diff --git a/testing/web-platform/tests/IndexedDB/writer-starvation.htm b/testing/web-platform/tests/IndexedDB/writer-starvation.htm
new file mode 100644
index 000000000..ae6c90150
--- /dev/null
+++ b/testing/web-platform/tests/IndexedDB/writer-starvation.htm
@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Writer starvation</title>
+<link rel="author" href="mailto:odinho@opera.com" title="Odin Hørthe Omdal">
+<meta name=timeout content=long>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=support.js></script>
+
+<script>
+ var db, read_request_count = 0, read_success_count = 0;
+ var write_request_count = 0, write_success_count = 0;
+ var RQ_COUNT = 25;
+
+ var open_rq = createdb(async_test(undefined, {timeout: 20000}));
+ open_rq.onupgradeneeded = function(e) {
+ db = e.target.result;
+ db.createObjectStore("s")
+ .add("1", 1);
+ }
+
+ open_rq.onsuccess = function(e) {
+ var i = 0, continue_reading = true;
+
+ /* Pre-fill some read requests */
+ for (i = 0; i < RQ_COUNT; i++)
+ {
+ read_request_count++;
+
+ db.transaction("s")
+ .objectStore("s")
+ .get(1)
+ .onsuccess = this.step_func(function(e) {
+ read_success_count++;
+ assert_equals(e.target.transaction.mode, "readonly");
+ });
+ }
+
+ this.step(loop);
+
+ function loop() {
+ read_request_count++;
+
+ db.transaction("s")
+ .objectStore("s")
+ .get(1)
+ .onsuccess = this.step_func(function(e)
+ {
+ read_success_count++;
+ assert_equals(e.target.transaction.mode, "readonly");
+
+ if (read_success_count >= RQ_COUNT && write_request_count == 0)
+ {
+ write_request_count++;
+
+ db.transaction("s", "readwrite")
+ .objectStore("s")
+ .add("written", read_request_count)
+ .onsuccess = this.step_func(function(e)
+ {
+ write_success_count++;
+ assert_equals(e.target.transaction.mode, "readwrite");
+ assert_equals(e.target.result, read_success_count,
+ "write cb came before later read cb's")
+ });
+
+ /* Reads done after the write */
+ for (i = 0; i < 5; i++)
+ {
+ read_request_count++;
+
+ db.transaction("s")
+ .objectStore("s")
+ .get(1)
+ .onsuccess = this.step_func(function(e)
+ {
+ read_success_count++;
+ });
+ }
+ }
+ });
+
+ if (read_success_count < RQ_COUNT + 5)
+ setTimeout(this.step_func(loop), write_request_count ? 1000 : 100);
+ else
+ // This is merely a "nice" hack to run finish after the last request is done
+ db.transaction("s")
+ .objectStore("s")
+ .count()
+ .onsuccess = this.step_func(function()
+ {
+ setTimeout(this.step_func(finish), 100);
+ });
+ }
+ }
+
+
+function finish() {
+ assert_equals(read_request_count, read_success_count, "read counts");
+ assert_equals(write_request_count, write_success_count, "write counts");
+ this.done();
+}
+</script>
+
+<div id=log></div>