clone-before-keypath-eval.any.js (4282B)
1 // META: title=IndexedDB: clone before key path evaluation 2 // META: global=window,worker 3 // META: script=resources/support.js 4 5 'use strict'; 6 7 function ProbeObject() { 8 this.id_count = 0; 9 this.invalid_id_count = 0; 10 this.prop_count = 0; 11 Object.defineProperties(this, { 12 id: { 13 enumerable: true, 14 get() { 15 ++this.id_count; 16 return 1000 + this.id_count; 17 }, 18 }, 19 invalid_id: { 20 enumerable: true, 21 get() { 22 ++this.invalid_id_count; 23 return {}; 24 }, 25 }, 26 prop: { 27 enumerable: true, 28 get() { 29 ++this.prop_count; 30 return 2000 + this.prop_count; 31 }, 32 }, 33 }); 34 } 35 36 function createObjectStoreWithKeyPath( 37 storeName, keyPath, autoIncrement = false) { 38 return (t, db) => { 39 db.createObjectStore(storeName, {keyPath, autoIncrement}); 40 }; 41 } 42 43 function createObjectStoreWithIndex( 44 storeName, keyPath, indexName, indexKeyPath) { 45 return (t, db) => { 46 const storeOptions = keyPath ? {keyPath} : {}; 47 const store = db.createObjectStore(storeName, storeOptions); 48 49 // If index parameters are provided, create the index. 50 if (indexName && indexKeyPath) { 51 store.createIndex(indexName, indexKeyPath); 52 } 53 }; 54 } 55 56 function createTransactionAndReturnObjectStore(db, storeName) { 57 const tx = db.transaction(storeName, 'readwrite'); 58 const store = tx.objectStore(storeName); 59 return {tx, store}; 60 } 61 62 indexeddb_test(createObjectStoreWithKeyPath('store', 'id', true), (t, db) => { 63 const {store} = createTransactionAndReturnObjectStore(db, 'store'); 64 const obj = new ProbeObject(); 65 store.put(obj); 66 assert_equals( 67 obj.id_count, 1, 68 'put() operation should access primary key property once'); 69 assert_equals( 70 obj.prop_count, 1, 'put() operation should access other properties once'); 71 t.done(); 72 }, 'Key generator and key path validity check operates on a clone'); 73 74 indexeddb_test( 75 createObjectStoreWithKeyPath('store', 'invalid_id', true), (t, db) => { 76 const {store} = createTransactionAndReturnObjectStore(db, 'store'); 77 const obj = new ProbeObject(); 78 assert_throws_dom('DataError', () => { 79 store.put(obj); 80 }, 'put() should throw if primary key cannot be injected'); 81 assert_equals( 82 obj.invalid_id_count, 1, 83 'put() operation should access primary key property once'); 84 assert_equals( 85 obj.prop_count, 1, 86 'put() operation should access other properties once'); 87 t.done(); 88 }, 'Failing key path validity check operates on a clone'); 89 90 indexeddb_test( 91 createObjectStoreWithIndex('store', null, 'index', 'prop'), (t, db) => { 92 const {store} = createTransactionAndReturnObjectStore(db, 'store'); 93 const obj = new ProbeObject(); 94 store.put(obj, 'key'); 95 assert_equals( 96 obj.prop_count, 1, 'put() should access index key property once'); 97 assert_equals( 98 obj.id_count, 1, 99 'put() operation should access other properties once'); 100 t.done(); 101 }, 'Index key path evaluations operate on a clone'); 102 103 indexeddb_test( 104 createObjectStoreWithIndex('store', 'id', 'index', 'prop'), (t, db) => { 105 const {store} = createTransactionAndReturnObjectStore(db, 'store'); 106 const obj = new ProbeObject(); 107 store.put(obj); 108 assert_equals( 109 obj.id_count, 1, 'put() should access primary key property once'); 110 assert_equals( 111 obj.prop_count, 1, 'put() should access index key property once'); 112 t.done(); 113 }, 'Store and index key path evaluations operate on the same clone'); 114 115 indexeddb_test( 116 createObjectStoreWithIndex('store', 'id', 'index', 'prop'), (t, db) => { 117 const {store} = createTransactionAndReturnObjectStore(db, 'store'); 118 store.put(new ProbeObject()); 119 120 store.openCursor().onsuccess = t.step_func((event) => { 121 const cursor = event.target.result; 122 123 const obj = new ProbeObject(); 124 cursor.update(obj); 125 assert_equals( 126 obj.id_count, 1, 'put() should access primary key property once'); 127 assert_equals( 128 obj.prop_count, 1, 'put() should access index key property once'); 129 130 t.done(); 131 }); 132 }, 'Cursor update checks and keypath evaluations operate on a clone');