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.

Introduction

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.

A script can efficiently find records in an object store that come closest to the required value provided the value is stored in either a primary or a secondary key. In the following example, the 'books' object store holds data about books which are stored by their 'isbn' attribute. Additionally, an index is maintained on the 'author' attribute of the objects stored in the object store. This index can be used to look up books for a given author. If an exact match is not found, the operation raises an exception.

var db = indexedDB.open('books', 'Book store', false); if (db.version !== '1.0') { var olddb = indexedDB.open('books', 'Book store'); olddb.createObjectStore('books', 'isbn'); olddb.createIndex('BookAuthor', 'books', 'author', false); olddb.setVersion("1.0"); } // db.version === "1.0"; var index = db.openIndex('BookAuthor'); var matching = index.get('fred'); if (matching) report(matching.isbn, matching.name, matching.author); else report(null);

The next example performs the exact same logic as above asynchronously.

function findFred() { db.request.onsuccess = function() { var index = db.request.result; index.request.onsuccess = function() { var matching = index.request.result; if (matching) report(matching.isbn, matching.name, matching.author); else report(null); } index.get('fred'); } db.openIndex('BookAuthor'); } indexedDB.request.onsuccess = function() { var db = indexedDB.request.result; if (db.version !== '1.0') { indexedDB.request.onsuccess = function() { var olddb = indexedDB.request.result; olddb.request.onsuccess = function() { olddb.request.onsuccess = function() { olddb.request.onsuccess = function() { findFred(db); } olddb.setVersion("1.0"); } olddb.createIndex('BookAuthor', 'books', 'author', false); } olddb.createObjectStore('books', 'isbn'); } indexedDB.open('books', 'Book store'); } findFred(db); }; indexedDB.open('books', 'Book store', false);

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.

Dependencies

This specification relies on several other underlying specifications.

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]].
WebWorkers
The term Worker is defined by the WebWorkers specification [[!WEBWORKERS]].

Indexed Database API

Constructs

An indexed database is made of records holding simple values and hierarchical objects. Each record consists of a key and a value.

Keys

In order to efficiently retrieve records stored in an indexed database, a user agent needs to organize each record according to its key. Conforming user agents MUST support the use of values null and the IDL data types [[!WEBIDL]] DOMString and long long as keys.

For purposes of comparison, a DOMString key is always evaluated greater than any long long key. Moreover, null always evaluates lesser than any DOMString or long long key.

Only data types with natural ordering can be used as keys. The ECMAScript undefined MUST NOT be used as a key.

Values

Values can be any data type supported by the structured clone algorithm [[!HTML5]]. This includes simple types such as DOMString and Date as well as Object and Array instances.

A database can derive a key from the contents of the value being stored. In such a case, only Object instances MAY be stored as values. Only the direct enumerable properties of a stored Object instance SHOULD be used to derive a key value.

Object Store

An object store is a persistent storage mechanism that holds key-value pairs, also called records. An object store's records are sorted by keys to enable fast insertion and look up as well as ordered retrieval. Every object store has a name.

If an object store uses keys generated from a monotonically increasing sequence, it MUST have a key generator that produces unique keys for records in that object store. Alternatively, if an application provides keys, they MAY either be identified as a part of the value being stored, also called in-line keys, or be identified separately, also called out-of-line keys. No two records in an object store MAY be identified by the same key. An object store MUST have a key path if it uses in-line keys. The key path MUST be the name of an enumerated property of all objects being stored in that object store.

Concurrent access to an object store MAY be isolated in one of three modes. These are:

  1. READ_ONLY
  2. READ_WRITE
  3. SNAPSHOT_READ

Any number of readers MAY concurrently access an object store. A writer is not allowed if there is any reader concurrently accessing the object store, unless the reader is detached, i.e., looking at a snapshot view of the data that does not change once created.

The IDBObjectStore interface provides access to the metadata of an object store.

const unsigned short READ_WRITE = 0
Modification operations are allowed on the object store in this mode.
const unsigned short READ_ONLY = 1
Modification operations are not allowed on the object store in this mode.
const unsigned short SNAPSHOT_READ = 2
This mode is used solely for reading from a snapshot of the data in the object store.
readonly attribute unsigned short mode
On getting, provide the mode for isolating access to data inside this object store
readonly attribute DOMString name
On getting, provide the name of this object store.
readonly attribute DOMString keyPath
On getting, provide the key path of this object store. If this attribute is null, the application MUST provide a key value for each modification operation.
readonly attribute DOMStringList indexNames
On getting, provide a list of the names of indexes on objects in this object store.

Index

Records in an object store can be retrieved using the record's key. However, that MAY not always be adequate to recall records. An index is used to lookup records in an object store other than through a record key.

An index is a specialized persistent store that holds key-value pairs such that each value is the key of objects in the referenced object store. If an index's unique flag is set, then it MUST NOT allow duplicate values for a key. Every index has a name.

If an index is auto-populated, then the user agent populates records using the values stored in the referenced object store. An auto-populated index MUST have a key path. This key path MUST be the name of an enumerated property of every object to be stored in the object store referenced by that index. The auto-populated index record corresponding to an object store record MUST satisfy the following index maintenance conditions:

The IDBIndex interface provides the metadata of an index.

