tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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');