Indexed Database API

W3C

Indexed Database API

W3C Working Draft 24 May 2012

This version:
http://www.w3.org/TR/2012/WD-IndexedDB-20120524/
Latest published version:
http://www.w3.org/TR/IndexedDB/
Latest editor's draft:
http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html
Previous version:
http://www.w3.org/TR/2011/WD-IndexedDB-20111206/
Editors:
Nikunj Mehta, Invited Expert
Jonas Sicking, Mozilla
Eliot Graff, Microsoft
Andrei Popescu, Google
Jeremy Orlow, Google

Abstract

This document defines APIs for a database of records holding simple values and hierarchical objects. Each record consists of a key and some value. Moreover, the database maintains indexes over records it stores. An application developer directly uses an API to locate records either by their key or by using an index. A query language can be layered on this API. An indexed database can be implemented using a persistent B-tree data structure.

Status of This Document

This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at http://www.w3.org/TR/.

Features at risk

The following features are at risk and may be removed, due to potential lack of implementations.

Disposition of Comments

The Disposition of Comments received during the Last Call period may be found at http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/IndexedDB Disposition of Comments.html.

This document was published by the Web Applications Working Group as a Last Call Working Draft. This document is intended to become a W3C Recommendation. If you wish to make comments regarding this document, please send them to public-webapps@w3.org (subscribe, archives). The Last Call period ends 21 June 2012. All feedback is welcome.

Publication as a Working Draft does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.

This is a Last Call Working Draft and thus the Working Group has determined that this document has satisfied the relevant technical requirements and is sufficiently stable to advance through the Technical Recommendation process.

This document was produced by a group operating under the 5 February 2004 W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.

Table of Contents

1. Introduction

This section is non-normative.

User agents need to store large numbers of objects locally in order to satisfy off-line data requirements of Web applications. [WEBSTORAGE] is useful for storing pairs of keys and their corresponding values. However, it does not provide in-order retrieval of keys, efficient searching over values, or storage of duplicate values for a key.

This specification provides a concrete API to perform advanced key-value data management that is at the heart of most sophisticated query processors. It does so by using transactional databases to store keys and their corresponding values (one or more per key), and providing a means of traversing keys in a deterministic order. This is often implemented through the use of persistent B-tree data structures that are considered efficient for insertion and deletion as well as in-order traversal of very large numbers of data records.

TODO: Add examples using the sync and the async APIs.

2. Conformance

As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.

The key words must, must not, required, should, should not, recommended, may, and optional in this specification are to be interpreted as described in [RFC2119].

This specification defines one class of products:

Conforming user agent

A user agent must behave as described in this specification in order to be considered conformant.

User agents may implement algorithms given in this specification in any way desired, so long as the end result is indistinguishable from the result that would be obtained by the specification's algorithms.

A conforming Indexed Database API user agent must also be a conforming implementation of the IDL fragments of this specification, as described in the “Web IDL” specification. [WEBIDL]

This specification uses both the terms "conforming user agent(s)" and "user agent(s)" to refer to this product class.

2.1 Dependencies

This specification relies on several other underlying specifications.

DOM-LEVEL-3-EVENTS
The terms default action and propagation path are defined by the Document Object Model (DOM) Level 3 Events Specification [DOM-LEVEL-3-EVENTS].
HTML5
The terms and algorithms document base URL, event handler attributes, event handler event type, Function, origin, same origin, structured clone, structured clone algorithm, task, task source, and queue a task are defined by the HTML 5 specification [HTML5].
WebIDL
Many of the interface definitions and all of the IDL in this spec depends on [WEBIDL].
WebWorkers
The term Worker is defined by the WebWorkers specification [WEBWORKERS].

3. Indexed Database API

3.1 Constructs

3.1.1 Database

Each origin has an associated set of databases. A database comprises one or more object stores which hold the data stored in the database.

Every database has a name which identifies it within a specific origin. The name can be any string value, including the empty string, and stays constant for the lifetime of the database. Each database also has a current version. When a database is first created, its version is 0.

Implementations must support all names. If an implementation uses a storage mechanism which can't handle arbitrary database names, the implementation must use an escaping mechanism or something similar to map the provided name to a name that it can handle.

Each database has one version at a time; a database can't exist in multiple versions at once. The only way to change the version is using a "versionchange" transaction.

Databases has a delete pending flag which is used during deletion. When a database is requested to be deleted the flag is set to true and all attempts at opening the database are stalled until the database can be deleted.

The act of opening a database creates a connection. There may be multiple connections to a given database at any given time. Each connection has a closePending flag which initially is set to false.

When a connection is initially created it is in opened state. The connection can be closed through several means. If the connection is GCed or execution context where the connection is created is destroyed (for example due to the user navigating away from that page), the connection is closed. The connection can also be closed explicitly using the steps for closing a database connection. When the connection is closed the closePending flag is always set to true if it hasn't already been.

The IDBDatabase and IDBDatabaseSync interfaces represent a connection to a database.

3.1.2 Object Store

An object store is the primary storage mechanism for storing data in a database.

Each database contain a set of object stores. The set of object stores can be changed, but can only be changed using a "versionchange" transactions, i.e. in response to a upgradeneeded event. When a new database is created it doesn't contain any object stores.

The object store has a list of records which hold the data stored in the object store. Each record consists of a key and a value. The list is sorted according to key in ascending order. There can never be multiple records in a given object store with the same key.

Every object store has a name. The name is unique within the database to which it belongs. Every object store also optionally has a key generator and an optional key path. If the object store has a key path it is said to use in-line keys. Otherwise it is said to use out-of-line keys.

The object store can derive the key from one of three sources:

  1. A key generator. A key generator generates a monotonically increasing numbers every time a key is needed.
  2. Keys can be derived via a key path.
  3. Keys can also be explicitly specified when a value is stored in the object store.

The IDBObjectStore and IDBObjectStoreSync interfaces represent an object store. Note however that multiple instances of those interfaces representing the same object store can exist.

3.1.3 Keys

In order to efficiently retrieve records stored in an indexed database, each record is organized according to its key. A value is said to be a valid key if it is one of the following types: Array JavaScript objects [ECMA-262], DOMString [WEBIDL], Date [ECMA-262] or float [WEBIDL]. However Arrays are only valid keys if every item in the array is defined and is a valid key (i.e. sparse arrays can not be valid keys) and if the Array doesn't directly or indirectly contain itself. Any non-numeric properties are ignored, and thus does not affect whether the Array is a valid key. Additionally, if the value is of type float, it is only a valid key if it is not NaN, and if the value is of type Date it is only a valid key if its [[PrimitiveValue]] internal property, as defined by [ECMA-262], is not NaN. Conforming user agents must support all valid keys as keys.

Infinite float values are valid keys. As are empty Arrays.

For purposes of comparison, all Arrays are greater than all DOMString, Date and float values; all DOMString values are greater than all Date and float values; and all Date values are greater than all float values. Values of type float are compared to other float values numerically. Values of type Date are compared to other Date values chronologically. Values of type DOMString are compared to other values of type DOMString by using the algorithm defined by step 4 of section 11.8.5, The Abstract Relational Comparison Algorithm, of the ECMAScript Language Specification [ECMA-262]. Values of type Array are compared to other values of type Array as follows:

  1. Let A be the first Array value and B be the second Array value.
  2. Let length be the lesser of A's length and B's length.
  3. Let i be 0.
  4. If the ith value of A is less than the ith value of B, then A is less than B. Skip the remaining steps.
  5. If the ith value of A is greater than the ith value of B, then A is greater than B. Skip the remaining steps.
  6. Increase i by 1.
  7. If i is not equal to length, go back to step 4. Otherwise continue to next step.
  8. If A's length is less than B's length, then A is less than B. If A's length is greater than B's length, then A is greater than B. Otherwise A and B are equal.

Note that Arrays that contain other Arrays are allowed as valid keys. In this case the algorithm above runs recursively when comparing the individual values in the arrays.

As a result of the above rules, negative infinity is the lowest possible value for a key. There is no highest possible key value. This is because an array of any candidate highest key followed by another valid key is even higher.

The terms greater than, less than and equal to is defined in the terms of the above comparisons.

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

Example

If the following conditions are true:

Then the value provided by the key generator 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 object store the bar property is assigned a value of 4 because that is the next key generated by the object store.

ECMAScript

 "foo.bar"
{ foo: {} }
            

If the following conditions are true:

Then the value associated with the key path property is used. The auto-generated key is not used. In the example below the keypath 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 object store the bar property keeps its value of 10, because that is the key value.

ECMAScript

"foo.bar"
{ foo: { bar: 10 } }
            

The following example illustrates the scenario when the specified in-line key is defined through a key path 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 key path 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 object store the foo, 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.

ECMAScript

"foo.bar.baz"
{ zip: {} }
            

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.

ECMAScript

// The key generation will attempt to create and store the key path property on this primitive.
"foo"
4

// The key generation will attempt to create and store the key path property on this array.
"foo"
[10]
            
            

3.1.4 Values

Each record is associated with a value. Conforming user agents must support any value supported by the structured clone algorithm [HTML5]. This includes simple types such as DOMString and Date as well as Object and Array instances.

3.1.5 Key Path

A key path is a DOMString that defines how to extract a key from a value. A valid key path is either the empty string, a JavaScript identifier, or multiple Javascript identifiers separated by periods (ASCII character code 46) [ECMA-262]. (Note that spaces are not allowed within a key path.) To evaluate a key path, run the steps for extracting a key from a value using a key path.

Key path values can only be accessed from properties explicitly copied by the structured clone algorithm, as well as the following properties:

  • Blob.size
  • Blob.type
  • File.name
  • File.lastModifiedDate
  • Array.length
  • String.length

3.1.6 Index

It is sometimes useful to retrieve records in an object store through other means than their key. An index allows looking up records in an object store using properties of the values in the object stores records.

An index is a specialized persistent key-value storage and has a referenced object store. The index has a list of records which hold the data stored in the index. The records in an index are automatically populated whenever records in the referenced object store are inserted, updated or deleted. There can be several indexes referencing the same object store, in which changes to the object store cause all such indexes to get updated.

The values in the index's records are always values of keys in the index's referenced object store. The keys are derived from the referenced object store's values using a key path. If a given record with key X in the object store referenced by the index has the value A, and evaluating the index's key path on A yields the result Y, then the index will contain a record with key Y and value X.

Records in an index are said to have a referenced value. This is the value of the record in the index's referenced object store which has a key equal to the index's record's value. So in the example above, the record in the index whose key is Y and value is X has a referenced value of A.

Each record in an index reference one and only one record in the index's referenced object store. However there can be multiple records in an index which reference the same record in the object store. And there can also be no records in an index which reference a given record in an object store.

The records in an index are always sorted according to the records key. However unlike object stores, a given index can contain multiple records with the same key. Such records are additionally sorted according to the records value.

An index contains a unique flag. When this flag is set to true, the index enforces that no two records in the index has the same key. If a record in the index's referenced object store is attempted to be inserted or modified such that evaluating the index's key path on the records new value yields a result which already exists in the index, then the attempted modification to the object store fails.

An index also contains a multiEntry flag. This flag affects how the index behaves when the result of evaluating the index's key path yields an Array. If the multiEntry flag is false, then a single record whose key is an Array is added to the index. If the multiEntry flag is true, then the one record is added to the index for each item in the Array. The key for each record is the value of respective item in the Array.

The IDBIndex and IDBIndexSync interfaces provide access to the metadata of an index. Note however that multiple instances of those interfaces representing the same index can exist.

3.1.7 Transaction

A transaction is used to interact with the data in a database. Whenever data is read or written to the database it is done by using a transaction.

All transactions are created through a connection, which is the transaction's connection. The transaction has a mode that determines which types of interactions can be performed upon that transaction. The mode is set when the transaction is created and remains fixed for the life of the transaction. The transaction also has a scope that determines the object stores with which the transaction may interact. Transactions have an active flag, which determines if new requests can be made against the transaction. Finally, transactions also contain a request list of requests which have been made against the transaction.

Each transaction has a fixed scope, determined when the transaction is created. A transaction's scope remains fixed for the lifetime of that transaction.

Transactions offer some protection from application and system failures. A transaction may be used to store multiple data records or to conditionally modify certain data records. A transaction represents an atomic and durable set of data access and data mutation operations.

Transactions are expected to be short lived. This is encouraged by the automatic committing functionality described below. Authors can still cause transactions to run for a long time; however, this usage pattern is not generally recommended as it can lead to a bad user experience.

The lifetime of a transaction is as follows:

  1. A transaction is created using IDBDatabase.transaction. The arguments passed determine the scope of the transaction and whether the transaction is read-only. When a transaction is created its active flag is initially set to true.
  2. The implementation must allow requests to be placed against the transaction whenever the active flag is true. This is the case even if the transaction has not yet been started. Until the transaction is started the implementation must not execute these requests; however, the implementation must keep track of the requests and their order. Requests may be placed against a transaction only while that transaction is active. If an attempt is made to place a request against a transaction when that transaction is not active, the implementation must reject the attempt by throwing a DOMException of type TransactionInactiveError.
  3. Once an implementation is able to enforce the constraints defined for the transaction mode, defined below, the implementation must queue up an operation to start the transaction asynchronously. The timing for when this happens is affected by:
    • The mode in which the transaction is opened.
    • Which object stores are included in the scope of the transaction.
  4. Once the transaction has been started the implementation can start executing the requests placed against the transaction. Unless otherwise defined, requests must be executed in the order in which they were made against the transaction. Likewise, their results must be returned in the order the requests were placed against a specific transaction. There is no guarantee about the order that results from requests in different transactions are returned. Similarly, the transaction modes ensure that two requests placed against different transactions can execute in any order without affecting what resulting data is stored in the database.
  5. A transaction can be aborted at any time before it is finished, even if the transaction isn't currently active or hasn't yet started. When a transaction is aborted the implementation must undo (roll back) any changes that were made to the database during that transaction. This includes both changes to the contents of object stores as well as additions and removals of object stores and indexes.
  6. A transaction can fail for reasons not tied to a particular DOMRequest. For example due to IO errors when committing the transaction, or due to running into a quota limit where the implementation can't tie exceeding the quota to a partcular request. In this case the implementation must run the steps for aborting a transaction using the transaction as transaction and the appropriate error type as error. For example if quota was exceeded then QuotaExceededError should be used as error, and if an IO error happened, UnknownError should be used as error.
  7. When a transaction can no longer become active, the implementation must attempt to commit it, as long as the transaction has not been aborted. This usually happens after all requests placed against the transaction have been executed and their returned results handled, and no new requests have been placed against the transaction. When a transaction is committed, the implementation must atomically write any changes to the database made by requests placed against the transaction. That is, either all of the changes must be written, or if an error occurs, such as a disk write error, the implementation must not write any of the changes to the database. If such an error occurs, the implementation must abort the transaction by following the steps for aborting a transaction, otherwise it must commit the transaction by following the steps for committing a transaction.
  8. When a transaction is committed or aborted, it is said to be finished. If a transaction can't be finished, for example due to the implementation crashing or the user taking some explicit action to cancel it, the implementation must abort the transaction.

Transactions are opened in one of three modes. The mode determines how concurrent access to object stores in the transaction are isolated.

  1. "readonly". This mode means that the transaction is only allowed to read data. No modifications can be done by this type of transaction. This has the advantage that several "readonly" transactions can run at the same time even if their scopes are overlapping, i.e. if they are using the same object stores. This type of transaction can be created any time once a database has been opened using the IDBDatabase.transaction() or IDBDatabaseSync.transaction() functions.
  2. "readwrite". The type of transaction is allowed to read, modify and delete data from existing object stores. However object stores and indexes can't be added or removed. Multiple "readwrite" transactions can't run at the same time if their scopes are overlapping since that would mean that they can modify each other's data in the middle of the transaction. This type of transaction can be created any time once a database has been opened using the IDBDatabase.transaction() function.
  3. "versionchange". This is similar to a "readwrite" transaction, however it can additionally create and remove object stores and indexes. It's the only type of transaction that can do so. This type of transaction can't be manually created, but instead is created automatically when a upgradeneeded event is fired.

The this is defined in more detail below.

Any number of transactions opened in "readonly" mode are allowed to run concurrently, even if the transaction's scope overlap and include the same object stores. As long as a "readonly" transaction is running, the data that the implementation returns through requests created with that transaction must remain constant. That is, two requests to read the same piece of data must yield the same result both for the case when data is found and the result is that data, and for the case when data is not found and a lack of data is indicated.

There are a number of ways that an implementation ensures this. The implementation can prevent any "readwrite" transaction, whose scope overlaps the scope of the "readonly" transaction, from starting until the "readonly" transaction finishes. Or the implementation can allow the "readonly" transaction to see a snapshot of the contents of the object stores which is taken when the "readonly" transaction started.

Similarly, implementations must ensure that a "readwrite" transaction is only affected by changes to object stores that are made using the transaction itself. For example, the implementation must ensure that another transaction does not modify the contents of object stores in the "readwrite" transaction's scope. The implementation must also ensure that if the "readwrite" transaction completes successfully, the changes written to object stores using the transaction can be committed to the database without merge conflicts. An implementation must not abort a transaction due to merge conflicts.

If multiple "readwrite" transactions are attempting to access the same object store (i.e. if they have overlapping scope), the transaction that was created first must be the transaction which gets access to the object store first. Due to the requirements in the previous paragraph, this also means that it is the only transaction which has access to the object store until the transaction is finished.

Generally speaking, the above requirements mean that "readwrite" transactions which have overlapping scopes always run in the order they were created, and never run in parallel.

A "versionchange" transaction never run concurrently with other transactions. When a database is opened with a version number higher than the current version, a new "versionchange" transaction is automatically created and made available through the "upgradeneeded" event. The "upgradeneeded" event isn't fired, and thus the "versionchange" transaction isn't started, until all other connections to the same database are closed. This ensures that all other transactions are finished.

As long as a "versionchange" transaction is running, attempts to open more connections to the same database are delayed, and any attempts to use the same connection to start additional transactions will result in an exception being thrown. Thus "versionchange" transactions not only ensure that no other transactions are running concurrently, but also ensure that no other transactions are queued against the same database as long as the transaction is running.

