This is the Third Edition of Indexed Database API. The First Edition became a W3C Recommendation on 8 January 2015. The Second Edition became a W3C Recommendation on 30 January 2018.
1. Introduction
User agents need to store large numbers of objects locally in order to satisfy off-line data requirements of Web applications. [WEBSTORAGE] is useful for storing pairs of keys and their corresponding values. However, it does not provide in-order retrieval of keys, efficient searching over values, or storage of duplicate values for a key.
This specification provides a concrete API to perform advanced key-value data management that is at the heart of most sophisticated query processors. It does so by using transactional databases to store keys and their corresponding values (one or more per key), and providing a means of traversing keys in a deterministic order. This is often implemented through the use of persistent B-tree data structures that are considered efficient for insertion and deletion as well as in-order traversal of very large numbers of data records.
2. Constructs
A
name
is
a
string
equivalent
to
a
DOMString
;
that
is,
an
arbitrary
sequence
of
16-bit
code
units
of
any
length,
including
the
empty
string.
Names
are
always
compared
as
opaque
sequences
of
16-bit
code
units.
A sorted name list is a list containing names sorted in ascending order by 16-bit code unit.
Details
This matches the Array.prototype.sort on an Array of Strings . This ordering compares the 16-bit code units in each string, producing a highly efficient, consistent, and deterministic sort order. The resulting list will not match any particular alphabet or lexicographical order, particularly for code points represented by a surrogate pair.
2.1. Database
Each origin has an associated set of databases . A database has zero or more object stores which hold the data stored in the database.
A database has a name which identifies it within a specific origin . The name is a name , and stays constant for the lifetime of the database.
A database has a version . When a database is first created, its version is 0 (zero).
A database has at most one associated upgrade transaction , which is either null or an upgrade transaction , and is initially null.
2.1.1. Database Connection
Script does not interact with databases directly. Instead, script has indirect access via a connection . A connection object can be used to manipulate the objects of that database . It is also the only way to obtain a transaction for that database .
The act of opening a database creates a connection . There may be multiple connections to a given database at any given time.
A connection can only access databases associated with the origin of the global scope from which the connection is opened.
A connection has a version , which is set when the connection is created. It remains constant for the lifetime of the connection unless an upgrade is aborted , in which case it is set to the previous version of the database . Once the connection is closed the version does not change.
Each connection has a close pending flag which is initially unset.
When a connection is initially created it is in an opened state. The connection can be closed through several means. If the execution context where the connection was 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 to close a database connection . When the connection is closed the close pending flag is always set if it hasn’t already been.
A connection may be closed by a user agent in exceptional circumstances, for example due to loss of access to the file system, a permission change, or clearing of the origin’s storage. If this occurs the user agent must run the steps to close a database connection with the connection and with the forced flag set.
A connection has an object store set , which is initialized to the set of object stores in the associated database when the connection is created. The contents of the set will remain constant except when an upgrade transaction is running.
A connection 's get the parent algorithm returns null.
A
versionchange
will
be
fired
at
an
open
connection
if
an
attempt
is
made
to
upgrade
or
delete
the
database
.
This
gives
the
connection
the
opportunity
to
close
to
allow
the
upgrade
or
delete
to
proceed.
2.2. Object Store
An object store is the primary storage mechanism for storing data in a database .
Each
database
has
a
set
of
object
stores
.
The
set
of
object
stores
can
be
changed,
but
only
using
an
upgrade
transaction
,
i.e.
in
response
to
an
upgradeneeded
event.
When
a
new
database
is
created
it
doesn’t
contain
any
object
stores
.
An 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.
An object store has a name , which is a name . At any one time, the name is unique within the database to which it belongs.
An object store optionally has a 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 .
An object store optionally has a key generator .
An object store can derive a key for a record from one of three sources:
-
A key generator . A key generator generates a monotonically increasing numbers every time a key is needed.
-
Keys can be derived via a key path .
-
Keys can also be explicitly specified when a value is stored in the object store.
2.2.1. Object Store Handle
Script does not interact with object stores directly. Instead, within a transaction , script has indirect access via an object store handle .
An object store handle has an associated object store and an associated transaction . Multiple handles may be associated with the same object store in different transactions , but there must be only one object store handle associated with a particular object store within a transaction .
An object store handle has an index set , which is initialized to the set of indexes that reference the associated object store when the object store handle is created. The contents of the set will remain constant except when an upgrade transaction is running.
An object store handle has a name , which is initialized to the name of the associated object store when the object store handle is created. The name will remain constant except when an upgrade transaction is running.
2.3. Values
Each
record
is
associated
with
a
value
.
User
agents
must
support
any
serializable
object
.
This
includes
simple
types
such
as
String
primitive
values
and
Date
objects
as
well
as
Object
and
Array
instances,
File
objects,
Blob
objects,
ImageData
objects,
and
so
on.
Record
values
are
stored
and
retrieved
by
value
rather
than
by
reference;
later
changes
to
a
value
have
no
effect
on
the
record
stored
in
the
database.
Record values are Records output by the StructuredSerializeForStorage operation.
2.4. Keys
In order to efficiently retrieve records stored in an indexed database, each record is organized according to its key .
A key has an associated type which is one of: number , date , string , binary , or array .
A
key
also
has
an
associated
value
,
which
will
be
either:
an
unrestricted
double
if
type
is
number
or
date
,
a
DOMString
if
type
is
string
,
a
list
of
octet
s
if
type
is
binary
,
or
a
list
of
other
keys
if
type
is
array
.
An ECMAScript [ECMA-262] value can be converted to a key by following the steps to convert a value to a key .
An array key is a key with type array . The subkeys of an array key are the members of the array key 's value list.
To compare two keys a and b , run these steps:
-
Let ta be the type of a .
-
Let tb be the type of b .
-
If ta is array and tb is binary , string , date or number , return 1.
-
If tb is array and ta is binary , string , date or number , return -1.
-
If ta is binary and tb is string , date or number , return 1.
-
If tb is binary and ta is string , date or number , return -1.
-
If ta is string and tb is date or number , return 1.
-
If tb is string and ta is date or number , return -1.
-
If ta is date and tb is number , return 1.
-
If tb is date and ta is number , return -1.
-
Assert: ta and tb are equal.
-
Let va be the value of a .
-
Let vb be the value of b .
-
Switch on ta :
-
number
- date
-
-
If va is greater than vb , then return 1.
-
If va is less than vb , then return -1.
-
Return 0.
-
- string
-
-
Let length be the lesser of va ’s length and vb ’s length.
-
Let i be 0.
-
While i is less than length , then:
-
Let u be the code unit of va at index i .
-
Let v be the code unit of vb at index i .
-
If u is greater than v then return 1.
-
If u is less than v then return -1.
-
Increase i by 1.
-
-
If va ’s length is greater than vb ’s length, then return 1.
-
If va ’s length is less than vb ’s length, then return -1.
-
Return 0.
-
- binary
-
-
Let length be the lesser of va ’s length and vb ’s length.
-
Let i be 0.
-
While i is less than length , then:
-
If va ’s length is greater than vb ’s length, then return 1.
-
If va ’s length is less than vb ’s length, then return -1.
-
Return 0.
-
- array
-
-
Let length be the lesser of va ’s length and vb ’s length.
-
Let i be 0.
-
While i is less than length , then:
-
Let u be the key in va at index i .
-
Let v be the key in vb at index i .
-
Let c be the result of recursively running the steps to compare two keys with u and v .
-
If c is not 0, return c .
-
Increase i by 1.
-
-
If va ’s length is greater than vb ’s length, then return 1.
-
If va ’s length is less than vb ’s length, then return -1.
-
Return 0.
-
-
number
The key a is greater than the key b if the result of running the steps to compare two keys with a and b is 1.
The key a is less than the key b if the result of running the steps to compare two keys with a and b is -1.
The key a is equal to the key b if the result of running the steps to compare two keys with a and b is 0.
2.5. Key Path
A key path is a string or list of strings that defines how to extract a key from a value . A valid key path is one of:
-
An empty string.
-
An identifier , which is a string matching the IdentifierName production from the ECMAScript Language Specification [ECMA-262] .
-
A string consisting of two or more identifiers separated by periods (U+002E FULL STOP).
-
A non-empty list containing only strings conforming to the above requirements.
Key path values can only be accessed from properties explicitly copied by StructuredSerializeForStorage , as well as the following type-specific properties:
Type | Properties |
---|---|
Blob
|
size
,
type
|
File
|
name
,
lastModified
,
lastModifiedDate
|
Array |
length
|
String |
length
|
2.6. Index
It is sometimes useful to retrieve records in an object store through other means than their key . An index allows looking up records in an object store using properties of the values in the object stores records .
An index is a specialized persistent key-value storage and has a referenced object store . The index has a list of records which hold the data stored in the index. The records in an index are automatically populated whenever records in the referenced object store are inserted, updated or deleted. There can be several indexes referencing the same object store , in which changes to the object store cause all such indexes to get updated.
The values in the index’s records are always values of keys in the index’s referenced object store. The keys are derived from the referenced object store’s values using a key path . If a given record with key X in the object store referenced by the index has the value A , and evaluating the index’s key path on A yields the result Y , then the index will contain a record with key Y and value X .
Records in an index are said to have a referenced value . This is the value of the record in the index’s referenced object store which has a key equal to the index’s record’s value. So in the example above, the record in the index whose key is Y and value is X has a referenced value of A .
The records in an index are always sorted according to the record 's key. However unlike object stores, a given index can contain multiple records with the same key. Such records are additionally sorted according to the index 's record 's value (meaning the key of the record in the referenced object store ).
An index has a name , which is a name . At any one time, the name is unique within index’s referenced object store .
An index has a unique flag . When this flag is set, 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 has a multiEntry flag . This flag affects how the index behaves when the result of evaluating the index’s key path yields an array key . If the multiEntry flag is unset, then a single record whose key is an array key is added to the index. If the multiEntry flag is true, then the one record is added to the index for each of the subkeys .
2.6.1. Index Handle
Script does not interact with indexes directly. Instead, within a transaction , script has indirect access via an index handle .
An index handle has an associated index and an associated object store handle . The transaction of an index handle is the transaction of its associated object store handle . Multiple handles may be associated with the same index in different transactions , but there must be only one index handle associated with a particular index within a transaction .
An index handle has a name , which is initialized to the name of the associated index when the index handle is created. The name will remain constant except when an upgrade transaction is running.
2.7. Transactions
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 .
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.
All transactions are created through a connection , which is the transaction’s connection .
A transaction has a scope that determines the object stores with which the transaction may interact. A transaction’s scope remains fixed for the lifetime of that transaction.
A 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. A transaction 's mode is one of the following:
-
"readonly"
- The transaction is only allowed to read data. No modifications can be done by this type of transaction. This has the advantage that several read-only 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.
-
"readwrite"
-
The
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. -
"versionchange"
-
The
transaction
is
allowed
to
read,
modify
and
delete
data
from
existing
object
stores,
and
can
also
create
and
remove
object
stores
and
indexes.
It
is
the
only
type
of
transaction
that
can
do
so.
This
type
of
transaction
can’t
be
manually
created,
but
instead
is
created
automatically
when
an
upgradeneeded
event is fired.
A
transaction
has
an
active
flag
,
which
determines
if
new
requests
can
be
made
against
the
transaction.
A
transaction
is
said
to
be
active
if
its
active
flag
is
set.
A
transaction
optionally
has
a
cleanup
event
loop
which
is
an
event
loop
.
A transaction has a request list of pending requests which have been made against the transaction.
A transaction has a error which is set if the transaction is aborted .
A transaction 's get the parent algorithm returns the transaction’s connection .
A
read-only
transaction
is
a
transaction
with
mode
"readonly"
.
A
read/write
transaction
is
a
transaction
with
mode
"readwrite"
.
2.7.1.
Transaction
Lifetime
Lifecycle
A transaction has a state , which is one of the following:
- active
-
A
transaction
is
in
this
state
when
it
is
first
created
,
and
during
dispatch
of
an
event
from
a
request
associated
with
the
transaction.
New requests can be made against the transaction when it is in this state.
- inactive
-
A
transaction
is
in
this
state
after
control
returns
to
the
event
loop
after
its
creation,
and
when
events
are
not
being
dispatched.
No requests can be made against the transaction when it is in this state.
- committing
-
Once
all
requests
associated
with
a
transaction
have
completed,
the
transaction
will
enter
this
state
as
it
attempts
to
commit
.
No requests can be made against the transaction when it is in this state.
- finished
-
Once
a
transaction
has
committed
or
aborted,
it
enters
this
state.
No requests can be made against the transaction when it is in this state.
Transactions are expected to be short lived. This is encouraged by the automatic committing functionality described below.
The lifetime of a transaction is as follows:
-
A transaction is created with a scope and a mode . When a transaction is created its
active flagstate is initiallyset. The implementation must allow requests to be placed against the transaction whenever the active flag is set. This is the case even if the transaction has not yet been started . Until the transaction is started the implementation must not execute these requests; however, the implementation must keep track of the requests and their order. Requests may be placed against a transaction only while that transaction isactive .If an attempt is made to place a request against a transaction when that transaction is not active , the implementation must reject the attempt by throwing a " TransactionInactiveError " DOMException . -
OnceWhen an implementation is able to enforce the constraintsdefinedfor thetransactiontransaction’s scope and mode , definedbelow,below , the implementation must queue a task to start the transaction asynchronously.Once the transaction has been started the implementation can
startbegin executing the requests placed against the transaction.Unless otherwise defined, requestsRequests must be executed in the order in which they were made against the transaction. Likewise, their results must be returned in the order the requests were placed against a specific transaction. There is no guarantee about the order that results from requests in different transactions are returned.Similarly, the transaction -
When each request associated with a transaction is processed , a
success
orerror
event will be fired. While the event is being dispatched , the transaction state is set to active , allowing additional requests to be made against the transaction. Once the event dispatch is complete, the transaction’s state is set to inactive again. -
A transaction can be aborted at any time before it is finished , even if the transaction isn’t currently active or hasn’t yet started .
An explicit call to
abort()
will initiate an abort . An abort will also be initiated following a failed request that is not handled by script.When a transaction is aborted the implementation must undo (roll back) any changes that were made to the database during that transaction. This includes both changes to the contents of object stores as well as additions and removals of object stores and indexes .
-
A transaction can fail for reasons not tied to a particular request . For example due to IO errors when committing the transaction, or due to running into a quota limit where the implementation can’t tie exceeding the quota to a partcular request. In this case the implementation must run the steps to abort a transaction using the transaction as transaction and the appropriate error type as error . For example if quota was exceeded then a " QuotaExceededError " DOMException should be used as error , and if an IO error happened, an " UnknownError " DOMException should be used as error . When a transaction has been started and it can no longer become active , theThe implementation must attempt to commitit, as long as thea transactionhas not been aborted . This usually happens afterwhen all requests placed against the transaction havebeen executedcompleted and their returned results handled,andno new requests have been placed against thetransaction. Whentransaction, and the transaction has not been abortedAn explicit call to
commit()
will initiate a commit without waiting for request results to be handled by script.When committing, the transaction state is
committed, theset to committing . The implementation must atomically write any changes to the database made by requests placed against the transaction. That is, either all of the changes must be written, or if an error occurs, such as a disk write error, the implementation must not write any of the changes to thedatabase. If such an error occurs, the implementation must abort the transaction by followingdatabase, and the steps to abort a transaction, otherwise it must committhe transaction by following the steps to commit a transaction .will be followed. -
When a transaction is committed or aborted ,
itits state issaidset tobefinished. If a transaction can’t be finished, for example due.
The
implementation
must
allow
requests
to
be
placed
against
the
implementation
crashing
or
transaction
whenever
it
is
active
.
This
is
the
user
taking
some
explicit
action
to
cancel
it,
case
even
if
the
transaction
has
not
yet
been
started
.
Until
the
transaction
is
started
the
implementation
must
abort
not
execute
these
requests;
however,
the
implementation
must
keep
track
of
the
requests
and
their
order.
To cleanup Indexed Database transactions , run these steps. They will return true if any transactions were cleaned up, or false otherwise.
If there are no transactions with cleanup event loop matching the
transaction.current event loop , return false.For each transaction with cleanup event loop matching the current event loop :
Set the transaction 's state to inactive .
Clear the transaction 's cleanup event loop .
Return true.
2.7.2. Transaction Scheduling
An
event
with
type
complete
is
fired
at
a
transaction
that
has
successfully
committed
.
An
event
with
type
abort
is
fired
at
a
transaction
that
has
aborted
.
The following constraints define when a transaction can be started :
-
Any number of read-only transactions are allowed to run concurrently, even if the transaction’s scope overlap and include the same object stores . As long as a read-only 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.
-
Similarly, implementations must ensure that a read/write 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 read/write transaction ’s scope . The implementation must also ensure that if the read/write 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 read/write 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 .
-
Any transaction created after a read/write transaction must see the changes written by the read/write transaction . So if a read/write transaction , A, is created, and later another transaction B, is created, and the two transactions have overlapping scopes , then B must see any changes made to any object stores that are part of that overlapping scope . Due to the requirements in the previous paragraph, this also means that the B transaction does not have access to any object stores in that overlapping scope until the A transaction is finished .
-
User agents must ensure a reasonable level of fairness across transactions to prevent starvation. For example, if multiple read-only transactions are started one after another the implementation must not indefinitely prevent a pending read/write transaction from starting .
2.7.2.
2.7.3.
Upgrade
Transactions
An
upgrade
transaction
is
a
transaction
with
mode
"versionchange"
.
An
upgrade
transaction
is
automatically
created
when
running
the
steps
to
run
an
upgrade
transaction
after
a
connection
is
opened
to
a
database
,
if
a
version
greater
than
the
current
version
is
specified.
This
transaction
will
be
active
inside
the
upgradeneeded
event
handler.
2.8. Requests
Each asynchronous operation on a database is done using a request . Every request represents one operation.
A request has a processed flag which is initially unset. This flag is set when the operation associated with the request has been executed.
A request is said to be processed when its processed flag is set.
A request has a done flag which is initially unset. This flag is set when the result of the operation associated with the request is available.
A request has a source object.
A request has a result and an error , neither of which are accessible until the done flag is set.
A request has a transaction which is initially null. This will be set when a request is placed against a transaction using the steps to asynchronously execute a request .
When
a
request
is
made,
a
new
request
is
returned
with
its
done
flag
unset.
If
a
request
completes
successfully,
the
done
flag
is
set,
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
done
flag
is
set,
the
error
is
set
to
the
error,
and
an
event
with
type
error
is
fired
at
the
request.
A request 's get the parent algorithm returns the request’s transaction .
2.8.1. Open Requests
An
open
request
is
a
special
type
of
request
used
when
opening
a
connection
or
deleting
a
database
.
In
addition
to
success
and
error
events,
blocked
and
upgradeneeded
events
may
be
fired
at
an
open
request
to
indicate
progress.
The source of an open request is always null.
The
transaction
of
an
open
request
is
null
unless
an
upgradeneeded
event
has
been
fired.
An open request 's get the parent algorithm returns null.
Open requests are processed in a connection queue . The queue contains all open requests associated with an origin and a name . Requests added to the connection queue processed in order and each request must run to completion before the next request is processed. An open request may be blocked on other connections , requiring those connections to close before the request can complete and allow further requests to be processed.
2.9. Key Range
Records can be retrieved from object stores and indexes using either keys or key ranges . A key range is a continuous interval over some data type used for keys.
A key range has an associated lower bound (null or a key ).
A key range has an associated upper bound (null or a key ).
A key range has an associated lower open flag . Unless otherwise stated it is unset.
A key range has an associated upper open flag . Unless otherwise stated it is unset.
A key range may have a lower bound equal to its upper bound . A key range must not have a lower bound greater than its upper bound .
A key range containing only key has both lower bound and upper bound equal to key .
A key is in a key range if both of the following conditions are fulfilled:
-
The lower bound is null, or it is less than key , or it is both equal to key and the lower open flag is unset.
-
The upper bound is null, or it is greater than key , or it is both equal to key and the upper open flag is unset.
An unbounded key range is a key range that has both lower bound and upper bound equal to null. All keys are in an unbounded key range .
The steps to convert a value to a key range with value and optional null disallowed flag are as follows:
-
If value is a key range , return value .
-
If value is undefined or is null, then throw a "
DataError
"DOMException
if null disallowed flag is set, or return an unbounded key range otherwise. -
Let key be the result of running the steps to convert a value to a key with value . Rethrow any exceptions.
-
If key is invalid, throw a "
DataError
"DOMException
. -
Return a key range containing only key .
2.10. Cursor
A cursor is used to iterate over a range of records in an index or an object store in a specific direction.
A cursor has a transaction , the transaction that was active when the cursor was created.
A cursor has a range of records in either an index or an object store .
A cursor has a source that indicates which index or an object store is associated with the records over which the cursor is iterating.
A cursor has a direction that determines whether it moves in monotonically increasing or decreasing order of the record keys when iterated, and if it skips duplicated values when iterating indexes. The direction of a cursor also determines if the cursor initial position is at the start of its source or at its end. A cursor’s direction is one of the following:
-
"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
an
index
with
the
unique
flag
set,
this
direction
has
exactly
the
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
an
index
with
the
unique
flag
set,
this
direction
has
exactly
the
same
behavior
as
"prev"
.
A cursor has a position within its range. 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.
A cursor has a key and a value which represent the key and the value of the last iterated record .
A cursor has a got value flag . When this flag unset, the cursor is either in the process of loading the next value or it has reached the end of its range . When it is set, it indicates that the cursor is currently holding a value and that it is ready to iterate to the next one.
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 .
A cursor has a request , which is the request used to open the cursor.
A cursor also has a key only flag , that indicates whether the cursor’s value is exposed via the API. Unless stated otherwise it is unset.
2.11. Key Generators
When a object store is created it can be specified to use a key generator . A key generator is used to generate keys for records inserted into an object store if not otherwise specified.
A key generator has a current number . The current number is always a positive integer less than or equal to 2 53 (9007199254740992) + 1. The initial value of a key generator 's current number is 1, set when the associated object store is created. The current number is incremented as keys are generated, and may be updated to a specific value by using explicit keys.
Modifying a key generator’s current number is considered part of a database operation. This means that if the operation fails and the operation is reverted, the current number is reverted to the value it had before the operation started. This applies both to modifications that happen due to the current number getting increased by 1 when the key generator is used, and to modifications that happen due to a record being stored with a key value specified in the call to store the record .
Likewise, if a transaction is aborted, the current number of the key generator for each object store in the transaction’s scope is reverted to the value it had before the transaction was started.
The
current
number
for
a
key
generator
never
decreases,
other
than
as
a
result
of
database
operations
being
reverted.
Deleting
a
record
from
an
object
store
never
affects
the
object
store’s
key
generator.
Even
clearing
all
records
from
an
object
store,
for
example
using
the
clear()
method,
does
not
affect
the
current
number
of
the
object
store’s
key
generator.
When a record is stored and a key is not specified in the call to store the record, a key is generated.
To generate a key for an object store store , run these steps:
-
Let generator be the key generator associated with store .
-
Let key be generator ’s current number .
-
If key is greater than 2 53 (9007199254740992), then return failure.
-
Increase generator ’s current number by 1.
-
Return key .
When a record is stored and a key is specified in the call to store the record, the associated key generator may be updated.
To possibly update the key generator for an object store store with key , run these steps:
-
If the type of key is not number , abort these steps.
-
Let value be the value of key .
-
Let value be the minimum of value and 2 53 (9007199254740992).
-
Let value be the largest integer not greater than value .
-
Let generator be the key generator associated with store .
-
If value is greater than or equal to generator ’s current number , then set generator ’s current number to value + 1.
When
the
current
number
of
a
key
generator
reaches
above
the
value
2
53
(9007199254740992)
any
subsequent
attempts
to
use
the
key
generator
to
generate
a
new
key
will
result
in
a
"
ConstraintError
"
DOMException
.
It
is
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
such
records
is
to
delete
the
object
store
and
create
a
new
one.
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.
3. Exceptions
Each
of
the
exceptions
used
in
this
document
is
a
DOMException
with
a
specific
type.
The
exception
types
and
properties
such
as
legacy
code
value
are
defined
in
[WEBIDL]
.
The
table
below
lists
the
DOMException
s
used
in
this
document
along
with
a
description
of
the
exception
type’s
usage.
Type | Description |
---|---|
AbortError
| A request was aborted. |
ConstraintError
| A mutation operation in the transaction failed because a constraint was not satisfied. |
DataCloneError
| The data being stored could not be cloned by the internal structured cloning algorithm. |
DataError
| Data provided to an operation does not meet requirements. |
InvalidAccessError
| An invalid operation was performed on an object. |
InvalidStateError
| An operation was called on an object on which it is not allowed or at a time when it is not allowed, or if a request is made on a source object that has been deleted or removed. |
NotFoundError
| The operation failed because the requested database object could not be found. |
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. |
ReadOnlyError
| The mutating operation was attempted in a read-only transaction. |
TransactionInactiveError
| A request was placed against a transaction which is currently not active, or which is finished. |
UnknownError
| The operation failed for reasons unrelated to the database itself and not covered by any other errors. |
VersionError
| An attempt was made to open a database using a lower version than the existing version. |
4. API
The
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.
The task source for these tasks is the database access task source .
4.1.
The
IDBRequest
interface
The
IDBRequest
interface
provides
the
means
to
access
results
of
asynchronous
requests
to
databases
and
database
objects
using
event
handler
IDL
attributes
[HTML]
.
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
at
a
time.
[Exposed =(Window ,Worker )]interface :
IDBRequest EventTarget {readonly attribute any result ;;readonly attribute DOMException ?error ;readonly attribute (IDBObjectStore or IDBIndex or IDBCursor )?source ;readonly attribute IDBTransaction ?transaction ;readonly attribute IDBRequestReadyState readyState ; // Event handlers:attribute EventHandler onsuccess ;attribute EventHandler onerror ; };enum {
IDBRequestReadyState ,
"pending" };
"done"
-
request
.
result
-
When
a
request
is
completed,
returns
the
result
,
or
undefined
if the request failed. Throws a "InvalidStateError
"DOMException
if the request is still pending. -
request
.
error
-
When
a
request
is
completed,
returns
the
error
(a
DOMException
), or null if the request succeeded. Throws a "InvalidStateError
"DOMException
if the request is still pending. -
request
.
source
-
Returns
the
IDBObjectStore
,IDBIndex
, orIDBCursor
the request was made against, or null if is was an open request . -
request
.
transaction
-
Returns
the
IDBTransaction
the request was made within. If this as an open request , then it returns an upgrade transaction while it is running, or null otherwise. -
request
.
readyState
-
Returns
"pending"
until a request is complete, then returns"done"
.
The
result
attribute’s
getter
must
throw
an
"
InvalidStateError
"
DOMException
if
the
done
flag
is
unset.
Otherwise,
the
attribute’s
getter
must
return
the
result
of
the
request,
or
undefined
if
the
request
resulted
in
an
error.
The
error
attribute’s
getter
must
throw
an
"
InvalidStateError
"
DOMException
if
the
done
flag
is
unset.
Otherwise,
the
attribute’s
getter
must
return
the
error
of
the
request,
or
null
if
no
error
occurred.
The
source
attribute’s
getter
must
return
the
source
of
the
request
,
or
null
if
no
source
is
set.
The
transaction
attribute’s
getter
must
return
the
transaction
of
the
request
.
This
property
can
be
null
for
certain
requests,
such
as
for
requests
returned
from
open()
.
The
readyState
attribute’s
getter
must
return
"pending"
if
the
done
flag
is
unset,
and
"done"
otherwise.
The
onsuccess
attribute
is
the
event
handler
for
the
success
event.
The
onerror
attribute
is
the
event
handler
for
the
error
event.
Methods
on
IDBDatabase
that
return
a
open
request
use
an
extended
interface
to
allow
listening
to
the
blocked
and
upgradeneeded
events.
[Exposed =(Window ,Worker )]interface :
IDBOpenDBRequest IDBRequest { // Event handlers:attribute EventHandler onblocked ;attribute EventHandler onupgradeneeded ; };
The
onblocked
attribute
is
the
event
handler
for
the
blocked
event.
The
onupgradeneeded
attribute
is
the
event
handler
for
the
upgradeneeded
event.
4.2. Event interfaces
This specification fires events with the following custom interfaces:
[Exposed =(Window ,Worker ),(
Constructor DOMString ,
type optional IDBVersionChangeEventInit )]
eventInitDict interface :
IDBVersionChangeEvent Event {readonly attribute unsigned long long oldVersion ;readonly attribute unsigned long long ?newVersion ; };dictionary :
IDBVersionChangeEventInit EventInit {unsigned long long = 0;
oldVersion unsigned long long ?=
newVersion null ; };
The
oldVersion
attribute
getter
returns
the
previous
version
of
the
database.
The
newVersion
attribute
getter
returns
the
new
version
of
the
database,
or
null
if
the
database
is
being
deleted.
See
the
steps
to
run
an
upgrade
transaction
.
Events are constructed as defined in DOM Standard §constructing-events .
To fire a version change event named e at target given oldVersion and newVersion , run these steps:
-
Let event be the result of creating an event using
IDBVersionChangeEvent
. -
Set event ’s
type
attribute to e . -
Set event ’s
bubbles
andcancelable
attributes to false. -
Set event ’s
oldVersion
attribute to oldVersion . -
Set event ’s
newVersion
attribute to newVersion . -
Let legacyOutputDidListenersThrowFlag be unset.
-
Dispatch event at target with legacyOutputDidListenersThrowFlag .
-
Return legacyOutputDidListenersThrowFlag .
4.3.
The
IDBFactory
interface
Database
objects
are
accessed
through
methods
on
the
IDBFactory
interface.
A
single
object
implementing
this
interface
is
present
in
the
global
scope
of
environments
that
support
Indexed
DB
operations.
partial interface mixin WindowOrWorkerGlobalScope { [SameObject ]readonly attribute IDBFactory indexedDB ; };
The
indexedDB
attribute
provides
applications
a
mechanism
for
accessing
capabilities
of
indexed
databases.
[Exposed =(Window ,Worker )]interface { [
IDBFactory NewObject ]IDBOpenDBRequest open (DOMString ,
name optional [EnforceRange ]unsigned long long ); [
version NewObject ]IDBOpenDBRequest deleteDatabase (DOMString );
name Promise <sequence <IDBDatabaseInfo >>databases ();short cmp (any ,
first any ); };
second dictionary {
IDBDatabaseInfo DOMString ;
name unsigned long long ; };
version
-
request
=
indexedDB
.
open
( name ) -
Attempts
to
open
a
connection
to
the
named
database
with
the
current
version,
or
1
if
it
does
not
already
exist.
If
the
request
is
successful
request
’s
result
will be the connection . -
request
=
indexedDB
.
open
( name , version ) -
Attempts
to
open
a
connection
to
the
named
database
with
the
specified
version.
If
the
database
already
exists
with
a
lower
version
and
there
are
open
connections
that
don’t
close
in
response
to
a
versionchange
event, the request will be blocked until all they close, then an upgrade will occur. If the database already exists with a higher version the request will fail. If the request is successful request ’sresult
will be the connection . -
request
=
indexedDB
.
deleteDatabase
( name ) -
Attempts
to
delete
the
named
database
.
If
the
database
already
exists
and
there
are
open
connections
that
don’t
close
in
response
to
a
versionchange
event, the request will be blocked until all they close. If the request is successful request ’sresult
will be null. -
result
=
await
indexedDB
.
databases
() -
Returns a promise which resolves to a list of objects giving a snapshot of the names and versions of databases within the origin.
This API is intended for web applications to introspect the use of databases, for example to clean up from earlier versions of a site’s code. Note that the result is a snapshot; there are no guarantees about the sequencing of the collection of the data or the delivery of the response with respect to requests to create, upgrade, or delete databases by this context or others.
The
open(
name
,
version
)
method,
when
invoked,
must
run
these
steps:
-
Let origin be the origin of the global scope used to access this
IDBFactory
. -
If origin is an opaque origin , throw a "
SecurityError
"DOMException
and abort these steps. -
Let request be a new open request .
-
Run these steps in parallel :
-
Let result be the result of running the steps to open a database , with origin , name , version if given and undefined otherwise, and request .
-
Queue a task to run these steps:
-
If result is an error, then run these steps:
-
Set request ’s result to undefined.
-
Set request ’s error to result .
-
Set request ’s done flag .
-
Fire an event named
error
at request with itsbubbles
andcancelable
attributes initialized to true.
-
-
Otherwise, run these steps:
-
Set request ’s result to result .
-
Set request ’s done flag .
-
Fire an event named
success
at request .
Why aren’t the steps to fire a success event or fire an error event used?
There is no transaction associated with the request (at this point), so those steps — which activate an associated transaction before dispatch and deactivate the transaction after dispatch — do not apply. -
-
-
-
Return a new
IDBOpenDBRequest
object for request .
The
deleteDatabase(
name
)
method,
when
invoked,
must
run
these
steps:
-
Let origin be the origin of the global scope used to access this
IDBFactory
. -
If origin is an opaque origin , throw a "
SecurityError
"DOMException
and abort these steps. -
Let request be a new open request .
-
Run these steps in parallel :
-
Let result be the result of running the steps to delete a database , with origin , name , and request .
-
Set request ’s processed flag .
Queue a task to run these steps:
-
If result is an error, set request ’s error to result , set request ’s done flag , and fire an event named
error
at request with itsbubbles
andcancelable
attributes initialized to true. -
Otherwise, set request ’s result to undefined, set request ’s done flag , and fire a version change event named
success
at request with result and null.Why aren’t the steps to fire a success event or fire an error event used?
There is no transaction associated with the request, so those steps — which activate an associated transaction before dispatch and deactivate the transaction after dispatch — do not apply.Also, the
success
event here is aIDBVersionChangeEvent
which includes theoldVersion
andnewVersion
details.
-
-
-
Return a new
IDBOpenDBRequest
object for request .
The
databases()
method,
when
invoked,
must
run
these
steps:
-
Let origin be the origin of the global scope used to access this
IDBFactory
. -
If origin is an opaque origin , then return a new promise rejected with a "
SecurityError
"DOMException
. -
Let p be a new promise.
-
Run these steps in parallel :
-
Let databases be the set of databases in origin . If this cannot be determined for any reason, then reject p with an appropriate error (e.g. an "
UnknownError
"DOMException
) and terminate these steps. -
Let result be a new list .
-
For each db of databases :
-
Resolve p with result .
-
-
Return p .
-
result
=
indexedDB
.
cmp
( key1 , key2 ) -
Compares
two
values
as
keys
.
Returns
-1
if
key1
precedes
key2
,
1
if
key2
precedes
key1
,
and
0
if
the
keys
are
equal.
Throws a "
DataError
"DOMException
if either input is not a valid key .
The
cmp(
first
,
second
)
method,
when
invoked,
must
run
these
steps:
-
Let a be the result of running the steps to convert a value to a key with first . Rethrow any exceptions.
-
If a is invalid, throw a "
DataError
"DOMException
. -
Let b be the result of running the steps to convert a value to a key with second . Rethrow any exceptions.
-
If b is invalid, throw a "
DataError
"DOMException
. -
Return the results of running the steps to compare two keys with a and b .
4.4.
The
IDBDatabase
interface
The
IDBDatabase
interface
represents
a
connection
to
a
database
.
An
IDBDatabase
object
must
not
be
garbage
collected
if
its
associated
connection
's
close
pending
flag
is
unset
and
it
has
one
or
more
event
listeners
registers
whose
type
is
one
of
abort
,
error
,
or
versionchange
.
If
an
IDBDatabase
object
is
garbage
collected,
the
associated
connection
must
be
closed
.
[Exposed =(Window ,Worker )]interface :
IDBDatabase EventTarget {readonly attribute DOMString name ;readonly attribute unsigned long long version ;readonly attribute DOMStringList objectStoreNames ; [NewObject ]IDBTransaction transaction ((DOMString or sequence <DOMString >),
storeNames optional IDBTransactionMode = "readonly");
mode void close (); [NewObject ]IDBObjectStore createObjectStore (DOMString ,
name optional IDBObjectStoreParameters );
options void deleteObjectStore (DOMString ); // Event handlers:
name attribute EventHandler onabort ;attribute EventHandler onclose ;attribute EventHandler onerror ;attribute EventHandler onversionchange ; };dictionary { (
IDBObjectStoreParameters DOMString or sequence <DOMString >)?=
keyPath null ;boolean =
autoIncrement false ; };
The
name
attribute’s
getter
must
return
the
name
of
the
connected
database
.
The
attribute
must
return
this
name
even
if
the
close
pending
flag
is
set
on
the
connection
.
In
other
words,
the
value
of
this
attribute
stays
constant
for
the
lifetime
of
the
IDBDatabase
instance.
The
version
attribute’s
getter
must
return
this
connection
's
version
.
Is this the same as the database 's version ?
As long as the connection is open, this is the same as the connected database 's version . But once the connection has closed , this attribute will not reflect changes made with a later upgrade transaction .-
connection
.
objectStoreNames
- Returns a list of the names of object stores in the database.
-
store
=
connection
.
createObjectStore
( name [, options ]) -
Creates
a
new
object
store
with
the
given
name
and
options
and
returns
a
new
IDBObjectStore
.Throws a "
InvalidStateError
"DOMException
if not called within an upgrade transaction . -
connection
.
deleteObjectStore
( name ) -
Deletes
the
object
store
with
the
given
name
.
Throws a "
InvalidStateError
"DOMException
if not called within an upgrade transaction .
The
objectStoreNames
attribute’s
getter
must
return
a
DOMStringList
associated
with
a
sorted
name
list
of
the
names
of
the
object
stores
in
this
connection
's
object
store
set
.
Is this the same as the database 's object store names ?
As long as the connection is open, this is the same as the connected database 's object store names . But once the connection has closed , this attribute will not reflect changes made with a later upgrade transaction .
The
createObjectStore(
name
,
options
)
method,
when
invoked,
must
run
these
steps:
-
Let database be the database associated with this connection .
-
Let transaction be database ’s upgrade transaction if it is not null, or throw an "
InvalidStateError
"DOMException
otherwise. -
If transaction ’s state is not active , then throw a "
TransactionInactiveError
"DOMException
. -
Let keyPath be options ’s
keyPath
member if it is not undefined or null, or null otherwise. -
If keyPath is not null and is not a valid key path , throw a "
SyntaxError
"DOMException
. -
If an object store named name already exists in database throw a "
ConstraintError
"DOMException
. -
Let autoIncrement be set if options ’s
autoIncrement
member is true, or unset otherwise. -
If autoIncrement is set and keyPath is an empty string or any sequence (empty or otherwise), throw an "
InvalidAccessError
"DOMException
. -
Let store be a new object store in database . Set the created object store 's name to name . If autoIncrement is set, then the created object store uses a key generator . If keyPath is not null, set the created object store 's key path to keyPath .
-
Return a new object store handle associated with store and transaction .
This method creates and returns a new object store with the given name in the connected database . Note that this method must only be called from within an upgrade transaction .
This
method
synchronously
modifies
the
objectStoreNames
property
on
the
IDBDatabase
instance
on
which
it
was
called.
In
some
implementations
it
is
possible
for
the
implementation
to
run
into
problems
after
queuing
a
task
to
create
the
object
store
after
the
createObjectStore()
method
has
returned.
For
example
in
implementations
where
metadata
about
the
newly
created
object
store
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,
and
once
the
implementation
determines
that
creating
the
object
store
has
failed,
it
must
abort
the
transaction
using
the
steps
to
abort
a
transaction
using
the
appropriate
error.
For
example
if
creating
the
object
store
failed
due
to
quota
reasons,
a
"
QuotaExceededError
"
DOMException
must
be
used
as
error.
The
deleteObjectStore(
name
)
method,
when
invoked,
must
run
these
steps:
-
Let database be the database associated with this connection .
-
Let transaction be database ’s upgrade transaction if it is not null, or throw an "
InvalidStateError
"DOMException
otherwise. -
If transaction ’s state is not active , then throw a "
TransactionInactiveError
"DOMException
. -
Let store be the object store named name in database , or throw a "
NotFoundError
"DOMException
if none. -
Remove store from this connection 's object store set .
-
If there is an object store handle associated with store and transaction , remove all entries from its index set .
-
Destroy store .
This method destroys the object store with the given name in the connected database . Note that this method must only be called from within an upgrade transaction .
This
method
synchronously
modifies
the
objectStoreNames
property
on
the
IDBDatabase
instance
on
which
it
was
called.
-
transaction
=
connection
.
transaction
( scope [, mode = "readonly"]) -
Returns
a
new
transaction
with
the
given
mode
(
"readonly"
or"readwrite"
) and scope which can be a single object store name or an array of names . -
connection
.
close
() - Closes the connection once all running transactions have finished.
The
transaction(
storeNames
,
mode
)
method,
when
invoked,
must
run
these
steps:
-
If a running upgrade transaction is associated with the connection , throw an "
InvalidStateError
"DOMException
. -
If the connection 's close pending flag is set, throw an "
InvalidStateError
"DOMException
. -
Let scope be the set of unique strings in storeNames if it is a sequence, or a set containing one string equal to storeNames otherwise.
-
If any string in scope is not the name of an object store in the connected database , throw a "
NotFoundError
"DOMException
. -
If scope is empty, throw an "
InvalidAccessError
"DOMException
. -
If mode is not
"readonly"
or"readwrite"
, throw a TypeError . -
Let transaction be a newly created transaction with connection , mode and the set of object stores named in scope .
-
Set transaction ’s cleanup event loop to the current event loop .
-
Return an
IDBTransaction
object representing transaction .
The
close()
method,
when
invoked,
must
run
these
steps:
-
Run the steps to close a database connection with this connection .
The
onabort
attribute
is
the
event
handler
for
the
abort
event.
The
onclose
attribute
is
the
event
handler
for
the
close
event.
The
onerror
attribute
is
the
event
handler
for
the
error
event.
The
onversionchange
attribute
is
the
event
handler
for
the
versionchange
event.
4.5.
The
IDBObjectStore
interface
The
IDBObjectStore
interface
represents
an
object
store
handle
.
[Exposed =(Window ,Worker )]interface {
IDBObjectStore attribute DOMString name ;readonly attribute any keyPath ;readonly attribute DOMStringList indexNames ; [SameObject ]readonly attribute IDBTransaction transaction ;readonly attribute boolean autoIncrement ; [NewObject ]IDBRequest put (any ,
value optional any ); [
key NewObject ]IDBRequest add (any ,
value optional any ); [
key NewObject ]IDBRequest delete (any ); [
query NewObject ]IDBRequest clear (); [NewObject ]IDBRequest get (any ); [
query NewObject ]IDBRequest getKey (any ); [
query NewObject ]IDBRequest getAll (optional any ,
query optional [EnforceRange ]unsigned long ); [
count NewObject ]IDBRequest getAllKeys (optional any ,
query optional [EnforceRange ]unsigned long ); [
count NewObject ]IDBRequest count (optional any ); [
query NewObject ]IDBRequest openCursor (optional any ,
query optional IDBCursorDirection = "next"); [
direction NewObject ]IDBRequest openKeyCursor (optional any ,
query optional IDBCursorDirection = "next");
direction IDBIndex index (DOMString ); [
name NewObject ]IDBIndex createIndex (DOMString , (
name DOMString or sequence <DOMString >),
keyPath optional IDBIndexParameters );
options void deleteIndex (DOMString ); };
name dictionary {
IDBIndexParameters boolean =
unique false ;boolean =
multiEntry false ; };
-
store
.
name
- Returns the name of the store.
-
store
.
name
= newName -
Updates
the
name
of
the
store
to
newName
.
Throws "
InvalidStateError
"DOMException
if not called within an upgrade transaction . -
store
.
keyPath
- Returns the key path of the store, or null if none.
-
list
.
indexNames
- Returns a list of the names of indexes in the store.
-
store
.
transaction
- Returns the associated transaction .
-
store
.
autoIncrement
- Returns true if the store has a key generator , and false otherwise.
The
name
attribute’s
getter
must
return
this
object
store
handle
's
name
.
Is this the same as the object store 's name ?
As long as the transaction has not finished , this is the same as the associated object store 's name . But once the transaction has finished , this attribute will not reflect changes made with a later upgrade transaction .
The
name
attribute’s
setter
must
run
these
steps:
-
Let name be the given value.
-
Let transaction be this object store handle 's transaction .
-
Let store be this object store handle 's object store .
-
If store has been deleted, throw an "
InvalidStateError
"DOMException
. -
If transaction is not an upgrade transaction , throw an "
InvalidStateError
"DOMException
. -
If transaction ’s state is not active , throw a "
TransactionInactiveError
"DOMException
. -
If store ’s name is equal to name , terminate these steps.
-
If an object store named name already exists in store ’s database , throw a "
ConstraintError
"DOMException
. -
Set store ’s name to name .
-
Set this object store handle 's name to name .
The
keyPath
attribute’s
getter
must
return
this
object
store
handle
's
object
store
's
key
path
,
or
null
if
none.
The
key
path
is
converted
as
a
DOMString
(if
a
string)
or
a
sequence<DOMString>
(if
a
list
of
strings),
per
[WEBIDL]
.
The returned value is not the same instance that was used when the object store was created. However, if this attribute returns an object (specifically an Array ), it returns the same object instance every time it is inspected. Changing the properties of the object has no effect on the object store .
The
indexNames
attribute’s
getter
must
return
a
DOMStringList
associated
with
a
sorted
name
list
of
the
names
of
indexes
in
this
object
store
handle
's
index
set
.
Is this the same as object store 's list of index names ?
As long as the transaction has not finished , this is the same as the associated object store 's list of index names . But once the transaction has finished , this attribute will not reflect changes made with a later upgrade transaction .
The
transaction
attribute’s
getter
must
return
this
object
store
handle
's
transaction
.
The
autoIncrement
attribute’s
getter
must
return
true
if
this
object
store
handle
's
object
store
has
a
key
generator
,
and
false
otherwise.
ReadOnlyError
"
DOMException
if
called
within
a
read-only
transaction
,
and
a
"
TransactionInactiveError
"
DOMException
if
called
when
the
transaction
is
not
active
.
-
request
=
store
.
put
( value [, key ])- request = store .
add
( value [, key ]) - request = store .
-
Adds
or
updates
a
record
in
store
with
the
given
value
and
key
.
If the store uses in-line keys and key is specified a "
DataError
"DOMException
will be thrown.If
put()
is used, any existing record with the key will be replaced. Ifadd()
is used, and if a record with the key already exists the request will fail, with request ’serror
set to a "ConstraintError
"DOMException
.If successful, request ’s
result
will be the record 's key . -
request
=
store
.
delete
( query ) -
Deletes
records
in
store
with
the
given
key
or
in
the
given
key
range
in
query
.
If successful, request ’s
result
will beundefined
. -
request
=
store
.
clear
() -
Deletes
all
records
in
store
.
If successful, request ’s
result
will beundefined
.
The
put(
value
,
key
)
method,
when
invoked,
must
run
these
steps:
-
Let transaction be this object store handle 's transaction .
-
Let store be this object store handle 's object store .
-
If store has been deleted, throw an "
InvalidStateError
"DOMException
. -
If transaction ’s state is not active , then throw a "
TransactionInactiveError
"DOMException
. -
If transaction is a read-only transaction , throw a "
ReadOnlyError
"DOMException
. -
If store uses in-line keys and key was given, throw a "
DataError
"DOMException
. -
If store uses out-of-line keys and has no key generator and key was not given, throw a "
DataError
"DOMException
. -
If key was given, then:
-
Let r be the result of running the steps to convert a value to a key with key . Rethrow any exceptions.
-
If r is invalid, throw a "
DataError
"DOMException
. -
Let key be r .
-
-
Let targetRealm be a user-agent defined Realm .
-
Let clone be a clone of value in targetRealm . Rethrow any exceptions.
Why create a copy of the value?
The value is be serialized when stored. Treating it as a copy here allows other algorithms in this specification to treat it as an ECMAScript value, but implementations can optimize this if the difference in behavior is not observable. -
If store uses in-line keys , then:
-
Let kpk be the result of running the steps to extract a key from a value using a key path with clone and store ’s key path . Rethrow any exceptions.
-
If kpk is invalid, throw a "
DataError
"DOMException
. -
If kpk is not failure, let key be kpk .
-
Otherwise ( kpk is failure):
-
If store does not have a key generator , throw a "
DataError
"DOMException
. -
Otherwise, if the steps to check that a key could be injected into a value with clone and store ’s key path return false, throw a "
DataError
"DOMException
.
-
-
-
Run the steps to asynchronously execute a request and return the
IDBRequest
created by these steps. The steps are run with this object store handle as source and the steps to store a record into an object store as operation , using store , the clone as value , key , and with the no-overwrite flag unset.
The
add(
value
,
key
)
method,
when
invoked,
must
run
these
steps:
-
Let transaction be this object store handle 's transaction .
-
Let store be this object store handle 's object store .
-
If store has been deleted, throw an "
InvalidStateError
"DOMException
. -
If transaction ’s state is not active , then throw a "
TransactionInactiveError
"DOMException
. -
If transaction is a read-only transaction , throw a "
ReadOnlyError
"DOMException
. -
If store uses in-line keys and key was given, throw a "
DataError
"DOMException
. -
If store uses out-of-line keys and has no key generator and key was not given, throw a "
DataError
"DOMException
. -
If key was given, then:
-
Let r be the result of running the steps to convert a value to a key with key . Rethrow any exceptions.
-
If r is invalid, throw a "
DataError
"DOMException
. -
Let key be r .
-
-
Let targetRealm be a user-agent defined Realm .
-
Let clone be a clone of value in targetRealm . Rethrow any exceptions.
Why create a copy of the value?
The value is serialized when stored. Treating it as a copy here allows other algorithms in this specification to treat it as an ECMAScript value, but implementations can optimize this if the difference in behavior is not observable. -
If store uses in-line keys , then:
-
Let kpk be the result of running the steps to extract a key from a value using a key path with clone and store ’s key path . Rethrow any exceptions.
-
If kpk is invalid, throw a "
DataError
"DOMException
. -
If kpk is not failure, let key be kpk .
-
Otherwise ( kpk is failure):
-
If store does not have a key generator , throw a "
DataError
"DOMException
. -
Otherwise, if the steps to check that a key could be injected into a value with clone and store ’s key path return false, throw a "
DataError
"DOMException
.
-
-
-
Run the steps to asynchronously execute a request and return the
IDBRequest
created by these steps. The steps are run with this object store handle as source and the steps to store a record into an object store as operation , using store , clone as value , key , and with the no-overwrite flag set.
The
delete(
query
)
method,
when
invoked,
must
run
these
steps:
-
Let transaction be this object store handle 's transaction .
-
Let store be this object store handle 's object store .
-
If store has been deleted, throw an "
InvalidStateError
"DOMException
. -
If transaction ’s state is not active , then throw a "
TransactionInactiveError
"DOMException
. -
If transaction is a read-only transaction , throw a "
ReadOnlyError
"DOMException
. -
Let range be the result of running the steps to convert a value to a key range with query and null disallowed flag set. Rethrow any exceptions.
-
Run the steps to asynchronously execute a request and return the
IDBRequest
created by these steps. The steps are run with this object store handle as source and the steps to delete records from an object store as operation , using store and range .
The
query
parameter
may
be
a
key
or
an
IDBKeyRange
identifying
the
records
keys
to
be
deleted.
The
clear()
method,
when
invoked,
must
run
these
steps:
-
Let transaction be this object store handle 's transaction .
-
Let store be this object store handle 's object store .
-
If store has been deleted, throw an "
InvalidStateError
"DOMException
. -
If transaction ’s state is not active , then throw a "
TransactionInactiveError
"DOMException
. -
If transaction is a read-only transaction , throw a "
ReadOnlyError
"DOMException
. -
Run the steps to asynchronously execute a request and return the
IDBRequest
created by these steps. The steps are run with this object store handle as source and the steps to clear an object store as operation , using store .
TransactionInactiveError
"
DOMException
if
called
when
the
transaction
is
not
active
.
-
request
=
store
.
get
( query ) -
Retrieves
the
value
of
the
first
record
matching
the
given
key
or
key
range
in
query
.
If successful, request ’s
result
will be the value , orundefined
if there was no matching record . -
request
=
store
.
getKey
( query ) -
Retrieves
the
key
of
the
first
record
matching
the
given
key
or
key
range
in
query
.
If successful, request ’s
result
will be the key , orundefined
if there was no matching record . -
request
=
store
.
getAll
( query [, count ]) -
Retrieves
the
values
of
the
records
matching
the
given
key
or
key
range
in
query
(up
to
count
if
given).
If successful, request ’s
result
will be an Array of the values . -
request
=
store
.
getAllKeys
( query [, count ]) -
Retrieves
the
keys
of
records
matching
the
given
key
or
key
range
in
query
(up
to
count
if
given).
If successful, request ’s
result
will be an Array of the keys . -
request
=
store
.
count
( query ) -
Retrieves
the
number
of
records
matching
the
given
key
or
key
range
in
query
.
If successful, request ’s
result
will be the count.
The
get(
query
)
method,
when
invoked,
must
run
these
steps:
-
Let transaction be this object store handle 's transaction .
-
Let store be this object store handle 's object store .
-
If store has been deleted, throw an "
InvalidStateError
"DOMException
. -
If transaction ’s state is not active , then throw a "
TransactionInactiveError
"DOMException
. -
Let range be the result of running the steps to convert a value to a key range with query and null disallowed flag set. Rethrow any exceptions.
-
Run the steps to asynchronously execute a request and return the
IDBRequest
created by these steps. The steps are run with this object store handle as source and the steps to retrieve a value from an object store as operation , using the current Realm as targetRealm , store and range .
The
query
parameter
may
be
a
key
or
an
IDBKeyRange
identifying
the
record
to
be
retrieved.
If
a
range
is
specified,
the
method
retrieves
the
first
existing
value
in
that
range.
The
getKey(
query
)
method,
when
invoked,
must
run
these
steps:
-
Let transaction be this object store handle 's transaction .
-
Let store be this object store handle 's object store .
-
If store has been deleted, throw an "
InvalidStateError
"DOMException
. -
If transaction ’s state is not active , then throw a "
TransactionInactiveError
"DOMException
. -
Let range be the result of running the steps to convert a value to a key range with query and null disallowed flag set. Rethrow any exceptions.
-
Run the steps to asynchronously execute a request and return the
IDBRequest
created by these steps. The steps are run with this object store handle as source and the steps to retrieve a key from an object store as operation , using store and range .
The
query
parameter
may
be
a
key
or
an
IDBKeyRange
identifying
the
record
key
to
be
retrieved.
If
a
range
is
specified,
the
method
retrieves
the
first
existing
key
in
that
range.
The
getAll(
query
,
count
)
method,
when
invoked,
must
run
these
steps:
-
Let transaction be this object store handle 's transaction .
-
Let store be this object store handle 's object store .
-
If store has been deleted, throw an "
InvalidStateError
"DOMException
. -
If transaction ’s state is not active , then throw a "
TransactionInactiveError
"DOMException
. -
Let range be the result of running the steps to convert a value to a key range with query . Rethrow any exceptions.
-
Run the steps to asynchronously execute a request and return the
IDBRequest
created by these steps. The steps are run with this object store handle as source and the steps to retrieve multiple values from an object store as operation , using the current Realm as targetRealm , store , range , and count if given.
The
query
parameter
may
be
a
key
or
an
IDBKeyRange
identifying
the
records
to
be
retrieved.
If
null
or
not
given,
an
unbounded
key
range
is
used.
If
count
is
specified
and
there
are
more
than
count
records
in
range,
only
the
first
count
will
be
retrieved.
The
getAllKeys(
query
,
count
)
method,
when
invoked,
must
run
these
steps:
-
Let transaction be this object store handle 's transaction .
-
Let store be this object store handle 's object store .
-
If store has been deleted, throw an "
InvalidStateError
"DOMException
. -
If transaction ’s state is not active , then throw a "
TransactionInactiveError
"DOMException
. -
Let range be the result of running the steps to convert a value to a key range with query . Rethrow any exceptions.
-
Run the steps to asynchronously execute a request and return the
IDBRequest
created by these steps. The steps are run with this object store handle as source and the steps to retrieve multiple keys from an object store as operation , using store , range , and count if given.
The
query
parameter
may
be
a
key
or
an
IDBKeyRange
identifying
the
records
keys
to
be
retrieved.
If
null
or
not
given,
an
unbounded
key
range
is
used.
If
count
is
specified
and
there
are
more
than
count
keys
in
range,
only
the
first
count
will
be
retrieved.
The
count(
query
)
method,
when
invoked,
must
run
these
steps:
-
Let transaction be this object store handle 's transaction .
-
Let store be this object store handle 's object store .
-
If store has been deleted, throw an "
InvalidStateError
"DOMException
. -
If transaction ’s state is not active , then throw a "
TransactionInactiveError
"DOMException
. -
Let range be the result of running the steps to convert a value to a key range with query . Rethrow any exceptions.
-
Run the steps to asynchronously execute a request and return the
IDBRequest
created by these steps. The steps are run with this object store handle as source and the steps to count the records in a range as operation , with source and range .
The
query
parameter
may
be
a
key
or
an
IDBKeyRange
identifying
the
records
keys
to
be
counted.
If
null
or
not
given,
an
unbounded
key
range
is
used.
TransactionInactiveError
"
DOMException
if
called
when
the
transaction
is
not
active
.
-
request
=
store
.
openCursor
([ query [, direction = "next"]]) -
Opens
a
cursor
over
the
records
matching
query
,
ordered
by
direction
.
If
query
is
null,
all
records
in
store
are
matched.
If successful, request ’s
result
will be anIDBCursorWithValue
pointing at the first matching record , or null if there were no matching records . -
request
=
store
.
openKeyCursor
([ query [, direction = "next"]]) -
Opens
a
cursor
with
key
only
flag
set
over
the
records
matching
query
,
ordered
by
direction
.
If
query
is
null,
all
records
in
store
are
matched.
If successful, request ’s
result
will be anIDBCursor
pointing at the first matching record , or null if there were no matching records .
The
openCursor(
query
,
direction
)
method,
when
invoked,
must
run
these
steps:
-
Let transaction be this object store handle 's transaction .
-
Let store be this object store handle 's object store .
-
If store has been deleted, throw an "
InvalidStateError
"DOMException
. -
If transaction ’s state is not active , then throw a "
TransactionInactiveError
"DOMException
. -
Let range be the result of running the steps to convert a value to a key range with query . Rethrow any exceptions.
-
Let cursor be a new cursor with transaction set to transaction , an undefined position , direction set to direction , got value flag unset, and undefined key and value . The source of cursor is store . The range of cursor is range .
-
Let request be the result of running the steps to asynchronously execute a request with this object store handle as source and the steps to iterate a cursor as operation , using the current Realm as targetRealm , and cursor .
-
Set cursor ’s request to request .
-
Return request .
The
query
parameter
may
be
a
key
or
an
IDBKeyRange
to
use
as
the
cursor
's
range
.
If
null
or
not
given,
an
unbounded
key
range
is
used.
The
openKeyCursor(
query
,
direction
)
method,
when
invoked,
must
run
these
steps:
-
Let transaction be this object store handle 's transaction .
-
Let store be this object store handle 's object store .
-
If store has been deleted, throw an "
InvalidStateError
"DOMException
. -
If transaction ’s state is not active , then throw a "
TransactionInactiveError
"DOMException
. -
Let range be the result of running the steps to convert a value to a key range with query . Rethrow any exceptions.
-
Let cursor be a new cursor with transaction set to transaction , an undefined position , direction set to direction , got value flag unset, and undefined key and value . The source of cursor is store . The range of cursor is range . The key only flag of cursor is set.
-
Let request be the result of running the steps to asynchronously execute a request with this object store handle as source and the steps to iterate a cursor as operation , using the current Realm as targetRealm , and cursor .
-
Set cursor ’s request to request .
-
Return request .
The
query
parameter
may
be
a
key
or
an
IDBKeyRange
to
use
as
the
cursor
's
range
.
If
null
or
not
given,
an
unbounded
key
range
is
used.
- index = store . index( name )
-
Returns
an
IDBIndex
for the index named name in store . -
index
=
store
.
createIndex
( name , keyPath [, options ]) -
Creates
a
new
index
in
store
with
the
given
name
,
keyPath
and
options
and
returns
a
new
IDBIndex
. If the keyPath and options define constraints that cannot be satisfied with the data already in store the upgrade transaction will abort with a "ConstraintError
"DOMException
.Throws an "
InvalidStateError
"DOMException
if not called within an upgrade transaction . -
store
.
deleteIndex
( name ) -
Deletes
the
index
in
store
with
the
given
name
.
Throws an "
InvalidStateError
"DOMException
if not called within an upgrade transaction .
The
createIndex(
name
,
keyPath
,
options
)
method,
when
invoked,
must
run
these
steps:
-
Let transaction be this object store handle 's transaction .
-
Let store be this object store handle 's object store .
-
If transaction is not an upgrade transaction , throw an "
InvalidStateError
"DOMException
. -
If store has been deleted, throw an "
InvalidStateError
"DOMException
. -
If transaction ’s state is not active , then throw a "
TransactionInactiveError
"DOMException
. -
If an index named name already exists in store , throw a "
ConstraintError
"DOMException
. -
If keyPath is not a valid key path , throw a "
SyntaxError
"DOMException
. -
Let unique be set if options ’s
unique
member is true, and unset otherwise. -
Let multiEntry be set if options ’s
multiEntry
member is true, and unset otherwise. -
If keyPath is a sequence and multiEntry is set, throw an "
InvalidAccessError
"DOMException
. -
Let index be a new index in store . Set index ’s name to name and key path to keyPath . If unique is set, set index ’s unique flag . If multiEntry is set, set index ’s multiEntry flag .
-
Add index to this object store handle 's index set .
-
Return a new index handle associated with index and this object store handle .
This method creates and returns a new index with the given name in the object store . Note that this method must only be called from within an upgrade transaction .
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
key
path
.
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,
and
the
implementation
must
queue
a
task
to
abort
the
upgrade
transaction
which
was
used
for
the
createIndex()
call.
This
method
synchronously
modifies
the
indexNames
property
on
the
IDBObjectStore
instance
on
which
it
was
called.
Although
this
method
does
not
return
an
IDBRequest
object,
the
index
creation
itself
is
processed
as
an
asynchronous
request
within
the
upgrade
transaction
.
In
some
implementations
it
is
possible
for
the
implementation
to
asynchronously
run
into
problems
creating
the
index
after
the
createIndex
method
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,
and
once
the
implementation
determines
that
creating
the
index
has
failed,
it
must
abort
the
transaction
using
run
the
steps
to
abort
a
transaction
using
an
appropriate
error
as
error
.
For
example
if
creating
the
index
failed
due
to
quota
reasons,
a
"
QuotaExceededError
"
DOMException
must
be
used
as
error
and
if
the
index
can’t
be
created
due
to
unique
flag
constraints,
a
"
ConstraintError
"
DOMException
must
be
used
as
error.
The
index(
name
)
method,
when
invoked,
must
run
these
steps:
-
Let transaction be this object store handle 's transaction .
-
Let store be this object store handle 's object store .
-
If store has been deleted, throw an "
InvalidStateError
"DOMException
. -
If transaction
has’s state is finished , then throw an "InvalidStateError
"DOMException
. -
Let index be the index named name in this object store handle 's index set if one exists, or throw a "
NotFoundError
"DOMException
otherwise. -
Return an index handle associated with index and this object store handle .
The
deleteIndex(
name
)
method,
when
invoked,
must
run
these
steps:
-
Let transaction be this object store handle 's transaction .
-
Let store be this object store handle 's object store .
-
If transaction is not an upgrade transaction , throw an "
InvalidStateError
"DOMException
. -
If store has been deleted, throw an "
InvalidStateError
"DOMException
. -
If transaction ’s state is not active , then throw a "
TransactionInactiveError
"DOMException
. -
Let index be the index named name in store if one exists, or throw a "
NotFoundError
"DOMException
otherwise. -
Remove index from this object store handle 's index set .
-
Destroy index .
This method destroys the index with the given name in the object store . Note that this method must only be called from within an upgrade transaction .
This
method
synchronously
modifies
the
indexNames
property
on
the
IDBObjectStore
instance
on
which
it
was
called.
Although
this
method
does
not
return
an
IDBRequest
object,
the
index
destruction
itself
is
processed
as
an
asynchronous
request
within
the
upgrade
transaction
.
4.6.
The
IDBIndex
interface
The
IDBIndex
interface
represents
an
index
handle
.
[Exposed =(Window ,Worker )]interface {
IDBIndex attribute DOMString name ; [SameObject ]readonly attribute IDBObjectStore objectStore ;readonly attribute any keyPath ;readonly attribute boolean multiEntry ;readonly attribute boolean unique ; [NewObject ]IDBRequest get (any ); [
query NewObject ]IDBRequest getKey (any ); [
query NewObject ]IDBRequest getAll (optional any ,
query optional [EnforceRange ]unsigned long ); [
count NewObject ]IDBRequest getAllKeys (optional any ,
query optional [EnforceRange ]unsigned long ); [
count NewObject ]IDBRequest count (optional any ); [
query NewObject ]IDBRequest openCursor (optional any ,
query optional IDBCursorDirection = "next"); [
direction NewObject ]IDBRequest openKeyCursor (optional any ,
query optional IDBCursorDirection = "next"); };
direction
-
index
.
name
- Returns the name of the index.
-
index
.
name
= newName -
Updates
the
name
of
the
store
to
newName
.
Throws an "
InvalidStateError
"DOMException
if not called within an upgrade transaction . -
index
.
objectStore
-
Returns
the
IDBObjectStore
the index belongs to. - index . keyPath
- Returns the key path of the index.
- index . multiEntry
- Returns true if the index’s multiEntry flag is set.
- index . unique
- Returns true if the index’s unique flag is set.
The
name
attribute’s
getter
must
return
this
index
handle
's
name
.
Is this the same as the index 's name ?
As long as the transaction has not finished , this is the same as the associated index 's name . But once the transaction has finished , this attribute will not reflect changes made with a later upgrade transaction .
The
name
attribute’s
setter
must
run
these
steps:
-
Let name be the given value.
-
Let transaction be this index handle 's transaction .
-
Let index be this index handle 's index .
-
If transaction is not an upgrade transaction , throw an "
InvalidStateError
"DOMException
. -
If transaction ’s state is not active , then throw a "
TransactionInactiveError
"DOMException
. -
If index or index ’s object store has been deleted, throw an "
InvalidStateError
"DOMException
. -
If index ’s name is equal to name , terminate these steps.
-
If an index named name already exists in index ’s object store , throw a "
ConstraintError
"DOMException
. -
Set index ’s name to name .
-
Set this index handle 's name to name .
The
objectStore
attribute’s
getter
must
return
this
index
handle
's
object
store
handle
.
The
keyPath
attribute’s
getter
must
return
this
index
handle
's
index
's
key
path
.
The
key
path
is
converted
as
a
DOMString
(if
a
string)
or
a
sequence<DOMString>
(if
a
list
of
strings),
per
[WEBIDL]
.
The returned value is not the same instance that was used when the index was created. However, if this attribute returns an object (specifically an Array ), it returns the same object instance every time it is inspected. Changing the properties of the object has no effect on the index .
The
multiEntry
attribute’s
getter
must
return
true
if
this
index
handle
's
index
's
multiEntry
flag
is
set,
and
false
otherwise.
The
unique
attribute’s
getter
must
return
true
if
this
index
handle
's
index
's
unique
flag
is
set,
and
false
otherwise.
TransactionInactiveError
"
DOMException
if
called
when
the
transaction
is
not
active
.
-
request
=
store
.
get
( query ) -
Retrieves
the
value
of
the
first
record
matching
the
given
key
or
key
range
in
query
.
If successful, request ’s
result
will be the value , orundefined
if there was no matching record . -
request
=
store
.
getKey
( query ) -
Retrieves
the
key
of
the
first
record
matching
the
given
key
or
key
range
in
query
.
If successful, request ’s
result
will be the key , orundefined
if there was no matching record . -
request
=
store
.
getAll
( query [, count ]) -
Retrieves
the
values
of
the
records
matching
the
given
key
or
key
range
in
query
(up
to
count
if
given).
If successful, request ’s
result
will be an Array of the values . -
request
=
store
.
getAllKeys
( query [, count ]) -
Retrieves
the
keys
of
records
matching
the
given
key
or
key
range
in
query
(up
to
count
if
given).
If successful, request ’s
result
will be an Array of the keys . -
request
=
store
.
count
( query ) -
Retrieves
the
number
of
records
matching
the
given
key
or
key
range
in
query
.
If successful, request ’s
result
will be the count.
The
get(
query
)
method,
when
invoked,
must
run
these
steps:
-
Let transaction be this index handle 's transaction .
-
Let index be this index handle 's index .
-
If index or index ’s object store has been deleted, throw an "
InvalidStateError
"DOMException
. -
If transaction ’s state is not active , then throw a "
TransactionInactiveError
"DOMException
. -
Let range be the result of running the steps to convert a value to a key range with query and null disallowed flag set. Rethrow any exceptions.
-
Run the steps to asynchronously execute a request and return the
IDBRequest
created by these steps. The steps are run with this index handle as source and the steps to retrieve a referenced value from an index as operation , using the current Realm as targetRealm , index and range .
The
query
parameter
may
be
a
key
or
an
IDBKeyRange
identifying
the
record
to
be
retrieved.
If
a
range
is
specified,
the
method
retrieves
the
first
existing
record
in
that
range.
The
getKey(
query
)
method,
when
invoked,
must
run
these
steps:
-
Let transaction be this index handle 's transaction .
-
Let index be this index handle 's index .
-
If index or index ’s object store has been deleted, throw an "
InvalidStateError
"DOMException
. -
If transaction ’s state is not active , then throw a "
TransactionInactiveError
"DOMException
. -
Let range be the result of running the steps to convert a value to a key range with query and null disallowed flag set. Rethrow any exceptions.
-
Run the steps to asynchronously execute a request and return the
IDBRequest
created by these steps. The steps are run with this index handle as source and the steps to retrieve a value from an index as operation , using index and range .
The
query
parameter
may
be
a
key
or
an
IDBKeyRange
identifying
the
record
key
to
be
retrieved.
If
a
range
is
specified,
the
method
retrieves
the
first
existing
key
in
that
range.
The
getAll(
query
,
count
)
method,
when
invoked,
must
run
these
steps:
-
Let transaction be this index handle 's transaction .
-
Let index be this index handle 's index .
-
If index or index ’s object store has been deleted, throw an "
InvalidStateError
"DOMException
. -
If transaction ’s state is not active , then throw a "
TransactionInactiveError
"DOMException
. -
Let range be the result of running the steps to convert a value to a key range with query . Rethrow any exceptions.
-
Run the steps to asynchronously execute a request and return the
IDBRequest
created by these steps. The steps are run with this index handle as source and the steps to retrieve multiple referenced values from an index as operation , using the current Realm as targetRealm , index , range , and count if given.
The
query
parameter
may
be
a
key
or
an
IDBKeyRange
identifying
the
records
to
be
retrieved.
If
null
or
not
given,
an
unbounded
key
range
is
used.
If
count
is
specified
and
there
are
more
than
count
records
in
range,
only
the
first
count
will
be
retrieved.
The
getAllKeys(
query
,
count
)
method,
when
invoked,
must
run
these
steps:
-
Let transaction be this index handle 's transaction .
-
Let index be this index handle 's index .
-
If index or index ’s object store has been deleted, throw an "
InvalidStateError
"DOMException
. -
If transaction ’s state is not active , then throw a "
TransactionInactiveError
"DOMException
. -
Let range be the result of running the steps to convert a value to a key range with query . Rethrow any exceptions.
-
Run the steps to asynchronously execute a request and return the
IDBRequest
created by these steps. The steps are run with this index handle as source and the steps to retrieve multiple values from an index as operation , using index , range , and count if given.
The
query
parameter
may
be
a
key
or
an
IDBKeyRange
identifying
the
records
keys
to
be
retrieved.
If
null
or
not
given,
an
unbounded
key
range
is
used.
If
count
is
specified
and
there
are
more
than
count
keys
in
range,
only
the
first
count
will
be
retrieved.
The
count(
query
)
method,
when
invoked,
must
run
these
steps:
-
Let transaction be this index handle 's transaction .
-
Let index be this index handle 's index .
-
If index or index ’s object store has been deleted, throw an "
InvalidStateError
"DOMException
. -
If transaction ’s state is not active , then throw a "
TransactionInactiveError
"DOMException
. -
Let range be the result of running the steps to convert a value to a key range with query . Rethrow any exceptions.
-
Run the steps to asynchronously execute a request and return the
IDBRequest
created by these steps. The steps are run with this index handle as source and the steps to count the records in a range as operation , with index as source and range .
The
query
parameter
may
be
a
key
or
an
IDBKeyRange
identifying
the
records
keys
to
be
counted.
If
null
or
not
given,
an
unbounded
key
range
is
used.
TransactionInactiveError
"
DOMException
if
called
when
the
transaction
is
not
active
.
-
request
=
store
.
openCursor
([ query [, direction = "next"]]) -
Opens
a
cursor
over
the
records
matching
query
,
ordered
by
direction
.
If
query
is
null,
all
records
in
index
are
matched.
If successful, request ’s
result
will be anIDBCursorWithValue
, or null if there were no matching records . -
request
=
store
.
openKeyCursor
([ query [, direction = "next"]]) -
Opens
a
cursor
with
key
only
flag
set
over
the
records
matching
query
,
ordered
by
direction
.
If
query
is
null,
all
records
in
index
are
matched.
If successful, request ’s
result
will be anIDBCursor
, or null if there were no matching records .
The
openCursor(
query
,
direction
)
method,
when
invoked,
must
run
these
steps:
-
Let transaction be this index handle 's transaction .
-
Let index be this index handle 's index .
-
If index or index ’s object store has been deleted, throw an "
InvalidStateError
"DOMException
. -
If transaction ’s state is not active , then throw a "
TransactionInactiveError
"DOMException
. -
Let range be the result of running the steps to convert a value to a key range with query . Rethrow any exceptions.
-
Let cursor be a new cursor with transaction set to transaction , an undefined position , direction set to direction , got value flag unset, and undefined key and value . The source of cursor is index . The range of cursor is range .
-
Let request be the result of running the steps to asynchronously execute a request with this index handle as source and the steps to iterate a cursor as operation , using the current Realm as targetRealm , and cursor .
-
Set cursor ’s request to request .
-
Return request .
The
query
parameter
may
be
a
key
or
an
IDBKeyRange
to
use
as
the
cursor
's
range
.
If
null
or
not
given,
an
unbounded
key
range
is
used.
The
openKeyCursor(
query
,
direction
)
method,
when
invoked,
must
run
these
steps:
-
Let transaction be this index handle 's transaction .
-
Let index be this index handle 's index .
-
If index or index ’s object store has been deleted, throw an "
InvalidStateError
"DOMException
. -
If transaction ’s state is not active , then throw a "
TransactionInactiveError
"DOMException
. -
Let range be the result of running the steps to convert a value to a key range with query . Rethrow any exceptions.
-
Let cursor be a new cursor with transaction set to transaction , an undefined position , direction set to direction , got value flag unset, and undefined key and value . The source of cursor is index . The range of cursor is range . The key only flag of cursor is set.
-
Let request be the result of running the steps to asynchronously execute a request with this index handle as source and the steps to iterate a cursor as operation , using the current Realm as targetRealm , and cursor .
-
Set cursor ’s request to request .
-
Return request .
The
query
parameter
may
be
a
key
or
an
IDBKeyRange
to
use
as
the
cursor
's
range
.
If
null
or
not
given,
an
unbounded
key
range
is
used.
4.7.
The
IDBKeyRange
interface
The
IDBKeyRange
interface
represents
a
key
range
.
[Exposed =(Window ,Worker )]interface {
IDBKeyRange readonly attribute any lower ;readonly attribute any upper ;readonly attribute boolean lowerOpen ;readonly attribute boolean upperOpen ; // Static construction methods: [NewObject ]static IDBKeyRange only (any ); [
value NewObject ]static IDBKeyRange (
lowerBound any ,
lower optional boolean =
open false ); [NewObject ]static IDBKeyRange (
upperBound any ,
upper optional boolean =
open false ); [NewObject ]static IDBKeyRange bound (any ,
lower any ,
upper optional boolean =
lowerOpen false ,optional boolean =
upperOpen false );boolean (
_includes any ); };
key
-
range
.
lower
-
Returns
lower
bound
,
or
undefined
if none. -
range
.
upper
-
Returns
upper
bound
,
or
undefined
if none. -
range
.
lowerOpen
- Returns true if the lower open flag is set, and false otherwise.
-
range
.
upperOpen
- Returns true if the upper open flag is set, and false otherwise.
The
lower
attribute’s
getter
must
return
result
of
running
the
steps
to
convert
a
key
to
a
value
with
the
lower
bound
if
it
is
not
null,
or
undefined
otherwise.
The
upper
attribute’s
getter
must
return
the
result
of
running
the
steps
to
convert
a
key
to
a
value
with
the
upper
bound
if
it
is
not
null,
or
undefined
otherwise.
The
lowerOpen
attribute’s
getter
must
return
true
if
the
lower
open
flag
is
set,
and
false
otherwise.
The
upperOpen
attribute’s
getter
must
return
true
if
the
upper
open
flag
is
set,
and
false
otherwise.
-
range
=
IDBKeyRange
.only
( key ) -
Returns
a
new
IDBKeyRange
spanning only key . -
range
=
IDBKeyRange
.lowerBound
( key [, open = false]) -
Returns
a
new
IDBKeyRange
starting at key with no upper bound. If open is true, key is not included in the range. -
range
=
IDBKeyRange
.upperBound
( key [, open = false]) -
Returns
a
new
IDBKeyRange
with no lower bound and ending at key . If open is true, key is not included in the range. -
range
=
IDBKeyRange
.bound
( lower , upper [, lowerOpen = false [, upperOpen = false]]) -
Returns
a
new
IDBKeyRange
spanning from lower to upper . If lowerOpen is true, lower is not included in the range. If upperOpen is true, upper is not included in the range.
The
only(
value
)
method,
when
invoked,
must
run
these
steps:
-
Let key be the result of running the steps to convert a value to a key with value . Rethrow any exceptions.
-
If key is invalid, throw a "
DataError
"DOMException
. -
Create and return a new key range containing only key .
The
lowerBound(
lower
,
lowerOpen
)
method,
when
invoked,
must
run
these
steps:
-
Let lowerKey be the result of running the steps to convert a value to a key with lower . Rethrow any exceptions.
-
If lowerKey is invalid, throw a "
DataError
"DOMException
. -
Create and return a new key range with lower bound set to lowerKey , lower open flag set if lowerOpen is true, upper bound set to null and upper open flag set.
The
upperBound(
upper
,
upperOpen
)
method,
when
invoked,
must
run
these
steps:
-
Let upperKey be the result of running the steps to convert a value to a key with upper . Rethrow any exceptions.
-
If upperKey is invalid, throw a "
DataError
"DOMException
. -
Create and return a new key range with lower bound set to null, lower open flag set, upper bound set if upperKey , and upper open flag set to upperOpen .
The
bound(
lower
,
upper
,
lowerOpen
,
upperOpen
)
method,
when
invoked,
must
run
these
steps:
-
Let lowerKey be the result of running the steps to convert a value to a key with lower . Rethrow any exceptions.
-
If lowerKey is invalid, throw a "
DataError
"DOMException
. -
Let upperKey be the result of running the steps to convert a value to a key with upper . Rethrow any exceptions.
-
If upperKey is invalid, throw a "
DataError
"DOMException
. -
If lowerKey is greater than upperKey , throw a "
DataError
"DOMException
. -
Create and return a new key range with lower bound set to lowerKey , lower open flag set if lowerOpen is true, upper bound set to upperKey and upper open flag set if upperOpen is true.
-
range
.
includes
( key ) - Returns true if key is included in the range, and false otherwise.
The
includes(
key
)
method,
when
invoked,
must
run
these
steps:
-
Let k be the result of running the steps to convert a value to a key with key . Rethrow any exceptions.
-
If k is invalid, throw a "
DataError
"DOMException
. -
Return true if k is in this range, and false otherwise.
4.8.
The
IDBCursor
interface
Cursor
objects
implement
the
IDBCursor
interface.
There
is
only
ever
one
IDBCursor
instance
representing
a
given
cursor
.
There
is
no
limit
on
how
many
cursors
can
be
used
at
the
same
time.
[Exposed =(Window ,Worker )]interface {
IDBCursor readonly attribute (IDBObjectStore or IDBIndex )source ;readonly attribute IDBCursorDirection direction ;readonly attribute any key ;readonly attribute any primaryKey ;void advance ([EnforceRange ]unsigned long );
count void continue (optional any );
key void continuePrimaryKey (any ,
key any ); [
primaryKey NewObject ]IDBRequest update (any ); [
value NewObject ]IDBRequest delete (); };enum {
IDBCursorDirection ,
"next" ,
"nextunique" ,
"prev" };
"prevunique"
-
cursor
.
source
-
Returns
the
IDBObjectStore
orIDBIndex
the cursor was opened from. -
range
.
direction
-
Returns
the
direction
(
"next"
,"nextunique"
,"prev"
or"prevunique"
) of the cursor. -
cursor
.
key
-
Returns
the
key
of
the
cursor.
Throws
a
"
InvalidStateError
"DOMException
if the cursor is advancing or is finished. -
cursor
.
primaryKey
-
Returns
the
effective
key
of
the
cursor.
Throws
a
"
InvalidStateError
"DOMException
if the cursor is advancing or is finished.
The
source
attribute’s
getter
must
return
the
source
of
this
cursor
.
This
attribute
never
returns
null
or
throws
an
exception,
even
if
the
cursor
is
currently
being
iterated,
has
iterated
past
its
end,
or
its
transaction
is
not
active
.
The
direction
attribute’s
getter
must
return
the
direction
of
the
cursor
.
The
key
attribute’s
getter
must
return
the
result
of
running
the
steps
to
convert
a
key
to
a
value
with
the
cursor’s
current
key
.
Note
that
if
this
property
returns
an
object
(e.g.
a
Date
or
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.
The
primaryKey
attribute’s
getter
must
return
the
result
of
running
the
steps
to
convert
a
key
to
a
value
with
the
cursor’s
current
effective
key
.
Note
that
if
this
property
returns
an
object
(e.g.
a
Date
or
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.
success
event
will
be
fired
at
the
same
IDBRequest
returned
when
the
cursor
was
opened.
The
result
will
be
the
same
cursor
if
a
record
was
in
range,
or
undefined
otherwise.
If
called
while
the
cursor
is
already
advancing,
an
"
InvalidStateError
"
DOMException
will
be
thrown.
The
following
methods
throw
a
"
TransactionInactiveError
"
DOMException
if
called
when
the
transaction
is
not
active
.
-
cursor
.
advance
( count ) - Advances the cursor through the next count records in range.
-
cursor
.
continue
() - Advances the cursor to the next record in range.
-
cursor
.
continue
( key ) - Advances the cursor to the next record in range matching or after key .
-
cursor
.
continuePrimaryKey
( key , primaryKey ) -
Advances
the
cursor
to
the
next
record
in
range
matching
or
after
key
and
primaryKey
.
Throws
an
"
InvalidAccessError
"DOMException
if the source is not an index .
The
advance(
count
)
method,
when
invoked,
must
run
these
steps:
-
Let transaction be this cursor 's transaction .
-
If transaction ’s state is not active , then throw a "
TransactionInactiveError
"DOMException
. -
If the cursor’s source or effective object store has been deleted, throw an "
InvalidStateError
"DOMException
. -
If this cursor’s got value flag is unset, indicating that the cursor is being iterated or has iterated past its end, throw an "
InvalidStateError
"DOMException
. -
Unset this cursor 's got value flag .
-
Unset request ’s processed flag and done flag .
-
Run the steps to asynchronously execute a request with the cursor’s source as source , the steps to iterate a cursor as operation and request , using the current Realm as targetRealm , this cursor and count .
The
continue(
key
)
method,
when
invoked,
must
run
these
steps:
-
Let transaction be this cursor 's transaction .
-
If transaction ’s state is not active , then throw a "
TransactionInactiveError
"DOMException
. -
If the cursor’s source or effective object store has been deleted, throw an "
InvalidStateError
"DOMException
. -
If this cursor’s got value flag is unset, indicating that the cursor is being iterated or has iterated past its end, throw an "
InvalidStateError
"DOMException
. -
If key is given, then:
-
Let r be the result of running the steps to convert a value to a key with key . Rethrow any exceptions.
-
If r is invalid, throw a "
DataError
"DOMException
. -
Let key be r .
-
If key is less than or equal to this cursor’s position and this cursor’s direction is
"next"
or"nextunique"
, throw a "DataError
"DOMException
. -
If key is greater than or equal to this cursor’s position and this cursor’s direction is
"prev"
or"prevunique"
, throw a "DataError
"DOMException
.
-
-
Unset this cursor 's got value flag .
-
Unset request ’s processed flag and done flag .
-
Run the steps to asynchronously execute a request with the cursor’s source as source , the steps to iterate a cursor as operation and request , using the current Realm as targetRealm , this cursor and key (if given).
The
continuePrimaryKey(
key
,
primaryKey
)
method,
when
invoked,
must
run
these
steps:
-
Let transaction be this cursor 's transaction .
-
If transaction ’s state is not active , then throw a "
TransactionInactiveError
"DOMException
. -
If the cursor’s source or effective object store has been deleted, throw an "
InvalidStateError
"DOMException
. -
If this cursor’s source is not an index throw an "
InvalidAccessError
"DOMException
. -
If this cursor’s direction is not
"next"
or"prev"
, throw an "InvalidAccessError
"DOMException
. -
If this cursor’s got value flag is unset, indicating that the cursor is being iterated or has iterated past its end, throw an "
InvalidStateError
"DOMException
. -
Let r be the result of running the steps to convert a value to a key with key . Rethrow any exceptions.
-
If r is invalid, throw a "
DataError
"DOMException
. -
Let key be r .
-
Let r be the result of running the steps to convert a value to a key with primaryKey . Rethrow any exceptions.
-
If r is invalid, throw a "
DataError
"DOMException
. -
Let primaryKey be r .
-
If key is less than this cursor’s position and this cursor’s direction is
"next"
, throw a "DataError
"DOMException
. -
If key is greater than this cursor’s position and this cursor’s direction is
"prev"
, throw a "DataError
"DOMException
. -
If key is equal to this cursor’s position and primaryKey is less than or equal to this cursor’s object store position and this cursor’s direction is
"next"
, throw a "DataError
"DOMException
. -
If key is equal to this cursor’s position and primaryKey is greater than or equal to this cursor’s object store position and this cursor’s direction is
"prev"
, throw a "DataError
"DOMException
. -
Unset this cursor 's got value flag .
-
Unset request ’s processed flag and done flag .
-
Run the steps to asynchronously execute a request with the cursor’s source as source , the steps to iterate a cursor as operation and request , using the current Realm as targetRealm , this cursor , key and primaryKey .
ReadOnlyError
"
DOMException
if
called
within
a
read-only
transaction
,
and
a
"
TransactionInactiveError
"
DOMException
if
called
when
the
transaction
is
not
active
.
-
request
=
cursor
.
update
( value ) -
Updated
the
record
pointed
at
by
the
cursor
with
a
new
value.
Throws a "
DataError
"DOMException
if the effective object store uses in-line keys and the key would have changed.If successful, request ’s
result
will be the record 's key . -
request
=
cursor
.
delete
() -
Delete
the
record
pointed
at
by
the
cursor
with
a
new
value.
If successful, request ’s
result
will beundefined
.
The
update(
value
)
method,
when
invoked,
must
run
these
steps:
-
Let transaction be this cursor 's transaction .
-
If transaction ’s state is not active , then throw a "
TransactionInactiveError
"DOMException
. -
If transaction is a read-only transaction , throw a "
ReadOnlyError
"DOMException
. -
If the cursor’s source or effective object store has been deleted, throw an "
InvalidStateError
"DOMException
. -
If this cursor’s got value flag is unset, indicating that the cursor is being iterated or has iterated past its end, throw an "
InvalidStateError
"DOMException
. -
If this cursor’s key only flag is set, throw an "
InvalidStateError
"DOMException
. -
Let targetRealm be a user-agent defined Realm .
-
Let clone be a clone of value in targetRealm . Rethrow any exceptions.
Why create a copy of the value?
The value is serialized when stored. Treating it as a copy here allows other algorithms in this specification to treat it as an ECMAScript value, but implementations can optimize this if the difference in behavior is not observable. -
If the effective object store of this cursor uses in-line keys , then:
-
Let kpk be the result of running the steps to extract a key from a value using a key path with clone and the key path of the effective object store . Rethrow any exceptions.
-
If kpk is failure, invalid, or not equal to the cursor’s effective key , throw a "
DataError
"DOMException
.
-
-
Run the steps to asynchronously execute a request and return the
IDBRequest
created by these steps. The steps are run with this cursor as source and the steps to store a record into an object store as operation , using this cursor’s effective object store as store , the clone as value , this cursor’s effective key as key , and with the no-overwrite flag unset.
The
delete()
method,
when
invoked,
must
run
these
steps:
-
Let transaction be this cursor 's transaction .
-
If transaction ’s state is not active , then throw a "
TransactionInactiveError
"DOMException
. -
If transaction is a read-only transaction , throw a "
ReadOnlyError
"DOMException
. -
If the cursor’s source or effective object store has been deleted, throw an "
InvalidStateError
"DOMException
. -
If this cursor’s got value flag is unset, indicating that the cursor is being iterated or has iterated past its end, throw an "
InvalidStateError
"DOMException
. -
If this cursor’s key only flag is set, throw an "
InvalidStateError
"DOMException
. -
Run the steps to asynchronously execute a request and return the
IDBRequest
created by these steps. The steps are run with this cursor as source and the steps to delete records from an object store as operation , using this cursor’s effective object store and effective key as store and key respectively.
A
cursor
that
has
the
key
only
flag
unset
implements
the
IDBCursorWithValue
interface
as
well.
[Exposed =(Window ,Worker )]interface :
IDBCursorWithValue IDBCursor {readonly attribute any value ; };
The
value
attribute’s
getter
must
return
the
cursor’s
current
value
.
Note
that
if
this
property
returns
an
object,
it
returns
the
same
object
instance
every
time
it
is
inspected,
until
the
cursor’s
value
is
changed.
This
means
that
if
the
object
is
modified,
those
modifications
will
be
seen
by
anyone
inspecting
the
value
of
the
cursor.
However
modifying
such
an
object
does
not
modify
the
contents
of
the
database.
4.9.
The
IDBTransaction
interface
transaction objects implement the following interface:
[Exposed =(Window ,Worker )]interface :
IDBTransaction EventTarget {readonly attribute DOMStringList objectStoreNames ;readonly attribute IDBTransactionMode mode ; [SameObject ]readonly attribute IDBDatabase db ;;readonly attribute DOMException error ;IDBObjectStore objectStore (DOMString );
name ();void commit ();void abort (); // Event handlers:attribute EventHandler onabort ;attribute EventHandler oncomplete ;attribute EventHandler onerror ; };enum {
IDBTransactionMode ,
"readonly" ,
"readwrite" };
"versionchange"
-
transaction
.
objectStoreNames
- Returns a list of the names of object stores in the transaction’s scope . For an upgrade transaction this is all object stores in the database .
-
transaction
.
mode
-
Returns
the
mode
the
transaction
was
created
with
(
"readonly"
or"readwrite"
), or"versionchange"
for an upgrade transaction . -
transaction
.
db
- Returns the transaction’s connection .
-
transaction
.
error
-
If
the
transaction
was
aborted
,
returns
the
error
(a
DOMException
) providing the reason.
The
objectStoreNames
attribute’s
getter
must
run
these
steps:
-
If this transaction is an upgrade transaction , return a
DOMStringList
associated with a sorted name list of the names of the object stores in this transaction 's connection 's object store set . -
Otherwise, return a
DOMStringList
associated with a sorted name list of the names of the object stores in this transaction 's scope .
The
mode
attribute’s
getter
must
return
the
mode
of
the
transaction
.
The
db
attribute’s
getter
must
return
the
database
connection
of
which
this
transaction
is
a
part.
The
error
attribute’s
getter
must
return
this
transaction
's
error
,
or
null
if
none.
-
transaction
.
objectStore
( name ) -
Returns
an
IDBObjectStore
in the transaction 's scope . -
transaction
.
abort()
-
Aborts
the
transaction.
All
pending
requests
will
fail
with
a
"
AbortError
"DOMException
and all changes made to the database will be reverted. -
transaction
.
commit()
-
Attempts
to
commit
the
transaction.
All
pending
requests
will
be
allowed
to
complete,
but
no
new
requests
will
be
accepted.
This
can
be
used
to
force
a
transaction
to
quickly
finish,
without
waiting
for
pending
requests
to
fire
success
events before attempting to commit normally.The transaction will abort if a pending request fails, for example due to a constraint error. The
success
events for successful requests will still fire, but throwing an exception in an event handler will not abort the transaction. Similarly,error
events for failed requests will still fire, but callingpreventDefault()
will not prevent the transaction from aborting.
The
objectStore(
name
)
method,
when
invoked,
must
run
these
steps:
-
If transaction
has’s state is finished , then throw an "InvalidStateError
"DOMException
. -
Let store be the object store named name in this transaction 's scope , or throw a "
NotFoundError
"DOMException
if none. -
Return an object store handle associated with store and this transaction .
The
abort()
method,
when
invoked,
must
run
these
steps:
-
If this transaction 's state is committing or finished , then throw an "
InvalidStateError
"DOMException
. -
UnsetSet the transaction 's state to activeflagand run the steps to abort a transaction with null as error .
The
commit()
method,
when
invoked,
must
run
these
steps:
If this transaction 's state is not active , then throw an "
InvalidStateError
"DOMException
.Run the steps to commit a transaction with this transaction .
The
onabort
attribute
is
the
event
handler
for
the
abort
event.
The
oncomplete
attribute
is
the
event
handler
for
the
complete
event.
The
onerror
attribute
is
the
event
handler
for
the
error
event.
5. Algorithms
5.1. Opening a database
The steps to open a database are as follows. The algorithm in these steps takes four arguments: the origin which requested the database to be opened, a database name , a database version , and a request .
-
Let queue be the connection queue for origin and name .
-
Add request to queue .
-
Wait until all previous requests in queue have been processed.
-
Let db be the database named name in origin , or null otherwise.
-
If version is undefined, let version be 1 if db is null, or db ’s version otherwise.
-
If db is null, let db be a new database with name name , version 0 (zero), and with no object stores . If this fails for any reason, return an appropriate error (e.g. a "
QuotaExceededError
" or "UnknownError
"DOMException
). -
If db ’s version is greater than version , return a newly created "
VersionError
"DOMException
and abort these steps. -
Let connection be a new connection to db .
-
Set connection ’s version to version .
-
If db ’s version is less than version , then:
-
Let openConnections be the set of all connections , except connection , associated with db .
-
For each entry of openConnections that does not have its close pending flag set, queue a task to fire a version change event named
versionchange
at entry with db ’s version and version . -
Wait for all of the events to be fired.
-
If any of the connections in openConnections are still not closed, queue a task to fire a version change event named
blocked
at request with db ’s version and version . -
Wait until all connections in openConnections are closed .
-
Run the steps to run an upgrade transaction using connection , version and request .
-
If connection was closed , return a newly created "
AbortError
"DOMException
and abort these steps. -
If the upgrade transaction was aborted, run the steps to close a database connection with connection , return a newly created "
AbortError
"DOMException
and abort these steps.
-
-
Return connection .
5.2. Closing a database
The steps to close a database connection are as follows. These steps take two arguments, a connection object, and an optional forced flag .
-
Set connection ’s close pending flag .
-
If the forced flag is set, then for each transaction created using connection run the steps to abort a transaction with transaction and newly created "
AbortError
"DOMException
. -
Wait for all transactions created using connection to complete. Once they are complete, connection is closed .
-
If the forced flag is set, then fire an event named
close
at connection .
5.3. Deleting a database
The steps to delete 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 a request .
-
Let queue be the connection queue for origin and name .
-
Add request to queue .
-
Wait until all previous requests in queue have been processed.
-
Let db be the database named name in origin , if one exists. Otherwise, return 0 (zero).
-
Let openConnections be the set of all connections associated with db .
-
For each entry of openConnections that does not have its close pending flag set, queue a task to fire a version change event named
versionchange
at entry with db ’s version and null. -
Wait for all of the events to be fired.
-
If any of the connections in openConnections are still not closed, queue a task to fire a version change event named
blocked
at request with db ’s version and null. -
Wait until all connections in openConnections are closed .
-
Let version be db ’s version .
-
Delete db . If this fails for any reason, return an appropriate error (e.g. "
QuotaExceededError
" or "UnknownError
"DOMException
). -
Return version .
5.4. Committing a transaction
The steps to commit a transaction are as follows. This algorithm takes one argument, the transaction to commit.
-
All the changes madeSet transaction ’s state to committing . Run the
databasefollowing steps in parallel :Wait until every item in transaction ’s request list is processed .
If transaction ’s state is no longer committing , then terminate these steps.
Attempt to write any outstanding changes made by transaction
are writtento the database .-
If an error occurs while writing the changes to the database ,
abort the transaction by followingthen run the steps to abort a transaction with transaction and an appropriate type for the error, for example "QuotaExceededError
" or "UnknownError
"DOMException
, and terminate these steps.. -
Queue a task to run these steps:
-
If transaction is an upgrade transaction , set the database 's upgrade transaction to null.
Fire an event named
complete
at transaction .-
If transaction is an upgrade transaction , then let request be the request associated with transaction and set request ’s transaction to null.
-
5.5. Aborting a transaction
The steps to abort a transaction are as follows. This algorithm takes two arguments: the transaction to abort, and error .
-
All the changes made to the database by the transaction are reverted. For upgrade transactions this includes changes to the set of object stores and indexes , as well as the change to the version . Any object stores and indexes which were created during the transaction are now considered deleted for the purposes of other algorithms.
-
If transaction is an upgrade transaction , run the steps to abort an upgrade transaction with transaction .
If error is not null, set transaction ’s error to error .
-
For each request of transaction ’s request list
with done flag unset,, abort the steps to asynchronously execute a request for request , set request ’s processed flag if not already set, and queue a task to run these steps:-
Set request ’s done flag .
-
Set request ’s result to undefined.
-
Set request ’s error to a newly created "
AbortError
"DOMException
. -
Fire an event named
error
at request with itsbubbles
andcancelable
attributes initialized to true.
-
-
Queue a task to run these steps:
-
If transaction is an upgrade transaction , set the database 's upgrade transaction to null.
-
Fire an event named
abort
at transaction with itsbubbles
attribute initialized to true. -
If transaction is an upgrade transaction , then:
-
Let request be the open request associated with transaction .
-
Set request ’s transaction to null.
-
Set request ’s result to undefined.
-
Unset request ’s processed flag and done flag .
-
-
5.6. Asynchronously executing a request
The steps to asynchronously execute a request are as follows. The algorithm takes a source object and an operation to perform on a database, and an optional request .
These steps can be aborted at any point if the transaction the created request belongs to is aborted using the steps to abort a transaction .
-
Let transaction be the transaction associated with source .
-
If request was not given, let request be a new request with source as source .
-
Add request to the end of transaction ’s request list .
-
Run these steps in parallel :
-
Wait until
all previously added requestsrequest is the first item in transactionhave their done flag’s request listset.that is not processed . -
Let result be the result of performing operation .
-
If result is an error and transaction ’s state is committing , then run the steps to abort a transaction with transaction and error , and terminate these steps.
If result is an error, then revert all changes made by operation .
-
Set request ’s processed flag .
Queue a task to run these steps:
-
Remove request from transaction ’s request list .
Set request ’s done flag .
-
If result is an error, then:
-
Set request ’s result to undefined.
-
Set request ’s error to result .
-
Fire an error event at request .
-
-
Otherwise:
-
Set request ’s result to result .
-
Set request ’s error to undefined.
-
Fire a success event at request .
-
-
-
-
Return request .
5.7. Running an upgrade transaction
The steps to run an upgrade transaction are as follows. This algorithm takes three arguments: a connection object which is used to update the database , a new version to be set for the database , and a request .
-
Let db be connection ’s database .
-
Let transaction be a new upgrade transaction with connection used as connection . The scope of transaction includes every object store in connection .
-
Set database ’s upgrade transaction to transaction .
-
Start transaction .
-
Let old version be db ’s version .
-
Set db ’s version to version . This change is considered part of the transaction , and so if the transaction is aborted , this change is reverted.
-
Set request ’s processed flag .
Queue a task to run these steps:
-
Set request ’s result to connection .
-
Set request ’s transaction to transaction .
-
Set request ’s done flag .
-
Set transaction ’s state to active
flag. -
Let didThrow be the result of running the steps to fire a version change event named
upgradeneeded
at request with old version and version . -
If didThrow is set, run the steps to abort a transaction with the error property set to a newly created "
AbortError
"DOMException
.
-
-
Wait for transaction to finish .
5.8. Aborting an upgrade transaction
The steps to abort an upgrade transaction with transaction are as follows.
-
Let connection be transaction ’s connection .
-
Let database be connection ’s database .
-
Set connection ’s version to database ’s version if database previously existed, or 0 (zero) if database was newly created.
-
Set connection ’s object store set to the set of object stores in database if database previously existed, or the empty set if database was newly created.
-
For each object store handle handle associated with transaction , including those for object stores that were created or deleted during transaction :
-
If handle ’s object store was not newly created during transaction , set handle ’s name to its object store 's name .
-
Set handle ’s index set to the set of indexes that reference its object store .
How is this observable?
Although script cannot access an object store by using theobjectStore()
method on anIDBTransaction
instance after the transaction is aborted, it can still have references toIDBObjectStore
instances where thename
andindexNames
properties can be queried. -
-
For each index handle handle associated with transaction , including those for indexes that were created or deleted during transaction :
-
If handle ’s index was not newly created during transaction , set handle ’s name to its index 's name .
How is this observable?
Although script cannot access an index by using theindex()
method on anIDBObjectStore
instance after the transaction is aborted, it can still have references toIDBIndex
instances where thename
property can be queried. -
5.9. Firing a success event
To fire a success event at a request , the implementation must run these steps:
-
Let event be the result of creating an event using
Event
. -
Set event ’s
type
attribute to "success
". -
Set event ’s
bubbles
andcancelable
attributes to false. -
Let transaction be request ’s transaction .
-
Let legacyOutputDidListenersThrowFlag be initially unset.
-
SetIf transaction ’s state is inactive , then set transaction ’s state to activeflag. -
Dispatch event at request with legacyOutputDidListenersThrowFlag .
-
UnsetIf transaction ’s state is activeflag, then run these steps:-
If legacyOutputDidListenersThrowFlag is set, then run the steps to abort a transaction with transaction and a newly created "
AbortError
"DOMException
. -
If transaction ’s request list is empty, then run the steps to commit a transaction with transaction .
5.10. Firing an error event
To fire an error event at a request , the implementation must run these steps:
-
Let event be the result of creating an event using
Event
. -
Set event ’s
type
attribute to "error
". -
Set event ’s
bubbles
andcancelable
attributes to true. -
Let transaction be request ’s transaction .
-
Let legacyOutputDidListenersThrowFlag be initially unset.
-
SetIf transaction ’s state is inactive , then set transaction ’s state to activeflag. -
Dispatch event at request with legacyOutputDidListenersThrowFlag .
-
UnsetIf transaction ’s state is activeflag, then run these steps:-
If legacyOutputDidListenersThrowFlag is set, then run the steps to abort a transaction with transaction and a newly created "
AbortError
"DOMException
and terminate these steps. This is done even if the event’s canceled flag is not set. -
If the event’s canceled flag is not set, then run the steps to abort a transaction using transaction and request 's error
., and terminate these steps. If transaction ’s request list is empty, then run the steps to commit a transaction with transaction .
5.11. Clone a value
To make a clone of value in targetRealm , the implementation must run these steps:
-
Let serialized be ? StructuredSerializeForStorage ( value ).
-
Let clone be ? StructuredDeserialize ( serialized , targetRealm ).
-
Return clone .
6. Database operations
This section describes various operations done on the data in object stores and indexes in a database . These operations are run by the steps to asynchronously execute a request .
6.1. Object Store Storage Operation
The steps to store a record into an object store with store , value , an optional key , and a no-overwrite flag are as follows.
-
If store uses a key generator , then:
-
If key is undefined, then:
-
Let key be the result of running the steps to generate a key for store .
-
If key is failure, then this operation failed with a "
ConstraintError
"DOMException
. Abort this algorithm without taking any further steps. -
If store also uses in-line keys , then run the steps to inject a key into a value using a key path with value , key and store ’s key path .
-
-
Otherwise, run the steps to possibly update the key generator for store with key .
-
-
If the no-overwrite flag was given to these steps and is set, and a record already exists in store with its key equal to key , then this operation failed with a "
ConstraintError
"DOMException
. Abort this algorithm without taking any further steps. -
If a record already exists in store with its key equal to key , then remove the record from store using the steps to delete records from an object store .
-
Store a record in store containing key as its key and ! StructuredSerializeForStorage ( value ) as its value. The record is stored in the object store’s list of records such that the list is sorted according to the key of the records in ascending order.
-
For each index which references store :
-
Let index key be the result of running the steps to extract a key from a value using a key path with value , index ’s key path , and index ’s multiEntry flag .
-
If index key is an exception, or invalid, or failure, take no further actions for index , and continue these steps for the next index.
-
If index ’s multiEntry flag is unset, or if index key is not an array key , and if index already contains a record with key equal to index key , and index has its unique flag set, then this operation failed with a "
ConstraintError
"DOMException
. Abort this algorithm without taking any further steps. -
If index ’s multiEntry flag is set and index key is an array key , and if index already contains a record with key equal to any of the subkeys of index key , and index has its unique flag set, then this operation failed with a "
ConstraintError
"DOMException
. Abort this algorithm without taking any further steps. -
If index ’s multiEntry flag is unset, or if index key is not an array key then store a record in index containing 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.
-
If index ’s multiEntry flag is set and index key is an array key , then for each subkey of the subkeys of index key store a record in index containing subkey 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.
-
-
Return key .
6.2. Object Store Retrieval Operations
The steps to retrieve a value from an object store with targetRealm , store and range are as follows:
-
Let record be the first record in store ’s list of records whose key is in range , if any.
-
If record was not found, return undefined.
-
Let serialized be of record ’s value .
-
Return ! StructuredDeserialize ( serialized , targetRealm ).
The steps to retrieve multiple values from an object store with targetRealm , store , range and optional count are as follows:
-
If count is not given or is 0 (zero), let count be infinity.
-
Let records be a list containing the first count records in store ’s list of records whose key is in range .
-
Let list be an empty list.
-
For each record of records :
-
Let serialized be record ’s value .
-
Let entry be ! StructuredDeserialize ( serialized , targetRealm ).
-
Append entry to list .
-
-
Return list converted to a sequence<any> .
The steps to retrieve a key from an object store with store and range are as follows:
-
Let record be the first record in store ’s list of records whose key is in range , if any.
-
If record was not found, return undefined.
-
Return the result of running the steps to convert a key to a value with record ’s key.
The steps to retrieve multiple keys from an object store with store , range and optional count are as follows:
-
If count is not given or is 0 (zero), let count be infinity.
-
Let records be a list containing the first count records in store ’s list of records whose key is in range .
-
Let list be an empty list .
-
For each record of records :
-
Let entry be the result of running the steps to convert a key to a value with record ’s key.
-
Append entry to list .
-
-
Return list converted to a sequence<any> .
6.3. Index Retrieval Operations
The steps to retrieve a referenced value from an index with targetRealm , index and range are as follows.
-
Let record be the first record in index ’s list of records whose key is in range , if any.
-
If record was not found, return undefined.
-
Let serialized be record ’s referenced value .
-
Return ! StructuredDeserialize ( serialized , targetRealm ).
The steps to retrieve multiple referenced values from an index with targetRealm , index , range and optional count are as follows:
-
If count is not given or is 0 (zero), let count be infinity.
-
Let records be a list containing the first count records in index ’s list of records whose key is in range .
-
Let list be an empty list .
-
For each record of records :
-
Let serialized be record ’s referenced value .
-
Let entry be ! StructuredDeserialize ( serialized , targetRealm ).
-
Append entry to list .
-
-
Return list converted to a sequence<any> .
The steps to retrieve a value from an index with index and range are as follows.
-
Let record be the first record in index ’s list of records whose key is in range , if any.
-
If record was not found, return undefined.
-
Return the of running the steps to convert a key to a value with record ’s value .
The steps to retrieve multiple values from an index with index , range and optional count are as follows:
-
If count is not given or is 0 (zero), let count be infinity.
-
Let records be a list containing the first count records in index ’s list of records whose key is in range .
-
Let list be an empty list .
-
For each record of records :
-
Let entry be the result of running the steps to convert a key to a value with record ’s value.
-
Append entry to list .
-
-
Return list converted to a sequence<any> .
6.4. Object Store Deletion Operation
The steps to delete records from an object store with store and range are as follows.
-
Remove all records, if any, from store ’s list of records with key in range .
-
For each index which references store , remove every record from index ’s list of records whose value is in range , if any such records exist.
-
Return undefined.
6.5. Record Counting Operation
The steps to count the records in a range with source and range are as follows:
-
Let count be the number of records, if any, in source ’s list of records with key in range .
-
Return count .
6.6. Object Store Clear Operation
The steps to clear an object store with store are as follows.
6.7. Cursor Iteration Operation
The steps to iterate a cursor with targetRealm , cursor , an optional key and primaryKey to iterate to, and an optional count are as follows.
-
Let source be cursor ’s source .
-
Let direction be cursor ’s direction .
-
Assert: if primaryKey is given, source is an index and direction is
"next"
or"prev"
. -
Let records be the list of records in source .
-
Let range be cursor ’s range .
-
Let position be cursor ’s position .
-
Let object store position be cursor ’s object store position .
-
If count is not given, let count be 1.
-
While count is greater than 0:
-
Switch on direction :
-
"next"
-
Let
found
record
be
the
first
record
in
records
which
satisfy
all
of
the
following
requirements:
-
If key is defined, the record’s key is greater than or equal to key .
-
If primaryKey is defined, the record’s key is equal to key and the record’s value is greater than or equal to primaryKey , or the record’s key is greater than key .
-
If position is defined, and source is an object store , the record’s key is greater than position .
-
If position is defined, and source is an index , the record’s key is equal to position and the record’s value is greater than object store position or the record’s key is greater than position .
-
The record’s key is in range .
-
-
"nextunique"
-
Let
found
record
be
the
first
record
in
records
which
satisfy
all
of
the
following
requirements:
-
If key is defined, the record’s key is greater than or equal to key .
-
If position is defined, the record’s key is greater than position .
-
The record’s key is in range .
-
-
"prev"
-
Let
found
record
be
the
last
record
in
records
which
satisfy
all
of
the
following
requirements:
-
If key is defined, the record’s key is less than or equal to key .
-
If primaryKey is defined, the record’s key is equal to key and the record’s value is less than or equal to primaryKey , or the record’s key is less than key .
-
If position is defined, and source is an object store , the record’s key is less than position .
-
If position is defined, and source is an index , the record’s key is equal to position and the record’s value is less than object store position or the record’s key is less than position .
-
The record’s key is in range .
-
-
"prevunique"
-
Let
temp
record
be
the
last
record
in
records
which
satisfy
all
of
the
following
requirements:
-
If key is defined, the record’s key is less than or equal to key .
-
If position is defined, the record’s key is less than position .
-
The record’s key is in range .
If temp record is defined, let found record be the first record in records whose key is equal to temp record ’s key .
-
-
-
If found record is not defined, then:
-
Set cursor ’s key to undefined.
-
If source is an index , set cursor ’s object store position to undefined.
-
If cursor ’s key only flag is unset, set cursor ’s value to undefined.
-
Return null.
-
-
Let position be found record ’s key.
-
If source is an index , let object store position be found record ’s value.
-
Decrease count by 1.
-
-
Set cursor ’s position to position .
-
If source is an index , set cursor ’s object store position to object store position .
-
Set cursor ’s key to found record ’s key.
-
If cursor ’s key only flag is unset, then:
-
Let serialized be found record ’s referenced value .
-
Set cursor ’s value to ! StructuredDeserialize ( serialized , targetRealm )
-
-
Set cursor ’s got value flag .
-
Return cursor .
7. ECMAScript binding
This section defines how key values defined in this specification are converted to and from ECMAScript values, and how they may be extracted from and injected into ECMAScript values using key paths . This section references types and algorithms and uses some algorithm conventions from the ECMAScript Language Specification. [ECMA-262] Conversions not detailed here are defined in [WEBIDL] .
7.1. Extract a key from a value
The steps to extract a key from a value using a key path with value , keyPath and an optional multiEntry flag are as follows. The result of these steps is a key , invalid, or failure, or the steps may throw an exception.
-
Let r be the result of running the steps to evaluate a key path on a value with value and keyPath . Rethrow any exceptions.
-
If r is failure, return failure.
-
Let key be the result of running the steps to convert a value to a key with r if the multiEntry flag is unset, and the result of running the steps to convert a value to a multiEntry key with r otherwise. Rethrow any exceptions.
-
If key is invalid, return invalid.
-
Return key .
The steps to evaluate a key path on a value with value and keyPath are as follows. The result of these steps is an ECMAScript value or failure, or the steps may throw an exception.
-
If keyPath is a list of strings, then:
-
Let result be a new Array object created as if by the expression
[]
. -
Let i be 0.
-
For each item of keyPath :
-
Let key be the result of recursively running the steps to evaluate a key path on a value using item as keyPath and value as value .
-
Assert: key is not an abrupt completion .
-
If key is failure, abort the overall algorithm and return failure.
-
Let status be CreateDataProperty ( result , p , key ).
-
Assert: status is true.
-
Increase i by 1.
-
-
Return result .
-
-
If keyPath is the empty string, return value and skip the remaining steps.
-
Let identifiers be the result of strictly splitting keyPath on U+002E FULL STOP characters (.).
-
For each identifier of identifiers , jump to the appropriate step below:
-
If
Type
(
value
)
is
String,
and
identifier
is
"
length
" - Let value be a Number equal to the number of elements in value .
-
If
value
is
an
Array
and
identifier
is
"
length
" -
Let
value
be
!
ToLength
(
!
Get
(
value
,
"
length
")). -
If
value
is
a
Blob
and identifier is "size
" -
Let
value
be
a
Number
equal
to
value
’s
size
. -
If
value
is
a
Blob
and identifier is "type
" -
Let
value
be
a
String
equal
to
value
’s
type
. -
If
value
is
a
File
and identifier is "name
" -
Let
value
be
a
String
equal
to
value
’s
name
. -
If
value
is
a
File
and identifier is "lastModified
" -
Let
value
be
a
Number
equal
to
value
’s
lastModified
. -
If
value
is
a
File
and identifier is "lastModifiedDate
" -
Let
value
be
a
new
Date
object
with
[[DateValue]]
internal
slot
equal
to
value
’s
lastModified
. - Otherwise
-
-
If Type ( value ) is not Object, return failure.
-
Let hop be ! HasOwnProperty ( value , identifier ).
-
If hop is false, return failure.
-
If value is undefined, return failure.
-
-
If
Type
(
value
)
is
String,
and
identifier
is
"
-
Assert: value is not an abrupt completion .
-
Return value .
7.2. Inject a key into a value
The steps to check that a key could be injected into a value are as follows. The algorithm takes a value and a keyPath , and outputs true or false.
-
Let identifiers be the result of strictly splitting keyPath on U+002E FULL STOP characters (.).
-
Assert: identifiers is not empty.
-
Remove the last member of identifiers .
-
For each remaining identifier of identifiers , if any:
-
Return true if value is an Object or an Array , or false otherwise.
The steps to inject a key into a value using a key path are as follows. The algorithm takes a value , a key and a keyPath .
-
Let identifiers be the result of strictly splitting keyPath on U+002E FULL STOP characters (.).
-
Assert: identifiers is not empty.
-
Let last be the last member of identifiers and remove it from the list.
-
For each remaining identifier of identifiers :
-
Let hop be ! HasOwnProperty ( value , identifier ).
-
If hop is false, then:
-
Let o be a new Object created as if by the expression
({})
. -
Let status be CreateDataProperty ( value , identifier , o ).
-
Assert: status is true.
-
-
Let keyValue be the result of running the steps to convert a key to a value with key .
-
Let status be CreateDataProperty ( value , last , keyValue ).
-
Assert: status is true.
7.3. Convert a key to a value
The steps to convert a key to a value are as follows. These steps take one argument, key , and return an ECMAScript value.
-
Let type be key ’s type .
-
Let value be key ’s value .
-
Switch on type :
- number
- Return an ECMAScript Number value equal to value
- string
- Return an ECMAScript String value equal to value
- date
-
-
Let date be the result of executing the ECMAScript Date constructor with the single argument value .
-
Assert: date is not an abrupt completion .
-
Return date .
-
- binary
-
-
Let len be the length of value .
-
Let buffer be the result of executing the ECMAScript ArrayBuffer constructor with len .
-
Assert: buffer is not an abrupt completion .
-
Set the entries in buffer ’s [[ArrayBufferData]] internal slot to the entries in value .
-
Return buffer .
-
- array
-
-
Let array be the result of executing the ECMAScript Array constructor with no arguments.
-
Assert: array is not an abrupt completion .
-
Let len be the length of value .
-
Let index be 0.
-
While index is less than len :
-
Let entry be the result of running the steps to convert a key to a value with the index th entry of value as input.
-
Let status be CreateDataProperty ( array , index , entry ).
-
Assert: status is true.
-
Increase index by 1.
-
-
Return array .
-
7.4. Convert a value to a key
The steps to convert a value to a key are as follows. These steps take two arguments, an ECMAScript value input , and an optional set seen . The result of these steps is a key or invalid, or the steps may throw an exception.
-
If seen was not given, let seen be a new empty set.
-
If input is in seen return invalid.
-
Jump to the appropriate step below:
- If Type ( input ) is Number
- If input is a Date (has a [[DateValue]] internal slot)
- If Type ( input ) is String
- If input is a buffer source type
-
-
Let octets be the result of running the steps to get a copy of the bytes held by the buffer source input . Rethrow any exceptions.
-
- If IsArray ( input )
-
-
Add input to seen .
-
Let keys be a new empty list.
-
Let index be 0.
-
While index is less than len :
-
Let hop be ? HasOwnProperty ( input , index ).
-
If hop is false, return invalid.
-
Let key be the result of running the steps to convert a value to a key with arguments entry and seen .
-
ReturnIfAbrupt ( key ).
-
If key is invalid abort these steps and return invalid.
-
Append key to keys .
-
Increase index by 1.
-
- Otherwise
- Return invalid.
The steps to convert a value to a multiEntry key are as follows. These steps take one argument, an ECMAScript value input . The result of these steps is a key or invalid, or the steps may throw an exception.
-
If IsArray ( input ), then:
-
Let seen be a new set containing only input .
-
Let keys be a new empty set.
-
Let index be 0.
-
While index is less than len :
-
Let entry be Get ( input , index ).
-
If entry is not an abrupt completion , then:
-
Let key be the result of running the steps to convert a value to a key with arguments entry and seen .
-
If key is not invalid or an abrupt completion , add key to keys if there are no other members of keys equal to key .
-
-
Increase index by 1.
-
-
Return a new array key with value set to a list of the members of keys .
-
Otherwise, return the result of running the steps to convert a value to a key with argument input . Rethrow any exceptions.
8. Privacy Considerations
This section is non-normative.
8.1. User tracking
A third-party host (or any object capable of getting content distributed to multiple sites) could use a unique identifier stored in its client-side database to track a user across multiple sessions, building a profile of the user’s activities. In conjunction with a site that is aware of the user’s real id object (for example an e-commerce site that requires authenticated credentials), this could allow oppressive groups to target individuals with greater accuracy than in a world with purely anonymous Web usage.
There are a number of techniques that can be used to mitigate the risk of user tracking:
- Blocking third-party storage
-
User
agents
may
restrict
access
to
the
database
objects
to
scripts
originating
at
the
domain
of
the
top-level
document
of
the
browsing
context
,
for
instance
denying
access
to
the
API
for
pages
from
other
domains
running
in
iframe
s. - Expiring stored data
-
User agents may automatically delete stored data after a period of time.
This can restrict the ability of a site to track a user, as the site would then only be able to track the user across multiple sessions when she authenticates with the site itself (e.g. by making a purchase or logging in to a service).
However, this also puts the user’s data at risk.
- Treating persistent storage as cookies
-
User agents should present the database feature to the user in a way that associates them strongly with HTTP session cookies. [COOKIES]
This might encourage users to view such storage with healthy suspicion.
- Site-specific safe-listing of access to databases
-
User agents may require the user to authorize access to databases before a site can use the feature.
- Origin-tracking of stored data
-
User agents may record the origins of sites that contained content from third-party origins that caused data to be stored.
If this information is then used to present the view of data currently in persistent storage, it would allow the user to make informed decisions about which parts of the persistent storage to prune. Combined with a blocklist ("delete this data and prevent this domain from ever storing data again"), the user can restrict the use of persistent storage to sites that she trusts.
- Shared blocklists
-
User agents may allow users to share their persistent storage domain blocklists.
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 visitors' IP addresses and other user-specific data (e.g. user-agent headers and configuration settings) to combine separate sessions into coherent user profiles.
8.2. Cookie resurrection
If the user interface for persistent storage presents data in the persistent storage features described in this specification separately from data in HTTP session cookies, then users are likely to delete data in one and not the other. This would allow sites to use the two features as redundant backup for each other, defeating a user’s attempts to protect his privacy.
8.3. Sensitivity of data
User agents should treat persistently stored data as potentially sensitive; it is 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.
9. Security Considerations
9.1. DNS spoofing attacks
Because of the potential for DNS spoofing attacks, one cannot guarantee that a host claiming to be in a certain domain really is from that domain. To mitigate this, pages can use TLS. Pages using TLS can be sure that only pages using TLS that have certificates identifying them as being from the same domain can access their databases.
9.2. Cross-directory attacks
Different
authors
sharing
one
host
name,
for
example
users
hosting
content
on
geocities.com
,
all
share
one
set
of
databases.
There is no feature to restrict the access by pathname. Authors on shared hosts are therefore recommended to avoid using these features, as it would be trivial for other authors to read the data and overwrite it.
9.3. Implementation risks
The two primary risks when implementing these persistent storage features are letting hostile sites read information from other domains, and letting hostile sites write information that is then read from other domains.
Letting third-party sites read data that is not supposed to be read from their domain causes information leakage , For example, a user’s shopping wish list on one domain could be used by another domain for targeted advertising; or a user’s work-in-progress confidential documents stored by a word-processing site could be examined by the site of a competing company.
Letting third-party sites write data to the persistent storage of other domains can result in information spoofing , which is equally dangerous. For example, a hostile site could add records to a user’s wish list; or a hostile site could set a user’s session identifier to a known ID that the hostile site can then use to track the user’s actions on the victim site.
Thus, strictly following the origin model described in this specification is important for user security.
If
origins
or
database
names
are
used
to
construct
paths
for
persistence
to
a
file
system
they
must
be
appropriately
escaped
to
prevent
an
adversary
from
accessing
information
from
other
origins
using
relative
paths
such
as
"
../
".
9.4. Persistence risks
Practical implementations will persist data to a non-volatile storage medium. Data will be serialized when stored and deserialized when retrieved, although the details of the serialization format will be user-agent specific. User agents are likely to change their serialization format over time. For example, the format may be updated to handle new data types, or to improve performance. To satisfy the operational requirements of this specification, implementations must therefore handle older serialization formats in some way. Improper handling of older data can result in security issues. In addition to basic serialization concerns, serialized data could encode assumptions which are not valid in newer versions of the user agent.
A practical example of this is the RegExp type. The StructuredSerializeForStorage operation allows serializing RegExp objects. A typical user agent will compile a regular expression into native machine instructions, with assumptions about how the input data is passed and results returned. If this internal state was serialized as part of the data stored to the database, various problems could arise when the internal representation was later deserialized. For example, the means by which data was passed into the code could have changed. Security bugs in the compiler output could have been identified and fixed in updates to the user agent, but remain in the serialized internal state.
User agents must identify and handle older data appropriately. One approach is to include version identifiers in the serialization format, and to reconstruct any internal state from script-visible state when older data is encountered.
10. Revision History
This section is non-normative.
The following is an informative summary of the changes since the last publication of this specification. A complete revision history can be found here . For the revision history of the first edition, see that document’s Revision History . For the revision history of the second edition, see that document’s Revision History .
-
The cleanup Indexed Database transactions algorithm now returns a value for integration with other specs. ( PR #232 )
-
Updated partial interface definition since
WindowOrWorkerGlobalScope
is now amixin
( PR #238 ). -
Added
databases()
method. ( Issue #31 ) -
Added
commit()
method. ( Issue #234 )
11. Acknowledgements
This section is non-normative.
Special thanks to Nikunj Mehta, the original author of the first edition, and Jonas Sicking, Eliot Graff, Andrei Popescu, and Jeremy Orlow, additional editors of the first edition.
Garret Swart was extremely influential in the design of this specification.
Thanks to Tab Atkins, Jr. for creating and maintaining Bikeshed , the specification authoring tool used to create this document, and for his general authoring advice.
Special thanks to Chris Anderson, Andreas Butler, Pablo Castro, Victor Costan, Kristof Degrave, Domenic Denicola, Jake Drew, Ben Dilts, João Eiras, Alec Flett, Dana Florescu, David Grogan, Israel Hilerio, Jerome Hode, Kyle Huey, Philip Jägenstedt, Laxminarayan G Kamath A, Anne van Kesteren, Adam Klein, Tobie Langel, Kang-Hao Lu, Andrea Marchesini, Glenn Maynard, Ms2ger, Odin Omdal, Danillo Paiva, Olli Pettay, Addison Phillips, Simon Pieters, Anthony Ramine, Yonathan Randolph, Arun Ranganathan, Kagami Sascha Rosylight, Margo Seltzer, Maciej Stachowiak, Andrew Sutherland, Bevis Tseng, Ben Turner, Kyaw Tun, Hans Wennborg, Shawn Wilsher, Brett Zamir, Boris Zbarsky, Zhiqiang Zhang, and Kris Zyp, all of whose feedback and suggestions have led to improvements to this specification.