readonly attribute DOMString name
On getting, provide the name of this index.
readonly attribute DOMString storeName
On getting, provide the name of this index's referenced object store.
readonly attribute DOMString keyPath
On getting, provide the key path of this index. If this attribute is null, this index is not auto-populated.
readonly attribute boolean unique
On getting, provide the unique flag of this index.

Database

Each origin has an associated set of databases. A database comprises:

The object stores and indexes of a database are also referred as its objects.

Each database has a valid name and a human readable description. A valid name is any string including the empty string. An exact match of names means that their UTF-8 encodings are identical.

If an implementation does not support all sets of strings, it may implement support for arbitrary strings by mapping database names (e.g. using a hashing algorithm) to the supported set of names.

Each database also has a current version.

Each database has one version at a time; a database can't exist in multiple versions at once.

The object store name and index name MUST be valid and unique within the database.

The act of opening a database is creates a connection. There MAY be multiple connections to a given database at any given time. A connection that is attempting to read a given piece of data in a database is called a reader and one that is attempting to write a piece of data is called a writer. A connection MAY have zero or one active transactions.

An IDBDatabase object represents a connection to a database. This API does not provide a way to enumerate the databases available for an origin from this API.

readonly attribute DOMString name
On getting, this attribute MUST return the name of the connected database.
readonly attribute DOMString description
On getting, this attribute MUST return the description of the connected database.
readonly attribute DOMString version
On getting, this attribute MUST return the version of this database. This attribute has the null value when the connected database is first created.
readonly attribute DOMStringList objectStores
On getting, this attribute MUST return a list of names of the object stores currently in the connected database.
readonly attribute DOMStringList indexes
On getting, this attribute MUST return a list of names of the indexes currently in the connected database.
readonly attribute IDBTransaction currentTransaction
On getting, this attribute MUST return a IDBTransaction object corresponding to the transaction that is active in this database connection.

Key Range

An individual record can be retrieved from an object store using either the record's key or the key applicable for some index that references that object store. Multiple records can be fetched using a key range. A key range is a continuous interval over some data type used for keys.

A key range MAY be left-bounded or right-bounded if 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 left- and right-bounded and unbounded otherwise. A valid key range MUST be either half-bounded or bounded. A key range MAY be open, i.e., not including its endpoints or closed, i.e., including its endpoints. A key range MAY consist of a single value.

The IDBKeyRange interface defines a key range.

const unsigned short SINGLE = 0
This flag indicates a single-valued key range.
const unsigned short LEFT_OPEN = 1
This flag indicates a left-open key range.
const unsigned short RIGHT_OPEN = 2
This flag indicates a right-open key range.
const unsigned short LEFT_BOUND = 4
This flag indicates a left-bound key range.
const unsigned short RIGHT_BOUND = 8
This flag indicates a right-bound key range.
readonly attribute any left
This value is the left-bound of the key range.
readonly attribute any right
This value is the right-bound of the key range.
readonly attribute unsigned short flags
Flags for bounding values
IDBKeyRange only()
Create a new single-valued key range.
any value
The only value
IDBKeyRange leftBound()
Create a new left-bound key range.
any bound
The left bound value
optional boolean open
Is the left-bound value included in the key range.
IDBKeyRange rightBound()
Create a new right-bound key range.
any bound
The right bound value
optional boolean open
Is the right-bound value included in the key range.
IDBKeyRange bound()
Create a new left- and right-bound key range.
any left
The left-bound value
any right
The right-bound value
optional boolean openLeft
Is the left-bound value included in the key range.
optional boolean openRight
Is the right-bound value included in the key range.

Cursor

Cursors are a transient mechanism used to iterate over multiple records in a database. The 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. A cursor maintains a position over this series, which moves in a direction that is either monotonically increasing or decreasing order of the record keys.

const unsigned short NEXT = 0
indicates that this cursor should yield all records, including duplicates and its direction is monotonically increasing order of keys.
const unsigned short NEXT_NO_DUPLICATE = 1
indicates that this cursor should yield all records, not including duplicates and its direction is monotonically increasing order of keys. For every key with duplicate values, only the first record is yielded.
const unsigned short PREV = 2
indicates that cursor should yield all records, including duplicates and its direction is monotonically decreasing order of keys.
const unsigned short PREV_NO_DUPLICATE = 3
indicates that this cursor should yield all records, not including duplicates and its direction is monotonically decreasing order of keys. For every key with duplicate values, only the first record is yielded.
readonly attribute unsigned short direction
On getting, provide the traversal direction of the cursor.

Transaction

A transaction has a scope and a database. A transaction's scope is either static or dynamic. If the scope is static, it can cover either all the object stores and indexes in a database or it MAY include a subset of them.

A connection MAY have at most one transaction at any given time. Moreover, there MAY not be any overlap among the scopes of all open connections to a given database.

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 mutation operations.

Transactions are expected to be short lived. Conforming user agents MAY terminate transactions that take too long to complete in order to free up storage resources that are locked by a long running transaction.

attribute boolean static
If true, then this transaction is static and false otherwise.
attribute IDBDatabase db
The database connection of which this transaction is a part

Algorithms

Opening the database

The steps for opening a database are as follows. These steps MUST be run with an origin, a database name and description. All the steps MUST be run atomically:

  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 with the given name from the origin origin exists, then create the database db with the name and description passed to these steps.
  3. Create a connection to db and call it result.
  4. Return result.

