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.
The following features are at risk and may be removed, due to potential lack of implementations.
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.
This specification defines one class of products:
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 relies on several other underlying specifications.
Function
,
origin, same origin, structured clone,
structured clone algorithm, task, task source,
and queue a task are defined by the HTML 5
specification [[!HTML5]].
Worker
is defined by
the WebWorkers specification [[!WEBWORKERS]].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.
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:
The IDBObjectStore
and IDBObjectStoreSync
interfaces represent an object store. Note however that multiple instances of those
interfaces representing the same object store can exist.
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 Array
s 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 Array
s.
For purposes of comparison, all Array
s 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:
Array
value and B be the second Array
value.
Note that Array
s that contain other Array
s 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.
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.
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.
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.
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.
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.
A key path is a DOMString
or Array
that defines how to extract a key
from a value. A valid key path is one of:
DOMString
.DOMString
containing a JavaScript identifier [[!ECMA-262]].DOMString
containing multiple Javascript identifiers separated by
periods (ASCII character code 46) [[!ECMA-262]].Array
containing only DOMString
s conforming to
the above requirements.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
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.
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:
DOMException
of type TransactionInactiveError
.
QuotaExceededError
should
be used as error, and if an IO error happened, UnknownError
should be used as
error.
Transactions are opened in one of three modes. The mode determines how concurrent access to object stores in the transaction are isolated.
"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."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."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.
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.
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.
undefined
and
and upperOpen set to true.
undefined
, lowerOpen set to true,
upper set to upper and
and upperOpen set to open.
A key is in a key range if both the following conditions are fulfilled:
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.
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. |
BlockedError |
Connections on another page didn't close when asked, thus blocking a database change request. |
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. |
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.
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;
};
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.
1
when the
object store for that key generator is first created.
1
.
When a record is stored and an key value is specified in the call to store the record,
if the specified key 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 greater than the explicit key.
A key can be specified both for object stores which use in-line keys, by setting the
property on the stored value which the object store's key path
points to, and for object stores which use out-of-line keys, by passing a key argument
to the call to store the record.
Only specified keys values which
are float
values affect the current number of the key generator.
Date
s and Array
s which contain float
s do not affect
the current number of the key generator. Nor do DOMString
values which
could be parsed as float
s. Likewise, negative float
numbers
do not affect the current number since they are always lower than the current
number.
1
when the key
generator is used, and to modifications that happen due to
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.
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.
Each object store gets it's own key generator:
If an insertion fails due to constraint violations or IO error, the key generator is not updated.
Removing items from an objectStore never affects the key generator. Including when .clear() is called.
Inserting an item with an explicit key affects the key generator if, and only if, the key is numeric and higher than the last generated key.
Aborting a transaction rolls back any increases to the key generator which happened during the transaction. This is to make all rollbacks consistent since rollbacks that happen due to crash never has a chance to commit the increased key generator value.
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.
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.
undefined
when the request resulted
in an error. When the done flag is
false, getting this property MUST throw a DOMException
of type InvalidStateError
.
DOMException
of type InvalidStateError.
null
when there is no source set.
"pending"
, otherwise returns
"done"
.
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 upgradeneeded event
easier.
upgradeneeded event
The task source for these tasks is the database access task source.
This specification fires events with the following custom interfaces:
"versionchange"
transaction.Events are constructed as defined in Constructing events, in [[!DOM4]].
Window
and
WorkerUtils
objects
MUST implement the IDBEnvironment
interface.
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.
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.
version
is 0
(zero) or a negative number.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 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.
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.
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.
"versionchange"
transaction if createObjectStore
or deleteObjectStore
is called on this IDBDatabase instance itself.
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 not a valid key path then a DOMException
of type SyntaxError MUST be
thrown. Otherwise set the created object store's key path 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.
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."versionchange"
transaction callback. Also occurs if a request is made on a source object that has been deleted or removed.Array
containing the empty string.
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.
"versionchange"
transaction callback.
Also occurs if a request is made on a source object that has been deleted or removed.
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.
"readonly"
.DOMString
,
an Array
of DOMString
s or null
.
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.
"readonly"
.
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.
To determine if a transaction has completed successfully,
listen to the transaction’s complete
event rather than the IDBObjectStore.add
request’s success
event,
because the transaction may still fail after the success
event fires.
"readonly"
.
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.
"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 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.
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.
"readonly"
.
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.
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 not a valid key path then a DOMException
of type SyntaxError MUST be
thrown. Otherwise set the created object store's key path to the value of
keyPath. If keyPath is
an Array
and the multiEntry property in the optionalParameters is true,
then a DOMException
of type InvalidAccessError MUST be thrown. Otherwise set the created index's
key path 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.
unique
specifies whether the index's unique flag is
set.
multiEntry
specifies whether the index's multiEntry flag is
set.
"versionchange"
transaction callback. Also occurs if a request is made on a source object that has been deleted or removed.
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.
"versionchange"
transaction callback.
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.
IDBKeyRange
.
Index objects implement the following interface:
DOMString
or
an Array
of DOMString
s.
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
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
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.
Gets the primary key of the record from the referenced object store entry.
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.
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.
IDBKeyRange
.
Cursor objects implement the following interface:
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.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.
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.
"readonly"
openKeyCursor
or if the cursor
is currently being iterated or has iterated past the end.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.
count
parameter was zero or a negative number.
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.
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.
"readonly"
.openKeyCursor
or the cursor
is currently being iterated or has iterated past the end.Transaction objects implement the following interface:
abort
function, this property
returns null
.
If this transaction was aborted due to a failed request, this property returns the same
DOMError
as the request which caused this transaction to be aborted.
If this transaction was aborted due to an error when committing the transaction, and not due to a failed
request, this property returns a DOMError
which contains the reason for the transaction
failure (e.g. QuotaExceededError
or UnknownError
).
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
.
To determine if a transaction has completed successfully,
listen to the transaction’s complete
event rather than the IDBObjectStore.add
request’s success
event,
because the transaction may still fail after the success
event fires.
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.
WorkerUtils
objects MUST implement the
IDBEnvironmentSync
interface.
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.
"versionchange"
transaction. If the parameter is not provided,
the value of timeout is infinite.open
method was called within the IDBTransactionCallback of a
transaction
method or IDBVersionChangeCallback of a
open
method.
version
is 0
(zero) or a negative number.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.
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.
A database object provides access to the schema and data of a particular database.
"versionchange"
transaction if
createObjectStore
or deleteObjectStore
is called on this IDBDatabaseSync instance itself.
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 not a valid key path then a DOMException
of type SyntaxError MUST be
thrown. Otherwise set the created object store's key path 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.
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."versionchange"
transaction.
Also occurs if a request is made on a source object that has been deleted or removed.
Array
containing the empty string.
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.
"versionchange"
transaction callback.
Also occurs if a request is made on a source object that has been deleted or removed.
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.
"readonly"
.
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.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.
Using this database, we can store records in the Contact object store.
A stored value can be retrieved using the same key used by the first put operation.
A put operation will overwrite the record stored by the first add operation with the same key.
Now when the object store is read with the same key, the result is different compared to the object read earlier.
Additionally, all the records of an object store matching a certain key range can be retrieved in key order.
DOMString
,
an Array
of DOMString
s or null
.
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.
"readonly"
.
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.
"readonly"
.
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.
"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 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.
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.
"readonly"
.
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 not a valid key path then a DOMException
of type SyntaxError MUST be
thrown. Otherwise set the created object store's key path to the value of
keyPath. If keyPath is
an Array
and the multiEntry property in the optionalParameters is true,
then a DOMException
of type InvalidAccessError MUST be thrown. Otherwise set the created index's
key path to the value of keyPath.
unique
specifies whether the index's unique flag is
set.
multiEntry
specifies whether the index's multiEntry flag is
set.
"versionchange"
transaction. Also occurs if a request is made on a source object that has been deleted or removed.
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.
"versionchange"
transaction.
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.
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.
IDBKeyRange
.
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.
For example, the id of an object with the name property value 'Lincoln' can be retrieved using the ContactName index.
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.
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.
DOMString
or
an Array
of DOMString
s.
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
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
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.
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.
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.
IDBKeyRange
.
Using the synchronous API, an application can process all the records in the cursor's range.
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.
To start at the last record and end in the first record, the cursor
should be created with the direction parameter "prev"
.
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.
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.
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.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.
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.
"readonly"
openKeyCursor
or if the cursor
is currently being iterated or has iterated past the end.
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.
count
parameter was zero or a negative number.
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:
"next"
or "nextunique"
.
"prev"
or "prevunique"
.
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.
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.
"readonly"
.openKeyCursor
or the cursor
is currently being iterated or has iterated past the end.When an application creates a transaction synchronously, it blocks until the user agent is able to reserve the required database objects.
abort
function, this property
returns null
.
If this transaction was aborted due to a failed request, this property returns the same
DOMError
as the request which caused this transaction to be aborted.
If this transaction was aborted due to an error when committing the transaction, and not due to a failed
request, this property returns a DOMError
which contains the reason for the transaction
failure (e.g. QuotaExceededError
or UnknownError
).
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 with the error
parameter set to null
.
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 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.
"versionchange"
transaction.
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.
0
as version, and with no object stores. Let db
be the new database.
DOMError
of type VersionError.
"versionchange"
transaction using connection,
version, request and upgrade callback.
"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.
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.
DOMException
of type InvalidStateError.
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.
DOMException
of type InvalidStateError.
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.
name
of the exception that was thrown as the error
parameter, abort this algorithm without taking any further steps, and re-throw the exception.
When taking the steps for committing a transaction the implementation MUST execute the following algorithm. This algorithm takes one parameter, the transaction to commit.
QuotaExceededError
or UnknownError
.
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.
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.
"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.
null
, create a DOMError
object and set its name
to error. Set transaction's error
property to this newly created DOMError
.
undefined
and set the request's error
attribute to a DOMError
with a type of AbortError.
Event
interface and have its type
set to "error"
.
The event bubbles and is cancelable. The
propagation path for the event is transaction's connection,
then transaction and finally the request. There is no default action for the event.
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.
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.
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
DOMException
of type TransactionInactiveError.
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.
error
attribute of the request to undefined
.
Finally fire a success event at request.
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.
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.
DOMException
of type TransactionInactiveError.
DOMException
with the type
of error from the operation.
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.
Array
, then let result be newly constructed empty
Array
. For each item in the keyPath Array
, perform the following
substeps:
This will only ever "recurse" one level since keyPath arrays can't ever be nested.
"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.
IDBDatabase
and IDBDatabaseSync
objects, except connection, connected to the same database as connection.
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.
If any of the connections in openDatabases are neither closed
nor have their closePending flag set after its versionchange
handlers has run
to completion, abort these steps and return a DOMError
of type BlockedError.
If .close() is called immediately but a transaction associated with the connection keeps running for a "long time", we should probably give up and return a BlockedError.
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
"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.
result
property of request to connection.
transaction
property of request to transaction.
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"
.
AbortError
.
"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 |
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.
"versionchange"
transaction
The Steps for aborting a "versionchange"
transaction are as follows.
"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.
"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.
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.
The steps for closing a database connection are as follows. These steps take one argument, a connection object.
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.
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.
IDBDatabase
and IDBDatabaseSync
objects connected to db.
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.
If any of the connections in openDatabases are neither closed
nor have their closePending flag set after its versionchange
handlers
has run to completion, clear db's delete pending flag, abort these steps and return a
DOMError
of type BlockedError.
If .close() is called immediately but a transaction associated with the connection keeps running for a "long time", we should probably give up and return a BlockedError.
To fire a success event at a request, the implementation MUST run the following steps:
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.
AbortError
as error.
To fire an error event at a request, the implementation MUST run the following steps:
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. However the default action is
not taken if any of the event handlers threw an exception.
AbortError
as error. This is done even if the error event is not
canceled.
This means that if an error event is fired and any of the event handlers throw an exception, the error
property
on the transaction is set to an AbortError
rather than whatever DOMError
the error
property on the request was set to. Even if preventDefault
is never called.
The steps to assign a key to a value using a key path are as follows:
Object
object or an Array
object (see structured clone algorithm
[[!HTML5]]), then throw a DOMException
of type DataError
.
Object
or an Array
, and not a Date
, RegExp
, Blob
,
or other nonsupported type.
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.
The key path used here is always a DOMString
and never an Array
since it is not
possible to create a object store whose multiEntry flag is true and whose
key path is an Array
.
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.
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.
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.
ConstraintError
. Abort this algorithm without taking
any further steps.
Array
,
and if index key is not a valid key, take no further actions for this index.
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.
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.
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.
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.
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, Array
s are not recursively
"unpacked" to produce multiple rows. Only the outer-most Array
is.
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.
undefined
.
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.
undefined
.
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.
undefined
.
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.
undefined
.
The steps for clearing an object store are as follows. The algorithm run by these steps takes one parameter: an object store store.
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.
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.
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 direction is "prev"
, let found record be the last record in records which
satisfy all of the following requirements:
If direction is "prevunique"
, let temp record be the last record in
records which satisfy all of the following requirements:
If temp record is defined, let found record be the first record in records whose key is equal to temp record's key.
undefined
.
If cursor implements IDBCursorWithValue or IDBCursorWithValueSync, then set
cursor's value to undefined
.
The result of this algorithm is null
. Abort these steps.
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.
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.
Once data has been successfully read, schedule a task which when run will set the cursor's value and fire a success event.
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:
iframe
s.
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.
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.
User agents MAY require the user to authorize access to databases before a site can use the feature.
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.
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.
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.
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.