"versionchange" transaction is automatically created when a database version number is provided that is greater than the current database version. This transaction will be active inside the onupgradeneeded event handler, allowing the creation of new object stores and indexes.

User agents must ensure a reasonable level of fairness across transactions to prevent starvation. For example, if multiple "readonly" transactions are started one after another the implementation must not indefinitely prevent a pending "readwrite" transaction from starting.

Each transaction object implements either the IDBTransaction or the IDBTransactionSync interface.

3.1.8 Requests

Each reading and writing operation on a database is done using a request. Every request represents one read or write operation. Requests have a done flag which initially is false, and a source object. Every request also has a result and an error attribute, neither of which are accessible until the done flag is set to true.

Finally, requests have a request transaction. When a request is created, it is always placed against a transaction using either the steps for asynchronously executing a request or the steps for synchronously executing a request. The steps set the request transaction to be that transaction. The steps do not set the request transaction to be that request for the request returned from an IDBFactory.open call however. That function create requests which have a null request transaction.

3.1.9 Key Range

Records can be retrieved from object stores and indexes using either keys or key ranges. A key range is a continuous interval over some data type used for keys.

A key range may be lower-bounded or upper-bounded (there is a value that is, respectively, smaller than or larger than all its elements). A key range is said to be bounded if it is both lower-bounded and upper-bounded. If a key range is neither lower-bounded nor upper-bounded it is said to be unbounded. A key range may be open (the key range does not include its endpoints) or closed (the key range includes its endpoints). A key range may consist of a single value.

The IDBKeyRange interface defines a key range.

interface IDBKeyRange {
    readonly attribute any     lower;
    readonly attribute any     upper;
    readonly attribute boolean lowerOpen;
    readonly attribute boolean upperOpen;
    static IDBKeyRange only (any value);
    static IDBKeyRange lowerBound (any lower, optional boolean open);
    static IDBKeyRange upperBound (any upper, optional boolean open);
    static IDBKeyRange bound (any lower, any upper, optional boolean lowerOpen, optional boolean upperOpen);
};
Attributes
lower of type any, readonly
This value is the lower-bound of the key range.
No exceptions.
lowerOpen of type boolean, readonly
Returns false if the lower-bound value is included in the key range. Returns true if the lower-bound value is excluded from the key range.
No exceptions.
upper of type any, readonly
This value is the upper-bound of the key range.
No exceptions.
upperOpen of type boolean, readonly
Returns false if the upper-bound value is included in the key range. Returns true if the upper-bound value is excluded from the key range.
No exceptions.
Methods
bound
Creates and returns a new key range with lower set to lower, lowerOpen set to lowerOpen, upper set to upper and upperOpen set to upperOpen.
ParameterTypeNullableOptionalDescription
loweranyThe lower-bound value
upperanyThe upper-bound value
lowerOpenbooleanSet to false if the lower-bound should be included in the key range. Set to true if the lower-bound value should be excluded from the key range. Defaults to false (lower-bound value is included).
upperOpenbooleanSet to false if the upper-bound should be included in the key range. Set to true if the upper-bound value should be excluded from the key range. Defaults to false (upper-bound value is included).
ExceptionDescription
DOMException
DataErrorEither the lower or upper parameters were not passed a valid key or the lower key is greater than the upper key or the lower key and upper key match and either of the bounds are open.
Return type: static IDBKeyRange
lowerBound
Creates and returns a new key range with lower set to lower, lowerOpen set to open, upper set to undefined and and upperOpen set to true.
ParameterTypeNullableOptionalDescription
loweranyThe lower bound value
openbooleanSet to false if the lower-bound should be included in the key range. Set to true if the lower-bound value should be excluded from the key range. Defaults to false (lower-bound value is included).
ExceptionDescription
DOMException
DataErrorThe value parameter was not passed a valid key.
Return type: static IDBKeyRange
only
Creates and returns a new key range with both lower and upper set to value and both lowerOpen and upperOpen set to false.
ParameterTypeNullableOptionalDescription
valueanyThe only value
ExceptionDescription
DOMException
DataErrorThe value parameter was not passed a valid key.
Return type: static IDBKeyRange
upperBound
Creates and returns a new key range with lower set to undefined, lowerOpen set to true, upper set to upper and and upperOpen set to open.
ParameterTypeNullableOptionalDescription
upperanyThe upper bound value
openbooleanSet to false if the upper-bound should be included in the key range. Set to true if the upper-bound value should be excluded from the key range. Defaults to false (upper-bound value is included).
ExceptionDescription
DOMException
DataErrorThe value parameter was not passed a valid key.
Return type: static IDBKeyRange

A key is in a key range if both the following conditions are fulfilled:

3.1.10 Cursor

Cursors are a transient mechanism used to iterate over multiple records in a database. Storage operations are performed on the underlying index or an object store.

A cursor comprises a range of records in either an index or an object store. The cursor has a source that indicates which index or object store is associated with the records over which the cursor is iterating. A cursor maintains a position over this series, which moves in a direction that is in either monotonically increasing or decreasing order of the record keys. Cursors also have a key and a value which represent the key and the value of the last iterated record. Cursors finally have a got value flag. When this flag is false, the cursor is either in the process of loading the next value or it has reached the end of its range, when it is true, it indicates that the cursor is currently holding a value and that it is ready to iterate to the next one.

There are four possible values for a cursor's direction. The direction of a cursor determines if the cursor initial position is at the start of its source or at its end. It also determines in which direction the cursor moves when iterated, and if it skips duplicated values when iterating indexes. The allowed values for a cursor's direction is as follows:

  • "next". This direction causes the cursor to be opened at the start of the source. When iterated, the cursor should yield all records, including duplicates, in monotonically increasing order of keys.
  • "nextunique". This direction causes the cursor to be opened at the start of the source. When iterated, the cursor should not yield records with the same key, but otherwise yield all records, in monotonically increasing order of keys. For every key with duplicate values, only the first record is yielded. When the source is an object store or a unique index, this direction has the exact same behavior as "next".
  • "prev". This direction causes the cursor to be opened at the end of the source. When iterated, the cursor should yield all records, including duplicates, in monotonically decreasing order of keys.
  • "prevunique". This direction causes the cursor to be opened at the end of the source. When iterated, the cursor should not yield records with the same key, but otherwise yield all records, in monotonically decreasing order of keys. For every key with duplicate values, only the first record is yielded. When the source is an object store or a unique index, this direction has the exact same behavior as "prev".

If the source of a cursor is an object store, the effective object store of the cursor is that object store and the effective key of the cursor is the cursor's position. If the source of a cursor is an index, the effective object store of the cursor is that index's referenced object store and the effective key is the cursor's object store position.

It is possible for the list of records which the cursor is iterating over to change before the full range of the cursor has been iterated. In order to handle this, cursors maintain their position not as an index, but rather as a key of the previously returned record. For a forward iterating cursor, the next time the cursor is asked to iterate to the next record it returns the record with the lowest key greater than the one previously returned. For a backwards iterating cursor, the situation is opposite and it returns the record with the highest key less than the one previously returned.

For cursors iterating indexes the situation is a little bit more complicated since multiple records can have the same key and are therefore also sorted by value. When iterating indexes the cursor also has an object store position, which indicates the value of the previously found record in the index. Both position and the object store position are used when finding the next appropriate record.

Cursor objects implement the IDBCursor or the IDBCursorSync interfaces. There is only ever one IDBCursor or IDBCursorSync instance representing a given cursor. However there is no limit on how many cursors can be used at the same time.

3.1.11 Exceptions

Each of the exceptions defined in the IndexedDB spec is a DOMException with a specific type. [DOM4] Existing DOM Level 4 exceptions will set their code to a legacy value; however, the new indexedDB type exceptions will have a code value of 0. The message value is optional.

IndexedDB uses the following new DOMException types with their various messages. All of these new types will have a code value of 0 zero.

Type Message (Optional)
UnknownError The operation failed for reasons unrelated to the database itself and not covered by any other errors.
ConstraintError A mutation operation in the transaction failed because a constraint was not satisfied. For example, an object such as an object store or index already exists and a request attempted to create a new one.
DataError Data provided to an operation does not meet requirements.
TransactionInactiveError A request was placed against a transaction which is currently not active, or which is finished.
ReadOnlyError The mutating operation was attempted in a "readonly" transaction.
VersionError An attempt was made to open a database using a lower version than the existing version.

IndexedDB reuses the following existing DOMException types from [DOM4]. These types will continue to return the codes and names as specified in DOM4; however, they will have the following messages when thrown from an IndexedDB API:

Type Message (Optional)
NotFoundError The operation failed because the requested database object could not be found. For example, an object store did not exist but was being opened.
InvalidStateError An operation was called on an object on which it is not allowed or at a time when it is not allowed. Also occurs if a request is made on a source object that has been deleted or removed. Use TransactionInactiveError or ReadOnlyError when possible, as they are more specific variations of InvalidStateError.
InvalidAccessError An invalid operation was performed on an object. For example transaction creation attempt was made, but an empty scope was provided.
AbortError A request was aborted, for example through a call to IDBTransaction.abort.
TimeoutError A lock for the transaction could not be obtained in a reasonable time.
QuotaExceededError The operation failed because there was not enough remaining storage space, or the storage quota was reached and the user declined to give more space to the database.
SyntaxError The keypath argument contains an invalid key path.
DataCloneError The data being stored could not be cloned by the internal structured cloning algorithm.

3.1.12 Options Object

Options objects are dictionary objects [WEBIDL] which are used to supply optional parameters to some indexedDB functions like createObjectStore and createIndex. The attributes on the object correspond to optional parameters on the function called.

IDL

The following WebIDL defines IDBObjectStoreParameters dictionary type.

                  
dictionary IDBObjectStoreParameters {
  DOMString? keyPath = null;
  boolean autoIncrement = false;
};
                
              

The following WebIDL defines IDBIndexParameters dictionary type.

                
dictionary IDBIndexParameters {
  boolean unique = false;
  boolean multiEntry = false;
};
                
              

The following WebIDL defines IDBVersionChangeEventInit dictionary type.

                
dictionary IDBVersionChangeEventInit : EventInit {
  unsigned long long oldVersion = 0;
  unsigned long long? newVersion = null;
};
                
              

3.1.13 Key Generators

When a object store is created it can be specified to use a key generator. A key generator keeps an internal current number. The current number is always a positive integer. Whenever the key generator is used to generate a new key, the generator's current number is returned and then incremented to prepare for the next time a new key is needed. Implementations must use the following rules for generating numbers when a key generator is used.

  • Every object store that uses key generators use a seprate generator. I.e. interacting with one object store never affects the key generator of any other object store.
  • The current number of a key generator is always set to 1 when the object store for that key generator is first created.
  • When a key generator is used to generate a new key for a object store, the key generator's current number is used as the new key value and then the key generator's current number is increased by 1.
  • When a record is stored in a object store which uses a key generator, and an explicit key is defined, if the key's value is a float greater than or equal to the key generator's current number, then the key generator's current number is set to the smallest integer number larger than the explicit key. Only explicit keys which are float values affect the current number of the key generator. Dates and Arrays which contain floats do not affect the current number of the key generator. Likewise, negative float numbers do not affect the current number since they are always lower than the current number.

    This can happen both with in-line keys, if the property of the stored value is set, or with out-of-line keys, if an explicit key argument is provided.

  • Modifying a key generator's current number 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 current number getting increased by 1 when the key generator is used, and to modifications that happen due to
  • Likewise, if a transaction is aborted, the current number of the key generator's for all object stores in the transaction's scope is reverted to the values they had before the transaction was started.
  • When the current number of a key generator reaches above the value 2^53 (9007199254740992) any attempts to use the key generator to generate a new key will result in an error. It's still possible to insert records into the object store by specifying an explicit key, however the only way to use a key generator again for the object store is to delete the object store and create a new one.

    Note that as long as key generators are used in a normal fashion this 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.

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

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.

Example

Each object store gets it's own key generator:

ECMAScript

store1 = db.createObjectStore("store1", { autoIncrement: true });
store1.put("a"); // Will get key 1
store2 = db.createObjectStore("store2", { autoIncrement: true });
store2.put("a"); // Will get key 1
store1.put("b"); // Will get key 2
store2.put("b"); // Will get key 2
            

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

ECMAScript

transaction.onerror = function(e) { e.preventDefault() };
store = db.createObjectStore("store1", { autoIncrement: true });
index = store.createIndex("index1", "ix", { unique: true });
store.put({ ix: "a"}); // Will get key 1
store.put({ ix: "a"}); // Will fail
store.put({ ix: "b"}); // Will get key 2
            

Removing items from an objectStore never affects the key generator. Including when .clear() is called.

ECMAScript

store = db.createObjectStore("store1", { autoIncrement: true });
store.put("a"); // Will get key 1
store.delete(1);
store.put("b"); // Will get key 2
store.clear();
store.put("c"); // Will get key 3
store.delete(IDBKeyRange.lowerBound(0));
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.

ECMAScript

store = db.createObjectStore("store1", { autoIncrement: true });
store.put("a"); // Will get key 1
store.put("b", 3); // Will use key 3
store.put("c"); // Will get key 4
store.put("d", -10); // Will use key -10
store.put("e"); // Will get key 5
store.put("f", 6.00001); // Will use key 6.0001
store.put("g"); // Will get key 7
store.put("f", 8.9999); // Will use key 8.9999
store.put("g"); // Will get key 9
store.put("h", "foo"); // Will use key "foo"
store.put("i"); // Will get key 10
store.put("j", [1000]); // Will use key [1000]
store.put("k"); // Will get key 11
// All of these would behave the same if the objectStore used a
keyPath and the explicit key was passed inline in the object
            

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.

ECMAScript

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

3.2 Asynchronous APIs

The asynchronous API methods return without blocking the calling thread. All asynchronous operations immediately return an IDBRequest instance. This object does not initially contain any information about the result of the operation. Once information becomes available, an event is fired on the request and the information becomes available through the properties of the IDBRequest instance.

3.2.1 The IDBRequest Interface

The IDBRequest interface provides means to access results of asynchronous requests to databases and database objects using event handler attributes [DOM-LEVEL-3-EVENTS].

Example

In the following example, we open a database asynchronously. Various event handlers are registered for responding to various situations.

ECMAScript

 var request = indexedDB.open('AddressBook', 15);
 request.onsuccess = function(evt) {...};
 request.onerror = function(evt) {...};
            
interface IDBRequest : EventTarget {
    readonly attribute any            result;
    readonly attribute DOMError       error;
    readonly attribute Object         source;
    readonly attribute IDBTransaction transaction;
    readonly attribute DOMString      readyState;
    [TreatNonCallableAsNull]
             attribute Function?      onsuccess;
    [TreatNonCallableAsNull]
             attribute Function?      onerror;
};
Attributes
error of type DOMError, readonly
When the done flag is true, getting this property must return the error of the request. This is null when no error occurred. When the done flag is false, getting this property must throw a DOMException of type InvalidStateError.
ExceptionOn GetOn SetDescription
DOMException
InvalidStateErrorThrown when this attribute was read when the done flag was set to false.
onerror of type Function, nullable
The event handler for the error event
No exceptions.
onsuccess of type Function, nullable
The event handler for the success event
No exceptions.
readyState of type DOMString, readonly
When the done flag is false, returns "pending", otherwise returns "done".
No exceptions.
result of type any, readonly
When the done flag is true, getting this property must return the result of the request. This is undefined when the request resulted in an error. When the done flag is false, getting this property must throw a DOMException of type InvalidStateError.
ExceptionOn GetOn SetDescription
DOMException
InvalidStateErrorThrown when this attribute was read when the done flag was set to false.
source of type Object, readonly
Getting this property must return the source for the request. Returns null when there is no source set.
No exceptions.
transaction of type IDBTransaction, readonly
Getting this property must return the transaction for the request. This property can be null for certain requests, such as for request returned from IDBFactory.open.
No exceptions.

When a request is made, a new request is returned with its readyState set to "pending". If a request completes successfully, the readyState is changed to "done", the result is set to the result of the request, and an event with type success is fired at the request.

If an error occurs while performing the operation, the readyState is changed to "done", the error attribute is set to a DOMError type that matches the error, and an event with type error is fired at the request.

The open and deleteDatabase functions on IDBFactory uses a separate interface for its requests in order to make use of the blocked event and upgradeneeded event easier.

interface IDBOpenDBRequest : IDBRequest {
    [TreatNonCallableAsNull]
    attribute Function? onblocked;
    [TreatNonCallableAsNull]
    attribute Function? onupgradeneeded;
};
Attributes
onblocked of type Function, nullable
The event handler for the blocked event
No exceptions.
onupgradeneeded of type Function, nullable
The event handler for the upgradeneeded event
No exceptions.

The task source for these tasks is the database access task source.

3.2.2 Event interfaces

This specification fires events with the following custom interfaces:

[Constructor(DOMString type, optional IDBVersionChangeEventInit eventInitDict)]
interface IDBVersionChangeEvent : Event {
    readonly attribute unsigned long long  oldVersion;
    readonly attribute unsigned long long? newVersion;
};
Attributes
newVersion of type unsigned long long, readonly, nullable
Returns the new version of the database. See the steps for running a "versionchange" transaction.
No exceptions.
oldVersion of type unsigned long long, readonly
Returns the old version of the database.
No exceptions.

3.2.3 Opening a database

Window and WorkerUtils objects must implement the IDBEnvironment interface.

Window implements IDBEnvironment;

All instances of the Window type are defined to also implement the IDBEnvironment interface.

WorkerUtils implements IDBEnvironment;

All instances of the WorkerUtils type are defined to also implement the IDBEnvironment interface.

[NoInterfaceObject]
interface IDBEnvironment {
    readonly attribute IDBFactory indexedDB;
};
Attributes
indexedDB of type IDBFactory, readonly
This attribute provides applications a mechanism for accessing capabilities of indexed databases.
No exceptions.

Every method for making asynchronous requests returns an IDBRequest object that communicates back to the requesting application through events. This design means that any number of requests can be active on any database or object handle at a time.