Object Store Storage steps

The steps for storing a record into an object store are as follows. These steps MUST be run with four parameters: the object store, a value, an optional key, and an optional no-overwrite flag.

  1. Let store be the object store, key be the key and value be the value passed to these steps.
  2. If store uses out-of-line keys but no key generator, then a key MUST be passed to these steps. If not, terminate these steps and set error code DATA_ERR.
  3. If store uses in-line keys, then let key be the property of object at store's key path.
  4. Produce a structured clone of value and call it object.
  5. If key is not defined or null, then perform the following steps.
    1. Using store's key generator, produce the next key and store it as key.
    2. If store uses in-line keys, then store key as the property value for object at store's key path.
  6. If the no-overwrite flag was passed to these steps and is set, and a record already exists with its key being key, then terminate these steps and set error code CONSTRAINT_ERR.
  7. Store a record in store containing key as its key and object as its value. If any indexes are auto-populated for store, then store a record in that index according to index maintenance conditions.

    Storing would mean inserting if no record exists for that key or updating an existing record, otherwise. Auto populated index record will also be respectively inserted or updated depending on what storing results in.
  8. Return the key.

Index Storage steps

The steps for storing a record into an index are as follows. These steps MUST be run with four parameters: the index, a key, a value, and a no-overwrite flag.

  1. Let index be the index, key be the key and value be the value passed to these steps.
  2. If index has a key path, then terminate these steps and set error code CONSTRAINT_ERR.
  3. If the no-overwrite flag was passed to these steps and is set, and a record already exists in index with its key being key, then terminate these steps and set error code CONSTRAINT_ERR.
  4. If no record exists in index's referenced object store whose key is value, then terminate these steps and set error code CONSTRAINT_ERR.
  5. Store a record in index containing key as its key and value as its value.

    Storing would mean inserting if no record exists for that key or updating an existing record, otherwise.
  6. Return the key.

Object Store Retrieval steps

The steps for retrieving a record 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 no record exists with key key in store, then terminate these steps and set error code NOT_FOUND_ERR.
  3. Return the a new structured clone of the value in the record with key key in store.

Index Referenced Value Retrieval steps

The steps for retrieving a record 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 no record exists with key key in index, then terminate these steps and set error code NOT_FOUND_ERR.
  3. Let value be the value of the record with key key in index.
  4. Return the value for the record with key value in index's referenced object store.

Index Value Retrieval steps

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 no record exists with key key in index, then terminate these steps and set error code NOT_FOUND_ERR.
  3. Return the value of the record with key key in index.

Object Store Deletion steps

The steps for deleting a record from an object store are as follows. These steps MUST be run with two parameters: the key of the record to be deleted and the object store.

  1. Let key be the key and store be the object store passed to these steps.
  2. If no record exists with key key in store, then terminate these steps and set error code NOT_FOUND_ERR.
  3. If any indexes are auto-populated for store, then remove the record in that index according to index maintenance conditions.
  4. Remove the record from store with key key.

Index Deletion steps

The steps for deleting a record from an index are as follows. These steps MUST be run with two parameters: the key of the record to be deleted and the index.

  1. Let key be the key and index be the index passed to these steps.
  2. If no record exists with key key in index, then terminate these steps and set error code NOT_FOUND_ERR.
  3. Remove the records from index with key key.

Transaction Creation steps

When the user agent is to create a transaction it MUST run the following steps. These steps MUST be run with two parameters - database and an optional list of names of database objects to be reserved.

  1. If the database passed to these steps has an active transaction, then terminate these steps and set error code NON_TRANSIENT_ERR.
  2. Pick the appropriate steps:
    If these steps are not called with a list of database objects
    Acquire a lock on the entire database.
    If these steps are called with a non-empty list of database objects
    1. If any of the objects in this array is not a database object, then set code to NON_TRANSIENT_ERR and jump to the last step.
    2. Acquire appropriate locks on each of the database objects and the objects they depend on in an ordered sequence.
      If the database does not allow fine grained locking, then a user agent MAY obtain a shared or exclusive lock on the database.
    If these steps are called with an empty array of database objects
    Do not acquire locks on any database objects now. Locks are obtained as the application attempts to access those objects.
    Using the database in this style MAY lead to deadlocks. Programmers MUST use caution to acquire and release database objects in the same global order to avoid deadlocks.
  3. If a timeout duration is passed to these steps and is exceeded when acquiring locks, then set code to TIMEOUT_ERR and jump to the last step.
  4. Open a new transaction to the database, and create a IDBTransaction object that represents that transaction. Let transaction be this object.
  5. Set the current transaction of this IDBDatabase object to transaction.
  6. Return transaction. End these steps.
  7. This step is only performed in case of error. If this step is performed synchronously, then raise a newly constructed IDBDatabaseException exception exception with the code code.

Synchronous APIs

Opening a database connection

Worker objects MUST implement the IDBEnvironmentSync interface.

readonly attribute IDBIndexedDatabase indexedDB
This attribute provides applications a mechanism for accessing capabilities of indexed databases.
IDBDatabaseSync open()
DOMString name
The name for the database
DOMString description
The description for the database
optional boolean modifyDatabase
This defaults to true
UNKNOWN_ERR
if an error occurs while the database connection is being opened
NON_TRANSIENT_ERR
if the name parameter is not valid

