2 <title>IndexedDB: Exceptions thrown during key conversion
</title>
3 <script src=
"../../resources/testharness.js"></script>
4 <script src=
"../../resources/testharnessreport.js"></script>
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
);
17 open
.onsuccess
= t
.step_func(function() {
24 // Key that throws during conversion.
25 function throwing_key(name
) {
28 Object
.defineProperty(throws, '0', {get: function() {
29 var err
= new Error('throwing from getter');
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
44 function check_method(receiver
, method
, args
) {
47 assert_throws({name
:'getter'}, function() {
48 receiver
[method
](throwing_key('getter'));
49 }, 'key conversion with throwing getter should rethrow');
51 assert_throws('DataError', function() {
52 receiver
[method
](invalid_key
);
53 }, 'key conversion with invalid key should throw DataError');
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');
59 assert_throws('DataError', function() {
60 receiver
[method
](invalid_key
, throwing_key('getter 2'));
61 }, 'first key conversion with invalid key should throw DataError');
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');
67 assert_throws('DataError', function() {
68 receiver
[method
](valid_key
, invalid_key
);
69 }, 'second key conversion with invalid key should throw DataError');
73 // Static key comparison utility on IDBFactory.
75 check_method(indexedDB
, 'cmp', 2);
76 }, 'IDBFactory cmp() static with throwing/invalid keys');
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');
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');
90 }, 'IDBCursor continue() method with throwing/invalid keys');
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');
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');
103 check_method(cursor
, 'continuePrimaryKey', 2);
105 }, 'IDBCursor continuePrimaryKey() method with throwing/invalid keys');
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');
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');
118 // Put property on prototype because the keypath is
119 // evaluated against a structured clone, not the passed value.
122 value
.__proto__
.prop
= throwing_key('getter');
123 assert_throws({name
:'getter'}, function() {
124 cursor
.update(value
);
125 }, 'key conversion with throwing getter should rethrow');
127 value
.__proto__
.prop
= invalid_key
;
128 assert_throws('DataError', function() {
129 cursor
.update(value
);
130 }, 'key conversion with invalid key should throw DataError');
132 }, 'IDBCursor update() method with throwing/invalid keys');
134 // Static constructors on IDBKeyRange
135 ['only', 'lowerBound', 'upperBound'].forEach(function(method
) {
137 check_method(IDBKeyRange
, method
);
138 }, 'IDBKeyRange ' + method
+ '() static with throwing/invalid keys');
142 check_method(IDBKeyRange
, 'bound', 2);
143 }, 'IDBKeyRange bound() static with throwing/invalid keys');
145 // Insertion methods on IDBObjectStore.
146 ['add', 'put'].forEach(function(method
) {
147 simple_idb_test(function(t
, db
) {
148 var out_of_line
= db
.createObjectStore('out-of-line keys');
149 var in_line
= db
.createObjectStore('in-line keys', {keyPath
: 'prop'});
151 assert_throws({name
:'getter'}, function() {
152 out_of_line
[method
]('value', throwing_key('getter'));
153 }, 'key conversion with throwing getter should rethrow');
155 assert_throws('DataError', function() {
156 out_of_line
[method
]('value', invalid_key
);
157 }, 'key conversion with invalid key should throw DataError');
159 // Put property on prototype because the keypath is
160 // evaluated against a structured clone, not the passed value.
163 value
.__proto__
.prop
= throwing_key('getter');
164 assert_throws({name
:'getter'}, function() {
165 in_line
[method
](value
);
166 }, 'key conversion with throwing getter should rethrow');
168 value
.__proto__
.prop
= invalid_key
;
169 assert_throws('DataError', function() {
170 in_line
[method
](value
);
171 }, 'key conversion with invalid key should throw DataError');
172 }, 'IDBObjectStore ' + method
+ '() method with throwing/invalid keys');
175 // Generic (key-or-key-path) methods on IDBObjectStore.
177 // TODO(jsbell): Add 'getAllKeys'
178 'delete', 'get', 'getAll', 'count', 'openCursor', 'openKeyCursor'
179 ].forEach(function(method
) {
180 simple_idb_test(function(t
, db
) {
181 var store
= db
.createObjectStore('store');
183 check_method(store
, method
);
184 }, 'IDBObjectStore ' + method
+ '() method with throwing/invalid keys');
187 // Generic (key-or-key-path) methods on IDBIndex.
189 // TODO(jsbell): Add 'getAllKeys'
190 'get', 'getKey', 'getAll', 'count', 'openCursor', 'openKeyCursor'
191 ].forEach(function(method
) {
192 simple_idb_test(function(t
, db
) {
193 var store
= db
.createObjectStore('store');
194 var index
= store
.createIndex('index', 'keyPath');
196 check_method(index
, method
);
197 }, 'IDBIndex ' + method
+ '() method with throwing/invalid keys');