interface IDBFactory {
    IDBOpenDBRequest open (DOMString name, [EnforceRange] optional unsigned long long version);
    IDBOpenDBRequest deleteDatabase (DOMString name);
    short            cmp (any first, any second);
};
Methods
cmp

When invoked, this method must compare two keys. The method returns 1 if the first key is greater than the second, -1 if the first is less than the second, and 0 if the first is equal to the second.

ParameterTypeNullableOptionalDescription
firstanyThe first key to compare.
secondanyThe second key to compare.
ExceptionDescription
DOMException
DataErrorOne of the supplied keys was not a valid key.
Return type: short
deleteDatabase

When invoked, this method must create a request and return it. The created request must implement the IDBOpenDBRequest interface and have its source set to null. The created request has no source and must implement the IDBVersionChangeRequest interface. The method then queues up an operation to run the steps for deleting a database. Let origin be the origin of the IDBEnvironment used to access this IDBFactory and name be the name parameter passed to this function.

If an error is returned from the steps above, the implementation must set the error attribute of the request to a DOMError whose name is the same as the error returned, and dispatch an event at the request. The event must use the Event interface and have its type set to "error". The event does bubble but is not cancelable. The propagation path of the event is just the request.

If the steps above are successful, the implementation must set the result of the request to undefined and fire a success event at the request. The event must implement the IDBVersionChangeEvent interface and have oldVersion set to database version and have the newVersion property set to null.

The firing of "success" or "error" events do not follow the normal steps to fire a success event or fire an error event as there is no active transaction at the time when they fire.

ParameterTypeNullableOptionalDescription
nameDOMStringThe name for the database
No exceptions.
Return type: IDBOpenDBRequest
open

When invoked, this method must create a request and return it. The created request must implement the IDBOpenDBRequest interface and have its source set to null. The method then queues up an operation to run the steps for opening a database. Let origin be the origin of the IDBEnvironment used to access this IDBFactory, name and version be the name and version parameters passed to this function, and request be the newly created request.

If no version is specified and a database exists, use the current database version and follow the steps for opening a database. If no version is specified and no database exists, set database version to 1, follow the steps for opening a database, and return a database without object stores.

If an error is returned from the steps above, the implementation must set the error attribute of the request to a DOMError whose name is the same as the error returned, and dispatch an event at the request. The event must use the Event interface and have its type set to "error". The event does bubble but is not cancelable. The propagation path of the event is just the request.

If the steps above are successful, the implementation must set the result to the connection created by the steps above and dispatch an event at request. The event must use the Event interface and have its type set to "success". The event does not bubble and is not cancelable. The propagation path of the event is just the request. If the steps above resulted in a "versionchange" transaction being run, then firing the "success" event must be done after the “versionchange” transaction completes.

The last requirement is to ensure that in case another version upgrade is about to happen, the success event is fired on the connection first so that the page gets a chance to register a listener for the versionchange event.

The firing of "success" or "error" events do not follow the normal steps to fire a success event or fire an error event as there is no active transaction at the time when they fire.

ParameterTypeNullableOptionalDescription
nameDOMStringThe name for the database
versionunsigned long longThe version for the database
ExceptionDescription
DOMException
TypeErrorThe value of version is 0 (zero) or a negative number.
Return type: IDBOpenDBRequest

3.2.4 Database

A database object can be used to manipulate the objects of that database. It is also the only way to obtain a transaction for that database.

interface IDBDatabase : EventTarget {
    readonly attribute DOMString          name;
    readonly attribute unsigned long long version;
    readonly attribute DOMStringList      objectStoreNames;
    IDBObjectStore createObjectStore (DOMString name, optional IDBObjectStoreParameters optionalParameters);
    void           deleteObjectStore (DOMString name);
    IDBTransaction transaction (any storeNames, optional DOMString mode);
    void           close ();
    [TreatNonCallableAsNull]
             attribute Function?          onabort;
    [TreatNonCallableAsNull]
             attribute Function?          onerror;
    [TreatNonCallableAsNull]
             attribute Function?          onversionchange;
};
Attributes
name of type DOMString, readonly
On getting, this attribute must return the name of the connected database. The function must return this name even if the closePending flag is set on the connection. In other words, the return value from this function stays constant for the lifetime of the IDBDatabase instance.
No exceptions.
objectStoreNames of type DOMStringList, readonly
On getting, this attribute must return a list of names of the object stores currently in the connected database. The list must be sorted in ascending order using the algorithm defined by step 4 of section 11.8.5, The Abstract Relational Comparison Algorithm of the ECMAScript Language Specification [ECMA-262]. Once the closePending flag is set on the connection, this function must return a snapshot of the list of names of the object stores taken at the time when the close method was called. Even if other connections are later used to change the set of object stores that exist in the database. In other words, the return value from this function stays constant for the lifetime of the IDBDatabase instance, except during a "versionchange" transaction if createObjectStore or deleteObjectStore is called on this IDBDatabase instance itself.
No exceptions.
onabort of type Function, nullable
The event handler for the abort event.
No exceptions.
onerror of type Function, nullable
The event handler for the error event.
No exceptions.
onversionchange of type Function, nullable
The event handler for the versionchange event.
No exceptions.
version of type unsigned long long, readonly
On getting, this attribute must return the version of the database when this IDBDatabase instance was created. When a IDBDatabase instance is created, this is always the number passed as the version argument passed to the open call used to create the IDBDatabase instance. This value remains constant for the lifetime of the IDBDatabase object. If the connection is closed, this attribute represents a snapshot of the version that the database had when the connection was closed. Even if another connection is later used to modify the version, that attribute on closed instances are not changed.
No exceptions.
Methods
close
This method returns immediately and performs the steps for closing a database connection.
No parameters.
No exceptions.
Return type: void
createObjectStore

This method creates and returns a new object store with the given name in the connected database. If this function is called from outside a "versionchange" transaction callback, or if this function is called on a IDBDatabase object other than that transaction's connection, the implementation must throw a DOMException of type InvalidStateError.

If an objectStore with the same name already exists, the implementation must throw a DOMException of type ConstraintError. Otherwise, the implementation must create a new object store and return an IDBObjectStore object representing it.

This method synchronously modifies the IDBDatabase.objectStoreNames property. However it only changes the IDBDatabase.objectStoreNames property on the IDBDatabase instance on which it was called.

If the optionalParameters argument is specified and has a keyPath property which is not undefined or null, then set keyPath to the value of this property. If keyPath is an Array, then each item in the array is converted to a string. If keyPath is not an Array, it is converted to a string.

If keyPath is an Array and any items in the array is not a valid key path, or if keyPath is a string and is not a valid key path then a DOMException of type SyntaxError must be thrown. Otherwise set the created object store's key path is set to the value of keyPath.

If the optionalParameters parameter is specified, and autoIncrement is set to true, and the keyPath parameter is specified to the empty string, or specified to an Array, this function must throw a InvalidAccessError exception.

In some implementations it's possible for the implementation to run into problems after queuing up an operation to create the object store after the createObjectStore function has returned. For example in implementations where metadata about the newly created objectStore is inserted into the database asynchronously, or where the implementation might need to ask the user for permission for quota reasons. Such implementations must still create and return an IDBObjectStore object. Instead, once the implementation realizes that creating the objectStore has failed, it must abort the transaction using the steps for aborting a transaction using the appropriate error as error parameter. For example if creating the object store failed due to quota reasons, QuotaError must be used as error.

ParameterTypeNullableOptionalDescription
nameDOMStringThe name of a new object store
optionalParametersIDBObjectStoreParametersThe options object whose attributes are optional parameters to this function. keyPath specifies the key path of the new object store. If the attribute is null, no key path is specified and thus keys are out-of-line. autoIncrement specifies whether the object store created should have a key generator.
ExceptionDescription
DOMException
InvalidStateErrorThis method was not called from a "versionchange" transaction callback. Also occurs if a request is made on a source object that has been deleted or removed.
ConstraintErrorAn object store with the same name, compared in a case-sensitive manner, already exists in the connected database.
InvalidAccessErrorIf autoIncrement is set to true, and keyPath either is the empty string, or an Array containing the empty string.
Return type: IDBObjectStore
deleteObjectStore

This method destroys the object store with the given name in the connected database. If this function is called from outside a "versionchange" transaction callback, or if this function is called on a IDBDatabase object other than that transactions connection, the implementation must throw a DOMException of type InvalidStateError.

This method synchronously modifies the IDBDatabase.objectStoreNames property. However it only changes the IDBDatabase.objectStoreNames property on the IDBDatabase instance on which it was called.

ParameterTypeNullableOptionalDescription
nameDOMStringThe name of an existing object store
ExceptionDescription
DOMException
InvalidStateError This method was not called from a "versionchange" transaction callback. Also occurs if a request is made on a source object that has been deleted or removed.
NotFoundErrorThere is no object store with the given name, compared in a case-sensitive manner, in the connected database.
Return type: void
transaction

This method, when called must execute the steps for creating a transaction in an asychronous fashion. The storeNames and mode arguments are forwarded to the algorithm as-is. The callback argument is set to null. The timeout argument is set to infinite. The connection argument is set to the IDBDatabase that the transaction() method was called on.

The method returns an IDBTransaction object representing the transaction returned by the steps above.

If this method is called on IDBDatabase object for which a "versionchange" transaction is still running, a InvalidStateError exception must be thrown. I.e. if a "versionchange" transaction is started when a database is opened and this method is called on the IDBDatabase instance for that transaction before the transaction is committed, a InvalidStateError exception must be thrown. Likewise, if this method is called on a IDBDatabase instance where the closePending flag is set, a InvalidStateError exception must be thrown.

ParameterTypeNullableOptionalDescription
storeNamesanyThe names of object stores and indexes in the scope of the new transaction
modeDOMString The mode for isolating access to data inside the given object stores. If this parameter is not provided, the default access mode is "readonly".
ExceptionDescription
DOMException
InvalidStateError The close() method has been called on this IDBDatabase instance.
NotFoundErrorOne of the names provided in the storeNames argument doesn't exist in this database.
TypeErrorThe value for the mode parameter is invalid.
InvalidAccessErrorThe function was called with an empty list of store names
Return type: IDBTransaction

3.2.5 Object Store

Object store objects implement the following interface:
interface IDBObjectStore {
    readonly attribute DOMString      name;
    readonly attribute DOMString      keyPath;
    readonly attribute DOMStringList  indexNames;
    readonly attribute IDBTransaction transaction;
    readonly attribute boolean        autoIncremenent;;
    IDBRequest put (any value, optional any key);
    IDBRequest add (any value, optional any key);
    IDBRequest delete (any key);
    IDBRequest get (any key);
    IDBRequest clear ();
    IDBRequest openCursor (optional any? range, optional DOMString direction);
    IDBIndex   createIndex (DOMString name, any keyPath, optional IDBIndexParameters optionalParameters);
    IDBIndex   index (DOMString name);
    void       deleteIndex (DOMString indexName);
    IDBRequest count (optional any key);
};
Attributes
autoIncremenent; of type boolean, readonly
On getting, provides the auto increment flag for this object store.
No exceptions.
indexNames of type DOMStringList, readonly
On getting, provide a list of the names of indexes on objects in this object store. The list must be sorted in ascending order using the algorithm defined by step 4 of section 11.8.5, The Abstract Relational Comparison Algorithm of the ECMAScript Language Specification [ECMA-262].
No exceptions.
keyPath of type DOMString, readonly
On getting, provide the key path of this object store. This will be either a DOMString, an Array of DOMStrings or null.
No exceptions.
name of type DOMString, readonly
On getting, provide the name of this object store.
No exceptions.
transaction of type IDBTransaction, readonly
On getting, returns the transaction this object store belongs to.
No exceptions.
Methods
add

This method throws a DOMException of type ReadOnlyError if the transaction which this IDBObjectStore belongs to is has its mode set to "readonly". If any of the following conditions are true, this method throws a DOMException of type DataError:

Otherwise this method creates a structured clone of the value parameter. If the structure clone algorithm throws an exception, that exception is rethrown. Otherwise, run the steps for asynchronously executing a request and return the IDBRequest created by these steps. The steps are run with this IDBObjectStore as source and the steps for storing a record into an object store as operation, using this IDBObjectStore as store, the created clone as value, the key parameter as key, and with the no-overwrite flag flag set to true.

ParameterTypeNullableOptionalDescription
valueanyThe value to be stored in the record
keyanyThe key used to identify the record
ExceptionDescription
DOMException
TransactionInactiveErrorThe transaction this IDBObjectStore belongs to is not active.
ReadOnlyErrorThe mode of the associated transaction is "readonly".
DataErrorThe calculated key for the insertion was not a valid key. Also thrown if the calculated key for any of the indexes which belong to this object store had a calculated key which was not a valid key
InvalidStateErrorOccurs if a request is made on a source object that has been deleted or removed.
DataCloneErrorThe data being stored could not be cloned by the internal structured cloning algorithm.
Return type: IDBRequest
clear

This method throws a DOMException of type ReadOnlyError if the transaction which this IDBObjectStore belongs to is has its mode set to "readonly".

Otherwise this method runs the steps for asynchronously executing a request and returns the IDBRequest created by these steps. The steps are run with this IDBObjectStore as source and the steps for clearing an object store as operation, using this IDBObjectStore as store.

No parameters.
ExceptionDescription
DOMException
TransactionInactiveErrorThe transaction this IDBObjectStore belongs to is not active.
ReadOnlyErrorThe mode of the transaction this IDBObjectStore belongs to is "readonly".
InvalidStateErrorOccurs if a request is made on a source object that has been deleted or removed.
Return type: IDBRequest
count

If the optional key parameter is not a valid key or a key range, this method throws a DOMException of type DataError. This method runs the steps for asynchronously executing a request and returns the IDBRequest created by these steps. The steps are run with this IDBObjectStore as source and the steps for iterating a cursor as operation, using the created cursor as cursor. If provided, use the key parameter as key, otherwise, use undefined as key. If the result of the algorithm is null return 0 (zero) as the result for the request. Otherwise, use the return cursor to determine the total number of objects that share the key or key range and return that value as the result for the request.

ParameterTypeNullableOptionalDescription
keyany Key identifying the record to be retrieved. This can also be an IDBKeyRange.
ExceptionDescription
DOMException
TransactionInactiveErrorThe transaction this IDBObjectStore belongs to is not active.
DataErrorThe key parameter is not a valid key or a key range.
InvalidStateErrorOccurs if a request is made on a source object that has been deleted or removed.
Return type: IDBRequest
createIndex

This method creates and returns a new index with the given name and parameters in the connected database. If this function is called from outside a "versionchange" transaction callback, the implementation must throw an DOMException of type InvalidStateError exception. If an index with the same name already exists, the implementation must throw a DOMException of type ConstraintError. Otherwise, the implementation must create a new index and return an IDBIndex object representing it. The created index has its unique and multiEntry flags are set to the values of the unique and multiEntry properties in the optionalParameters argument.

If the keyPath argument is an Array, then each item in the array is converted to a DOMString. If keyPath is not an Array, it is converted to a DOMString.

If keyPath is an Array and any items in the array is not a valid key path, or if keyPath is a string and is not a valid key path then a DOMException of type SyntaxError must be thrown. If keyPath is and Array and the multiEntry property in the optionalParameters is true, then a DOMException of type NotSupportedError must be thrown. Otherwise set the created object store's key path is set to the value of keyPath.

The index that is requested to be created can contain constraints on the data allowed in the index's referenced object store, such as requiring uniqueness of the values referenced by the index's keyPath. If the referenced object store already contains data which violates these constraints, this must not cause the implementation of createIndex to throw an exception or affect what it returns. The implementation must still create and return an IDBIndex object. Instead the implementation must queue up an operation to abort the "versionchange" transaction which was used for the createIndex call.

This method will synchronously modify the IDBObjectStore.indexNames property.

In some implementations it's possible for the implementation to asynchronously run into problems creating the index after the createIndex function has returned. For example in implementations where metadata about the newly created index is queued up to be inserted into the database asynchronously, or where the implementation might need to ask the user for permission for quota reasons. Such implementations must still create and return an IDBIndex object. Instead, once the implementation realizes that creating the index has failed, it must abort the transaction using the steps for aborting a transaction using the appropriate error as error parameter. For example if creating the index failed due to quota reasons, QuotaError must be used as error and if the index can't be created due to unique constraints, ConstraintError must be used as error.

ParameterTypeNullableOptionalDescription
nameDOMStringThe name of a new index
keyPathanyThe key path used by the new index.
optionalParametersIDBIndexParametersThe options object whose attributes are optional parameters to this function. unique specifies whether the index's unique flag is set. multiEntry specifies whether the index's multiEntry flag is set.
ExceptionDescription
DOMException
InvalidStateErrorThis method was not called from a "versionchange" transaction callback. Also occurs if a request is made on a source object that has been deleted or removed.
ConstraintErrorAn index with the same name, compared in a case-sensitive manner, already exists in the connected database.
Return type: IDBIndex
delete

This method throws a ReadOnlyError if the transaction which this IDBObjectStore belongs to is has its mode set to "readonly". If the key parameter is not a valid key or a key range this method throws a DOMException of type DataError.

Otherwise this method runs the steps for asynchronously executing a request and returns the IDBRequest created by these steps. The steps are run with this IDBObjectStore as source and the steps for deleting records from an object store as operation, using this IDBObjectStore as store and the key parameter as key.

Unlike other methods which take keys or key ranges, this method does not allow null to be passed as key. This is to reduce the risk that a small bug would clear a whole object store.

ParameterTypeNullableOptionalDescription
keyanyKey identifying the record to be deleted
ExceptionDescription
DOMException
TransactionInactiveErrorThe transaction this IDBObjectStore belongs to is not active.
ReadOnlyErrorThe mode of the transaction this IDBObjectStore belongs to is "readonly".
Return type: IDBRequest
deleteIndex

This method destroys the index with the given name in the connected database. Note that this method must only be called from a "versionchange" transaction callback.

This method will synchronously modify the IDBObjectStore.indexNames property.

ParameterTypeNullableOptionalDescription
indexNameDOMStringThe name of an existing index
ExceptionDescription
DOMException
InvalidStateErrorThis method was not called from a "versionchange" transaction callback.
NotFoundErrorThere is no index with the given name, compared in a case-sensitive manner, in the connected database.
Return type: void
get