The synchronous API for databases blocks the calling thread until a IDBDatabaseSync object is ready to return. When this method is invoked, the user agent MUST run the following steps:

  1. Let origin be the origin of the scripts in the worker.
  2. Perform the steps for opening a database, with origin, the name parameter and description parameter, and call its result as result.
  3. If the steps were aborted with an error code, then throw a newly constructed IDBDatabaseException exception with the code of that error and abort these steps.
  4. Create a IDBDatabaseSync object using result and call it db.
  5. Return db.

Database connection

A database connection can be used to manipulate the objects of that database. That is also the only way to obtaining a transaction for that database.

IDBObjectStoreSync createObjectStore()

This method creates a and returns a new object store with the given name in the connected database.

DOMString name
The name of a new object store
[Null=Null] DOMString keyPath
The key path of a new object store. If null path is specified, then the object store created will not have a key path and will use out-of-line keys.
optional boolean autoIncrement
Whether the object store created should have a key generator. The default value of this parameter is false.
CONSTRAINT_ERR
If an object store with the same name, compared in a case-sensitive manner, already exists in the connected database.
IDBObjectStoreSync openObjectStore()

This method opens the object store with the given name in the connected database for the mode specified.

DOMString name
The name of an existing object store
optional unsigned short mode
The mode used to access the object store. The default for this is IDBObjectStore.READ_WRITE
NOT_FOUND_ERR
If an object store with the same name, compared in a case-sensitive manner, already exists in the connected database.
IDBIndexSync createIndex()

This method creates a and returns a new index with the given name in the connected database.

DOMString name
The name of a new index
DOMString storeName
The name of an existing object store referenced by the new index
DOMString keyPath
The key path used by the new index
optional boolean unique
The unique flag for the new index. The default value of this parameter is false.
CONSTRAINT_ERR
If an index with the same name, compared in a case-sensitive manner, already exists in the connected database.
NOT_FOUND_ERR
If the object store with the given name does not exist in the connected database.
IDBIndexSync openIndex()

This method opens the index with the given name in the connected database for the mode specified.

DOMString name
The name of an existing index
NOT_FOUND_ERR
If the index with the given name does not exist in the connected database.
void removeObjectStore()

This method destroys an object store with the given name as well as all indexes that are referencing that object store.

DOMString storeName
The name of an existing object store
NOT_FOUND_ERR
If the object store with the given name, compared in a case-sensitive manner, does not already exist in the connected database.
void removeIndex()

This method destroys an index with the given name.

DOMString indexName
The name of an existing index
NOT_FOUND_ERR
If the index with the given name does not exist in the connected database.
void setVersion()
This method sets the version of the connected database.
[TreatNullAs=EmptyString] DOMString version
The version to store in the database
IDBTransactionSync transaction()
Perform the steps for creating a transaction with the list of database objects in the scope of this transaction and a timeout duration in milliseconds, and return the resulting IDBTransactionSync object.
optional DOMStringList storeNames
The names of object stores and indexes in the scope of the new transaction
optional unsigned long timeout
The 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
TIMEOUT_ERR
If reserving all the database objects identified in the new transaction's scope takes longer than the specified interval.

Object Store

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.

var db = indexedDB.open('AddressBook', 'Address Book'); if (db.version !== '1') { var olddb = indexedDB.open('AddressBook', 'Address Book'); olddb.createObjectStore('Contact', 'id', true); olddb.setVersion('1'); }

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

var store = db.openObjectStore('Contact'); var lincoln = {name: 'Lincoln', number: '7012'}; var contact = store.put(lincoln); // contact.id === 1

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

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

A second put operation will overwrite the record stored by the first put operation.

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.

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.

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();
any put()
Store the given value in this object store by following the steps for storing a record into an object store. The returned object from this method is the key for the stored record.
any value
The value to be stored in the record
optional any key
The key used to identify the record
optional boolean noOverwrite
Whether to overwrite an existing record with the same key
DATA_ERR
This object store uses out-of-line keys and no key generator but the key parameter was not passed
SERIAL_ERR
The data being stored could not be serialized by the internal structured cloning algorithm
CONSTRAINT_ERR
The noOverwrite parameter was true and a record exists in this object store for the key key parameter.
void remove()
Remove the record from this object store by following the steps for deleting a record from an object store corresponding to the given key.
any key
Key identifying the record to be removed
NOT_FOUND_ERR
A record did not exist in this object store for the key key
any get()
Retrieve the value from this object store for the record corresponding to the given key by following the steps for retrieving a record from an object store. The value returned from this method is the retrieved value.
any key
Key identifying the record to be retrieved
SERIAL_ERR
The data being stored could not be deserialized by the internal structured cloning algorithm
NOT_FOUND_ERR
A record did not exist in this object store for the key key parameter.
IDBCursorSync openCursor()
Create a cursor over the records of this object store. The range of this cursor matches the key range specified as the range parameter, or if that parameter is not specified or null, then the range includes all the records.
optional IDBKeyRange range
The key range to use as the cursor's range
optional unsigned short direction
The cursor's required direction
NOT_FOUND_ERR
No records exist in this object store for the requested key range.

Index

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

