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