| OLD | NEW |
| (Empty) |
| 1 <!DOCTYPE html> | |
| 2 <title>IndexedDB: Exceptions thrown during key conversion</title> | |
| 3 <script src="../../resources/testharness.js"></script> | |
| 4 <script src="../../resources/testharnessreport.js"></script> | |
| 5 <script> | |
| 6 | |
| 7 function simple_idb_test(upgrade_callback, description) { | |
| 8 async_test(function(t) { | |
| 9 var dbname = document.location + '-' + t.name; | |
| 10 var del = indexedDB.deleteDatabase(dbname); | |
| 11 del.onerror = t.unreached_func('deleteDatabase should succeed'); | |
| 12 var open = indexedDB.open(dbname); | |
| 13 open.onerror = t.unreached_func('open should succeed'); | |
| 14 open.onupgradeneeded = t.step_func(function(e) { | |
| 15 upgrade_callback(t, open.result); | |
| 16 }); | |
| 17 open.onsuccess = t.step_func(function() { | |
| 18 open.result.close(); | |
| 19 t.done(); | |
| 20 }); | |
| 21 }, description); | |
| 22 } | |
| 23 | |
| 24 // Key that throws during conversion. | |
| 25 function throwing_key(name) { | |
| 26 var throws = []; | |
| 27 throws.length = 1; | |
| 28 Object.defineProperty(throws, '0', {get: function() { | |
| 29 var err = new Error('throwing from getter'); | |
| 30 err.name = name; | |
| 31 throw err; | |
| 32 }, enumerable: true}); | |
| 33 return throws; | |
| 34 } | |
| 35 | |
| 36 var valid_key = []; | |
| 37 var invalid_key = {}; | |
| 38 | |
| 39 // Calls method on receiver with the specified number of args (default 1) | |
| 40 // and asserts that the method fails appropriately (rethrowing if | |
| 41 // conversion throws, or DataError if not a valid key), and that | |
| 42 // the first argument is fully processed before the second argument | |
| 43 // (if appropriate). | |
| 44 function check_method(receiver, method, args) { | |
| 45 args = args || 1; | |
| 46 if (args < 2) { | |
| 47 assert_throws({name:'getter'}, function() { | |
| 48 receiver[method](throwing_key('getter')); | |
| 49 }, 'key conversion with throwing getter should rethrow'); | |
| 50 | |
| 51 assert_throws('DataError', function() { | |
| 52 receiver[method](invalid_key); | |
| 53 }, 'key conversion with invalid key should throw DataError'); | |
| 54 } else { | |
| 55 assert_throws({name:'getter 1'}, function() { | |
| 56 receiver[method](throwing_key('getter 1'), throwing_key('getter 2'))
; | |
| 57 }, 'first key conversion with throwing getter should rethrow'); | |
| 58 | |
| 59 assert_throws('DataError', function() { | |
| 60 receiver[method](invalid_key, throwing_key('getter 2')); | |
| 61 }, 'first key conversion with invalid key should throw DataError'); | |
| 62 | |
| 63 assert_throws({name:'getter 2'}, function() { | |
| 64 receiver[method](valid_key, throwing_key('getter 2')); | |
| 65 }, 'second key conversion with throwing getter should rethrow'); | |
| 66 | |
| 67 assert_throws('DataError', function() { | |
| 68 receiver[method](valid_key, invalid_key); | |
| 69 }, 'second key conversion with invalid key should throw DataError'); | |
| 70 } | |
| 71 } | |
| 72 | |
| 73 // Static key comparison utility on IDBFactory. | |
| 74 test(function(t) { | |
| 75 check_method(indexedDB, 'cmp', 2); | |
| 76 }, 'IDBFactory cmp() static with throwing/invalid keys'); | |
| 77 | |
| 78 // Continue methods on IDBCursor. | |
| 79 simple_idb_test(function(t, db) { | |
| 80 var store = db.createObjectStore('store'); | |
| 81 store.put('a', 1).onerror = t.unreached_func('put should succeed'); | |
| 82 | |
| 83 var request = store.openCursor(); | |
| 84 request.onerror = t.unreached_func('openCursor should succeed'); | |
| 85 request.onsuccess = t.step_func(function() { | |
| 86 var cursor = request.result; | |
| 87 assert_not_equals(cursor, null, 'cursor should find a value'); | |
| 88 check_method(cursor, 'continue'); | |
| 89 }); | |
| 90 }, 'IDBCursor continue() method with throwing/invalid keys'); | |
| 91 | |
| 92 simple_idb_test(function(t, db) { | |
| 93 var store = db.createObjectStore('store'); | |
| 94 var index = store.createIndex('index', 'prop'); | |
| 95 store.put({prop: 'a'}, 1).onerror = t.unreached_func('put should succeed'); | |
| 96 | |
| 97 var request = index.openCursor(); | |
| 98 request.onerror = t.unreached_func('openCursor should succeed'); | |
| 99 request.onsuccess = t.step_func(function() { | |
| 100 var cursor = request.result; | |
| 101 assert_not_equals(cursor, null, 'cursor should find a value'); | |
| 102 | |
| 103 check_method(cursor, 'continuePrimaryKey', 2); | |
| 104 }); | |
| 105 }, 'IDBCursor continuePrimaryKey() method with throwing/invalid keys'); | |
| 106 | |
| 107 // Mutation methods on IDBCursor. | |
| 108 simple_idb_test(function(t, db) { | |
| 109 var store = db.createObjectStore('store', {keyPath: 'prop'}); | |
| 110 store.put({prop: 1}).onerror = t.unreached_func('put should succeed'); | |
| 111 | |
| 112 var request = store.openCursor(); | |
| 113 request.onerror = t.unreached_func('openCursor should succeed'); | |
| 114 request.onsuccess = t.step_func(function() { | |
| 115 var cursor = request.result; | |
| 116 assert_not_equals(cursor, null, 'cursor should find a value'); | |
| 117 | |
| 118 var value = {}; | |
| 119 value.prop = throwing_key('getter'); | |
| 120 assert_throws({name: 'getter'}, function() { | |
| 121 cursor.update(value); | |
| 122 }, 'throwing getter should rethrow during clone'); | |
| 123 | |
| 124 // Throwing from the getter during key conversion is | |
| 125 // not possible since (1) a clone is used, (2) only own | |
| 126 // properties are cloned, and (3) only own properties | |
| 127 // are used for key path evaluation. | |
| 128 | |
| 129 value.prop = invalid_key; | |
| 130 assert_throws('DataError', function() { | |
| 131 cursor.update(value); | |
| 132 }, 'key conversion with invalid key should throw DataError'); | |
| 133 }); | |
| 134 }, 'IDBCursor update() method with throwing/invalid keys'); | |
| 135 | |
| 136 // Static constructors on IDBKeyRange | |
| 137 ['only', 'lowerBound', 'upperBound'].forEach(function(method) { | |
| 138 test(function(t) { | |
| 139 check_method(IDBKeyRange, method); | |
| 140 }, 'IDBKeyRange ' + method + '() static with throwing/invalid keys'); | |
| 141 }); | |
| 142 | |
| 143 test(function(t) { | |
| 144 check_method(IDBKeyRange, 'bound', 2); | |
| 145 }, 'IDBKeyRange bound() static with throwing/invalid keys'); | |
| 146 | |
| 147 // Insertion methods on IDBObjectStore. | |
| 148 ['add', 'put'].forEach(function(method) { | |
| 149 simple_idb_test(function(t, db) { | |
| 150 var out_of_line = db.createObjectStore('out-of-line keys'); | |
| 151 var in_line = db.createObjectStore('in-line keys', {keyPath: 'prop'}); | |
| 152 | |
| 153 assert_throws({name:'getter'}, function() { | |
| 154 out_of_line[method]('value', throwing_key('getter')); | |
| 155 }, 'key conversion with throwing getter should rethrow'); | |
| 156 | |
| 157 assert_throws('DataError', function() { | |
| 158 out_of_line[method]('value', invalid_key); | |
| 159 }, 'key conversion with invalid key should throw DataError'); | |
| 160 | |
| 161 var value = {}; | |
| 162 value.prop = throwing_key('getter'); | |
| 163 assert_throws({name:'getter'}, function() { | |
| 164 in_line[method](value); | |
| 165 }, 'throwing getter should rethrow during clone'); | |
| 166 | |
| 167 // Throwing from the getter during key conversion is | |
| 168 // not possible since (1) a clone is used, (2) only own | |
| 169 // properties are cloned, and (3) only own properties | |
| 170 // are used for key path evaluation. | |
| 171 | |
| 172 value.prop = invalid_key; | |
| 173 assert_throws('DataError', function() { | |
| 174 in_line[method](value); | |
| 175 }, 'key conversion with invalid key should throw DataError'); | |
| 176 }, 'IDBObjectStore ' + method + '() method with throwing/invalid keys'); | |
| 177 }); | |
| 178 | |
| 179 // Generic (key-or-key-path) methods on IDBObjectStore. | |
| 180 [ | |
| 181 // TODO(jsbell): Add 'getAllKeys' | |
| 182 'delete', 'get', 'getAll', 'count', 'openCursor', 'openKeyCursor' | |
| 183 ].forEach(function(method) { | |
| 184 simple_idb_test(function(t, db) { | |
| 185 var store = db.createObjectStore('store'); | |
| 186 | |
| 187 check_method(store, method); | |
| 188 }, 'IDBObjectStore ' + method + '() method with throwing/invalid keys'); | |
| 189 }); | |
| 190 | |
| 191 // Generic (key-or-key-path) methods on IDBIndex. | |
| 192 [ | |
| 193 // TODO(jsbell): Add 'getAllKeys' | |
| 194 'get', 'getKey', 'getAll', 'count', 'openCursor', 'openKeyCursor' | |
| 195 ].forEach(function(method) { | |
| 196 simple_idb_test(function(t, db) { | |
| 197 var store = db.createObjectStore('store'); | |
| 198 var index = store.createIndex('index', 'keyPath'); | |
| 199 | |
| 200 check_method(index, method); | |
| 201 }, 'IDBIndex ' + method + '() method with throwing/invalid keys'); | |
| 202 }); | |
| 203 | |
| 204 </script> | |
| OLD | NEW |