var db = indexedDB.open('AddressBook', 'Address Book'); if (db.version === '1') { var olddb = indexedDB.open('AddressBook', 'Address Book'); olddb.createObjectStore('Contact', 'id', true); olddb.createIndex('ContactName', 'Contact', 'name', false); olddb.setVersion('2'); }

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

var index = db.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.

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 but not the Contact objects for a given range, then we can use a different mechanism for that.

var range = new IDBKeyRange.bound('L', 'M'); var cursor = index.openObjectCursor(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();
void openObjectCursor()
Create a cursor over the records of this index's referenced object store as arranged by this index. The range of this cursor matches the key range specified as the range parameter, or if that parameter is not specified or null, then the range includes all the records.
optional IDBKeyRange range
The key range to use as the cursor's range
optional unsigned short direction
The cursor's required direction
NOT_FOUND_ERR
No records exist in this index for the requested key range.
void openCursor()
Create a cursor over the records of this index. The range of this cursor matches the key range specified as the range parameter, or if that parameter is not specified or null, then the range includes all the records.
optional IDBKeyRange range
The key range to use as the cursor's range
optional unsigned short direction
The cursor's required direction
NOT_FOUND_ERR
No records exist in this index for the requested key range.
any put()
Store the given value in this index by following the steps for storing a record into an index. The returned object from this method is the key for the stored record.
any value
The value to be stored in the record
optional any key
The key used to identify the record
optional boolean noOverwrite
Whether to overwrite an existing record with the same key. This defaults to false.
CONSTRAINT_ERR
The noOverwrite parameter was true and a record exists in this index for the key key parameter or this index is auto-populated or if no record exists with key value parameter in the index's referenced object store.
any getObject()
Retrieve the value from this index's referenced object store for the record corresponding to the given key by following the steps for retrieving a record from an index. The value returned from this method is the retrieved value.
any key
Key identifying the record to be retrieved
NOT_FOUND_ERR
A record did not exist in this index for the key key parameter.
any get()
Retrieve the value from this index for the record corresponding to the given key by following the steps for retrieving a value from an index. The value returned from this method is the retrieved value.
any key
Key identifying the record to be retrieved
NOT_FOUND_ERR
A record did not exist in this index for the key key parameter.
void remove()
Remove the records from this index by following the steps for deleting a record from an index corresponding to the given key.
any key
Key identifying the record to be removed
NOT_FOUND_ERR
A record did not exist in this index for the key key

Cursor

Using the synchronous API, an application can process all the records in the cursor's range. No two values provided by the user agent to callbacks processing data in this cursor can be identical.

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. If the cursor callback returns true, then the iteration is stopped.

var objects = ... var cursor = objects.openCursor(); // act on each object and continue the cursor to its end cursor.continue();

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

var objects = ... var cursor = objects.openCursor(IDBCursor.PREV); // act on each object and continue the cursor to its end cursor.continue();

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.

var objects = ... var range = IDBKeyRange.leftBound(key); objects.openCursor(range, IDBCursor.NEXT_NO_DUPLICATE); // act on each object and continue the cursor to its end cursor.continue();

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.

var objects = ... var range = IDBKeyRange.bound(start, end); objects.openCursor(range); // act on each object and continue the cursor to its end cursor.continue();
readonly attribute any key
The key for the record at the cursor's position.
attribute any value
The value for the record at the cursor's position.
DATA_ERR
If the underlying object store uses in-line keys and the property at the key path does not match the key in this cursor's position.
SERIAL_ERR
The data being stored could not be serialized by the internal structured cloning algorithm
NOT_ALLOWED_ERR
The underlying index or object store does not support updating the item because it is open in the READ_ONLY or SNAPSHOT_READ mode.
NOT_ALLOWED_ERR
An index record cannot be changed because the underlying index is auto-populated.
readonly attribute unsigned long long count
On getting, provide the approximate number of objects in the cursor.
boolean continue()
Advance the cursor to the next position along its direction to the item whose key matches the optional parameter. If no such parameter is provided, advance to the immediate next position. If the cursor has reached the end of its range, then this method returns false, otherwise it returns true.
optional any key
The next key to position this cursor at
void remove()

Delete the object at the cursor's position. The cursor's position is not changed. Any attempts to retrieve the cursor's current value will return null.

NOT_ALLOWED_ERR
The underlying index or object store does not support updating the item because it is open in the READ_ONLY or SNAPSHOT_READ mode.

Transaction

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

void abort()
This method signals the need to cancel the effects of operations performed in this transaction. To perform this method, the user agent ignores all the changes performed to the objects of this database since the creation of this transaction.
NON_TRANSIENT_ERR
If this transaction has already been committed or aborted.
void commit()
This method signals the normal and satisfactory completion of a transaction. At this point, the user agent should durably store all the changes performed to the objects of this database since the creation of this transaction.
RECOVERABLE_ERR
If this transaction's scope is dynamic, and the user agent cannot commit all the changes due to another transaction.
NON_TRANSIENT_ERR
If this transaction has already been committed or aborted.
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.

The IDBDatabaseException Interface

const unsigned short UNKNOWN_ERR = 0
The operation failed for reasons unrelated to the database itself and not covered by any other error code.
const unsigned short NON_TRANSIENT_ERR = 1
This error occurred because an operation was not allowed on an object. A retry of the same operation would fail unless the cause of the error is corrected.
const unsigned short NOT_FOUND_ERR = 2
The operation failed because the requested database object could not be found. For example, an object store did not exist but was being opened.
const unsigned short CONSTRAINT_ERR = 3
A mutation operation in the transaction failed due to a because a constraint was not satisfied. For example, an object such as an object store or index already exists and a new one was being attempted to be created.
const unsigned short DATA_ERR = 4
Data provided to an operation does not meet requirements.
const unsigned short NOT_ALLOWED_ERR = 5
A mutation operation was attempted on a database that did not allow mutations.
const unsigned short SERIAL_ERR = 11
The operation failed because of the size of the data set being returned or because there was a problem in serializing or deserializing the object being processed.
const unsigned short RECOVERABLE_ERR = 21
The operation failed because the database was prevented from taking an action. The operation might be able to succeed if the application performs some recovery steps and retries the entire transaction. For example, there was not enough remaining storage space, or the storage quota was reached and the user declined to give more space to the database.
const unsigned short TRANSIENT_ERR = 31
The operation failed because of some temporary problems. The failed operation might be able to succeed when the operation is retried without any intervention by application-level functionality.
const unsigned short TIMEOUT_ERR = 32
A lock for the transaction could not be obtained in a reasonable time.
const unsigned short DEADLOCK_ERR = 33
The current transaction was automatically rolled back by the database because of deadlock or other transaction serialization failures.
attribute unsigned short code
Return the most appropriate error code.
attribute DOMString message
Return an error message describing the exception raised. The message should be localized to the user's language.

Asynchronous APIs

The asynchronous API returns without blocking the calling thread. This API can only be used in a Window. Asynchronous APIs are essentially the same as the synchronous ones except that the result of an operation is not available when the operation returns.

Event summary

Events are fired during asynchronous access as database objects are created and data is consumed from these objects. As requests are made to database objects, the user agent loads information about them into memory and when the required object handle is available, it alerts the application through the firing of events. The events are as follows:

Event nameDispatched when...
success The database request has been completed and its results are available.
error There was an error performing the database request.

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]].

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

