2 <title>IndexedDB: Verify bindings edge cases
</title>
3 <script src=
"../../resources/testharness.js"></script>
4 <script src=
"../../resources/testharnessreport.js"></script>
5 <script src=
"resources/testharness-helpers.js"></script>
9 db
.createObjectStore('store');
12 var tx
= db
.transaction('store', 'readwrite');
13 var request
= tx
.objectStore('store').put('value', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'key']);
15 var setter_called
= false;
16 Object
.defineProperty(Object
.prototype, '10', {
17 set: t
.step_func(function(value
) { setter_called
= true; })
19 request
.onerror
= t
.unreached_func('request should not fail');
20 request
.onsuccess
= t
.step_func(function() {
21 var result
= request
.result
;
22 assert_false(setter_called
,
23 'Setter should not be called for key result.');
24 assert_true(result
.hasOwnProperty('10'),
25 'Result should have own-property overriding prototype setter.');
26 assert_equals(result
[10], 'key',
27 'Result should have expected property.');
31 'Returning keys to script should bypass prototype setters'
36 db
.createObjectStore('store', {autoIncrement
: true, keyPath
: 'id'});
39 var tx
= db
.transaction('store', 'readwrite');
40 tx
.objectStore('store').put({});
41 var request
= tx
.objectStore('store').get(1);
43 var setter_called
= false;
44 Object
.defineProperty(Object
.prototype, 'id', {
45 set: t
.step_func(function(value
) { setter_called
= true; })
47 request
.onerror
= t
.unreached_func('request should not fail');
48 request
.onsuccess
= t
.step_func(function() {
49 var result
= request
.result
;
50 assert_false(setter_called
,
51 'Setter should not be called for key result.');
52 assert_true(result
.hasOwnProperty('id'),
53 'Result should have own-property overriding prototype setter.');
54 assert_equals(result
.id
, 1,
55 'Own property should match primary key generator value');
59 'Returning values to script should bypass prototype setters'
64 db
.createObjectStore('store', {autoIncrement
: true, keyPath
: 'a.b.c'});
67 var tx
= db
.transaction('store', 'readwrite');
68 tx
.objectStore('store').put({});
69 var request
= tx
.objectStore('store').get(1);
71 Object
.prototype.a
= {b
: {c
: 'on proto'}};
73 request
.onerror
= t
.unreached_func('request should not fail');
74 request
.onsuccess
= t
.step_func(function() {
75 var result
= request
.result
;
76 assert_true(result
.hasOwnProperty('a'),
77 'Result should have own-properties overriding prototype.');
78 assert_true(result
.a
.hasOwnProperty('b'),
79 'Result should have own-properties overriding prototype.');
80 assert_true(result
.a
.b
.hasOwnProperty('c'),
81 'Result should have own-properties overriding prototype.');
82 assert_equals(result
.a
.b
.c
, 1,
83 'Own property should match primary key generator value');
84 assert_equals(Object
.prototype.a
.b
.c
, 'on proto',
85 'Prototype should not be modified');
89 'Returning values to script should bypass prototype chain'
94 db
.createObjectStore('store', {autoIncrement
: true, keyPath
: 'a.b.c'});
97 var tx
= db
.transaction('store', 'readwrite');
98 assert_throws({name
: 'DataError'}, function() {
99 tx
.objectStore('store').put({a
: {b
: "foo"}});
100 }, 'Put should throw if key can not be inserted at key path location.');
103 'The last element of keypath is validated'
115 instance
: ['a', 'b', 'c']
120 instance
: new Blob(['abc'])
125 instance
: new Blob([''], {type
:'foo/bar'})
130 instance
: new File([''], 'foo')
134 property
: 'lastModified',
135 instance
: new File([''], '', {lastModified
: 123})
139 property
: 'lastModifiedDate',
140 instance
: new File([''], '', {lastModified
: 123})
142 ].forEach(function(testcase
) {
145 db
.createObjectStore('store', {autoIncrement
: true, keyPath
: testcase
.property
});
148 var key
= testcase
.instance
[testcase
.property
];
149 var tx
= db
.transaction('store', 'readwrite');
150 tx
.objectStore('store').put(testcase
.instance
);
151 var request
= tx
.objectStore('store').get(key
);
152 request
.onerror
= t
.unreached_func('request should not fail');
153 request
.onsuccess
= t
.step_func(function() {
154 var result
= request
.result
;
155 assert_key_equals(result
[testcase
.property
], key
,
156 'Property should be used as key');
160 'Type: ' + testcase
.type
+ ', implicit property: ' + testcase
.property
164 function throws(name
) {
175 Object
.defineProperty(o
, 'throws', {get: throws('getter'),
176 enumerable
: false, configurable
: true});
178 // Value should be cloned before key path is evaluated,
179 // and non-enumerable getter will be ignored. The clone
180 // will have no such property, so key path evaluation
182 var s1
= db
.createObjectStore('s1',
183 {keyPath
: 'throws'});
184 assert_throws('DataError', function() {
186 }, 'Key path failing to resolve should throw');
188 // Value should be cloned before key path is evaluated,
189 // and non-enumerable getter will be ignored. The clone
190 // will have no such property, so key path evaluation
192 var s2
= db
.createObjectStore('s2',
193 {keyPath
: 'throws.x'});
194 assert_throws('DataError', function() {
196 }, 'Key path failing to resolve should throw');
198 // Value should be cloned before key path is evaluated,
199 // and non-enumerable getter will be ignored. The clone
200 // will have no such property, so generated key can be
202 var s3
= db
.createObjectStore('s3',
203 {keyPath
: 'throws', autoIncrement
: true});
204 assert_class_string(s3
.put(o
), 'IDBRequest',
205 'Key injectability test at throwing getter should succeed');
207 // Value should be cloned before key path is evaluated,
208 // and non-enumerable getter will be ignored. The clone
209 // will have no such property, so intermediate object
210 // and generated key can be inserted.
211 var s4
= db
.createObjectStore('s4',
212 {keyPath
: 'throws.x', autoIncrement
: true});
213 assert_class_string(s4
.put(o
), 'IDBRequest',
214 'Key injectability test past throwing getter should succeed');
219 'Key path evaluation: Exceptions from non-enumerable getters'
225 Object
.defineProperty(o
, 'throws', {get: throws('getter'),
226 enumerable
: true, configurable
: true});
228 // Value should be cloned before key path is evaluated,
229 // and enumerable getter will rethrow.
230 var s1
= db
.createObjectStore('s1',
231 {keyPath
: 'throws'});
232 assert_throws({name
: 'getter'}, function() {
234 }, 'Key path resolving to throwing getter rethrows');
236 // Value should be cloned before key path is evaluated,
237 // and enumerable getter will rethrow.
238 var s2
= db
.createObjectStore('s2',
239 {keyPath
: 'throws.x'});
240 assert_throws({name
: 'getter'}, function() {
242 }, 'Key path resolving past throwing getter rethrows');
244 // Value should be cloned before key path is evaluated,
245 // and enumerable getter will rethrow.
246 var s3
= db
.createObjectStore('s3',
247 {keyPath
: 'throws', autoIncrement
: true});
248 assert_throws({name
: 'getter'}, function() {
250 }, 'Key injectability test at throwing getter should rethrow');
252 // Value should be cloned before key path is evaluated,
253 // and enumerable getter will rethrow.
254 var s4
= db
.createObjectStore('s4',
255 {keyPath
: 'throws.x', autoIncrement
: true});
256 assert_throws({name
: 'getter'}, function() {
258 }, 'Key injectability test past throwing getter should rethrow');
263 'Key path evaluation: Exceptions from enumerable getters'
268 // Implemented as function wrapper to clean up
269 // immediately after use, otherwise it may
270 // interfere with the test harness.
271 function with_proto_getter(f
) {
273 Object
.defineProperty(Object
.prototype, 'throws', {
274 get: throws('getter'),
275 enumerable
: false, configurable
: true
280 delete Object
.prototype['throws'];
285 // Value should be cloned before key path is evaluated,
286 // and non-enumerable getter will be ignored. The clone
287 // will have no such property, so key path evaluation
288 // will hit prototype property and rethrow.
289 var s1
= db
.createObjectStore('s1',
290 {keyPath
: 'throws'});
291 assert_throws({name
: 'getter'}, with_proto_getter(function() {
293 }), 'Key path resolving to throwing getter rethrows');
295 // Value should be cloned before key path is evaluated,
296 // and non-enumerable getter will be ignored. The clone
297 // will have no such property, so key path evaluation
298 // will hit prototype property and rethrow.
299 var s2
= db
.createObjectStore('s2',
300 {keyPath
: 'throws.x'});
301 assert_throws({name
: 'getter'}, with_proto_getter(function() {
303 }), 'Key path resolving past throwing getter rethrows');
305 // Value should be cloned before key path is evaluated,
306 // and non-enumerable getter will be ignored. The clone
307 // will have no such property, so key path evaluation
308 // will hit prototype property and rethrow.
309 var s3
= db
.createObjectStore('s3',
310 {keyPath
: 'throws', autoIncrement
: true});
311 assert_throws({name
: 'getter'}, with_proto_getter(function() {
313 }), 'Key injectability test at throwing getter rethrows');
315 // Value should be cloned before key path is evaluated,
316 // and non-enumerable getter will be ignored. The clone
317 // will have no such property, so key path evaluation
318 // will hit prototype property and rethrow.
319 var s4
= db
.createObjectStore('s4',
320 {keyPath
: 'throws.x', autoIncrement
: true});
321 assert_throws({name
: 'getter'}, with_proto_getter(function() {
323 }), 'Key injectability test past throwing getter rethrows');
328 'Key path evaluation: Exceptions from non-enumerable getters on prototype'
333 // Implemented as function wrapper to clean up
334 // immediately after use, otherwise it may
335 // interfere with the test harness.
336 function with_proto_getter(f
) {
338 Object
.defineProperty(Object
.prototype, 'throws', {
339 get: throws('getter'),
340 enumerable
: true, configurable
: true
345 delete Object
.prototype['throws'];
350 // Value should be cloned before key path is evaluated,
351 // and enumerable getter will rethrow.
352 var s1
= db
.createObjectStore('s1',
353 {keyPath
: 'throws'});
354 assert_throws({name
: 'getter'}, with_proto_getter(function() {
356 }), 'Key path resolving to throwing getter rethrows');
358 // Value should be cloned before key path is evaluated,
359 // and enumerable getter will rethrow.
360 var s2
= db
.createObjectStore('s2',
361 {keyPath
: 'throws.x'});
362 assert_throws({name
: 'getter'}, with_proto_getter(function() {
364 }), 'Key path resolving past throwing getter rethrows');
366 // Value should be cloned before key path is evaluated,
367 // and enumerable getter will rethrow.
368 var s3
= db
.createObjectStore('s3',
369 {keyPath
: 'throws', autoIncrement
: true});
370 assert_throws({name
: 'getter'}, with_proto_getter(function() {
372 }), 'Key injectability test at throwing getter rethrows');
374 // Value should be cloned before key path is evaluated,
375 // and enumerable getter will rethrow.
376 var s4
= db
.createObjectStore('s4',
377 {keyPath
: 'throws.x', autoIncrement
: true});
378 assert_throws({name
: 'getter'}, with_proto_getter(function() {
380 }), 'Key injectability test past throwing getter rethrows');
385 'Key path evaluation: Exceptions from enumerable getters on prototype'