If the key parameter is not a valid key or a key range, this method throws a DOMException of type DataError. Otherwise, this method runs the steps for asynchronously executing a request and returns the IDBRequest created by these steps. The steps are run with this IDBObjectStore as source and the steps for retrieving a value from an object store as operation, using this IDBObjectStore as store and the key parameter as key.

This function produces the same result if a record with the given key doesn't exist as when a record exists, but has undefined as value. If you need to tell the two situations apart, you can use openCursor with the same key. This will return a cursor with undefined as value if a record exists, or no cursor if no such record exists.

ParameterTypeNullableOptionalDescription
keyanyKey identifying the record to be retrieved. This can also be an IDBKeyRange in which case the function retreives the first existing value in that range.
ExceptionDescription
DOMException
TransactionInactiveErrorThe transaction this IDBObjectStore belongs to is not active.
DataErrorThe key parameter was not passed a valid value.
InvalidStateErrorOccurs if a request is made on a source object that has been deleted or removed.
Return type: IDBRequest
index
Returns an IDBIndex representing an index that is part of the object store. Every call to this function on the same IDBObjectStore instance and with the same name returns the same IDBIndex instance. However the retured IDBIndex instance is specific to this IDBObjectStore instance. If this function is called on a different IDBObjectStore instance, a different IDBIndex instance is returned. A result of this is that different IDBTransactions use different IDBIndex instances to represent the same index.
ParameterTypeNullableOptionalDescription
nameDOMStringThe name of an existing index
ExceptionDescription
DOMException
NotFoundErrorThere is no index with the given name, compared in a case-sensitive manner, in the connected database.
InvalidStateErrorOccurs if a request is made on a source object that has been deleted or removed, or if the transaction the object store belongs to has finished.
Return type: IDBIndex
openCursor

If the range parameter is specified but is not a valid key or a key range, this method throws a DOMException of type DataError. Otherwise, this method creates a cursor. The cursor must implement the IDBCursorWithValue interface.

The newly created cursor must have an undefined position, a direction set to the value of the direction parameter, false as iterable flag value, and undefined key and value. The source of the cursor is the IDBObjectStore this function was called on.

If the range parameter is a key range then the cursor's range must be set to that range. Otherwise, if the range parameter is a valid key then the cursor's range is set to key range containing only that key value. If the range parameter is not specified, the cursor's key range is left as undefined.

This method runs the steps for asynchronously executing a request and returns the IDBRequest created by these steps. The steps are run with this IDBObjectStore as source and the steps for iterating a cursor as operation, using the created cursor as cursor and with undefined as key.

ParameterTypeNullableOptionalDescription
rangeanyThe key range to use as the cursor's range
directionDOMStringThe cursor's required direction
ExceptionDescription
DOMException
TransactionInactiveErrorThe transaction this IDBObjectStore belongs to is not active.
TypeErrorThe value for the direction parameter is invalid.
DataErrorThe range parameter was not passed key range or a valid key.
InvalidStateErrorOccurs if a request is made on a source object that has been deleted or removed.
Return type: IDBRequest
put

This method throws a DOMException of type ReadOnlyError if the transaction which this IDBObjectStore belongs to is has its mode set to "readonly". If any of the following conditions are true, this method throws a DOMException of type DataError:

Otherwise this method creates a structured clone of the value parameter. If the structured clone algorithm throws an exception, that exception is rethrown. Otherwise, run the steps for asynchronously executing a request and return the IDBRequest created by these steps. The steps are run with this IDBObjectStore as source and the steps for storing a record into an object store as operation, using this IDBObjectStore as store, the created clone as value, the key parameter as key, and with the no-overwrite flag flag set to false.

ParameterTypeNullableOptionalDescription
valueanyThe value to be stored in the record
keyanyThe key used to identify the record
ExceptionDescription
DOMException
TransactionInactiveErrorThe transaction this IDBObjectStore belongs to is not active.
ReadOnlyErrorThe mode of the associated transaction is "readonly".
DataErrorThe calculated key for the insertion was not a valid key. Also thrown if the calculated key for any of the indexes which belong to this object store had a calculated key which was not a valid key
InvalidStateErrorOccurs if a request is made on a source object that has been deleted or removed.
DataCloneErrorThe data being stored could not be cloned by the internal structured cloning algorithm.
Return type: IDBRequest

3.2.6 Index

Index objects implement the following interface:

interface IDBIndex {
    readonly attribute DOMString      name;
    readonly attribute IDBObjectStore objectStore;
    readonly attribute DOMString      keyPath;
    readonly attribute boolean        multiEntry;
    readonly attribute boolean        unique;
    IDBRequest openCursor (optional any? range, optional DOMString direction);
    IDBRequest openKeyCursor (optional any? range, optional DOMString direction);
    IDBRequest get (any key);
    IDBRequest getKey (any key);
    IDBRequest count (optional any key);
};
Attributes
keyPath of type DOMString, readonly
On getting, provide the key path of this object store. This will be either a DOMString or an Array of DOMStrings.
No exceptions.
multiEntry of type boolean, readonly
On getting, provide the multiEntry flag of this index.
No exceptions.
name of type DOMString, readonly
On getting, provide the name of this index.
No exceptions.
objectStore of type IDBObjectStore, readonly
On getting, returns a reference to the IDBObjectStore instance for the referenced object store in this IDBIndex's transaction. This must return the same IDBObjectStore instance as was used to get a reference to this IDBIndex.
No exceptions.
unique of type boolean, readonly
On getting, provide the unique flag of this index.
No exceptions.
Methods
count

If the optional key parameter is not a valid key or a key range, this method throws a DOMException of type DataError. This method runs the steps for asynchronously executing a request and returns the IDBRequest created by these steps. The steps are run with this IDBIndex as source and the steps for iterating a cursor as operation, using the created cursor as cursor. If provided, use the key parameter as key, otherwise, use undefined as key. If the result of the algorithm is null return 0 (zero) as the result for the request. Otherwise, use the return cursor to determine the total number of objects that share the key or key range and return that value as the result for the request.

ParameterTypeNullableOptionalDescription
keyany Key identifying the record to be retrieved. This can also be an IDBKeyRange.
ExceptionDescription
DOMException
TransactionInactiveErrorThe transaction this IDBIndex belongs to is not active.
DataErrorThe key parameter is not a valid key or a key range.
InvalidStateErrorOccurs if a request is made on a source object that has been deleted or removed.
Return type: IDBRequest
get

If the key parameter is not a valid key or a key range, this method throws a DOMException of type DataError. This method runs the steps for asynchronously executing a request and returns the IDBRequest created by these steps. The steps are run with this IDBObjectStore as source and the steps for retrieving a referenced value from an index as operation, using this IDBIndex as index and the key parameter as key.

This function produces the same result if a record with the given key doesn't exist as when a record exists, but has undefined as value. If you need to tell the two situations apart, you can use openCursor with the same key. This will return a cursor with undefined as value if a record exists, or no cursor if no such record exists.

ParameterTypeNullableOptionalDescription
keyanyKey identifying the record to be retrieved. This can also be an IDBKeyRange in which case the function retreives the first existing value in that range.
ExceptionDescription
DOMException
TransactionInactiveErrorThe transaction this IDBIndex belongs to is not active.
DataErrorThe key parameter was not passed a valid value.
InvalidStateErrorOccurs if a request is made on a source object that has been deleted or removed.
Return type: IDBRequest
getKey

If the key parameter is not a valid key or a key range, this method throws a DOMException of type DataError. This method runs the steps for asynchronously executing a request and returns the IDBRequest created by these steps. The steps are run with this IDBObjectStore as source and the steps for retrieving a value from an index as operation, using this IDBIndex as index and the key parameter as key.

ParameterTypeNullableOptionalDescription
keyanyKey identifying the record to be retrieved. This can also be an IDBKeyRange in which case the function retreives the first existing value in that range.
ExceptionDescription
DOMException
TransactionInactiveErrorThe transaction this IDBIndex belongs to is not active.
DataErrorThe key parameter was not passed a valid value.
InvalidStateErrorOccurs if a request is made on a source object that has been deleted or removed.
Return type: IDBRequest
openCursor

If the range parameter is specified but is not a valid key or a key range, this method throws a DOMException of type DataError. Otherwise, this method creates a cursor. The cursor must implement the IDBCursorWithValue interface.

The newly created cursor must have an undefined position, a direction set to the value of the direction parameter, false as iterable flag value, and undefined key and value. The source of the cursor is the IDBIndex this function was called on.

If the range parameter is a key range then the cursor's range is set to that range. Otherwise, if the range parameter is a valid key then the cursor's range is set to key range containing only that key value. If the range parameter is not specified, the cursor's key range is left as undefined.

This method runs the steps for asynchronously executing a request and returns the IDBRequest created by these steps. The steps are run with this IDBIndex as source and the steps for iterating a cursor as operation, using the created cursor as cursor and with undefined as key

ParameterTypeNullableOptionalDescription
rangeanyThe key range to use as the cursor's range
directionDOMStringThe cursor's required direction
ExceptionDescription
DOMException
TransactionInactiveErrorThe transaction this IDBIndex belongs to is not active.
TypeErrorThe value for the direction parameter is invalid.
DataErrorThe range parameter was not passed key range or a valid key.
InvalidStateErrorOccurs if a request is made on a source object that has been deleted or removed.
Return type: IDBRequest
openKeyCursor

If the range parameter is specified but is not a valid key or a key range, this method throws a DOMException of type DataError. Otherwise, this method creates a cursor. The cursor must implement the IDBCursor interface, but must not implement the IDBCursorWithValue interface.

The newly created cursor must have an undefined position, a direction set to the value of the direction parameter, false as iterable flag value, and undefined key and value. The source of the cursor is the IDBIndex this function was called on.

If the range parameter is a key range then the cursor's range is set to that range. Otherwise, if the range parameter is a valid key then the cursor's range is set to key range containing only that key value. If the range parameter is not specified, the cursor's key range is left as undefined.

This method runs the steps for asynchronously executing a request and returns the IDBRequest created by these steps. The steps are run with this IDBObjectStore as source and the steps for iterating a cursor as operation, using the created cursor as cursor and with undefined as key

ParameterTypeNullableOptionalDescription
rangeanyThe key range to use as the cursor's range
directionDOMStringThe cursor's required direction
ExceptionDescription
DOMException
TransactionInactiveErrorThe transaction this IDBIndex belongs to is not active.
TypeErrorThe value for the direction parameter is invalid.
DataErrorThe range parameter was not passed key range or a valid key.
InvalidStateErrorOccurs if a request is made on a source object that has been deleted or removed.
Return type: IDBRequest

3.2.7 Cursor

Cursor objects implement the following interface:

interface IDBCursor {
    readonly attribute Object    source;
    readonly attribute DOMString direction;
    readonly attribute any       key;
    readonly attribute any       primaryKey;
    IDBRequest update (any value);
    void       advance ([EnforceRange] unsigned long count);
    void       continue (optional any key);
    IDBRequest delete ();
};
Attributes
direction of type DOMString, readonly
On getting, provide the traversal direction of the cursor.
No exceptions.
key of type any, readonly
Returns the cursor's current key. Note that if this property returns an object (specifically an Array), it returns the same object instance every time it is inspected, until the cursor's key is changed. This means that if the object is modified, those modifications will be seen by anyone inspecting the value of the cursor. However modifying such an object does not modify the contents of the database.
No exceptions.
primaryKey of type any, readonly
Returns the cursor's current effective key. Note that if this property returns an object (specifically an Array), it returns the same object instance every time it is inspected, until the cursor's effective key is changed. This means that if the object is modified, those modifications will be seen by anyone inspecting the value of the cursor. However modifying such an object does not modify the contents of the database.
No exceptions.
source of type Object, readonly
On getting, returns the IDBObjectStore or IDBIndex which this cursor is iterating. This function never returns null or throws an exception, even if the cursor is currently being iterated, has iterated past its end, or its transaction is not active.
No exceptions.
Methods
advance

This method runs the steps for asynchronously executing a request. However, the steps are slightly modified such that instead of creating a new IDBRequest, it reuses the request originally created when this cursor was created. The done flag on the request is set to false before the request is returned. The steps are run with the cursor's source as source. The operation runs the steps for iterating a cursor count number of times with null as key and this cursor as cursor.

Before this method returns, unless an exception was thrown, it sets the got value flag on the cursor to false.

Calling this method more than once before new cursor data has been loaded is not allowed and results in a DOMException of type InvalidStateError being thrown. For example, calling advance() twice from the same onsuccess handler results in a DOMException of type InvalidStateError being thrown on the second call.

If the value for count is 0 (zero) or a negative number, this method must throw a JavaScript TypeError exception.

ParameterTypeNullableOptionalDescription
countunsigned longThe number of advances forward the cursor should make.
ExceptionDescription
DOMException
TypeErrorThe value passed into the count parameter was zero or a negative number.
TransactionInactiveErrorThe transaction this IDBCursor belongs to is not active.
InvalidStateErrorThe cursor is currently being iterated, or has iterated past its end.
Return type: void
continue

If this cursor's got value flag is false, this method throws a DOMException of type InvalidStateError. If the key parameter is specified and fulfills any of these conditions this method must throw a DOMException of type DataError:

Otherwise this method runs the steps for asynchronously executing a request. However, the steps are slightly modified such that instead of creating a new IDBRequest, it reuses the request originally created when this cursor was created. The done flag on the request is set to false before the request is returned. The steps are run with the cursor's source as source and the steps for iterating a cursor as operation, using this cursor as cursor and the key parameter as key.

Before this method returns, unless an exception was thrown, it sets the got value flag on the cursor to false.

Calling this method more than once before new cursor data has been loaded is not allowed and results in a DOMException of type InvalidStateError being thrown. For example, calling continue() twice from the same onsuccess handler results in a DOMException of type InvalidStateError being thrown on the second call.

ParameterTypeNullableOptionalDescription
keyanyThe next key to position this cursor at
ExceptionDescription
DOMException
TransactionInactiveErrorThe transaction this IDBCursor belongs to is not active.
InvalidStateErrorThe cursor is currently being iterated, or has iterated past its end.
DataErrorThe key parameter was specified but did not contain a valid key.
Return type: void
delete

This method throws a DOMException of type ReadOnlyError if the transaction which this IDBCursor belongs to has its mode set to "readonly". If this cursor's got value flag is false, or if this cursor was created using openKeyCursor a DOMException of type InvalidStateError is thrown.

Otherwise this method runs the steps for asynchronously executing a request and returns the IDBRequest created by these steps. The steps are run with this IDBCursor as source and the steps for deleting records from an object store as operation, using this cursor's effective object store and effective key as store and key respectively.

No parameters.
ExceptionDescription
DOMException
TransactionInactiveErrorThe transaction this IDBCursor belongs to is not active.
ReadOnlyErrorThe mode of the transaction this IDBCursor belongs to is "readonly".
InvalidStateErrorThe cursor was created using openKeyCursor or the cursor is currently being iterated or has iterated past the end.
Return type: IDBRequest
update

This method throws a DOMException of type ReadOnlyError if the transaction which this IDBCursor belongs to has its mode set to "readonly". If this cursor's got value flag is false or if this cursor was created using openKeyCursor. This method throws a DOMException of type InvalidStateError. If the effective object store of this cursor uses in-line keys and evaluating the key path of the value parameter results in a different value than the cursor's effective key, this method throws a DOMException of type DataError.

Otherwise this method creates a structured clone of the value parameter. If the structured clone algorithm throws an exception, that exception is rethrown. Otherwise, run the steps for asynchronously executing a request and return the IDBRequest created by these steps. The steps are run with this IDBCursor as source and the steps for storing a record into an object store as operation, using this cursor's effective object store as store, the created clone as value, this cursor's effective key as key, and with the no-overwrite flag flag set to false.

A result of running the steps for storing a record into an object store is that if the record has been deleted since the cursor moved to it, a new record will be created.

ParameterTypeNullableOptionalDescription
valueanyThe new value to store at the current position.
ExceptionDescription
DOMException
TransactionInactiveErrorThe transaction this IDBCursor belongs to is not active.
ReadOnlyErrorThe mode of the transaction this IDBCursor belongs to is "readonly"
InvalidStateErrorThrown if cursor was created using openKeyCursor or if the cursor is currently being iterated or has iterated past the end.
DataError The underlying object store uses in-line keys and the property in value at the object store's key path does not match the key in this cursor's position.
DataCloneErrorThe data being stored could not be cloned by the internal structured cloning algorithm.
Return type: IDBRequest
interface IDBCursorWithValue : IDBCursor {
    readonly attribute any value;
};
Attributes
value of type any, readonly
Returns the cursor's current value. Note that if this property returns an object, it returns the same object instance every time it is inspected, until the cursor's value is changed. This means that if the object is modified, those modifications will be seen by anyone inspecting the value of the cursor. However modifying such an object does not modify the contents of the database.
No exceptions.

3.2.8 Transaction

Transaction objects implement the following interface:

interface IDBTransaction : EventTarget {
    readonly attribute DOMString   mode;
    readonly attribute IDBDatabase db;
    readonly attribute DOMError    error;
    IDBObjectStore objectStore (DOMString name);
    void           abort ();
    [TreatNonCallableAsNull]
             attribute Function?   onabort;
    [TreatNonCallableAsNull]
             attribute Function?   oncomplete;
    [TreatNonCallableAsNull]
             attribute Function?   onerror;
};
Attributes
db of type IDBDatabase, readonly
The database connection of which this transaction is a part
No exceptions.
error of type DOMError, readonly
When the done flag is true, getting this property must return the error of the request that caused the transaction to be aborted. If the error was generated when committing the transaction and not from an individual request, the error must contain the reasons for the transaction failure (e.g. QuotaExceededError, UnknownError). This is null when no error occurred or when the transaction is programmatically aborted. When the done flag is false, getting this property must throw a DOMException of type InvalidStateError.
ExceptionOn GetOn SetDescription
DOMException
InvalidStateErrorThrown when this attribute was read when the done flag was set to false.
mode of type DOMString, readonly
On getting, provide the mode for isolating access to data inside the object stores that are in the scope of the transaction.
No exceptions.
onabort of type Function, nullable
The event handler for the abort event.
No exceptions.
oncomplete of type Function, nullable
The event handler for the complete event.
No exceptions.
onerror of type Function, nullable
The event handler for the error event.
No exceptions.
Methods
abort
If this transaction is finished, throw a DOMException of type InvalidStateError. Otherwise this method sets the transaction's active flag to false and aborts the transaction by running the steps for aborting a transaction with the error parameter set to null.
No parameters.
ExceptionDescription
DOMException
InvalidStateErrorIf this transaction has already been committed or aborted.
Return type: void
objectStore
Returns an IDBObjectStore representing an object store that is part of the scope of this transaction. Every call to this function on the same IDBTransaction instance and with the same name returns the same IDBObjectStore instance. However the returned IDBObjectStore instance is specific to this IDBTransaction. If this function is called on a different IDBTransaction, a different IDBObjectStore instance is returned.
ParameterTypeNullableOptionalDescription
nameDOMStringThe requested object store
ExceptionDescription
DOMException
NotFoundError If the requested object store is not in this transaction's scope.
InvalidStateErrorOccurs if a request is made on a source object that has been deleted or removed, or if the transaction has finished.
Return type: IDBObjectStore

3.3 Synchronous APIs

The features in Section 3.3 Synchronous APIs are at risk and may be removed, due to potential lack of implementations.

The synchronous database API methods provide a blocking access pattern to IndexedDB databases. Since they block the calling thread they are only available from workers.

3.3.1 Opening a database

WorkerUtils objects must implement the IDBEnvironmentSync interface.

WorkerUtils implements IDBEnvironmentSync;
[NoInterfaceObject]
interface IDBEnvironmentSync {
    readonly attribute IDBFactorySync indexedDBSync;
};
Attributes
indexedDBSync of type IDBFactorySync, readonly
This attribute provides applications a mechanism for accessing capabilities of indexed databases.
No exceptions.
interface IDBFactorySync {
    IDBDatabaseSync open (DOMString name, [EnforceRange] optional unsigned long long version, optional IDBVersionChangeCallback upgradeCallback, optional unsigned long timeout);
    void            deleteDatabase (DOMString name);
    short           cmp (any first, any second);
};
Methods
cmp

When invoked, this method must compare two keys. The method returns 1 if the first key is greater than the second, -1 if the first is less than the second, and 0 if the first is equal to the second.

ParameterTypeNullableOptionalDescription
firstanyThe first key to compare.
secondanyThe second key to compare.
ExceptionDescription
DOMException
DataErrorOne of the supplied keys was not a valid key.
Return type: short
deleteDatabase

When invoked, this method synchronously runs the steps for deleting a database. Let origin be the origin of the IDBEnvironmentSync used to access this IDBFactorySync and name be the name argument passed to this function.

If an error is returned from the steps above, then the implementation must throw a DOMException with its name and message set to appropriate values for the error.

ParameterTypeNullableOptionalDescription
nameDOMStringThe name of the database to be deleted.
No exceptions.
Return type: void
open

When invoked, this method must throw a DOMException of type InvalidStateError when it is called within the IDBTransactionCallback of a transaction method or the IDBVersionChangeCallback of a open method. Otherwise this method synchronously runs the steps for opening a database. Let origin be the origin of the IDBEnvironmentSync used to access this IDBFactorySync, name, version and upgrade callback be the name, version and upgradeCallback arguments passed to this function.

If no version is specified and a database exists, use the current database version and follow the steps for opening a database. If no version is specified and no database exists, set database version to 1, follow the steps for opening a database, and return a database without object stores.

If a timeout parameter was supplied, then this limits the total waiting time allowed in step 3 of steps for opening a database and step 4 of the steps for running a "versionchange" transaction. If more waiting time would be needed in order to progress, then abort those algorithms and throw a DOMException of type TimeoutError.

The timeout parameter does not affect how long the upgradeCallback can run.

If an error is returned from the steps above, then the implementation must throw a DOMException with its name and message set to appropriate values for the error.

If the steps above are successful, the implementation must create an IDBDatabaseSync object representing the created connection and return it.

Processing a open call may take a long time as it could require running a "versionchange" transaction which requires all other connections to the database to be closed, which in turn may depend on user input or other long-running tasks. If blocking for a long period of time is not acceptable for a given scenario then the asynchronous API should be used for version changes.

If the value for version is 0 (zero) or a negative number, this method must throw a JavaScript TypeError exception.

ParameterTypeNullableOptionalDescription
nameDOMStringThe name for the database
versionunsigned long longThe version for the database
upgradeCallbackIDBVersionChangeCallbackCallback used if the database version needs to be upgraded before the database can be opened.
timeoutunsigned longDefines a transaction timeout value in milliseconds that will limit the how long waiting for the "versionchange" transaction. If the parameter is not provided, the value of timeout is infinite.
ExceptionDescription
DOMException
InvalidStateError The open method was called within the IDBTransactionCallback of a transaction method or IDBVersionChangeCallback of a open method.
TimeoutError Was unable to open the database with the requested version within the given timeout period.
TypeErrorThe value of version is 0 (zero) or a negative number.
Return type: IDBDatabaseSync

3.3.2 Database

A database object provides access to the schema and data of a particular database.

interface IDBDatabaseSync {
    readonly attribute DOMString          name;
    readonly attribute unsigned long long version;
    readonly attribute DOMStringList      objectStoreNames;
    IDBObjectStoreSync createObjectStore (DOMString name, optional IDBObjectStoreParameters optionalParameters);
    void               deleteObjectStore (DOMString name);
    void               transaction (any storeNames, IDBTransactionCallback callback, optional DOMString mode, optional unsigned long timeout);
    void               close ();
};
Attributes
name of type DOMString, readonly
On getting, this attribute must return the name of the connected database. The function must return this name even if the closePending flag is set on the connection. In other words, the return value from this function stays constant for the lifetime of the IDBDatabaseSync instance.
No exceptions.
objectStoreNames of type DOMStringList, readonly
On getting, this attribute must return a list of names of the object stores currently in the connected database. The list must be sorted in ascending order using the algorithm defined by step 4 of section 11.8.5, The Abstract Relational Comparison Algorithm of the ECMAScript Language Specification [ECMA-262]. Once the closePending flag is set on the connection, this function must return a snapshot of the list of names of the object stores taken at the time when the close method was called. Even if other connections are later used to change the set of object stores that exist in the database. In other words, the return value from this function stays constant for the lifetime of the IDBDatabaseSync instance except during a "versionchange" transaction if createObjectStore or deleteObjectStore is called on this IDBDatabaseSync instance itself.
No exceptions.
version of type unsigned long long, readonly
On getting, this attribute must return the version of the database when this IDBDatabaseSync instance was created. When a IDBDatabaseSync instance is created, this is always the number passed as the version argument passed to the open call used to create the IDBDatabaseSync instance. This value remains constant for the lifetime of the IDBDatabaseSync object. If the connection is closed, this attribute represents a snapshot of the version that the database had when the connection was closed. Even if another connection is later used to modify the version, that attribute on closed instances are not changed.
No exceptions.
Methods
close
This method synchronously performs the steps for closing a database connection and returns once the database has been closed.
No parameters.
No exceptions.
Return type: void
createObjectStore

This method creates and returns a new object store with the given name in the connected database. This method should only be called from inside a "versionchange" transaction.

This method synchronously modifies the IDBDatabaseSync.objectStoreNames property. However it only modifies the IDBDatabaseSync.objectStoreNames property on the IDBDatabaseSync instance on which it was called.

If the optionalParameters argument is specified and has a keyPath property which is not null, then set keyPath to the value of this property. If keyPath is an Array, then each item in the array is converted to a string. If keyPath is not an Array, it is converted to a string.

If keyPath is an Array and any items in the array is not a valid key path, or if keyPath is a string and is not a valid key path then a DOMException of type SyntaxError must be thrown. Otherwise set the created object store's key path is set to the value of keyPath.

If the optionalParameters parameter is specified, and autoIncrement is set to true, and the keyPath parameter is specified to the empty string, or specified to an Array, this function must throw a InvalidAccessError exception.

ParameterTypeNullableOptionalDescription
nameDOMStringThe name of a new object store
optionalParametersIDBObjectStoreParametersThe options object whose attributes are optional parameters to this function. keyPath specifies the key path of the new object store. If the attribute is null no key path is specified and thus keys are out-of-line. autoIncrement specifies whether the object store created should have a key generator.
ExceptionDescription
DOMException
InvalidStateError This method was not called from a "versionchange" transaction. Also occurs if a request is made on a source object that has been deleted or removed.
ConstraintErrorIf an object store with the same name, compared in a case-sensitive manner, already exists in the connected database.
InvalidAccessErrorIf autoIncrement is set to true, and keyPath either is the empty string, or an Array containing the empty string.
Return type: IDBObjectStoreSync
deleteObjectStore

This method destroys an object store with the given name as well as all indexes that are referencing that object store. This method should only be called from inside a "versionchange" transaction.

This method synchronously modifies the IDBDatabaseSync.objectStoreNames property. However it only modifies the IDBDatabaseSync.objectStoreNames property on the IDBDatabaseSync instance on which it was called.

ParameterTypeNullableOptionalDescription
nameDOMStringThe name of an existing object store
ExceptionDescription
DOMException
InvalidStateError This method was not called from a "versionchange" transaction callback. Also occurs if a request is made on a source object that has been deleted or removed.
NotFoundError If the object store with the given name, compared in a case-sensitive manner, does not already exist in the connected database.
Return type: void
transaction

This method, when called must execute the steps for creating a transaction in a sychronous fashion. The storeNames, callback, mode, and timeout arguments are forwarded to the algorithm as-is. The connection argument is set to the IDBDatabaseSync that the transaction() method was called on.

The method returns an IDBTransactionSync object representing the transaction returned by the steps above.

This method must throw an DOMException of type InvalidStateError when it is called within the IDBTransactionCallback of a transaction method or the IDBVersionChangeCallback of a open method.

ParameterTypeNullableOptionalDescription
storeNamesanyThe names of object stores and indexes in the scope of the new transaction
callbackIDBTransactionCallbackA callback which will be called with the newly created transaction. When the callback returns, the transaction is committed.
modeDOMString The mode for isolating access to data inside the given object stores. If this parameter is not provided, the default access mode is "readonly".
timeoutunsigned longThe interval in milliseconds which this operation is allowed to take to reserve all the database objects identified in the new transaction's scope. The default is user agent specific
ExceptionDescription
DOMException
TimeoutError If starting the transaction takes longer than the specified timeout.
InvalidStateError The close() method has been called on this IDBDatabase instance. Also thrown when The transaction() method was called within the IDBTransactionCallback of a transaction method or the IDBVersionChangeCallback of a open method.
NotFoundErrorOne of the names provided in the storeNames argument doesn't exist in this database.
TypeErrorThe value for the mode parameter is invalid.
InvalidAccessErrorThe function was called with an empty list of store names
Return type: void
[NoInterfaceObject, Callback]
interface IDBTransactionCallback {
    void transactionStarted (IDBTransactionSync transaction);
};
Methods
transactionStarted
Called once the transaction is allowed to run. The actions taken in this function make up the body of the transaction.
ParameterTypeNullableOptionalDescription
transactionIDBTransactionSyncThe newly started transaction
No exceptions.
Return type: void
[NoInterfaceObject, Callback]
interface IDBVersionChangeCallback {
    void transactionStarted (IDBTransactionSync transaction, unsigned long long oldVersion);
};
Methods
transactionStarted
Called if a database upgrade is needed once the transaction used to upgrade the database is allowed to run. The actions taken in this function make up the body of the transaction.
ParameterTypeNullableOptionalDescription
transactionIDBTransactionSyncThe newly started transaction
oldVersionunsigned long longThe version that the database had before the upgrade was needed. 0 if the database was newly created.
No exceptions.
Return type: void

3.3.3 Object Store

Example

In the following example, we set up an object store to use the key path id. This object store is also designed to use a key generator.

ECMAScript
var db = indexedDBSync.open('AddressBook', 1, function(trans, oldVersion) {
trans.db.createObjectStore('Contact', {keyPath:'id', autoIncrement:true} );
});
            

Using this database, we can store records in the Contact object store.

ECMAScript
var tx = db.transaction();
var store = tx.objectStore('Contact');
var contact = store.add({name: 'Lincoln', number: '7012'});
// contact.id === 1
            

A stored value can be retrieved using the same key used by the first put operation.

ECMAScript
var contact = store.get(1);
// contact.name === 'Lincoln'

A put operation will overwrite the record stored by the first add operation with the same key.

ECMAScript
var abraham = {id: 1, name: 'Abraham', number: '2107'};
store.put(abraham);

Now when the object store is read with the same key, the result is different compared to the object read earlier.

ECMAScript
var contact = store.get(1);
// contact.id === 1 && contact.name === 'Abraham';

Additionally, all the records of an object store matching a certain key range can be retrieved in key order.

ECMAScript
var range = new IDBKeyRange.bound(2, 4);
var cursor = store.openCursor(range);
// each value is a contact and each key is the id for that  
// contact whose id is between 2 and 4, both inclusive
cursor.continue();
interface IDBObjectStoreSync {
    readonly attribute DOMString          name;
    readonly attribute any                keyPath;
    readonly attribute DOMStringList      indexNames;
    readonly attribute IDBTransactionSync transaction;
    readonly attribute boolean            autoIncremenent;;
    any                    put (any value, optional any key);
    any                    add (any value, optional any key);
    boolean                delete (any key);
    any                    get (any key);
    void                   clear ();
    IDBIndexSync           createIndex (DOMString name, any keyPath, optional IDBIndexParameters optionalParameters);
    IDBIndexSync           index (DOMString name);
    void                   deleteIndex (DOMString indexName);
    IDBCursorWithValueSync openCursor (optional any? range, optional DOMString direction);
    unsigned long          count (optional any key);
};
Attributes
autoIncremenent; of type boolean, readonly
On getting, provides the auto increment flag for this object store.
No exceptions.
indexNames of type DOMStringList, readonly
On getting, provide a list of the names of indexes on objects in this object store. The list must be sorted in ascending order using the algorithm defined by step 4 of section 11.8.5, The Abstract Relational Comparison Algorithm of the ECMAScript Language Specification [ECMA-262].
No exceptions.
keyPath of type any, readonly
On getting, provide the key path of this object store. This will be either a DOMString, an Array of DOMStrings or null.
No exceptions.
name of type DOMString, readonly
On getting, provide the name of this object store.
No exceptions.
transaction of type IDBTransactionSync, readonly
On getting, returns the transaction this object store belongs to.
No exceptions.
Methods
add

This method throws a DOMException of type ReadOnlyError if the transaction which this IDBObjectStoreSync belongs to is has its mode set to "readonly". If any of the following conditions are true, this method throws a DOMException of type DataError:

Otherwise this method creates a structured clone of the value parameter. If the structured clone algorithm throws an exception, that exception is rethrown. Otherwise, run the steps for synchronously executing a request and return the key of the stored object. The steps are run with this IDBObjectStoreSync as source and the steps for storing a record into an object store as operation, using this IDBObjectStoreSync as store, the created clone as value, the key parameter as key, and with the no-overwrite flag flag set to true.

ParameterTypeNullableOptionalDescription
valueanyThe value to be stored in the record
keyanyThe key used to identify the record
ExceptionDescription
DOMException
TransactionInactiveErrorThe transaction this IDBObjectStoreSync belongs to is not active.
ReadOnlyErrorThe mode of the associated transaction is "readonly".
DataErrorThe calculated key for the insertion was not a valid key. Also thrown if the calculated key for any of the indexes which belong to this object store had a calculated key which was not a valid key
ConstraintErrorA record exists in this object store for the key key parameter, or another record in this object store has the same value for the keyPath of a unique index.
InvalidStateErrorOccurs if a request is made on a source object that has been deleted or removed.
DataCloneErrorThe data being stored could not be cloned by the internal structured cloning algorithm.
Return type: any
clear

This method throws a DOMException of type ReadOnlyError if the transaction which this IDBObjectStoreSync belongs to is has its mode set to "readonly".

Otherwise this method runs the steps for synchronously executing a request. The steps are run with this IDBObjectStoreSync as source and the steps for clearing an object store as operation, using this IDBObjectStoreSync as store.

No parameters.
ExceptionDescription
DOMException
TransactionInactiveErrorThe transaction this IDBObjectStoreSync belongs to is not active.
ReadOnlyErrorThe mode of the transaction this IDBObjectStoreSync belongs to is "readonly".
InvalidStateErrorOccurs if a request is made on a source object that has been deleted or removed.
Return type: void
count

If the optional key parameter is not a valid key or a key range, this method throws a DOMException of type DataError. This method runs the steps for asynchronously executing a request and returns the IDBRequest created by these steps. The steps are run with this IDBObjectStore as source and the steps for iterating a cursor as operation, using the created cursor as cursor. If provided, use the key parameter as key, otherwise, use undefined as key. If the result of the algorithm is null return 0 (zero) as the result for the request. Otherwise, use the return cursor to determine the total number of objects that share the key or key range and return that value as the result for the request.

ParameterTypeNullableOptionalDescription
keyany Key identifying the record to be retrieved. This can also be an IDBKeyRange.
ExceptionDescription
DOMException
TransactionInactiveErrorThe transaction this IDBObjectStoreSync belongs to is not active.
DataErrorThe key parameter is not a valid key or a key range.
InvalidStateErrorOccurs if a request is made on a source object that has been deleted or removed.
Return type: unsigned long
createIndex

This creates and returns a new index with the given name and parameters in the connected database. Note that this method must only be called from a "versionchange" transaction. The created index has its unique and multiEntry flags are set to the values of the unique and multiEntry properties in the optionalParameters argument.

If the keyPath argument is an Array, then each item in the array is converted to a DOMString. If keyPath is not an Array, it is converted to a DOMString.