indexedDB.request.onsuccess = function(evt) {...}; indexedDB.request.onerror = function(evt) {...}; indexedDB.open('AddressBook', 'Address Book');
void abort()
This method has no effect if the readyState is not LOADING. Otherwise, the implementation makes a best effort attempt to discontinue the in-flight request. The success event is fired if the implementation cannot abort this request and completes the request successfully, otherwise the error event is fired. The readyState moves to DONE. If the request aborts successfully, the error is set to UNKNOWN_ERR.
const unsigned short INITIAL = 0
This state indicates that a request has not been started.
const unsigned short LOADING = 1
This state indicates that a request has been started but its results is not yet available.
const unsigned short DONE = 2
This state indicates that a result to a previous request is available in the result attribute.
readonly attribute unsigned short readyState
The state of this object
readonly attribute IDBDatabaseError error
The error that occurred during the requested operation. In the readyState INITIAL and LOADING, getting this attribute returns null.
readonly attribute any result
The result of a successful requested operation
attribute Function onsuccess
The event handler for the success event
attribute Function onerror
The event handler for the error event

When a request is made, the readyState changes to LOADING. Once the result of the request is available, the readyState changes to DONE, place the result of the request in result, and queue a task to fire an event with the name success, with no namespace, which does not bubble, is not cancelable, and which uses the Event interface at each Window object.

If an exception occurs while performing the operation, the readyState changes to DONE, the error information is placed in a new IDBDatabaseError object at the error attribute, and queue a task to fire an event with the name error, with no namespace, which does not bubble, is not cancelable, and which uses the Event interface at each Window object.

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

Asynchronous Request API

Window objects MUST implement the IDBEnvironment interface.

readonly attribute IDBIndexedDatabaseRequest indexedDB
This attribute provides applications a mechanism for accessing capabilities of indexed databases.

Every interface for making asynchronous requests includes a IDBRequest object that communicates back to the requesting application through events. This design means that only a single request can be active on any database or object handle at a time. If a second request is started, the user agent MUST abort any previous active request.

readonly attribute IDBRequest request
The request associated with this object, which will be used to relay the results of processing back to the caller
void open()

This method returns immediately and runs the following steps in a different thread. If an error occurs while the database connection is being opened, then this object's request error is populated with a new IDBDatabaseError object whose code is set to UNKNOWN_ERR.

  1. Let origin be the origin of the active document from which the method was invoked.
  2. Perform the steps for opening a database, with origin, the name parameter and description parameter, and call its result as result.
  3. If the steps were aborted with an error code, then set this request's error with that code and abort these steps.
  4. Create a IDBDatabaseRequest object for result and call it db.
  5. Set the result of this object's request to db.
DOMString name
The name for the database
DOMString description
The description for the database
optional boolean modifyDatabase
This defaults to true
NON_TRANSIENT_ERR
if the name parameter is not valid
readonly attribute IDBRequest request
The request associated with this object, which will be used to relay the results of processing back to the caller
void createObjectStore()

This method returns immediately and creates a new object store with the given name in the connected database. If an object store with the same name, compared in a case-sensitive manner, already exists in the connected database, then this object's request error is populated with a new IDBDatabaseError object whose code is set to CONSTRAINT_ERR. If the object store is created, the result of this object's request is set to a new IDBObjectStoreRequest for that object store.

