A has a current number. The current number is always a positive integer less than or equal to 253 (9007199254740992) + 1. The initial value of a ‘s current number is 1, set when the associated is created. The current number is incremented as keys are generated, and may be updated to a specific value by using explicit keys.

    Every object store that uses key generators uses a separate generator. That is, interacting with one object store never affects the key generator of any other object store.

    Modifying a key generator’s is considered part of a database operation. This means that if the operation fails and the operation is reverted, the current number is reverted to the value it had before the operation started. This applies both to modifications that happen due to the getting increased by 1 when the key generator is used, and to modifications that happen due to a record being stored with a key value specified in the call to store the .

    Likewise, if a transaction is aborted, the of the key generator for each object store in the transaction’s is reverted to the value it had before the transaction was started.

    The for a key generator never decreases, other than as a result of database operations being reverted. Deleting a record from an never affects the object store’s key generator. Even clearing all records from an object store, for example using the method, does not affect the current number of the object store’s key generator.

    When a is stored and a key is not specified in the call to store the record, a key is generated.

    To generate a key for an store, run these steps:

    1. Let generator be the key generator associated with store.

    2. Let key be generator’s .

    3. If key is greater than 253 (9007199254740992), then return failure.

    4. Increase generator’s current number by 1.

    5. Return key.

    When a is stored and a key is specified in the call to store the record, the associated may be updated.

    To possibly update the key generator for an object store store with key, run these steps:

    1. Let value be the of key.

    2. Let value be the minimum of value and 253 (9007199254740992).

    3. Let value be the largest integer not greater than value.

    4. Let generator be the key generator associated with store.

    5. If value is greater than or equal to generator’s , then set generator’s current number to value + 1.

    A key can be specified both for object stores which use , by setting the property on the stored value which the object store’s key path points to, and for object stores which use , by passing a key argument to the call to store the record.

    Only specified keys of number can affect the current number of the key generator. Keys of date, array (regardless of the other keys they contain), binary, or string (regardless of whether they could be parsed as numbers) have no effect on the current number of the key generator. Keys of number with value less than 1 do not affect the since they are always lower than the current number.

    When the of a key generator reaches above the value 253 (9007199254740992) any subsequent attempts to use the key generator to generate a new key will result in a “[ConstraintError](https://www.w3.org/TR/WebIDL-1/#constrainterror)[DOMException](https://www.w3.org/TR/WebIDL-1/#idl-DOMException). It is still possible to insert into the object store by specifying an explicit key, however the only way to use a key generator again for such records is to delete the object store and create a new one.

    This limit arises because integers greater than 9007199254740992 cannot be uniquely represented as ECMAScript Numbers. As an example, 9007199254740992 + 1 === 9007199254740992 in ECMAScript.

    As long as key generators are used in a normal fashion this limit will not be a problem. If you generate a new key 1000 times per second day and night, you won’t run into this limit for over 285000 years.

    A practical result of this is that the first key generated for an object store is always 1 (unless a higher numeric key is inserted first) and the key generated for an object store is always a positive integer higher than the highest numeric key in the store. The same key is never generated twice for the same object store unless a transaction is rolled back.

    Each object store gets its own key generator:

    If an insertion fails due to constraint violations or IO error, the key generator is not updated.

    1. transaction.onerror = function(e) { e.preventDefault() };
    2. store = db.createObjectStore("store1", { autoIncrement: true });
    3. index = store.createIndex("index1", "ix", { unique: true });
    4. store.put({ ix: "a"}); // Will get key 1
    5. store.put({ ix: "a"}); // Will fail
    6. store.put({ ix: "b"}); // Will get key 2
    1. store = db.createObjectStore("store1", { autoIncrement: true });
    2. store.put("a"); // Will get key 1
    3. store.delete(1);
    4. store.put("b"); // Will get key 2
    5. store.put("c"); // Will get key 3
    6. store.delete(IDBKeyRange.lowerBound(0));
    7. store.put("d"); // Will get key 4

    Inserting an item with an explicit key affects the key generator if, and only if, the key is numeric and higher than the last generated key.

    Aborting a transaction rolls back any increases to the key generator which happened during the transaction. This is to make all rollbacks consistent since rollbacks that happen due to crash never has a chance to commit the increased key generator value.

    1. db.createObjectStore("store", { autoIncrement: true });
    2. trans1 = db.transaction(["store"], "readwrite");
    3. store_t1 = trans1.objectStore("store");
    4. store_t1.put("a"); // Will get key 1
    5. store_t1.put("b"); // Will get key 2
    6. trans1.abort();
    7. trans2 = db.transaction(["store"], "readwrite");
    8. store_t2 = trans2.objectStore("store");
    9. store_t2.put("c"); // Will get key 1
    10. store_t2.put("d"); // Will get key 2

    The following examples illustrate the different behaviors when trying to use in-line and key generators to save an object to an .

    If the following conditions are true:

    Then the value provided by the is used to populate the key value. In the example below the key path for the object store is “foo.bar“. The actual object has no value for the bar property, { foo: {} }. When the object is saved in the the property is assigned a value of 1 because that is the next key generated by the .

    1. var store = db.createObjectStore("store", { keyPath: "foo.bar",
    2. autoIncrement: true });
    3. store.put({ foo: {} }).onsuccess = function(e) {
    4. var key = e.target.result;
    5. console.assert(key === 1);
    6. };

    If the following conditions are true:

    • There is a value for the key path property.

    Then the value associated with the property is used. The auto-generated key is not used. In the example below the for the object store is “foo.bar“. The actual object has a value of 10 for the bar property, { foo: { bar: 10} }. When the object is saved in the the bar property keeps its value of 10, because that is the key value.

    The following example illustrates the scenario when the specified in-line key is defined through a but there is no property matching it. The value provided by the key generator is then used to populate the key value and the system is responsible for creating as many properties as it requires to suffice the property dependencies on the hierarchy chain. In the example below the for the object store is “foo.bar.baz“. The actual object has no value for the foo property, { zip: {} }. When the object is saved in the the , bar, and baz properties are created each as a child of the other until a value for foo.bar.baz can be assigned. The value for foo.bar.baz is the next key generated by the object store.

    1. var store = db.createObjectStore("store", { keyPath: "foo.bar.baz",
    2. autoIncrement: true });
    3. store.put({ zip: {} }).onsuccess = function(e) {
    4. var key = e.target.result;
    5. console.assert(key === 1);
    6. store.get(key).onsuccess = function(e) {
    7. var value = e.target.result;
    8. // value will be: { zip: {}, foo: { bar: { baz: 1 } } }
    9. console.assert(value.foo.bar.baz === 1);
    10. };
    11. };

    Attempting to store a property on a primitive value will fail and throw an error. In the first example below the key path for the object store is “foo“. The actual object is a primitive with the value, 4. Trying to define a property on that primitive value fails. The same is true for arrays. Properties are not allowed on an array. In the second example below, the actual object is an array, [10]. Trying to define a property on the array fails.

    1. var store = db.createObjectStore("store", { keyPath: "foo", autoIncrement: true });
    2.  
    3. // The key generation will attempt to create and store the key path
    4. // property on this primitive.
    5. store.put(4); // will throw DataError
    6.  
    7. // The key generation will attempt to create and store the key path
    8. // property on this array.
    9. store.put([10]); // will throw DataError