If keyPath is an Array and any items in the array is not a valid key path, or if keyPath is a string and is not a valid key path, then a DOMException of type SyntaxError must be thrown. If keyPath is and Array and the multiEntry property in the optionalParameters is true, then a DOMException of type NotSupportedError must be thrown. Otherwise set the created object store's key path is set to the value of keyPath.

ParameterTypeNullableOptionalDescription
nameDOMStringThe name of a new index
keyPathanyThe key path used by the new index
optionalParametersIDBIndexParametersThe options object whose attributes are optional parameters to this function. unique specifies whether the index's unique flag is set. multiEntry specifies whether the index's multiEntry flag is set.
ExceptionDescription
DOMException
InvalidStateErrorThis method was not called from a "versionchange" transaction. Also occurs if a request is made on a source object that has been deleted or removed.
ConstraintErrorAn index with the same name, compared in a case-sensitive manner, already exists in the connected database. Also thrown when creating a unique index on top of an object store that already contains records that violate the unique constraint.
Return type: IDBIndexSync
delete

This method throws a DOMException of type ReadOnlyError if the transaction which this IDBObjectStoreSync belongs to is has its mode set to "readonly". If the key parameter is not a valid key or a key range this method throws a DOMException of type DataError.

Otherwise this method runs the steps for synchronously executing a request. The steps are run with this IDBObjectStoreSync as source and the steps for deleting records from an object store as operation, using this IDBObjectStoreSync as store and the key parameter as key. The function returns the result of running these steps.

Unlike other methods which take keys or key ranges, this method does not allow null to be passed as key. This is to reduce the risk that a small bug would clear a whole object store.

ParameterTypeNullableOptionalDescription
keyanyKey identifying the record to be deleted
ExceptionDescription
DOMException
TransactionInactiveErrorThe transaction this IDBObjectStoreSync belongs to is not active.
ReadOnlyErrorThe mode of the transaction this IDBObjectStoreSync belongs to is "readonly".
NotFoundErrorA record did not exist in this object store for the key key parameter.
Return type: boolean
deleteIndex

This method destroys the index with the given name in the connected database. Note that this method must only be called from a "versionchange" transaction.

ParameterTypeNullableOptionalDescription
indexNameDOMStringThe name of an existing index
ExceptionDescription
DOMException
NotFoundError If the index with the given name does not exist in the connected database.
InvalidStateErrorThis method was not called from a "versionchange" transaction.
Return type: void
get

If the key parameter is not a valid key or a key range, this method throws a DOMException of type DataError. Otherwise, this method runs the steps for synchronously executing a request and returns the result of the operation. The steps are run with this IDBObjectStoreSync as source and the steps for retrieving a value from an object store as operation, using this IDBObjectStoreSync as store and the key parameter as key.

This function produces the same result if a record with the given key doesn't exist as when a record exists, but has undefined as value. If you need to tell the two situations apart, you can use openCursor with the same key. This will return a cursor with undefined as value if a record exists, or no cursor if no such record exists.

ParameterTypeNullableOptionalDescription
keyanyKey identifying the record to be retrieved. This can also be an IDBKeyRange in which case the function retrieves the first existing value in that range.
ExceptionDescription
DOMException
TransactionInactiveErrorThe transaction this IDBObjectStoreSync belongs to is not active.
DataErrorThe key parameter was not passed a valid value.
InvalidStateErrorOccurs if a request is made on a source object that has been deleted or removed.
Return type: any
index
Returns an IDBIndexSync representing an index that is part of the object store. Every call to this function on the same IDBObjectStoreSync instance and with the same name returns the same IDBIndexSync instance. However the retured IDBIndexSync instance is specific to this IDBObjectStoreSync instance. If this function is called on a different IDBObjectStoreSync instance, a different IDBIndexSync instance is returned. A result of this is that different IDBTransactionSyncs use different IDBIndexSync instances to represent the same index.
ParameterTypeNullableOptionalDescription
nameDOMStringThe name of an existing index
ExceptionDescription
DOMException
NotFoundError If the index with the given name does not exist in the connected database.
InvalidStateErrorOccurs if a request is made on a source object that has been deleted or removed, or if the transaction the object store belongs to has finished.
Return type: IDBIndexSync
openCursor

If the range parameter is specified but is not a valid key or a key range, this method throws a DOMException of type DataError. Otherwise, this method creates a cursor. The cursor must implement the IDBCursorWithValueSync interface.

The newly created cursor must have an undefined position, a direction set to the value of the direction parameter, false as iterable flag value, and undefined key and value. The source of the cursor is the IDBObjectStoreSync this function was called on.

If the range parameter is a key range then the cursor's range is set to that range. Otherwise, if the range parameter is a valid key then the cursor's range is set to key range containing only that key value. If the range parameter is not specified, the cursor's key range is left as undefined.

This method runs the steps for synchronously executing a request and returns the result of the operation, in this case an IDBCursorSync object. The steps are run with this IDBObjectStoreSync as source and the steps for iterating a cursor as operation, using the created cursor as cursor and with undefined as key.

ParameterTypeNullableOptionalDescription
rangeanyThe key range to use as the cursor's range
directionDOMStringThe cursor's required direction
ExceptionDescription
DOMException
TransactionInactiveErrorThe transaction this IDBObjectStoreSync belongs to is not active.
TypeErrorThe value for the direction parameter is invalid.
DataErrorThe range parameter was not passed key range or a valid key.
InvalidStateErrorOccurs if a request is made on a source object that has been deleted or removed.
put

This method throws a DOMException of type ReadOnlyError if the transaction which this IDBObjectStoreSync belongs to has its mode set to "readonly". If any of the following conditions are true, this method throws a DOMException of type DataError:

Otherwise this method creates a structured clone of the value parameter. If the structured clone algorithm throws an exception, that exception is rethrown. Otherwise, run the steps for synchronously executing a request and return the result, in this case the key of the stored object. The steps are run with this IDBObjectStoreSync as source and the steps for storing a record into an object store as operation, using this IDBObjectStoreSync as store, the created clone as value, the key parameter as key, and with the no-overwrite flag flag set to false.

ParameterTypeNullableOptionalDescription
valueanyThe value to be stored in the record
keyanyThe key used to identify the record
ExceptionDescription
DOMException
TransactionInactiveErrorThe transaction this IDBObjectStoreSync belongs to is not active.
ReadOnlyErrorThe mode of the associated transaction is "readonly".
DataErrorThe calculated key for the insertion was not a valid key. Also thrown if the calculated key for any of the indexes which belong to this object store had a calculated key which was not a valid key
ConstraintErrorAnother record in this object store has the same value for the keyPath of a unique index.
InvalidStateErrorOccurs if a request is made on a source object that has been deleted or removed.
DataCloneErrorThe data being stored could not be cloned by the internal structured cloning algorithm.
Return type: any

3.3.4 Index

Example

An index can be created for retrieving records other than by using record keys. Continuing the earlier example, an index could be maintained on the name property of objects in the Contact object store.

ECMAScript
var db = indexedDBSync.open('AddressBook', 2, function(trans, oldVersion) {
  if (oldVersion === 1) {
    trans.db.createObjectStore('Contact', {keyPath:'id', autoIncrement:true});
  }
  var store = vtx.objectStore('Contact');
  store.createIndex('ContactName', {unique:false, multiEntry:false});
});

For example, the id of an object with the name property value 'Lincoln' can be retrieved using the ContactName index.

ECMAScript
var index = store.openIndex('ContactName');
var id = index.get('Lincoln');
// id === 1

Additionally, all the records of an object store matching a certain range index keys can be retrieved in key order. When objects are retrieved from the Contact object store, they are arranged by the value of the id attribute. On the other hand, when objects are retrieved using the ContactName index, they are arranged by the value of the name property.

ECMAScript
var range = new IDBKeyRange.bound('L', 'M');
var cursor = index.openCursor(range);
// each value is a contact and each key is the name for that  
// contact whose name's first letter is either L or M
cursor.continue();

If, on the other hand, we only want the names and keys but not the whole Contact objects for a given range, then we can use a different mechanism for that.

ECMAScript
var range = new IDBKeyRange.bound('L', 'M');
var cursor = index.openKeyCursor(range);
// each value is a contact id and each key is the name for that  
// contact whose name's first letter is either L or M
cursor.continue();
interface IDBIndexSync {
    readonly attribute DOMString          name;
    readonly attribute IDBObjectStoreSync objectStore;
    readonly attribute any                keyPath;
    readonly attribute boolean            multiEntry;
    readonly attribute boolean            unique;
    IDBCursorWithValueSync openCursor (optional any? range, optional DOMString direction);
    IDBCursorSync          openKeyCursor (optional any? range, optional DOMString direction);
    any                    get (any key);
    any                    getKey (any key);
    unsigned long          count (optional any key);
};
Attributes
keyPath of type any, readonly
On getting, provide the key path of this object store. This will be either a DOMString or an Array of DOMStrings.
No exceptions.
multiEntry of type boolean, readonly
On getting, provide the multiEntry flag of this index.
No exceptions.
name of type DOMString, readonly
On getting, provide the name of this index.
No exceptions.
objectStore of type IDBObjectStoreSync, readonly
On getting, returns a reference to the IDBObjectStoreSync instance for the referenced object store in this IDBIndexSync's transaction. This must return the same IDBObjectStoreSync instance as was used to get a reference to this IDBIndexSync.
No exceptions.
unique of type boolean, readonly
On getting, provide the unique flag of this index.
No exceptions.
Methods
count

If the optional key parameter is not a valid key or a key range, this method throws a DOMException of type DataError. This method runs the steps for asynchronously executing a request and returns the IDBRequest created by these steps. The steps are run with this IDBIndex as source and the steps for iterating a cursor as operation, using the created cursor as cursor. If provided, use the key parameter as key, otherwise, use undefined as key. If the result of the algorithm is null return 0 (zero) as the result for the request. Otherwise, use the return cursor to determine the total number of objects that share the key or key range and return that value as the result for the request.

ParameterTypeNullableOptionalDescription
keyany Key identifying the record to be retrieved. This can also be an IDBKeyRange.
ExceptionDescription
DOMException
TransactionInactiveErrorThe transaction this IDBIndexSync belongs to is not active.
DataErrorThe key parameter is not a valid key or a key range.
InvalidStateErrorOccurs if a request is made on a source object that has been deleted or removed.
Return type: unsigned long
get

If the key parameter is not a valid key or a key range, this method throws a DOMException of type DataError. This method runs the steps for synchronously executing a request and returns the result from that, in this case an object from the underlying store. The steps are run with this IDBIndexSync as source and the steps for retrieving a referenced value from an index as operation, using this IDBIndexSync as index and the key parameter as key.

This function produces the same result if a record with the given key doesn't exist as when a record exists, but has undefined as value. If you need to tell the two situations apart, you can use openCursor with the same key. This will return a cursor with undefined as value if a record exists, or no cursor if no such record exists.

ParameterTypeNullableOptionalDescription
keyanyKey identifying the record to be retrieved. This can also be an IDBKeyRange in which case the function retreives the first existing value in that range.
ExceptionDescription
DOMException
TransactionInactiveErrorThe transaction this IDBIndexSync belongs to is not active.
DataErrorThe key parameter was not passed a valid value.
InvalidStateErrorOccurs if a request is made on a source object that has been deleted or removed.
Return type: any
getKey

If the key parameter is not a valid key or a key range, this method throws a DOMException of type DataError. This method runs the steps for synchronously executing a request and returns the result from that, in this case an index value (a key). The steps are run with the IDBObjectStoreSync associated with this index as source and the steps for retrieving a value from an index as operation, using this IDBIndexSync as index and the key parameter as key.

ParameterTypeNullableOptionalDescription
keyanyKey identifying the record to be retrieved. This can also be an IDBKeyRange in which case the function retreives the first existing value in that range.
ExceptionDescription
DOMException
TransactionInactiveErrorThe transaction this IDBIndexSync belongs to is not active.
DataErrorThe key parameter was not passed a valid value.
InvalidStateErrorOccurs if a request is made on a source object that has been deleted or removed.
Return type: any
openCursor

If the range parameter is specified but is not a valid key or a key range, this method throws a DOMException of type DataError. Otherwise, this method creates a cursor. The cursor must implement the IDBCursorWithValueSync interface.

The newly created cursor must have an undefined position, a direction set to the value of the direction parameter, false as iterable flag value, and undefined key and value. The source of the cursor is the IDBIndexSync this function was called on.

If the range parameter is a key range then the cursor's range is set to that range. Otherwise, if the range parameter is a valid key then the cursor's range is set to key range containing only that key value. If the range parameter is not specified, the cursor's key range is left as undefined.

This method runs the steps for synchronously executing a request and returns the result, in this case a cursor object. The steps are run with this IDBIndexSync as source and the steps for iterating a cursor as operation, using the created cursor as cursor and with undefined as key

ParameterTypeNullableOptionalDescription
rangeanyThe key range to use as the cursor's range
directionDOMStringThe cursor's required direction
ExceptionDescription
DOMException
TransactionInactiveErrorThe transaction this IDBIndexSync belongs to is not active.
TypeErrorThe value for the direction parameter is invalid.
DataErrorThe range parameter was not passed a valid value.
InvalidStateErrorOccurs if a request is made on a source object that has been deleted or removed.
openKeyCursor

If the range parameter is specified but is not a valid key or a key range, this method throws a DOMException of type DataError. Otherwise, this method creates a cursor. The cursor must implement the IDBCursorSync interface and must not implement the IDBCursorWithValueSync interface.

The newly created cursor must have an undefined position, a direction set to the value of the direction parameter, false as iterable flag value, and undefined key and value. The source of the cursor is the IDBIndexSync this function was called on.

If the range parameter is a key range then the cursor's range is set to that range. Otherwise, if the range parameter is a valid key then the cursor's range is set to key range containing only that key value. If the range parameter is not specified, the cursor's key range is left as undefined.

This method runs the steps for synchronously executing a request and returns the result, in this case a cursor object. The steps are run with this IDBIndexSync as source and the steps for iterating a cursor as operation, using the created cursor as cursor and with undefined as key

ParameterTypeNullableOptionalDescription
rangeanyThe key range to use as the cursor's range
directionDOMStringThe cursor's required direction
ExceptionDescription
DOMException
TransactionInactiveErrorThe transaction this IDBIndexSync belongs to is not active.
TypeErrorThe value for the direction parameter is invalid.
DataErrorThe range parameter was not passed key range or a valid key.
InvalidStateErrorOccurs if a request is made on a source object that has been deleted or removed.
Return type: IDBCursorSync

3.3.5 Cursor

Using the synchronous API, an application can process all the records in the cursor's range.

Example

By default, a cursor walks over objects starting at the first record and ending at the last record including all the duplicates encountered along the way.

ECMAScript
var tx = db.transaction('Contact');
var store = tx.objectStore('Contact');
var cursor = store.openCursor();
while(cursor.continue()) {
    var value = cursor.value;
    // act on each object or key
}

To start at the last record and end in the first record, the cursor should be created with the direction parameter "prev".

ECMAScript
var cursor = store.openCursor("prev");
while(cursor.continue()) {
    // act on each object or key
}

To start at a certain key and end in the last record, i.e., for a lower-bounded cursor, while skipping duplicates, the cursor should be created with both the required start key and the direction parameter.

ECMAScript
var range = IDBKeyRange.leftBound(key);
var cursor = store.openCursor(range, IDBCursorSync.NEXT_NO_DUPLICATE);

It is also possible to create a bounded cursor, i.e., with application-specified starting and ending points, the cursor should be created with both the required keys. If the range is inclusive of both keys, then additional flags are required. In the following example, all keys with values in the inclusive range (start, end) are returned with all their duplicates, from the beginning of the range to its end.

ECMAScript
var range = IDBKeyRange.bound(start, end);
var cursor = objects.openCursor(range);
interface IDBCursorSync {
    readonly attribute Object    source;
    readonly attribute DOMString direction;
    readonly attribute any       primaryKey;
    IDBRequest update (any value);
    boolean    advance ([EnforceRange] unsigned long count);
    boolean    continue (optional any key);
    boolean    delete ();
};
Attributes
direction of type DOMString, readonly
On getting, provide the traversal direction of the cursor.
No exceptions.
primaryKey of type any, readonly
Returns the cursor's current effective key. Note that if this property returns an object (specifically an Array), it returns the same object instance every time it is inspected, until the cursor is iterated. This means that if the object is modified, those modifications will be seen by anyone inspecting the value of the cursor. However modifying such an object does not modify the contents of the database.
No exceptions.
source of type Object, readonly
On getting, returns the IDBObjectStoreSync or IDBIndexSync which this cursor is iterating. This function never returns null or throws an exception, even if the cursor is currently being iterated, has iterated past its end, or its transaction is not active.
No exceptions.
Methods
advance

This method runs the steps for synchronously executing a request. The steps are run with the cursor's source as source. The operation runs the steps for iterating a cursor count number of times with null as key and this cursor as cursor. If the steps for synchronously executing a request returns a cursor, then this function returns true. Otherwise this function returns false.

Before this method returns, unless an exception was thrown, it sets the got value flag in the cursor to false.

Calling this method more than once before new cursor data has been loaded is not allowed and results in a DOMException of type InvalidStateError being thrown. For example, calling advance() twice from the same onsuccess handler results in a DOMException of type InvalidStateError being thrown on the second call.

If the value for count is 0 (zero) or a negative number, this method must throw a JavaScript TypeError exception.

ParameterTypeNullableOptionalDescription
countunsigned longThe number of advances forward the cursor should make.
ExceptionDescription
DOMException
TypeErrorThe value passed into the count parameter was zero or a negative number.
TransactionInactiveErrorThe transaction this IDBCursorSync belongs to is not active.
InvalidStateErrorThe cursor is currently being iterated, or has iterated past its end.
Return type: boolean
continue

If this cursor's got value flag is false, this method throws a DOMException of type InvalidStateError. If the key parameter is specified and fulfills any of these conditions this method must throw a DOMException of type DataError:

Otherwise this method runs the steps for synchronously executing a request. The steps are run with the cursor's source as source and the steps for iterating a cursor as operation, using the cursor this is called on as cursor and the key parameter as key. If the steps for synchronously executing a request returns a cursor, then this function returns true. Otherwise this function returns false.