DOMString name
The name of a new object store
[TreatNullAs=EmptyString] DOMString keyPath
The key path of a new object store. If null path is specified, then the object store created will not have a key path and will use out-of-line keys.
optional boolean autoIncrement
Whether the object store created should have a key generator.
void openObjectStore()

This method returns immediately and opens the object store with the given name in the connected database for the mode specified. If an object store with the given name does not exist in the connected database, then this object's request error is populated with a new IDBDatabaseError object whose code is set to NOT_FOUND_ERR. If the object store is opened, the result of this object's request is set to a new IDBObjectStoreRequest for that object store.

DOMString name
The name of an existing object store
optional unsigned short mode
The mode used to access the object store
void createIndex()

This method returns immediately and creates a new index with the given name and parameters in the connected database. If an index with the same name, compared in a case-sensitive manner, already exists in the connected database, then this object's request error is populated with a new IDBDatabaseError object whose code is set to CONSTRAINT_ERR. If the object store with the given name does not exist in the connected database then this object's request error is populated with a new IDBDatabaseError object whose code is set to NOT_FOUND_ERR. If the index is created, the result of this object's request is set to a new IDBIndexRequest for that index.

DOMString name
The name of a new index
DOMString storeName
The name of an existing object store referenced by the new index
DOMString keyPath
The key path used by the new index
optional boolean unique
The unique flag for the new index
void openIndex()

This method returns immediately and opens the index with the given name in the connected database. If an index with the given name does not exist in the connected database, then this object's request error is populated with a new IDBDatabaseError object whose code is set to NOT_FOUND_ERR. If the index is opened, the result of this object's request is set to a new IDBIndexRequest for that index.

DOMString name
The name of an existing index
void removeObjectStore()

This method returns immediately and destroys the object store with the given name in the connected database as well as all indexes that are referencing that object store. If an object store with the given name does not exist in the connected database, then this object's request error is populated with a new IDBDatabaseError object whose code is set to NOT_FOUND_ERR.

DOMString storeName
The name of an existing object store
void removeIndex()

This method returns immediately and destroys the index with the given name in the connected database. If an index with the given name does not exist in the connected database, then this object's request error is populated with a new IDBDatabaseError object whose code is set to NOT_FOUND_ERR.

DOMString indexName
The name of an existing index
void setVersion()
This method returns immediately and sets the version of the connected database.
[TreatNullAs=EmptyString] DOMString version
The version to store in the database
void openTransaction()
This method returns immediately and performs the steps for creating a transaction with the list of database objects for acquiring locks required in this transaction and an optional timeout duration. If a transaction can be created successfully, then the result of this object's request is set to a new IDBTransactionRequest object. If reserving all the database objects identified in the requested scope takes longer than the specified timeout interval, then the error of this object's request is set to the code TIMEOUT_ERR.
optional DOMStringList storeNames
The names of object stores and indexes in the scope of the new transaction
optional unsigned long timeout
The interval 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
readonly attribute IDBRequest request
The request associated with this object, which will be used to relay the results of processing back to the caller
void put()
This method returns immediately and stores the given value in this object store by following the steps for storing a record into an object store. If the record can be successfully stored in the object store, then the result of this object's request is set to the key for the stored record. If the noOverwrite parameter was true and a record exists in this object store for the key key parameter, then the error for this object's request is set to code CONSTRAINT_ERR. If this object store uses out-of-line keys but does not use a key generator and the key parameter was not passed, then the error for this object's request is set to code DATA_ERR. If the data being stored could not be serialized by the internal structured cloning algorithm, then the error for this object's request is set to code SERIAL_ERR.
any value
The value to be stored in the record
optional any key
The key used to identify the record
optional boolean noOverwrite
Whether to overwrite an existing record with the same key
void remove()
This method returns immediately and removes the record from this object store by following the steps for deleting a record from an object store corresponding to the given key. If a record did not exist in this object store for the key key parameter, then the error for this object's request is set to code NOT_FOUND_ERR.
any key
Key identifying the record to be removed
void get()
This method returns immediately and retrieves the value from this object store for the record corresponding to the given key by following the steps for retrieving a record from an object store. If the operation is successful, then the result of this object's request is set to the retrieved value. If a record did not exist in this object store for the key key parameter, then the error for this object's request is set to code NOT_FOUND_ERR.
any key
Key identifying the record to be retrieved
void openCursor()
This method returns immediately and creates a cursor over the records of this object store. The range of this cursor matches the key range specified as the range parameter, or if that parameter is not specified or null, then the range includes all the records. If there is even a single record that matches the key range, then the result of this object's request is set to the IDBCursorRequest object for that cursor. If no records match the key range, then the error of this object's request is set to code NOT_FOUND_ERR.
optional IDBKeyRange range
The key range to use as the cursor's range
optional unsigned short direction
The cursor's required direction
readonly attribute IDBRequest request
The request associated with this object, which will be used to relay the results of processing back to the caller
void openObjectCursor()
This method returns immediately and creates a cursor over the records of this index's referenced object store as arranged by this index. The range of this cursor matches the key range specified as the range parameter, or if that parameter is not specified or null, then the range includes all the records. If there is even a single record that matches the key range, then the result of this object's request is set to the IDBCursorRequest object for that cursor. If no records match the key range, then the error of this object's request is set to code NOT_FOUND_ERR.
optional IDBKeyRange range
The key range to use as the cursor's range
optional unsigned short direction
The cursor's required direction
void openCursor()
This method returns immediately and creates a cursor over the records of this index. The range of this cursor matches the key range specified as the range parameter, or if that parameter is not specified or null, then the range includes all the records. If there is even a single record that matches the key range, then the result of this object's request is set to the IDBCursorRequest object for that cursor. If no records match the key range, then the error of this object's request is set to code NOT_FOUND_ERR.
optional IDBKeyRange range
The key range to use as the cursor's range
optional unsigned short direction
The cursor's required direction
void put()
This method returns immediately and stores the given value in this index by following the steps for storing a record into an index. If the operation succeeds, then the result of this object's request is set to the key for the stored record. If the noOverwrite parameter was true and a record exists in this index for the key key parameter or this index is auto-populated or if no record exists with key value parameter in the index's referenced object store, then the error of this object's request is set to code CONSTRAINT_ERR.
any value
The value to be stored in the record
optional any key
The key used to identify the record
optional boolean noOverwrite
Whether to overwrite an existing record with the same key. This defaults to false.
void getObject()
This method returns immediately and retrieves the value from this index's referenced object store for the record corresponding to the given key by following the steps for retrieving a record from an index. If the operation is successful, then the result of this object's request is set to the retrieved value. If a record did not exist in this index for the key key parameter, then the error for this object's request is set to code NOT_FOUND_ERR.
any key
Key identifying the record to be retrieved
-
void get()
This method returns immediately and retrieves the value from this index for the record corresponding to the given key parameter by following the steps for retrieving a value from an index. If the operation is successful, then the result of this object's request is set to the retrieved value. If a record did not exist in this index for the key key parameter, then the error for this object's request is set to code NOT_FOUND_ERR.
any key
Key identifying the record to be retrieved
void remove()
This method returns immediately and removes the records from this index by following the steps for deleting a record from an index corresponding to the given key. If a record did not exist in this index for the key key parameter, then the error for this object's request is set to code NOT_FOUND_ERR.
any key
Key identifying the record to be removed
readonly attribute IDBRequest request
The request associated with this object, which will be used to relay the results of processing back to the caller. When the cursor is moved, the result attribute is set to false if there are no more records in the cursor.
readonly attribute any key
The key for the record at the cursor's position.
readonly attribute any value
The value for the record at the cursor's position.
readonly attribute unsigned long long count
On getting, provide the approximate number of objects in the cursor.
void update(in any value)
This method returns immediately and sets the value for the record at the cursor's position. If the underlying object store uses in-line keys and the property at the key path does not match the key in this cursor's position, then the error for this object's request is set to code DATA_ERR. If the underlying index or object store does not support updating the item because it is open in the READ_ONLY or SNAPSHOT_READ mode, then the error for this object's request is set to code NOT_ALLOWED_ERR. If the data being stored could not be serialized by the internal structured cloning algorithm, then the error for this object's request is set to code SERIAL_ERR.
void continue()
This method returns immediately and advances the cursor to the next position along its direction to the item whose key matches the optional parameter. If no such parameter is provided, advance to the immediate next position. If the cursor has reached the end of its range, then the error for this object's request is set to code NOT_ALLOWED_ERR.
optional any key
The next key to position this cursor at
void remove()

This method returns immediately and deletes the object at the cursor's position. The cursor's position is not changed. Any attempts to retrieve the cursor's current value will return null. If the underlying index or object store does not support updating the item because it is open in the READ_ONLY or SNAPSHOT_READ mode, then the error for this object's request is set to code NOT_ALLOWED_ERR.

readonly attribute IDBRequest request
The request associated with this object, which will be used to relay the results of processing back to the caller
void abort()
This method returns immediately and undoes all the changes performed to the objects of this database since the creation of this transaction. If this transaction has already been committed or aborted, then the error for this object's request is set to code NON_TRANSIENT_ERR.
void commit()
This method returns immediately and durably stores all the changes made to the objects of this database since the creation of this transaction. If this transaction has already been committed or aborted, then the error for this object's request is set to code NON_TRANSIENT_ERR. If this transaction's scope is dynamic, and the user agent cannot commit all the changes due to conflicts with another transaction, then the error for this object's request is set to code RECOVERABLE_ERR.

Events

The following are the event handlers (and their corresponding event handler event types) that MUST be supported, as IDL attributes, by objects implementing the IDBRequest interface:

Event handler Event handler event type
onsuccess success
onerror error

The IDBDatabaseError Interface

Errors in the asynchronous database API are reported using events that have a IDBDatabaseError object as one of their arguments.

attribute unsigned short code
Return the most appropriate error code.
attribute DOMString message
Return an error message describing the exception raised. The message should be localized to the user's language.

Privacy

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.

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.

Authorization

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.

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.

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.

Requirements

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

Acknowledgements

The editor of this specification was employed by Oracle Corp during its early drafts.
Garret Swart was extremely influential in the design of this specification. Feedback from Margo Seltzer, Jonas Sicking, Arun Ranganathan, Shawn Wilsher, Pablo Castro, Kris Zyp, Chris Anderson, and Dana Florescu have led to improvements to this specification over time.