Before this method returns, unless an exception was thrown, it sets the got value flag in the cursor to false.

Calling this method more than once before new cursor data has been loaded is not allowed and results in a DOMException of type InvalidStateError being thrown. For example, calling continue() twice from the same onsuccess handler results in a DOMException of type InvalidStateError being thrown on the second call.

ParameterTypeNullableOptionalDescription
keyanyThe next key to position this cursor at
ExceptionDescription
DOMException
TransactionInactiveErrorThe transaction this IDBCursorSync belongs to is not active.
InvalidStateErrorThe cursor is currently being iterated, or has iterated past its end.
DataErrorThe key parameter was specified but did not contain a valid key.
Return type: boolean
delete

This method throws a DOMException of type ReadOnlyError if the transaction which this IDBCursorSync belongs to has its mode set to "readonly". If this cursor's got value flag is false, or if this cursor was created using openKeyCursor a DOMException of type InvalidStateError is thrown.

Otherwise this method runs the steps for synchronously executing a request. The steps are run with this IDBCursorSync as source and the steps for deleting records from an object store as operation, using this cursor's effective object store and effective key as store and key respectively. The function returns the result of running these steps.

No parameters.
ExceptionDescription
DOMException
TransactionInactiveErrorThe transaction this IDBCursorSync belongs to is not active.
ReadOnlyErrorThe mode of the transaction this IDBCursorSync belongs to is "readonly".
InvalidStateErrorThe cursor was created using openKeyCursor or the cursor is currently being iterated or has iterated past the end.
Return type: boolean
update

This method throws a DOMException of type ReadOnlyError if the transaction which this IDBCursorSync belongs to has its mode set to "readonly". If this cursor's got value flag is false or if this cursor was created using openKeyCursor, this method throws a DOMException of type InvalidStateError. If the effective object store of this cursor uses in-line keys and evaluating the key path of the value parameter results in a different value than the cursor's effective key, this method throws DOMException of type DataError.

Otherwise this method creates a structured clone of the value parameter. If the structured clone algorithm throws an exception, that exception is rethrown. Otherwise, run the steps for synchronously executing a request and return the result returned by these steps. The steps are run with this IDBCursorSync as source and the steps for storing a record into an object store as operation, using this cursor's effective object store as store, the created clone as value, this cursor's effective key as key, and with the no-overwrite flag flag set to false.

A result of running the steps for storing a record into an object store is that if the record has been deleted since the cursor moved to it, a new record will be created.

ParameterTypeNullableOptionalDescription
valueanyThe new value to store at the current position.
ExceptionDescription
DOMException
TransactionInactiveErrorThe transaction this IDBCursor belongs to is not active.
ReadOnlyErrorThe mode of the transaction this IDBCursor belongs to is "readonly"
InvalidStateErrorThrown if cursor was created using openKeyCursor or if the cursor is currently being iterated or has iterated past the end.
DataError The underlying object store uses in-line keys and the property in value at the object store's key path does not match the key in this cursor's position.
DataCloneErrorThe data being stored could not be cloned by the internal structured cloning algorithm.
Return type: IDBRequest
interface IDBCursorWithValueSync : IDBCursorSync {
    attribute any value;
};
Attributes
value of type any
Returns the cursor's current value. Note that if this property returns an object, it returns the same object instance every time it is inspected, until the cursor is iterated. This means that if the object is modified, those modifications will be seen by anyone inspecting the value of the cursor. However modifying such an object does not modify the contents of the database.
No exceptions.

3.3.6 Transaction

When an application creates a transaction synchronously, it blocks until the user agent is able to reserve the required database objects.

interface IDBTransactionSync {
    readonly attribute DOMString       mode;
             attribute IDBDatabaseSync db;
    readonly attribute DOMError        error;
    IDBObjectStoreSync objectStore (DOMString name);
    void               abort ();
};
Attributes
db of type IDBDatabaseSync
The database connection of which this transaction is a part
No exceptions.
error of type DOMError, readonly
When the done flag is true, getting this property must return the error of the request that caused the transaction to be aborted. If the error was generated when committing the transaction and not from an individual request, the error must contain the reasons for the transaction failure (e.g. QuotaExceededError, UnknownError). This is null when no error occurred or when the transaction is programmatically aborted. When the done flag is false, getting this property must throw a DOMException of type InvalidStateError.
ExceptionOn GetOn SetDescription
DOMException
InvalidStateErrorThrown when this attribute was read when the done flag was set to false.
mode of type DOMString, readonly
On getting, provide the mode for isolating access to data inside the object stores that are in the scope of the transaction.
No exceptions.
Methods
abort
If this transaction is finished, throw a DOMException of type InvalidStateError. Otherwise this method sets the transactions's active flag to false and aborts the transaction by running the steps for aborting a transaction. It also sets the error attribute on the transaction to a DOMError of type AbortError.
No parameters.
ExceptionDescription
DOMException
InvalidStateErrorIf this transaction has already been committed or aborted.
Return type: void
objectStore
Returns an IDBObjectStoreSync representing an object store that is within the scope of this transaction. Every call to this function on the same IDBTransactionSync instance and with the same name returns the same IDBObjectStoreSync instance. However the retured IDBObjectStoreSync instance is specific to this IDBTransactionSync. If this function is called on a different IDBTransactionSync, a different IDBObjectStoreSync instance is returned.
ParameterTypeNullableOptionalDescription
nameDOMStringThe requested object store
ExceptionDescription
DOMException
NotFoundError If the requested object store is not in this transaction's scope.
InvalidStateErrorOccurs if a request is made on a source object that has been deleted or removed, or if the transaction has finished.
Return type: IDBObjectStoreSync
Applications must not assume that committing the transaction produces an instantaneously durable result. The user agent may delay flushing data to durable storage until an appropriate time.

Once a transaction is aborted or committed, the active transaction on this database connection is removed. A new transaction can be created to perform operations atomically.

4. Algorithms

4.1 Opening a database

The steps for opening a database are defined in the following steps. The algorithm in these steps takes three required arguments: an origin, which requested the database to be opened, a database name, and a database version. The algorithm also takes two optional arguments, a request which represents a request used when opening the database is done by using an asynchronous API or a upgrade callback which represents the callback used when opening the database is done by using the synchronous API.

  1. If these steps fail for any reason, return an error with the appropriate type and abort this algorithm.
  2. If there is already a database with the given name from the origin origin, then let db be that database.
  3. If db was found in previous step, wait until the following conditions are all fulfilled:
    • No already existing connections to db, have non-finished "versionchange" transaction.
    • If db has its delete pending flag set, wait until db has been deleted.
    • These steps are not run for any other connections with the same origin and name but with a higher version.

    If several connections with the same origin, name and version are opened at the same time, and that version is a higher version that the database's current version, then once any of those connections can proceed to the next step in this algorithm it will immediately start a "versionchange" transaction. This prevents the other connections from proceeding until that "versionchange" transaction is finished.

    This means that if two databases with the same name and origin, but with different versions, are being opened at the same time, the one with the highest version will attempt to be opened first. If it is able to successfully open, then the one with the lower version will receive an error.

  4. If no database with the given name from the origin origin was found, or if it was deleted during the previous step, then create a database with name name, with 0 as version, and with no object stores. Let db be the new database.
  5. If the version of db is higher than version, abort these steps and return a DOMError of type VersionError.
  6. Create a new connection to db and let connection represent it.
  7. If the version of db is lower than version, then run the steps for running a "versionchange" transaction using connection, version, request and upgrade callback.
  8. If the previous step resulted in an error, then return that error and abort these steps. If the "versionchange" transaction in the previous step was aborted, or if connection is closed, return a DOMError of type AbortError and abort these steps. In either of these cases, ensure that connection is closed by running the steps for closing a database connection before these steps are aborted.
  9. Return connection.

4.2 Transaction Creation steps

When the user agent is to create a transaction it must run the following steps. This algorithm takes five parameters: A connection, a mode, a list of storeNames of object stores to be included in the scope of the transaction, a timeout for the transaction starting, and a callback parameter for synchronously created transactions.

  1. If these steps are already running synchronously (a transaction was created within a transaction callback), throw a DOMException of type InvalidStateError.
  2. If storeNames is of type DOMStringList or Array leave it as is. Otherwise, interpret it as an Array with one value, and that value is the stringified version of storeNames. If any of the strings in storeNames identifies an object store which doesn't exist, throw a DOMException of type NotFoundError. If storeNames is an empty list throw a DOMException of type InvalidAccessError.
  3. If the closePending flag is set on connection the throw a DOMException of type InvalidStateError.
  4. Create a transaction using connection as connection, mode as mode, and the object stores identified in storeNames as scope.
  5. If these steps are running asynchronously, return the created transaction and queue up the remaining steps. When control is returned to the event loop, the implementation must set the active flag to false.
  6. Wait until the transaction can be started according to the transaction lifetime rules. If this takes longer than the specified timeout then a DOMException of type TimeoutError should be thrown.

    Because the asynchronous API always passes in a timeout of infinite, only the synchronous API will ever time out.

  7. If these steps are running synchronously, the implementation must synchronously call callback with a single parameter which is the transaction. If an exception is thrown and not caught within the scope of the callback, the implementation must abort the transaction by following the steps for aborting a transaction using the name of the exception that was thrown as the error parameter, abort this algorithm without taking any further steps, and re-throw the exception.
  8. If these steps are running synchronously, the implementation must commit the transaction synchronously.

4.3 Steps for committing a transaction

When taking the steps for committing a transaction the implementation must execute the following algorithm. This algorithm takes one parameter, the transaction to commit.

  1. All the changes made to the database by the transaction are written to the database.
  2. If an error occurs while writing the changes to the database, abort the transaction by following the steps for aborting a transaction with the transaction parameter set to transaction and the error parameter set to a value appropriate for the error, for example QuotaExceededError or UnknownError.
  3. Queue up an operation to dispatch an event at transaction. The event must use the Event interface and have its type set to "complete". The event does not bubble and is not cancelable. The propagation path for the event is transaction's connection and then transaction.

    Note that even if an exception is thrown from one of the event handlers of this event, the transaction is still committed since writing the database changes happens before the event takes places. Only after the transaction has been successfully written is the "complete" event fired.

4.4 Steps for aborting a transaction

When taking the steps for aborting a transaction the implementation must execute the following algorithm. This algorithm takes two parameters, the transaction to abort and an error name.

  1. All the changes made to the database by the transaction are reverted. For "versionchange" transactions this includes changes to the set of object stores and indexes, as well as the change to the version. Also run the steps for aborting a "versionchange" transaction which reverts changes to all IDBDatabase and IDBObjectStore instances.
  2. Unless error was set to null, create a DOMError object and set its name to error. Set transaction's error property to this newly created DOMError.
  3. If the transaction's request list contain any requests whose done flag is still false, abort the steps for asynchronously executing a request for each such request and queue a task to perform the following steps:
    1. Set the done flag on the request to true, set result of the request to undefined and set the request's error attribute to a DOMError with a type of AbortError.
    2. Fire an error event at the request. However when running these steps, ignore any request to run the steps for aborting a transaction as those steps are already running.

    This does not always result in any error events being fired. For example if a transaction is aborted due to an error while committing the transaction, or if it was the last remaining request that failed.

  4. Queue up an operation to dispatch an event at transaction. The event must use the Event interface and have its type set to "abort". The event does bubble but is not cancelable. The propagation path for the event is transaction's connection and then transaction.

4.5 Steps for asynchronously executing a request

When taking the steps for asynchronously executing a request the implementation must run the following algorithm. The algorithm takes a source object and an operation to perform on a database.

These steps can be aborted at any point if the transaction the created request belongs to is aborted using the steps for aborting a transaction

  1. Set transaction to the transaction associated with source.
  2. If transaction is not active throw a DOMException of type TransactionInactiveError.
  3. Create an IDBRequest object and set request to this object. Set request's source to source and add request to the end of the list of requests in transaction. Return this object and queue up the execution of the remaining steps in this algorithm.

    Cursors override this step to reuse an existing IDBRequest. However they still put the IDBRequest at the end of the list of requests in transaction.

  4. Wait until all previously added requests in transaction have their done flag set to true.
  5. Perform operation.
  6. If performing operation succeeded then set the done flag on the request to true, set result of the request to the result of the request and set the error attribute of the request to undefined. Finally fire a success event at request.
  7. If performing operation failed then revert all changes made by operation, set the done flag on the request to true, set result of the request to undefined and set the error attribute on the request to the a DOMError with the same error type of the operation that failed. Finally fire an error event at request.
    This only reverts the changes done by this request, not any other changes made by the transaction.

4.6 Steps for synchronously executing a request

When taking the steps for synchronously executing a request the implementation must run the following algorithm. The algorithm takes a source object and an operation to perform on a database.

  1. If the transaction associated with source is not active throw a DOMException of type TransactionInactiveError.
  2. Perform operation.
  3. If performing operation succeeded then return the result of the operation.
  4. If performing operation failed, then throw a DOMException with the type of error from the operation.

4.7 Steps for extracting a key from a value using a key path

When taking the steps for extracting a key from a value using a key path, the implementation must run the following algorithm. The algorithm takes a key path named keyPath and a value named value and in some cases returns a key which may or may not be a valid key.

  1. If keyPath is an Array, then let result be newly constructed empty Array. For each item in the keyPath Array, perform the following substeps:
    1. Evaluate the steps for extracting a key from a value using a key path using the item from the keyPath array as keyPath and value as value.
    2. If the result of the previous step was not a valid key, then abort the overall algorithm and no value is returned.
    3. Add the result of the first sub-step to end of the result array.
    Return result as result of this algorithm and perform no additional steps.

    This will only ever "recurse" one level since keyPath arrays can't ever be nested.

  2. If keyPath is the empty string, return value and skip the remaining steps.
  3. Let remainingKeypath be keyPath and object be value.
  4. If remainingKeypath has a period in it, assign remainingKeypath to be everything after the first period and assign attribute to be everything before that first period. Otherwise, assign attribute to be remainingKeypath and assign remainingKeypath to be null.
  5. If object does not have an attribute named attribute, then skip the rest of these steps and no value is returned.
  6. Assign object to be the value of the attribute named attribute on object.
  7. If remainingKeypath is not null, go to step 3.
  8. Return object.

4.8 "versionchange" transaction steps

The steps for running a "versionchange" transaction are as follows. This algorithm takes two required parameters: a connection object which is used to update the database, and a new version to be set for the database. The algorithm also takes two optional arguments: a request which represents a request used when the asynchronous API is used, or a upgrade callback which represents the callback used when the synchronous API is used.

  1. Let openDatabases be the set of all IDBDatabase and IDBDatabaseSync objects, except connection, connected to the same database as connection.
  2. Fire a versionchange event at each object in openDatabases that is open. The event must not be fired on objects which has the closePending flag set. The event must use the IDBVersionChangeEvent interface and have the oldVersion property set to db's version and have the newVersion property set to version. This event must not bubble or be cancelable. The propagation path for the event is just the IDBDatabase object itself.

    Firing this event might cause one or more of the other objects in openDatabases to be closed, in which case the versionchange event must not be fired at those objects if that hasn't yet been done.

  3. If running asynchronously and any of the connections in openDatabases are still not closed, queue up a blocked event for the request. The event must use the IDBVersionChangeEvent interface and have the oldVersion property set to db's version and have the newVersion property set to version. This event must not bubble or be cancelable. The propagation path for the event is just request.

  4. Wait until either all objects in openDatabases are closed and all of their transactions are finished.

    If .close() is called immediately but a transaction associated with the connection keeps running for a "long time", should we also fire a blocked event?

    If, while we're waiting here, someone calls open with a version number higher than version, we should probably let that upgrade run first and bail here if it was successful

  5. Create a new transaction with mode set to "versionchange" and connection used as connection. The scope of the transaction includes every object store in connection. Set its active flag to false. Let transaction represent this transaction.
  6. Start transaction. Note that until this transaction is finished, no other connections can be opened to the same database.
  7. Let old version be database's version.
  8. Set the version of database to version. This change is considered part of the transaction, and so if the transaction is aborted, this change is reverted. If the "versionchange" transaction fails to commit set the version attribute on the database to undefined.
  9. If running asynchronously, schedule a task to run the following steps:
    1. Set the result property of request to connection.
    2. Set the transaction property of request to transaction.
    3. Fire a upgradeneeded event targeted at request. The event must use the IDBVersionChangeEvent interface and have the oldVersion property set to old version and have the newVersion property set to version. The readyState on the request is set to "done".
    4. If an exception was propagated out from any event handler while dispatching the event in the previous step, abort the transaction by following the steps for aborting a transaction with the error property set to AbortError.
    5. If for any reason the "versionchange" transaction is aborted the IDBDatabase instance which represents connection will remain unchanged. I.e., it's name, version, and objectStoreNames properties will remain the value they were before the transaction was aborted. The default attributes for the IDBDatabase are:
      Attribute Value
      name the name provided to IDBFactory.open
      version 0 (zero)
      objectStoresNames null
  10. If running synchronously, call upgrade callback and pass it transaction as the first argument and old version the second argument.
  11. Follow the normal steps for executing a transaction and let the transaction finish normally.
  12. When the transaction is finished, if these steps are run asynchronously, immediately set request's transaction property to null. This must be done in the same task as the task firing the complete or abort event, but after those events has been fired.

4.9 Steps for aborting a "versionchange" transaction

The Steps for aborting a "versionchange" transaction are as follows.

  1. IDBDatabase.name is not modified at all. Even if the transaction is used to create a new database, and thus there is no on-disk database, IDBDatabase.name remains as it was.
  2. Revert IDBDatabase.version to the version the on-disk database had before the transaction was started. If the "versionchange" transaction was started because the database was newly created, revert IDBDatabase.version to version 0; if the transaction was started in response to a version upgrade, revert to the version it had before the transaction was started. Note that the only time that the IDBDatabase.version property ever changes value is during a "versionchange" transaction.
  3. Revert IDBDatabase.objectStoreNames to the list of names that it had before the transaction was started. If the "versionchange" transaction was started because the database was newly created, revert it to an empty list. If the "versionchange" transaction was started in response to a version upgrade, revert to the list of object store names it had before the transaction was started.
  4. Revert IDBObjectStore.indexNames (for each object store) to the list of names that IDBObjectStore.indexNames had before the transaction was started. For any object store that was created by the transaction, revert the list to an empty list. For any object store that existed before the transaction was started, revert to the list of index names it had before the transaction was started. For any object store that was deleted during the transaction, revert the list of names to the list it had before the transaction was started, potentially a non-empty list.

    Although you cannot access object stores by using the IDBTransaction.objectStore function after a transaction is aborted, the page may still have references to object store instances. In that case IDBObjectStore.indexNames can still be accessed.

4.10 Database closing steps

The steps for closing a database connection are as follows. These steps take one argument, a connection object.

  1. Set the internal closePending flag of connection to true.
  2. Wait for all transactions created using connection to complete. Once they are complete, connection is closed.

Once the closePending flag has ben set to true no new transactions can be created using connection. All functions that create transactions first check the closePending flag first and throw an exception if it is true.

Once the connection is closed, this can unblock the steps for running a "versionchange" transaction, and the steps for deleting a database, which both wait for connections to a given database to be closed before continuing.

4.11 Database deletion steps

The steps for deleting a database are as follows. The algorithm in these steps takes three arguments: the origin that requested the database to be deleted, a database name, and an optional request representing a request used when deleting the database from an asynchronous API.

  1. If there is already a database with the given name from the origin origin, then let db be that database.
  2. If no database was found, then these steps are considered successful. Abort these steps.
  3. Set db's delete pending flag to true.
  4. Let openDatabases be the set of all IDBDatabase and IDBDatabaseSync objects connected to db.
  5. Fire a versionchange event at each object in openDatabases that is open. The event must not be fired on objects which has the closePending flag set. The event must use the IDBVersionChangeEvent interface and have the oldVersion property set to db's version and have the newVersion property set to null. This event must not bubble or be cancelable.

    Firing this event might cause one or more of the other objects in openDatabases to be closed, in which case the versionchange event must not be fired at those objects if that hasn't yet been done.

  6. If any of the connections in openDatabases are still not closed, and request was provided, fire a blocked event at request. The event must use the IDBVersionChangeEvent interface and have the oldVersion property set to db's version and have the newVersion property set to null. This event must not bubble or be cancelable.

  7. Wait until all objects in openDatabases are closed and all of their transactions are finished.

    Should we allow blocked to be fired here too, if waiting takes "too long"?

  8. Delete db.

4.12 Fire a success event

To fire a success event at a request, the implementation must run the following steps:

  1. Set transaction to the transaction associated with the source.
  2. Set the active flag of transaction to true.
  3. Dispatch an event at request. The event must use the Event interface and have its type set to "success". The event does not bubble and is not cancelable. The propagation path for the event is the transaction's connection, then transaction and finally request.
  4. Set the active flag of transaction to false.
  5. If an exception was propagated out from any event handler while dispatching the event in step 3, abort the transaction by following the steps for aborting a transaction using transaction as transaction parameter, and AbortError as error.

4.13 Fire an error event

To fire an error event at a request, the implementation must run the following steps:

  1. Set transaction to the transaction associated with the source.
  2. Set the active flag of transaction to true.
  3. Dispatch an event at request. The event must use the Event interface and have its type set to "error". The event bubbles and is cancelable. The propagation path for the event is the transaction's connection, then transaction and finally request. The event's default action is to abort the transaction by running the steps for aborting a transaction using transaction as transaction and the name of request's error property as error.
  4. Set the active flag of transaction to false.
  5. If an exception was propagated out from any event handler while dispatching the event in step 3, abort the transaction by following the steps for aborting a transaction using transaction as transaction parameter, and AbortError as error.

4.14 Steps to assign a key to a value using a key path

The steps to assign a key to a value using a key path are as follows:

  1. Let remainingKeypath be keyPath and object be value.
  2. If object is not an Object object or an Array object (see structured clone algorithm [HTML5]), then throw a DOMException of type DataError.
  3. If remainingKeypath has a period in it, assign remainingKeypath to be everything after the first period, and assign attribute to be everything before that first period. Otherwise, go to step 7.
  4. If object does not have an attribute named attribute, then create the attribute and assign it an empty object.
  5. Assign object to be the value of the attribute named attribute on object.
  6. Go to step 2.
  7. The steps leading here ensure that remainingKeyPath is a single attribute name (that is, a string without periods) by this step. The steps also ensure that object is an Object or an Array, and not a Date, RegExp, Blob, or other nonsupported type.
  8. Let attribute be remainingKeyPath.
  9. Set an attribute named attribute on object with the value key.

The intent is that these steps are only executed if evaluating the key path did not yield a value. In other words, before you run these steps, first evaluate the key path against value, and only if that does not yield a value (where 'undefined' does count as a value) do you generate a key and use these steps to modify value to contain the generated key.

5. Database operations

This section describes various operations done on the data in object stores and indexes in a database. These operations are run by the steps for asynchronously executing a request and the steps for synchronously executing a request.

5.1 Object Store Storage Operation

The steps for storing a record into an object store are as follows. The algorithm run by these steps takes four parameters: an object store store, a value, an optional key, and a no-overwrite flag.

  1. If store does use in-line keys and evaluting store's key path on value does yield a value, then set key to that result.
  2. If store uses a key generator and key is undefined, set key to the next generated key. If store also uses in-line keys, then set the property in value pointed to by store's key path to the new value for key, as shown in the steps to assign a key to a value using a key path.
  3. If store uses a key generator, this key generator was not used to generate a value for key in the previous step, key is defined to a long or a float and this number is larger than, or equal to, the next key that store's key generator would generate, change store's key generator such that the next key it generates is the lowest integer larger than key.
  4. If the no-overwrite flag was passed to these steps and is set, and a record already exists in store with its key equal to key, then this operation failed with a ConstraintError. Abort this algorithm without taking any further steps.
  5. If a record already exists in store with its key equal to key, then remove the record from store using the steps for deleting records from an object store.
  6. Store a record in store containing key as its key and object as its value. The record is stored in the object store's list such that the list is sorted according key of the records in ascending order.
  7. If there are any indexes which reference store, perform the following sub steps on each such index.
    1. Set index to the index.
    2. Evaluate index's key path on value. If this does not yield a value, take no further actions for this index. Otherwise set the result to index key.
    3. If index's multiEntry flag is false or if index key is not an Array, and if index key is not a valid key, take no further actions for this index.
    4. If index's multiEntry flag is true, and index key is an Array, remove any elements from index key that are not valid keys and remove any duplicate elements from index key such that only one instance of the duplicate value remains.

      For example, the following value of index key [10, 20, null, 30, 20] is converted to [10, 20, 30].

      After this step index key is or contains only valid keys.

    5. If index's multiEntry flag is false, or if index key is not an Array, and if index already contains a record with key equal to index key, and index has it's unique flag set to true, then this operation failed with a ConstraintError. Abort this algorithm without taking any further steps.
    6. If index's multiEntry flag is true and index key is an Array, and if index already contains a record with key equal to any of the values in index key, and index has it's unique flag set to true, then this operation failed with a ConstraintError. Abort this algorithm without taking any further steps.
    7. If index's multiEntry flag is false, or if index key is not an Array, then store a record in index containig index key as its key and key as its value. The record is stored in index's list of records such that the list is sorted primarily on the records keys, and secondarily on the records values, in ascending order.
    8. If index's multiEntry flag is true and index key is an Array, then for each item in index key store a record in index containig the items value as its key and key as its value. The records are stored in index's list of records such that the list is sorted primarily on the records keys, and secondarily on the records values, in ascending order.

      Note that it is legal for the Array to have length 0, in this case no records are added to the index.

      If any of the items in the Array are themselves an Array, then the inner Array is used as a key for that entry. In other words, Arrays are not recursively "unpacked" to produce multiple rows. Only the outer-most Array is.

  8. The result of this algorithm is key.

5.2 Object Store Retrieval Operation

The steps for retrieving a value from an object store are as follows. These steps must be run with two parameters - the record key and the object store.

  1. Let key be the key and store be the object store passed to these steps.
  2. If key is not a key range then retreive the record with key key from store. If key is a key range, then retreive the first record from store whose key is in key.
  3. If no record was found, the result of this algorithm is undefined.
  4. The result of this algorithm is a new structured clone of the value in the found record.

5.3 Index Referenced Value Retrieval Operation

The steps for retrieving a referenced value from an index are as follows. These steps must be run with two parameters - the record key and the index.

  1. Let key be the key and index be the index passed to these steps.
  2. If key is not a key range then find the first record with key key from index. If key is a key range, then find the first record from index whose key is in key.
  3. If no record was found, the result of this algorithm is undefined.
  4. Otherwise, the result of the operation is a structured clone of the referenced value of the found record.

5.4 Index Value Retrieval Operation

The steps for retrieving a value from an index are as follows. These steps must be run with two parameters - the record key and the index.

  1. Let key be the key and index be the index passed to these steps.
  2. If key is not a key range then find the first record with key key from index. If key is a key range, then find the first record from index whose key is in key.
  3. If no record was found, the result of this algorithm is undefined.
  4. If a record was found, the result of this algorithm is the value of the found record.

5.5 Object Store Deletion Operation

The steps for deleting records from an object store are as follows. The algorithm run by these steps takes two parameters: an object store store and a key.

  1. If the key parameter is a key range then let range be that key range. Otherwise, let range be a key range which containing only key.
  2. Remove all records, if any, from store with key in range.
  3. In all indexes which reference store, remove all records whose value is in range, if any such records exist.
  4. The result of this algorithm is undefined.

5.6 Object Store Clear Operation

The steps for clearing an object store are as follows. The algorithm run by these steps takes one parameter: an object store store.

  1. Remove all records from store.
  2. In all indexes which reference store, remove all records.
  3. The result of this algorithm is undefined.

5.7 Cursor Iteration Operation

The steps for iterating a cursor are as follows. The algorithm run by these steps takes two parameters: a cursor and optional key to iterate to.

  1. Let source be cursor's source, let records be list of records in source, let direction be cursor's direction, let position be cursor's position, let object store position be cursor's object store position and let range be cursor's range.

    source is always an object store or an index.

    records is always sorted in ascending key order. In the case of source being an index, records is secondarily sorted in ascending value order.

  2. If direction is "next", let found record be the first record in records which satisfy all of the following requirements:

    If direction is "nextunique", let found record be the first record in records which satisfy all of the following requirements:

    • If key is defined, the record's key is greater than or equal to key.
    • If position is defined, the record's key is greater than position.
    • If range is defined, the record's key is in range.

    If direction is "prev", let found record be the last record in records which satisfy all of the following requirements:

    • If key is defined, the record's key is less than or equal to key.
    • If position is defined, and source is an object store, the record's key is less than position.
    • If position is defined, and source is an index, the record's key is equal to position and the record's value is less than object store position or the record's key is less than position.
    • If range is defined, the record's key is in range.

    If direction is "prevunique", let temp record be the last record in records which satisfy all of the following requirements:

    • If key is defined, the record's key is less than or equal to key.
    • If position is defined, the record's key is less than position.
    • If range is defined, the record's key is in range.

    If temp record is defined, let found record be the first record in records whose key is equal to temp record's key.

  3. If found record is not defined, set cursor's key and primary key to undefined. If cursor implements IDBCursorWithValue or IDBCursorWithValueSync, then set cursor's value to undefined. The result of this algorithm is null. Abort these steps.
  4. Set cursor's position to found record's key. If source is an index, set cursor's object store position to found record's value.

  5. Set cursor's key to found record's key.

    If cursor implements IDBCursorWithValue or IDBCursorWithValueSync, then set cursor's value to a structured clone of found record referenced value.

  6. Set cursor's got value flag to true.

    Once data has been successfully read, schedule a task which when run will set the cursor's value and fire a success event.

  7. The result of the algorithm is cursor.

6. Privacy

6.1 User tracking

A third-party host (or any object capable of getting content distributed to multiple sites) could use a unique identifier stored in its client-side database to track a user across multiple sessions, building a profile of the user's activities. In conjunction with a site that is aware of the user's real id object (for example an e-commerce site that requires authenticated credentials), this could allow oppressive groups to target individuals with greater accuracy than in a world with purely anonymous Web usage.

There are a number of techniques that can be used to mitigate the risk of user tracking:

Blocking third-party storage
User agents may restrict access to the database objects to scripts originating at the domain of the top-level document of the browsing context, for instance denying access to the API for pages from other domains running in iframes.
Expiring stored data

User agents may automatically delete stored data after a period of time.

This can restrict the ability of a site to track a user, as the site would then only be able to track the user across multiple sessions when he authenticates with the site itself (e.g. by making a purchase or logging in to a service).

However, this also puts the user's data at risk.

Treating persistent storage as cookies

User agents should present the database feature to the user in a way that associates them strongly with HTTP session cookies. [COOKIES]

This might encourage users to view such storage with healthy suspicion.

Site-specific white-listing of access to databases

User agents may require the user to authorize access to databases before a site can use the feature.

Origin-tracking of stored data

User agents may record the origins of sites that contained content from third-party origins that caused data to be stored.

If this information is then used to present the view of data currently in persistent storage, it would allow the user to make informed decisions about which parts of the persistent storage to prune. Combined with a blacklist ("delete this data and prevent this domain from ever storing data again"), the user can restrict the use of persistent storage to sites that he trusts.

Shared blacklists

User agents may allow users to share their persistent storage domain blacklists.

This would allow communities to act together to protect their privacy.

While these suggestions prevent trivial use of this API for user tracking, they do not block it altogether. Within a single domain, a site can continue to track the user during a session, and can then pass all this information to the third party along with any identifying information (names, credit card numbers, addresses) obtained by the site. If a third party cooperates with multiple sites to obtain such information, a profile can still be created.

However, user tracking is to some extent possible even with no cooperation from the user agent whatsoever, for instance by using session identifiers in URLs, a technique already commonly used for innocuous purposes but easily repurposed for user tracking (even retroactively). This information can then be shared with other sites, using using visitors' IP addresses and other user-specific data (e.g. user-agent headers and configuration settings) to combine separate sessions into coherent user profiles.

6.3 Sensitivity of data

User agents should treat persistently stored data as potentially sensitive; it's quite possible for e-mails, calendar appointments, health records, or other confidential documents to be stored in this mechanism.

To this end, user agents should ensure that when deleting data, it is promptly deleted from the underlying storage.

7. Authorization

7.1 DNS spoofing attacks

Because of the potential for DNS spoofing attacks, one cannot guarantee that a host claiming to be in a certain domain really is from that domain. To mitigate this, pages can use SSL. Pages using SSL can be sure that only pages using SSL that have certificates identifying them as being from the same domain can access their databases.

7.2 Cross-directory attacks

Different authors sharing one host name, for example users hosting content on geocities.com, all share one set of databases.

There is no feature to restrict the access by pathname. Authors on shared hosts are therefore recommended to avoid using these features, as it would be trivial for other authors to read the data and overwrite it.

Even if a path-restriction feature was made available, the usual DOM scripting security model would make it trivial to bypass this protection and access the data from any path.

7.3 Implementation risks

The two primary risks when implementing these persistent storage features are letting hostile sites read information from other domains, and letting hostile sites write information that is then read from other domains.

Letting third-party sites read data that is not supposed to be read from their domain causes information leakage, For example, a user's shopping wish list on one domain could be used by another domain for targeted advertising; or a user's work-in-progress confidential documents stored by a word-processing site could be examined by the site of a competing company.

Letting third-party sites write data to the persistent storage of other domains can result in information spoofing, which is equally dangerous. For example, a hostile site could add records to a user's wish list; or a hostile site could set a user's session identifier to a known ID that the hostile site can then use to track the user's actions on the victim site.

Thus, strictly following the origin model described in this specification is important for user security.

A. Requirements

Requirements will be written with an aim to verify that these were actually met by the API specified in this document.

B. Acknowledgements

Special thanks and great appreciation to Nikunj Mehta, the original author of this specification, who was employed by Oracle Corp when he wrote the early drafts.

Garret Swart was extremely influential in the design of this specification.

Special thanks to Chris Anderson, Pablo Castro, Dana Florescu, Israel Hilerio, Arun Ranganathan, Margo Seltzer, Ben Turner, Shawn Wilsher, and Kris Zyp, all of whose feedback and suggestions have led to improvements to this specification.

C. References

C.1 Normative references

[COOKIES]
Adam Barth. HTTP State Management Mechanism. April 2011. Internet Proposed Standard RFC 6265. URL: http://www.rfc-editor.org/rfc/rfc6265.txt
[DOM-LEVEL-3-EVENTS]
Björn Höhrmann; Tom Pixley; Philippe Le Hégaret. Document Object Model (DOM) Level 3 Events Specification. 31 May 2011. W3C Working Draft. (Work in progress.) URL: http://www.w3.org/TR/2011/WD-DOM-Level-3-Events-20110531/
[DOM4]
Anne van Kesteren; Aryeh Gregor; Ms2ger. DOM4. 5 January 2012. W3C Working Draft. (Work in progress.) URL: http://www.w3.org/TR/2012/WD-dom-20120105/
[ECMA-262]
ECMAScript Language Specification. December 1999. URL: http://www.ecma-international.org/publications/standards/Ecma-262.htm
[HTML5]
Ian Hickson; David Hyatt. HTML5. 25 May 2011. W3C Working Draft. (Work in progress.) URL: http://www.w3.org/TR/html5
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Internet RFC 2119. URL: http://www.ietf.org/rfc/rfc2119.txt
[WEBIDL]
Cameron McCormack. Web IDL. 27 September 2011. W3C Working Draft. (Work in progress.) URL: http://www.w3.org/TR/2011/WD-WebIDL-20110927/
[WEBWORKERS]
Ian Hickson. Web Workers. 1 September 2011. W3C Working Draft. (Work in progress.) URL: http://www.w3.org/TR/2011/WD-workers-20110901/

C.2 Informative references

[WEBSTORAGE]
Ian Hickson. Web Storage. 10 September 2009. W3C Working Draft. (Work in progress.) URL: http://www.w3.org/TR/2009/WD-webstorage-20090910/