Indexed Database API 3.0

W3C Working Draft,

More details about this document
This version:
https://www.w3.org/TR/2023/WD-IndexedDB-3-20231212/
Latest published version:
https://www.w3.org/TR/IndexedDB/
Editor's Draft:
https://w3c.github.io/IndexedDB/
Previous Versions:
History:
https://www.w3.org/standards/history/IndexedDB-3/
Test Suite:
https://github.com/web-platform-tests/wpt/tree/master/IndexedDB
Feedback:
GitHub
Editor:
(Google)
Former Editor:
Ali Alabbas (Formerly of Microsoft)

Abstract

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

Status of this document

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

This document was published by the Web Applications Working Group as a Working Draft. This document is intended to become a W3C Recommendation.

This document was published by the Web Applications Working Group as a Working Draft using the Recommendation track. Feedback and comments on this specification are welcome. Please use GitHub issues Historical discussions can be found in the public-webapps@w3.org archives.

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

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

This document is governed by the 03 November 2023 W3C Process Document.

This is the Third Edition of Indexed Database API. The First Edition, simply titled "Indexed Database API", became a W3C Recommendation on 8 January 2015. The Second Edition, titled "Indexed Database API 2.0", became a W3C Recommendation on 30 January 2018.

Indexed Database API 3.0 is intended to supersede Indexed Database API 2.0.

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.

The following example uses the API to access a "library" database. It has a "books" object store that holds books records stored by their "isbn" property as the primary key.

Book records have a "title" property. This example artificially requires that book titles are unique. The code enforces this by creating an index named "by_title" with the option set. This index is used to look up books by title, and will prevent adding books with non-unique titles.

Book records also have an "author" property, which is not required to be unique. The code creates another index named "by_author" to allow look-ups by this property.

The code first opens a connection to the database. The event handler code creates the object store and indexes, if needed. The event handler code saves the opened connection for use in later examples.

const request = indexedDB.open("library");
let db;

request.onupgradeneeded = function() {
  // The database did not previously exist, so create object stores and indexes.
  const db = request.result;
  const store = db.createObjectStore("books", {keyPath: "isbn"});
  const titleIndex = store.createIndex("by_title", "title", {unique: true});
  const authorIndex = store.createIndex("by_author", "author");

  // Populate with initial data.
  store.put({title: "Quarry Memories", author: "Fred", isbn: 123456});
  store.put({title: "Water Buffaloes", author: "Fred", isbn: 234567});
  store.put({title: "Bedrock Nights", author: "Barney", isbn: 345678});
};

request.onsuccess = function() {
  db = request.result;
};

The following example populates the database using a transaction.

const tx = db.transaction("books", "readwrite");
const store = tx.objectStore("books");

store.put({title: "Quarry Memories", author: "Fred", isbn: 123456});
store.put({title: "Water Buffaloes", author: "Fred", isbn: 234567});
store.put({title: "Bedrock Nights", author: "Barney", isbn: 345678});

tx.oncomplete = function() {
  // All requests have succeeded and the transaction has committed.
};

The following example looks up a single book in the database by title using an index.

const tx = db.transaction("books", "readonly");
const store = tx.objectStore("books");
const index = store.index("by_title");

const request = index.get("Bedrock Nights");
request.onsuccess = function() {
  const matching = request.result;
  if (matching !== undefined) {
    // A match was found.
    report(matching.isbn, matching.title, matching.author);
  } else {
    // No match was found.
    report(null);
  }
};

The following example looks up all books in the database by author using an index and a cursor.

const tx = db.transaction("books", "readonly");
const store = tx.objectStore("books");
const index = store.index("by_author");

const request = index.openCursor(IDBKeyRange.only("Fred"));
request.onsuccess = function() {
  const cursor = request.result;
  if (cursor) {
    // Called for each matching record.
    report(cursor.value.isbn, cursor.value.title, cursor.value.author);
    cursor.continue();
  } else {
    // No more matching records.
    report(null);
  }
};

The following example shows one way to handle errors when a request fails.

const tx = db.transaction("books", "readwrite");
const store = tx.objectStore("books");
const request = store.put({title: "Water Buffaloes", author: "Slate", isbn: 987654});
request.onerror = function(event) {
  // The uniqueness constraint of the "by_title" index failed.
  report(request.error);
  // Could call event.preventDefault() to prevent the transaction from aborting.
};
tx.onabort = function() {
  // Otherwise the transaction will automatically abort due the failed request.
  report(tx.error);
};

The database connection can be closed when it is no longer needed.

db.close();

In the future, the database might have grown to contain other object stores and indexes. The following example shows one way to handle migrating from an older version.

const request = indexedDB.open("library", 3); // Request version 3.
let db;

request.onupgradeneeded = function(event) {
  const db = request.result;
  if (event.oldVersion < 1) {
    // Version 1 is the first version of the database.
    const store = db.createObjectStore("books", {keyPath: "isbn"});
    const titleIndex = store.createIndex("by_title", "title", {unique: true});
    const authorIndex = store.createIndex("by_author", "author");
  }
  if (event.oldVersion < 2) {
    // Version 2 introduces a new index of books by year.
    const bookStore = request.transaction.objectStore("books");
    const yearIndex = bookStore.createIndex("by_year", "year");
  }
  if (event.oldVersion < 3) {
    // Version 3 introduces a new object store for magazines with two indexes.
    const magazines = db.createObjectStore("magazines");
    const publisherIndex = magazines.createIndex("by_publisher", "publisher");
    const frequencyIndex = magazines.createIndex("by_frequency", "frequency");
  }
};

request.onsuccess = function() {
  db = request.result; // db.version will be 3.
};
A single database can be used by multiple clients (pages and workers) simultaneously — transactions ensure they don’t clash while reading and writing. If a new client wants to upgrade the database (via the event), it cannot do so until all other clients close their connection to the current version of the database.

To avoid blocking a new client from upgrading, clients can listen for the event. This fires when another client is wanting to upgrade the database. To allow this to continue, react to the event by doing something that ultimately closes this client’s to the database.

One way of doing this is to reload the page:

db.onversionchange = function() {
  // First, save any unsaved data:
  saveUnsavedData().then(function() {
    // If the document isn't being actively used, it could be appropriate to reload
    // the page without the user's interaction.
    if (!document.hasFocus()) {
      location.reload();
      // Reloading will close the database, and also reload with the new JavaScript
      // and database definitions.
    } else {
      // If the document has focus, it can be too disruptive to reload the page.
      // Maybe ask the user to do it manually:
      displayMessage("Please reload this page for the latest version.");
    }
  });
};

function saveUnsavedData() {
  // How you do this depends on your app.
}

function displayMessage() {
  // Show a non-modal message to the user.
}

Another way is to call the 's method. However, you need to make sure your app is aware of this, as subsequent attempts to access the database will fail.

db.onversionchange = function() {
  saveUnsavedData().then(function() {
    db.close();
    stopUsingTheDatabase();
  });
};

function stopUsingTheDatabase() {
  // Put the app into a state where it no longer uses the database.
}

The new client (the one attempting the upgrade) can use the event to detect if other clients are preventing the upgrade from happening. The event fires if other clients still hold a connection to the database after their events have fired.

const request = indexedDB.open("library", 4); // Request version 4.
let blockedTimeout;

request.onblocked = function() {
  // Give the other clients time to save data asynchronously.
  blockedTimeout = setTimeout(function() {
    displayMessage("Upgrade blocked - Please close other tabs displaying this site.");
  }, 1000);
};

request.onupgradeneeded = function(event) {
  clearTimeout(blockedTimeout);
  hideMessage();
  // ...
};

function hideMessage() {
  // Hide a previously displayed message.
}

The user will only see the above message if another client fails to disconnect from the database. Ideally the user will never see this.

2. Constructs

A is a equivalent to a ; that is, an arbitrary sequence of 16-bit code units of any length, including the empty string. are always compared as opaque sequences of 16-bit code units.

NOTE: As a result, comparison is sensitive to variations in case as well as other minor variations such as normalization form, the inclusion or omission of controls, and other variations in Unicode text. [Charmod-Norm]

If an implementation uses a storage mechanism which does not support arbitrary strings, the implementation can use an escaping mechanism or something similar to map the provided name to a string that it can store.

To from a names, run these steps:

  1. Let sorted be names with the algorithm.

  2. Return a new associated with sorted.

Details This matches the method on an of . 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 has an associated set of . A has zero or more which hold the data stored in the database.

A has a which identifies it within a specific . The name is a , and stays constant for the lifetime of the database.

A has a . When a database is first created, its is 0 (zero).

NOTE: Each has one version at a time; a can’t exist in multiple versions at once. The only way to change the version is using an .

A has at most one associated , which is either null or an , and is initially null.

2.1.1. Database connection

Script does not interact with directly. Instead, script has indirect access via a . A object can be used to manipulate the objects of that . It is also the only way to obtain a for that .

The act of opening a creates a . There may be multiple to a given at any given time.

A can only access associated with the of the global scope from which the is opened.

NOTE: This is not affected by changes to the 's .

A has a , which is set when the is created. It remains constant for the lifetime of the unless an , in which case it is set to the previous version of the . Once the is closed the does not change.

Each connection has a which is initially false.

When a is initially created it is in an opened state. The connection can be through several means. If the execution context where the 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 . When the connection is closed its is always set to true if it hasn’t already been.

A 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 's storage. If this occurs the user agent must run with the and with the forced flag set to true.

A has an , which is initialized to the set of in the associated when the is created. The contents of the set will remain constant except when an is .

A 's algorithm returns null.

An event with type will be fired at an open if an attempt is made to upgrade or delete the . This gives the the opportunity to close to allow the upgrade or delete to proceed.

An event with type will be fired at a if the connection is abnormally.

2.2. Object store

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

Each database has a set of . The set of can be changed, but only using an , i.e. in response to an event. When a new database is created it doesn’t contain any .

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

An has a , which is a . At any one time, the name is unique within the to which it belongs.

An optionally has a . If the object store has a key path it is said to use . Otherwise it is said to use .

An optionally has a .

An object store can derive a for a from one of three sources:

  1. A . A key generator generates a monotonically increasing numbers every time a key is needed.

  2. Keys can be derived via a .

  3. Keys can also be explicitly specified when a is stored in the object store.

2.2.1. Object store handle

Script does not interact with directly. Instead, within a , script has indirect access via an .

An has an associated and an associated . Multiple handles may be associated with the same in different , but there must be only one associated with a particular within a .

An has an , which is initialized to the set of that reference the associated when the is created. The contents of the set will remain constant except when an is .

An has a , which is initialized to the of the associated when the is created. The name will remain constant except when an is .

2.3. Values

Each record is associated with a . User agents must support any . This includes simple types such as primitive values and objects as well as and instances, objects, objects, objects, and so on. Record 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 are output by the operation.

2.4. Keys

In order to efficiently retrieve stored in an indexed database, each is organized according to its .

A has an associated which is one of: number, date, string, binary, or array.

A also has an associated , which will be either: an if type is number or date, a if type is string, a if type is binary, or a of other if type is array.

An ECMAScript [ECMA-262] value can be converted to a by following the steps to .

NOTE: The following ECMAScript types are valid keys:

Attempting to convert other ECMAScript values to a will fail.

An is a with array. The of an are the of the 's .

To a and b, run these steps:

  1. Let ta be the of a.

  2. Let tb be the of b.

  3. If ta does not equal tb, then run these steps:

    1. If ta is array, then return 1.

    2. If tb is array, then return -1.

    3. If ta is binary, then return 1.

    4. If tb is binary, then return -1.

    5. If ta is string, then return 1.

    6. If tb is string, then return -1.

    7. If ta is date, then return 1.

    8. : tb is date.

    9. Return -1.

  4. Let va be the of a.

  5. Let vb be the of b.

  6. Switch on ta:

    number
    date
    1. If va is greater than vb, then return 1.

    2. If va is less than vb, then return -1.

    3. Return 0.

    string
    1. If va is vb, then return -1.

    2. If vb is va, then return 1.

    3. Return 0.

    binary
    1. If va is vb, then return -1.

    2. If vb is va, then return 1.

    3. Return 0.

    array
    1. Let length be the lesser of va’s and vb’s .

    2. Let i be 0.

    3. While i is less than length, then:

      1. Let c be the result of recursively with va[i] and vb[i].

      2. If c is not 0, return c.

      3. Increase i by 1.

    4. If va’s is greater than vb’s , then return 1.

    5. If va’s is less than vb’s , then return -1.

    6. Return 0.

The a is the b if the result of with a and b is 1.

The a is the b if the result of with a and b is -1.

The a is the b if the result of with a and b is 0.

NOTE: As a result of the above rules, negative infinity is the lowest possible value for a . Number keys are less than date keys. Date keys are less than string keys. String keys are less than binary keys. Binary keys are less than array keys. There is no highest possible value. This is because an array of any candidate highest followed by another is even higher.

NOTE: Members of binary keys are compared as unsigned values (in the range 0 to 255 inclusive) rather than signed values (in the range -128 to 127 inclusive).

2.5. Key path

A is a string or list of strings that defines how to extract a from a . A is one of:

NOTE: Spaces are not allowed within a key path.

values can only be accessed from properties explicitly copied by , as well as the following type-specific properties:

Type Properties
,
,
length
length

2.6. Index

It is sometimes useful to retrieve in an through other means than their . An allows looking up in an using properties of the in the .

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

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

For example, if an index’s object store contains a record with the key 123 and the value { name: "Alice", title: "CEO" }, and the index’s is "name" then the index would contain a record with the key "Alice" and the value 123.

Records in an index are said to have a . 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 is Y and value is X has a of A.

In the preceding example, the record in the index with key "Alice" and value 123 would have a of { name: "Alice", title: "CEO" }.

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

The in an index are always sorted according to the '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 's 's value (meaning the key of the record in the referenced ).

An has a , which is a . At any one time, the name is unique within index’s .

An has a . When true, the index enforces that no two in the index has the same key. If a 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 has a . This flag affects how the index behaves when the result of evaluating the index’s yields an . If its is false, then a single whose is an is added to the index. If its is true, then one is added to the index for each of the .

2.6.1. Index handle

Script does not interact with directly. Instead, within a , script has indirect access via an .

An has an associated and an associated . The of an is the of its associated . Multiple handles may be associated with the same in different , but there must be only one associated with a particular within a .

An has a , which is initialized to the of the associated when the is created. The name will remain constant except when an is .

2.7. Transactions

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

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

All transactions are created through a , which is the transaction’s .

A has a which is a of that the transaction may interact with.

NOTE: A 's remains fixed unless the is an .

Two have if any is in both transactions' .

A has a that determines which types of interactions can be performed upon that transaction. The is set when the transaction is created and remains fixed for the life of the transaction. A 's is one of the following:

""

The transaction is only allowed to read data. No modifications can be done by this type of transaction. This has the advantage that several can be at the same time even if their are , 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.

""

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 "" transactions can’t be at the same time if their are 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.

""

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 event is fired.

A has a . This is a hint to the user agent of whether to prioritize performance or durability when committing the transaction. The is one of the following:

""

The user agent may consider that the has successfully only after verifying that all outstanding changes have been successfully written to a persistent storage medium.

""

The user agent may consider that the has successfully as soon as all outstanding changes have been written to the operating system, without subsequent verification.

""

The user agent should use its default durability behavior for the . This is the default for if not otherwise specified.

NOTE: In a typical implementation, "" is a hint to the user agent to flush any operating system I/O buffers before a event is fired. While this provides greater confidence that the changes will be persisted in case of subsequent operating system crash or power loss, flushing buffers can take significant time and consume battery life on portable devices.

Web applications are encouraged to use "" for ephemeral data such as caches or quickly changing records, and "" in cases where reducing the risk of data loss outweighs the impact to performance and power. Implementations are encouraged to weigh the durability hint from applications against the impact to users and devices.

A optionally has a which is an .

A has a of pending which have been made against the transaction.

A has a which is set if the is .

A 's algorithm returns the transaction’s .

A is a with "".

A is a with "".

2.7.1. Transaction lifecycle

A has a , which is one of the following:

A transaction is in this state when it is first , and during dispatch of an event from a associated with the transaction.

New can be made against the transaction when it is in this state.

A transaction is in this state after control returns to the event loop after its creation, and when events are not being dispatched.

No can be made against the transaction when it is in this state.

Once all associated with a transaction have completed, the transaction will enter this state as it attempts to .

No can be made against the transaction when it is in this state.

Once a transaction has committed or aborted, it enters this state.

No can be made against the transaction when it is in this state.

Transactions are expected to be short lived. This is encouraged by the functionality described below.

NOTE: Authors can still cause transactions to stay for a long time; however, this usage pattern is not advised as it can lead to a poor user experience.

The of a is as follows:

  1. A transaction is with a and a . When a transaction is created its is initially .

  2. When an implementation is able to enforce the constraints for the transaction’s and , defined below, the implementation must to the transaction asynchronously.

    Once the transaction has been the implementation can begin executing the placed against the transaction. Requests must be executed in the order in which they were made against the transaction. Likewise, their results must be returned in the order the requests were placed against a specific transaction. There is no guarantee about the order that results from requests in different transactions are returned.

    NOTE: Transaction ensure that two requests placed against different transactions can execute in any order without affecting what resulting data is stored in the database.

  3. When each associated with a transaction is , a or will be fired. While the event is being , the transaction is set to , allowing additional requests to be made against the transaction. Once the event dispatch is complete, the transaction’s is set to again.

  4. A transaction can be at any time before it is , even if the transaction isn’t currently or hasn’t yet .

    An explicit call to will initiate an . 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 during that transaction. This includes both changes to the contents of as well as additions and removals of and .

  5. The implementation must attempt to a transaction when all placed against the transaction have completed and their returned results handled, no new requests have been placed against the transaction, and the transaction has not been

    An explicit call to will initiate a without waiting for request results to be handled by script.

    When committing, the transaction is set to . The implementation must atomically write any changes to the made by requests placed against the transaction. That is, either all of the changes must be written, or if an error occurs, such as a disk write error, the implementation must not write any of the changes to the database, and the steps to will be followed.

  6. When a transaction is or , its is set to .

The implementation must allow to be against the transaction whenever it is . This is the case even if the transaction has not yet been . Until the transaction is the implementation must not execute these requests; however, the implementation must keep track of the and their order.

A is said to be from when it is until its is set to .

To , run the following steps. They will return true if any transactions were cleaned up, or false otherwise.

  1. If there are no with matching the current , return false.

  2. For each transaction with matching the current :

    1. Set transaction’s to .

    2. Clear transaction’s .

  3. Return true.

NOTE: These steps are invoked by [HTML]. They ensure that created by a script call to are deactivated once the task that invoked the script has completed. The steps are run at most once for each .

An event with type is fired at a that has successfully .

An event with type is fired at a that has .

2.7.2. Transaction scheduling

The following constraints define when a can be :

Implementations may impose additional constraints. For example, implementations are not required to non- in parallel, or may impose limits on the number of transactions.

NOTE: These constraints imply the following:

2.7.3. Upgrade transactions

An is a with "".

An is automatically created when running the steps to after a is opened to a , if a greater than the current is specified. This will be active inside the event handler.

NOTE: An enables the creation, renaming, and deletion of and in a .

An is exclusive. The steps to ensure that only one to the database is open when an is . The event isn’t fired, and thus the isn’t started, until all other to the same are closed. This ensures that all previous transactions are .

As long as an is , attempts to open more to the same are delayed, and any attempts to use the same to start additional transactions by calling will throw an exception. This ensures that no other transactions are concurrently, and also ensures that no new transactions are queued against the same as long as the is .

This further ensures that once an is complete, the set of and in a remain constant for the lifetime of all subsequent and .

2.8. Requests

Each asynchronous operation on a is done using a . Every request represents one operation.

A has a which is initially false. This flag is set to true when the operation associated with the request has been executed.

A is said to be when its is true.

A has a which is initially false. This flag is set to true when the result of the operation associated with the request is available.

A has a object.

A has a and an , neither of which are accessible until its is true.

A has a which is initially null. This will be set when a request is against a using the steps to .

When a request is made, a new is returned with its set to false. If a request completes successfully, its is set to true, its is set to the result of the request, and an event with type is fired at the .

If an error occurs while performing the operation, the request’s is set to true, the request’s is set to the error, and an event with type is fired at the request.

A 's algorithm returns the request’s .

NOTE: Requests are not typically re-used, but there are exceptions. When a is iterated, the success of the iteration is reported on the same object used to open the cursor. And when an is necessary, the same is used for both the event and final result of the open operation itself. In some cases, the request’s will be set to false, then set to true again, and the can change or could be set instead.

2.8.1. Open requests

An is a special type of used when opening a or deleting a . In addition to and events, and events may be fired at an to indicate progress.

The of an is always null.

The of an is null unless an event has been fired.

An 's algorithm returns null.

2.8.2. Connection queues

are processed in a . The queue contains all associated with an and a . Requests added to the processed in order and each request must run to completion before the next request is processed. An open request may be blocked on other , requiring those connections to before the request can complete and allow further requests to be processed.

NOTE: A is not a associated with an , as the requests are processed outside any specific . The delivery of events to completed still goes through a associated with the of the context where the request was made.

2.9. Key range

Records can be retrieved from and using either or . A is a continuous interval over some data type used for keys.

A has an associated (null or a ).

A has an associated (null or a ).

A has an associated . Unless otherwise stated it is false.

A has an associated . Unless otherwise stated it is false.

A may have a its . A must not have a its .

A key has both and equal to key.

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

NOTE:

An is a that has both and equal to null. All are an .

To with value and optional null disallowed flag, run these steps:

  1. If value is a , return value.

  2. If value is undefined or is null, then a "" if null disallowed flag is true, or return an otherwise.

  3. Let key be the result of with value. Rethrow any exceptions.

  4. If key is invalid, a "" .

  5. Return a key.

2.10. Cursor

A is used to iterate over a range of records in an or an in a specific direction.

A has a , the that was when the cursor was created.

A has a of records in either an or an .

A has a that indicates which or an is associated with the records over which the is iterating.

A has a that determines whether it moves in monotonically increasing or decreasing order of the 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 or at its end. A cursor’s is one of the following:

""

This direction causes the cursor to be opened at the start of the . When iterated, the should yield all records, including duplicates, in monotonically increasing order of keys.

""

This direction causes the cursor to be opened at the start of the . When iterated, the 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 is an or an with its set to true, this direction has exactly the same behavior as "".

""

This direction causes the cursor to be opened at the end of the . When iterated, the should yield all records, including duplicates, in monotonically decreasing order of keys.

""

This direction causes the cursor to be opened at the end of the . When iterated, the 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 is an or an with its set to true, this direction has exactly the same behavior as "".

A has a within its range. It is possible for the list of records which the cursor is iterating over to change before the full of the cursor has been iterated. In order to handle this, cursors maintain their not as an index, but rather as a 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 the one previously returned. For a backwards iterating cursor, the situation is opposite and it returns the record with the highest 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 . When iterating indexes the also has an , which indicates the of the previously found in the index. Both and the are used when finding the next appropriate record.

A has a and a which represent the and the of the last iterated .

A has a . When this flag is false, the cursor is either in the process of loading the next value or it has reached the end of its . When it is true, it indicates that the cursor is currently holding a value and that it is ready to iterate to the next one.

If the of a cursor is an , the of the cursor is that object store and the of the cursor is the cursor’s . If the of a cursor is an , the of the cursor is that index’s object store and the is the cursor’s .

A has a , which is the used to open the cursor.

A also has a , that indicates whether the cursor’s is exposed via the API.

2.11. Key generators

When a is created it can be specified to use a . A key generator is used to generate keys for records inserted into an object store if not otherwise specified.

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

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

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

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

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

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

To for an store, run these steps:

  1. Let generator be store’s .

  2. Let key be generator’s .

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

  4. Increase generator’s by 1.

  5. Return key.

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

To for an store with key, run these steps:

  1. If the of key is not number, abort these steps.

  2. Let value be the of key.

  3. Set value to the minimum of value and 253 (9007199254740992).

  4. Set value to the largest integer not greater than value.

  5. Let generator be store’s .

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

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

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

When the of a key generator reaches above the value 253 (9007199254740992) any subsequent attempts to use the key generator to generate a new will result in a "" . It is still possible to insert into the object store by specifying an explicit key, however the only way to use a key generator again for such records is to delete the object store and create a new one.

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

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

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

Each object store gets its own key generator:

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

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

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

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

store = db.createObjectStore("store1", { autoIncrement: true });
store.put("a"); // Will get key 1
store.delete(1);
store.put("b"); // Will get key 2
store.clear();
store.put("c"); // Will get key 3
store.delete(IDBKeyRange.lowerBound(0));
store.put("d"); // Will get key 4

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

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

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

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

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

If the following conditions are true:

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

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

If the following conditions are true:

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

const store = db.createObjectStore("store", { keyPath: "foo.bar",
                                              autoIncrement: true });
store.put({ foo: { bar: 10 } }).onsuccess = function(e) {
  const key = e.target.result;
  console.assert(key === 10);
};

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

const store = db.createObjectStore("store", { keyPath: "foo.bar.baz",
                                              autoIncrement: true });
store.put({ zip: {} }).onsuccess = function(e) {
  const key = e.target.result;
  console.assert(key === 1);
  store.get(key).onsuccess = function(e) {
    const value = e.target.result;
    // value will be: { zip: {}, foo: { bar: { baz: 1 } } }
    console.assert(value.foo.bar.baz === 1);
  };
};

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

const store = db.createObjectStore("store", { keyPath: "foo", autoIncrement: true });

// The key generation will attempt to create and store the key path
// property on this primitive.
store.put(4); // will throw DataError

// The key generation will attempt to create and store the key path
// property on this array.
store.put([10]); // will throw DataError

3. Exceptions

Each of the exceptions used in this document is a with a specific type. The exception types and properties such as legacy code value are defined in [WEBIDL].

The table below lists the s used in this document along with a description of the exception type’s usage.

Type Description
A request was aborted.
A mutation operation in the transaction failed because a constraint was not satisfied.
The data being stored could not be cloned by the internal structured cloning algorithm.
Data provided to an operation does not meet requirements.
An invalid operation was performed on an object.
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.
The operation failed because the requested database object could not be found.
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.
The keyPath argument contains an invalid key path.
The mutating operation was attempted in a read-only transaction.
A request was placed against a transaction which is currently not active, or which is finished.
The operation failed for reasons unrelated to the database itself and not covered by any other errors.
An attempt was made to open a database using a lower version than the existing version.

NOTE: Given that multiple Indexed DB operations can throw the same type of error, and that even a single operation can throw the same type of error for multiple reasons, implementations are encouraged to provide more specific messages to enable developers to identify the cause of errors.

4. API

The API methods return without blocking the calling thread. All asynchronous operations immediately return an 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 instance.

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

4.1. The interface

The interface provides the means to access results of asynchronous requests to and objects using [HTML].

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

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

const request = indexedDB.open('AddressBook', 15);
request.onsuccess = function(evt) {...};
request.onerror = function(evt) {...};
[=(Window,Worker)]
interface  :  {
  readonly attribute  ;
  readonly attribute ? ;
  readonly attribute ( or  or )? ;
  readonly attribute ? ;
  readonly attribute  ;

  // Event handlers:
  attribute  ;
  attribute  ;
};

enum  {
  ,
  
};
request .

When a request is completed, returns the , or undefined if the request failed. Throws a "" if the request is still pending.

request .

When a request is completed, returns the (a ), or null if the request succeeded. Throws a "" if the request is still pending.

request .

Returns the , , or the request was made against, or null if it was an .

request .

Returns the the request was made within. If this as an , then it returns an while it is , or null otherwise.

request .

Returns "" until a request is complete, then returns "".

The getter steps are:
  1. If 's is false, then an "" .

  2. Otherwise, return 's , or undefined if the request resulted in an error.

The getter steps are:
  1. If 's is false, then an "" .

  2. Otherwise, return 's , or null if no error occurred.

The getter steps are to return 's , or null if no is set.

The getter steps are to return 's .

NOTE: The getter can return null for certain requests, such as for returned from .

The getter steps are to return "" if 's is false, and "" otherwise.

The attribute is an whose is .

The attribute is an whose is event.

Methods on that return a use an extended interface to allow listening to the and events.

[=(Window,Worker)]
interface  :  {
  // Event handlers:
  attribute  ;
  attribute  ;
};

The attribute is an whose is .

The attribute is an whose is .

4.2. Event interfaces

This specification fires events with the following custom interfaces:

[=(Window,Worker)]
interface  :  {
  constructor( type, optional  eventInitDict = {});
  readonly attribute  ;
  readonly attribute ? ;
};

dictionary  :  {
   oldVersion = 0;
  ? newVersion = null;
};

The getter steps are to return the value it was initialized to. It represents the previous version of the database.

The getter steps are to return the value it was initialized to. It represents the new version of the database, or null if the database is being deleted. See the steps to .

Events are constructed as defined in DOM § 2.5 Constructing events.

To named e at target given oldVersion and newVersion, run these steps:

  1. Let event be the result of using .

  2. Set event’s attribute to e.

  3. Set event’s and attributes to false.

  4. Set event’s attribute to oldVersion.

  5. Set event’s attribute to newVersion.

  6. Let legacyOutputDidListenersThrowFlag be false.

  7. event at target with legacyOutputDidListenersThrowFlag.

  8. Return legacyOutputDidListenersThrowFlag.

    NOTE: The return value of this algorithm is not always used.

4.3. The interface

objects are accessed through methods on the interface. A single object implementing this interface is present in the global scope of environments that support Indexed DB operations.

partial interface mixin  {
  [] readonly attribute  ;
};

The attribute provides applications a mechanism for accessing capabilities of indexed databases.

[=(Window,Worker)]
interface  {
  []  ( name,
                                    optional []  version);
  []  ( name);

  <<>> ();

   ( first,  second);
};

dictionary  {
   ;
   ;
};
request = indexedDB . (name)

Attempts to open a to the named with the current version, or 1 if it does not already exist. If the request is successful request’s will be the .

request = indexedDB . (name, version)

Attempts to open a to the named with the specified version. If the database already exists with a lower version and there are open that don’t close in response to a event, the request will be blocked until they all 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’s will be the .

request = indexedDB . (name)

Attempts to delete the named . If the database already exists and there are open that don’t close in response to a event, the request will be blocked until they all close. If the request is successful request’s will be null.

result = await indexedDB . ()

Returns a promise which resolves to a list of objects giving a snapshot of the names and versions of databases within the .

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 method steps are:

  1. If version is 0 (zero), a .

  2. Let environment be 's .

  3. Let storageKey be the result of running given environment. If failure is returned, then a "" and abort these steps.

  4. Let request be a new .

  5. Run these steps :

    1. Let result be the result of , with storageKey, name, version if given and undefined otherwise, and request.

      What happens if version is not given? If version is not given and a with that name already exists, a connection will be opened without changing the . If version is not given and no with that name exists, a new will be created with equal to 1.
    2. to run these steps:

      1. If result is an error, then:

        1. Set request’s to undefined.

        2. Set request’s to result.

        3. Set request’s to true.

        4. named at request with its and attributes initialized to true.

      2. Otherwise:

        1. Set request’s to result.

        2. Set request’s to true.

        3. named at request.

        NOTE: If the steps above resulted in an being run, these steps will run after that transaction finishes. This ensures that in the case where another version upgrade is about to happen, the success event is fired on the connection first so that the script gets a chance to register a listener for the event.

        Why aren’t the steps to or 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.
  6. Return a new object for request.

The method steps are:

  1. Let environment be 's .

  2. Let storageKey be the result of running given environment. If failure is returned, then a "" and abort these steps.

  3. Let request be a new .

  4. Run these steps :

    1. Let result be the result of , with storageKey, name, and request.

    2. Set request’s to true.

    3. to run these steps:

      1. If result is an error, set request’s to result, set request’s to true, and named at request with its and attributes initialized to true.

      2. Otherwise, set request’s to undefined, set request’s to true, and named at with result and null.

        Why aren’t the steps to or 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 event here is a which includes the and details.

  5. Return a new object for request.

The method steps are:

  1. Let environment be 's .

  2. Let storageKey be the result of running given environment. If failure is returned, then return a ""

  3. Let p be .

  4. Run these steps :

    1. Let databases be the of in storageKey. If this cannot be determined for any reason, then p with an appropriate error (e.g. an "" ) and terminate these steps.

    2. Let result be a new .

    3. db of databases:

      1. Let info be a new dictionary.

      2. Set info’s dictionary member to db’s .

      3. Set info’s dictionary member to db’s .

      4. info to result.

    4. p with result.

  5. Return p.

🚧 The method is new in this edition. It is supported in Chrome 71, Edge 79, and Safari 14. 🚧
result = indexedDB . (key1, key2)

Compares two values as . Returns -1 if key1 precedes key2, 1 if key2 precedes key1, and 0 if the keys are equal.

Throws a "" if either input is not a valid .

The method steps are:

  1. Let a be the result of with first. Rethrow any exceptions.

  2. If a is invalid, a "" .

  3. Let b be the result of with second. Rethrow any exceptions.

  4. If b is invalid, a "" .

  5. Return the results of with a and b.

4.4. The interface

The interface represents a to a .

An object must not be garbage collected if its associated 's is false and it has one or more event listeners registers whose type is one of , , or . If an object is garbage collected, the associated must be .

[=(Window,Worker)]
interface  :  {
  readonly attribute  ;
  readonly attribute  ;
  readonly attribute  ;

  []  (( or <>) storeNames,
                                         optional  mode = "readonly",
                                         optional  options = {});
   ();

  []  (
     name,
    optional  options = {});
   ( name);

  // Event handlers:
  attribute  ;
  attribute  ;
  attribute  ;
  attribute  ;
};

enum  { , ,  };

dictionary  {
    = "default";
};

dictionary  {
  ( or <>)?  = null;
    = false;
};
connection .

Returns the of the database.

connection .

Returns the of the database.

The getter steps are to return 's associated 's .

NOTE: The attribute returns this name even if 's is true. In other words, the value of this attribute stays constant for the lifetime of the instance.

The getter steps are to return 's .

Is this the same as the 's ? As long as the is open, this is the same as the connected 's . But once the has , this attribute will not reflect changes made with a later .
connection .

Returns a list of the names of in the database.

store = connection . (name [, options])

Creates a new with the given name and options and returns a new .

Throws a "" if not called within an .

connection . (name)

Deletes the with the given name.

Throws a "" if not called within an .

The getter steps are:
  1. Let names be a of the of the in 's .

  2. Return the result (a ) of with names.

Is this the same as the 's ? As long as the is open, this is the same as the connected 's . But once the has , this attribute will not reflect changes made with a later .

The method steps are:

  1. Let database be 's associated .

  2. Let transaction be database’s if it is not null, or an "" otherwise.

  3. If transaction’s is not , then a "" .

  4. Let keyPath be options’s member if it is not undefined or null, or null otherwise.

  5. If keyPath is not null and is not a , a "" .

  6. If an name already exists in database a "" .

  7. Let autoIncrement be options’s member.

  8. If autoIncrement is true and keyPath is an empty string or any sequence (empty or otherwise), an "" .

  9. Let store be a new in database. Set the created 's to name. If autoIncrement is true, then the created uses a . If keyPath is not null, set the created 's to keyPath.

  10. Return a new associated with store and transaction.

This method creates and returns a new with the given name in the . Note that this method must only be called from within an .

This method synchronously modifies the property on the 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 after the method has returned. For example in implementations where metadata about the newly created 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 object, and once the implementation determines that creating the has failed, it must abort the transaction using the steps to using the appropriate error. For example if creating the failed due to quota reasons, a "" must be used as error.

The method steps are:

  1. Let database be 's associated .

  2. Let transaction be database’s if it is not null, or an "" otherwise.

  3. If transaction’s is not , then a "" .

  4. Let store be the name in database, or a "" if none.

  5. Remove store from 's .

  6. If there is an associated with store and transaction, remove all entries from its .

  7. Destroy store.

This method destroys the with the given name in the . Note that this method must only be called from within an .

This method synchronously modifies the property on the instance on which it was called.

transaction = connection . (scope [, mode [, options ] ])

Returns a new with the given scope (which can be a single or an array of ), mode ("" or ""), and additional options including ("", "" or "").

The default mode is "" and the default is "".

connection . ()

Closes the once all running have finished.

The method steps are:

  1. If a is associated with the , an "" .

  2. If 's is true, then an "" .

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

  4. If any string in scope is not the name of an in the , a "" .

  5. If scope is empty, an "" .

  6. If mode is not "" or "", a .

  7. Let transaction be a newly with this , mode, options member, and the set of named in scope.

  8. Set transaction’s to the current .

  9. Return an object representing transaction.

🚧 The option is new in this edition. It is supported in Chrome 82, Edge 82, and Safari 15. 🚧

NOTE: The created transaction will follow the rules.

The method steps are:

  1. Run with this .

NOTE: The will not actually until all outstanding have completed. Subsequent calls to will have no effect.

The attribute is an whose is .

The attribute is an whose is .

The attribute is an whose is .

The attribute is an whose is .

4.5. The interface

The interface represents an .

[=(Window,Worker)]
interface  {
  attribute  ;
  readonly attribute  ;
  readonly attribute  ;
  [] readonly attribute  ;
  readonly attribute  ;

  []  ( value, optional  key);
  []  ( value, optional  key);
  []  ( query);
  []  ();
  []  ( query);
  []  ( query);
  []  (optional  query,
                                optional []  count);
  []  (optional  query,
                                    optional []  count);
  []  (optional  query);

  []  (optional  query,
                                    optional  direction = "next");
  []  (optional  query,
                                       optional  direction = "next");

   ( name);

  []  ( name,
                                   ( or <>) keyPath,
                                   optional  options = {});
   ( name);
};

dictionary  {
    = false;
    = false;
};
store .

Returns the of the store.

store . = newName

Updates the of the store to newName.

Throws "" if not called within an .

store .

Returns the of the store, or null if none.

store .

Returns a list of the names of indexes in the store.

store .

Returns the associated .

store .

Returns true if the store has a , and false otherwise.

The getter steps are to return 's .

Is this the same as the 's ? As long as the has not , this is the same as the associated 's . But once the has , this attribute will not reflect changes made with a later .

The setter steps are:

  1. Let name be .

  2. Let transaction be 's .

  3. Let store be 's .

  4. If store has been deleted, an "" .

  5. If transaction is not an , an "" .

  6. If transaction’s is not , a "" .

  7. If store’s is equal to name, terminate these steps.

  8. If an name already exists in store’s , a "" .

  9. Set store’s to name.

  10. Set 's to name.

The getter steps are to return 's 's , or null if none. The is converted as a (if a string) or a <> (if a list of strings), per [WEBIDL].

NOTE: The returned value is not the same instance that was used when the was created. However, if this attribute returns an object (specifically an ), it returns the same object instance every time it is inspected. Changing the properties of the object has no effect on the .

The getter steps are:
  1. Let names be a of the of the in 's .

  2. Return the result (a ) of with names.

Is this the same as 's list of ? As long as the has not , this is the same as the associated 's list of . But once the has , this attribute will not reflect changes made with a later .

The getter steps are to return 's .

The getter steps are to return true if 's has a , and false otherwise.

The following methods throw a "" if called within a , and a "" if called when the is not .
request = store . (value [, key])
request = store . (value [, key])

Adds or updates a in store with the given value and key.

If the store uses and key is specified a "" will be thrown.

If is used, any existing with the will be replaced. If is used, and if a with the already exists the request will fail, with request’s set to a "" .

If successful, request’s will be the 's .

request = store . (query)

Deletes in store with the given or in the given in query.

If successful, request’s will be undefined.

request = store . ()

Deletes all in store.

If successful, request’s will be undefined.

The method steps are to return the result of running with , value, key and the no-overwrite flag false.

The method steps are to return the result of running with , value, key and the no-overwrite flag true.

To with handle, value, key, and no-overwrite flag, run these steps:

  1. Let transaction be handle’s .

  2. Let store be handle’s .

  3. If store has been deleted, an "" .

  4. If transaction’s is not , then a "" .

  5. If transaction is a , a "" .

  6. If store uses and key was given, a "" .

  7. If store uses and has no and key was not given, a "" .

  8. If key was given, then:

    1. Let r be the result of with key. Rethrow any exceptions.

    2. If r is invalid, a "" .

    3. Let key be r.

  9. Let targetRealm be a user-agent defined .

  10. Let clone be a of value in targetRealm during transaction. 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.
  11. If store uses , then:

    1. Let kpk be the result of with clone and store’s . Rethrow any exceptions.

    2. If kpk is invalid, a "" .

    3. If kpk is not failure, let key be kpk.

    4. Otherwise (kpk is failure):

      1. If store does not have a , a "" .

      2. Otherwise, if with clone and store’s return false, a "" .

  12. Let operation be an algorithm to run with store, clone, key, and no-overwrite flag.

  13. Return the result (an ) of running with handle and operation.

The method steps are:

  1. Let transaction be 's .

  2. Let store be 's .

  3. If store has been deleted, an "" .

  4. If transaction’s is not , then a "" .

  5. If transaction is a , a "" .

  6. Let range be the result of with query and true. Rethrow any exceptions.

  7. Let operation be an algorithm to run with store and range.

  8. Return the result (an ) of running with and operation.

NOTE: The query parameter can be a or (an ) identifying the to be deleted.

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

The method steps are:

  1. Let transaction be 's .

  2. Let store be 's .

  3. If store has been deleted, an "" .

  4. If transaction’s is not , then a "" .

  5. If transaction is a , a "" .

  6. Let operation be an algorithm to run with store.

  7. Return the result (an ) of running with and operation.

The following methods throw a "" if called when the is not .
request = store . (query)

Retrieves the of the first matching the given or in query.

If successful, request’s will be the , or undefined if there was no matching .

request = store . (query)

Retrieves the of the first matching the given or in query.

If successful, request’s will be the , or undefined if there was no matching .

request = store . (query [, count])

Retrieves the of the matching the given or in query (up to count if given).

If successful, request’s will be an of the .

request = store . (query [, count])

Retrieves the of matching the given or in query (up to count if given).

If successful, request’s will be an of the .

request = store . (query)

Retrieves the number of matching the given or in query.

If successful, request’s will be the count.

The method steps are:

  1. Let transaction be 's .

  2. Let store be 's .

  3. If store has been deleted, an "" .

  4. If transaction’s is not , then a "" .

  5. Let range be the result of with query and true. Rethrow any exceptions.

  6. Let operation be an algorithm to run with , store, and range.

  7. Return the result (an ) of running with and operation.

NOTE: The query parameter can be a or (an ) identifying the value to be retrieved. If a range is specified, the method retrieves the first existing value in that range.

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

The method steps are:

  1. Let transaction be 's .

  2. Let store be 's .

  3. If store has been deleted, an "" .

  4. If transaction’s is not , then a "" .

  5. Let range be the result of with query and true. Rethrow any exceptions.

  6. Let operation be an algorithm to run with store and range.

  7. Return the result (an ) of running with and operation.

NOTE: The query parameter can be a or (an ) identifying the key to be retrieved. If a range is specified, the method retrieves the first existing key in that range.

The method steps are:

  1. Let transaction be 's .

  2. Let store be 's .

  3. If store has been deleted, an "" .

  4. If transaction’s is not , then a "" .

  5. Let range be the result of with query. Rethrow any exceptions.

  6. Let operation be an algorithm to run with , store, range, and count if given.

  7. Return the result (an ) of running with and operation.

NOTE: The query parameter can be a or (an ) identifying the values to be retrieved. If null or not given, an is used. If count is specified and there are more than count records in range, only the first count will be retrieved.

The method steps are:

  1. Let transaction be 's .

  2. Let store be 's .

  3. If store has been deleted, an "" .

  4. If transaction’s is not , then a "" .

  5. Let range be the result of with query. Rethrow any exceptions.

  6. Let operation be an algorithm to run with store, range, and count if given.

  7. Return the result (an ) of running with and operation.

NOTE: The query parameter can be a or (an ) identifying the keys to be retrieved. If null or not given, an is used. If count is specified and there are more than count keys in range, only the first count will be retrieved.

The method steps are:

  1. Let transaction be 's .

  2. Let store be 's .

  3. If store has been deleted, an "" .

  4. If transaction’s is not , then a "" .

  5. Let range be the result of with query. Rethrow any exceptions.

  6. Let operation be an algorithm to run with store and range.

  7. Return the result (an ) of running with and operation.

NOTE: The query parameter can be a or (an ) identifying the to be counted. If null or not given, an is used.

The following methods throw a "" if called when the is not .
request = store . ([query [, direction = "next"]])

Opens a over the matching query, ordered by direction. If query is null, all in store are matched.

If successful, request’s will be an pointing at the first matching , or null if there were no matching .

request = store . ([query [, direction = "next"]])

Opens a with set to true over the matching query, ordered by direction. If query is null, all in store are matched.

If successful, request’s will be an pointing at the first matching , or null if there were no matching .

The method steps are:

  1. Let transaction be 's .

  2. Let store be 's .

  3. If store has been deleted, an "" .

  4. If transaction’s is not , then a "" .

  5. Let range be the result of with query. Rethrow any exceptions.

  6. Let cursor be a new with its set to transaction, undefined , set to direction, set to false, undefined and , set to store, set to range, and set to false.

  7. Let operation be an algorithm to run with and cursor.

  8. Let request be the result of running with and operation.

  9. Set cursor’s to request.

  10. Return request.

NOTE: The query parameter can be a or (an ) to use as the 's . If null or not given, an is used.

The method steps are:

  1. Let transaction be 's .

  2. Let store be 's .

  3. If store has been deleted, an "" .

  4. If transaction’s is not , then a "" .

  5. Let range be the result of with query. Rethrow any exceptions.

  6. Let cursor be a new with its set to transaction, undefined , set to direction, set to false, undefined and , set to store, set to range, and set to true.

  7. Let operation be an algorithm to run with and cursor.

  8. Let request be the result of running with and operation.

  9. Set cursor’s to request.

  10. Return request.

NOTE: The query parameter can be a or (an ) to use as the 's . If null or not given, an is used.

index = store . index(name)

Returns an for the named name in store.

index = store . (name, keyPath [, options])

Creates a new in store with the given name, keyPath and options and returns a new . If the keyPath and options define constraints that cannot be satisfied with the data already in store the will with a "" .

Throws an "" if not called within an .

store . (name)

Deletes the in store with the given name.

Throws an "" if not called within an .

The method steps are:

  1. Let transaction be 's .

  2. Let store be 's .

  3. If transaction is not an , an "" .

  4. If store has been deleted, an "" .

  5. If transaction’s is not , then a "" .

  6. If an name already exists in store, a "" .

  7. If keyPath is not a , a "" .

  8. Let unique be options’s member.

  9. Let multiEntry be options’s member.

  10. If keyPath is a sequence and multiEntry is true, an "" .

  11. Let index be a new in store. Set index’s to name, to keyPath, to unique, and to multiEntry.

  12. Add index to 's .

  13. Return a new associated with index and .

This method creates and returns a new with the given name in the . Note that this method must only be called from within an .

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

This method synchronously modifies the property on the instance on which it was called. Although this method does not return an object, the index creation itself is processed as an asynchronous request within the .

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 object, and once the implementation determines that creating the index has failed, it must run the steps to using an appropriate error. For example if creating the failed due to quota reasons, a "" must be used as error and if the index can’t be created due to constraints, a "" must be used as error.

The asynchronous creation of indexes is observable in the following example:

const request1 = objectStore.put({name: "betty"}, 1);
const request2 = objectStore.put({name: "betty"}, 2);
const index = objectStore.createIndex("by_name", "name", {unique: true});

At the point where called, neither of the have executed. When the second request executes, a duplicate name is created. Since the index creation is considered an asynchronous , the index’s does not cause the second to fail. Instead, the will be when the index is created and the constraint fails.

The method steps are:

  1. Let transaction be 's .

  2. Let store be 's .

  3. If store has been deleted, an "" .

  4. If transaction’s is , then an "" .

  5. Let index be the name in 's if one exists, or a "" otherwise.

  6. Return an associated with index and .

NOTE: Each call to this method on the same instance with the same name returns the same instance.

NOTE: The returned instance is specific to this instance. If this method is called on a different instance with the same name, a different instance is returned.

The method steps are:

  1. Let transaction be 's .

  2. Let store be 's .

  3. If transaction is not an , an "" .

  4. If store has been deleted, an "" .

  5. If transaction’s is not , then a "" .

  6. Let index be the name in store if one exists, or a "" otherwise.

  7. Remove index from 's .

  8. Destroy index.

This method destroys the with the given name in the . Note that this method must only be called from within an .

This method synchronously modifies the property on the instance on which it was called. Although this method does not return an object, the index destruction itself is processed as an asynchronous request within the .

4.6. The interface

The interface represents an .

[=(Window,Worker)]
interface  {
  attribute  ;
  [] readonly attribute  ;
  readonly attribute  ;
  readonly attribute  ;
  readonly attribute  ;

  []  ( query);
  []  ( query);
  []  (optional  query,
                                optional []  count);
  []  (optional  query,
                                    optional []  count);
  []  (optional  query);

  []  (optional  query,
                                    optional  direction = "next");
  []  (optional  query,
                                       optional  direction = "next");
};
index .

Returns the of the index.

index . = newName

Updates the of the store to newName.

Throws an "" if not called within an .

index .

Returns the the index belongs to.

index . keyPath

Returns the of the index.

index . multiEntry

Returns true if the index’s is true.

index . unique

Returns true if the index’s is true.

The getter steps are to return 's .

Is this the same as the 's ? As long as the has not , this is the same as the associated 's . But once the has , this attribute will not reflect changes made with a later .

The setter steps are:

  1. Let name be .

  2. Let transaction be 's .

  3. Let index be 's .

  4. If transaction is not an , an "" .

  5. If transaction’s is not , then a "" .

  6. If index or index’s has been deleted, an "" .

  7. If index’s is equal to name, terminate these steps.

  8. If an name already exists in index’s , a "" .

  9. Set index’s to name.

  10. Set 's to name.

The getter steps are to return 's .

The getter steps are to return 's 's . The is converted as a (if a string) or a <> (if a list of strings), per [WEBIDL].

NOTE: The returned value is not the same instance that was used when the was created. However, if this attribute returns an object (specifically an ), it returns the same object instance every time it is inspected. Changing the properties of the object has no effect on the .

The getter steps are to return 's 's .

The getter steps are to return 's 's .

The following methods throw an "" if called when the is not .
request = index . (query)

Retrieves the of the first matching the given or in query.

If successful, request’s will be the , or undefined if there was no matching .

request = index . (query)

Retrieves the of the first matching the given or in query.

If successful, request’s will be the , or undefined if there was no matching .

request = index . (query [, count])

Retrieves the of the matching the given or in query (up to count if given).

If successful, request’s will be an of the .

request = index . (query [, count])

Retrieves the of matching the given or in query (up to count if given).

If successful, request’s will be an of the .

request = index . (query)

Retrieves the number of matching the given or in query.

If successful, request’s will be the count.

The method steps are:

  1. Let transaction be 's .

  2. Let index be 's .

  3. If index or index’s has been deleted, an "" .

  4. If transaction’s is not , then a "" .

  5. Let range be the result of with query and true. Rethrow any exceptions.

  6. Let operation be an algorithm to run with , index, and range.

  7. Return the result (an ) of running with and operation.

NOTE: The query parameter can be a or (an ) identifying the to be retrieved. If a range is specified, the method retrieves the first existing record in that range.

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

The method steps are:

  1. Let transaction be 's .

  2. Let index be 's .

  3. If index or index’s has been deleted, an "" .

  4. If transaction’s is not , then a "" .

  5. Let range be the result of with query and true. Rethrow any exceptions.

  6. Let operation be an algorithm to run with index and range.

  7. Return the result (an ) of running with and operation.

NOTE: The query parameter can be a or (an ) identifying the key to be retrieved. If a range is specified, the method retrieves the first existing key in that range.

The method steps are:

  1. Let transaction be 's .

  2. Let index be 's .

  3. If index or index’s has been deleted, an "" .

  4. If transaction’s is not , then a "" .

  5. Let range be the result of with query. Rethrow any exceptions.

  6. Let operation be an algorithm to run with , index, range, and count if given.

  7. Return the result (an ) of running with and operation.

NOTE: The query parameter can be a or (an ) identifying the to be retrieved. If null or not given, an is used. If count is specified and there are more than count records in range, only the first count will be retrieved.

The method steps are:

  1. Let transaction be 's .

  2. Let index be 's .

  3. If index or index’s has been deleted, an "" .

  4. If transaction’s is not , then a "" .

  5. Let range be the result of with query. Rethrow any exceptions.

  6. Let operation be an algorithm to run with index, range, and count if given.

  7. Return the result (an ) of running with and operation.

NOTE: The query parameter can be a or (an ) identifying the keys to be retrieved. If null or not given, an is used. If count is specified and there are more than count keys in range, only the first count will be retrieved.

The method steps are:

  1. Let transaction be 's .

  2. Let index be 's .

  3. If index or index’s has been deleted, an "" .

  4. If transaction’s is not , then a "" .

  5. Let range be the result of with query. Rethrow any exceptions.

  6. Let operation be an algorithm to run with index and range.

  7. Return the result (an ) of running with and operation.

NOTE: The query parameter can be a or (an ) identifying the to be counted. If null or not given, an is used.

The following methods throw an "" if called when the is not .
request = index . ([query [, direction = "next"]])

Opens a over the matching query, ordered by direction. If query is null, all in index are matched.

If successful, request’s will be an , or null if there were no matching .

request = index . ([query [, direction = "next"]])

Opens a with set to true over the matching query, ordered by direction. If query is null, all in index are matched.

If successful, request’s will be an , or null if there were no matching .

The method steps are:

  1. Let transaction be 's .

  2. Let index be 's .

  3. If index or index’s has been deleted, an "" .

  4. If transaction’s is not , then a "" .

  5. Let range be the result of with query. Rethrow any exceptions.

  6. Let cursor be a new with its set to transaction, undefined , set to direction, set to false, undefined and , set to index, set to range, and set to false.

  7. Let operation be an algorithm to run with and cursor.

  8. Let request be the result of running with and operation.

  9. Set cursor’s to request.

  10. Return request.

NOTE: The query parameter can be a or (an ) to use as the 's . If null or not given, an is used.

The method steps are:

  1. Let transaction be 's .

  2. Let index be 's .

  3. If index or index’s has been deleted, an "" .

  4. If transaction’s is not , then a "" .

  5. Let range be the result of with query. Rethrow any exceptions.

  6. Let cursor be a new with its set to transaction, undefined , set to direction, set to false, undefined and , set to index, set to range, and set to true.

  7. Let operation be an algorithm to run with and cursor.

  8. Let request be the result of running with and operation.

  9. Set cursor’s to request.

  10. Return request.

NOTE: The query parameter can be a or (an ) to use as the 's . If null or not given, an is used.

4.7. The interface

The interface represents a .

[=(Window,Worker)]
interface  {
  readonly attribute  ;
  readonly attribute  ;
  readonly attribute  ;
  readonly attribute  ;

  // Static construction methods:
  [] static  ( value);
  [] static  ( lower, optional  open = false);
  [] static  ( upper, optional  open = false);
  [] static  ( lower,
                                        upper,
                                       optional  lowerOpen = false,
                                       optional  upperOpen = false);

   ( key);
};
range .

Returns the range’s , or undefined if none.

range .

Returns the range’s , or undefined if none.

range .

Returns the range’s .

range .

Returns the range’s .

The getter steps are to return the result of with 's if it is not null, or undefined otherwise.

The getter steps are to return the result of with 's if it is not null, or undefined otherwise.

The getter steps are to return 's .

The getter steps are to return 's .

range = . (key)

Returns a new spanning only key.

range = . (key [, open = false])

Returns a new starting at key with no upper bound. If open is true, key is not included in the range.

range = . (key [, open = false])

Returns a new with no lower bound and ending at key. If open is true, key is not included in the range.

range = . (lower, upper [, lowerOpen = false [, upperOpen = false]])

Returns a new 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 method steps are:

  1. Let key be the result of with value. Rethrow any exceptions.

  2. If key is invalid, a "" .

  3. Create and return a new key.

The method steps are:

  1. Let lowerKey be the result of with lower. Rethrow any exceptions.

  2. If lowerKey is invalid, a "" .

  3. Create and return a new with set to lowerKey, set to open, set to null, and set to true.

The method steps are:

  1. Let upperKey be the result of with upper. Rethrow any exceptions.

  2. If upperKey is invalid, a "" .

  3. Create and return a new with set to null, set to true, set to upperKey, and set to open.

The method steps are:

  1. Let lowerKey be the result of with lower. Rethrow any exceptions.

  2. If lowerKey is invalid, a "" .

  3. Let upperKey be the result of with upper. Rethrow any exceptions.

  4. If upperKey is invalid, a "" .

  5. If lowerKey is upperKey, a "" .

  6. Create and return a new with set to lowerKey, set to lowerOpen, set to upperKey and set to upperOpen.

range . (key)

Returns true if key is included in the range, and false otherwise.

The method steps are:

  1. Let k be the result of with key. Rethrow any exceptions.

  2. If k is invalid, a "" .

  3. Return true if k is this range, and false otherwise.

4.8. The interface

objects implement the interface. There is only ever one instance representing a given . There is no limit on how many cursors can be used at the same time.

[=(Window,Worker)]
interface  {
  readonly attribute ( or ) ;
  readonly attribute  ;
  readonly attribute  ;
  readonly attribute  ;
  [] readonly attribute  ;

   ([]  count);
   (optional  key);
   ( key,  primaryKey);

  []  ( value);
  []  ();
};

enum  {
  ,
  ,
  ,
  
};
cursor .

Returns the or the cursor was opened from.

cursor .

Returns the ("", "", "" or "") of the cursor.

cursor .

Returns the of the cursor. Throws a "" if the cursor is advancing or is finished.

cursor .

Returns the of the cursor. Throws a "" if the cursor is advancing or is finished.

cursor .

Returns the that was used to obtain this cursor.

The getter steps are to return 's .

NOTE: The attribute never returns null or throws an exception, even if the cursor is currently being iterated, has iterated past its end, or its is not .

The getter steps are to return 's .

The getter steps are to return the result of with the cursor’s current .

NOTE: If returns an object (e.g. a or ), it returns the same object instance every time it is inspected, until the cursor’s 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 getter steps are to return the result of with the cursor’s current .

NOTE: If returns an object (e.g. a or ), it returns the same object instance every time it is inspected, until the cursor’s 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 getter steps are to return 's .

🚧 The attribute is new in this edition. It is supported in Chrome 76, Edge 79, Firefox 77, and Safari 15. 🚧
The following methods advance a . Once the cursor has advanced, a event will be fired at the same returned when the cursor was opened. The will be the same cursor if a was in range, or undefined otherwise.

If called while the cursor is already advancing, an "" will be thrown.

The following methods throw a "" if called when the is not .

cursor . (count)

Advances the cursor through the next count in range.

cursor . ()

Advances the cursor to the next in range.

cursor . (key)

Advances the cursor to the next in range matching or after key.

cursor . (key, primaryKey)

Advances the cursor to the next in range matching or after key and primaryKey. Throws an "" if the is not an .

The method steps are:

  1. If count is 0 (zero), a .

  2. Let transaction be 's .

  3. If transaction’s is not , then a "" .

  4. If 's or has been deleted, an "" .

  5. If 's is false, indicating that the cursor is being iterated or has iterated past its end, an "" .

  6. Set 's to false.

  7. Let request be 's .

  8. Set request’s to false.

  9. Set request’s to false.

  10. Let operation be an algorithm to run with , , and count.

  11. Run with 's , operation, and request.

NOTE: Calling this method more than once before new cursor data has been loaded - for example, calling twice from the same onsuccess handler - results in an "" being thrown on the second call because the cursor’s has been set to false.

The method steps are:

  1. Let transaction be 's .

  2. If transaction’s is not , then a "" .

  3. If 's or has been deleted, an "" .

  4. If 's is false, indicating that the cursor is being iterated or has iterated past its end, an "" .

  5. If key is given, then:

    1. Let r be the result of with key. Rethrow any exceptions.

    2. If r is invalid, a "" .

    3. Let key be r.

    4. If key is or 's and 's is "" or "", then a "" .

    5. If key is or 's and 's is "" or "", then a "" .

  6. Set 's to false.

  7. Let request be 's .

  8. Set request’s to false.

  9. Set request’s to false.

  10. Let operation be an algorithm to run with , , and key (if given).

  11. Run with 's , operation, and request.

NOTE: Calling this method more than once before new cursor data has been loaded - for example, calling twice from the same onsuccess handler - results in an "" being thrown on the second call because the cursor’s has been set to false.

The method steps are:

  1. Let transaction be 's .

  2. If transaction’s is not , then a "" .

  3. If 's or has been deleted, an "" .

  4. If 's is not an an "" .

  5. If 's is not "" or "", an "" .

  6. If 's is false, indicating that the cursor is being iterated or has iterated past its end, an "" .

  7. Let r be the result of with key. Rethrow any exceptions.

  8. If r is invalid, a "" .

  9. Let key be r.

  10. Let r be the result of with primaryKey. Rethrow any exceptions.

  11. If r is invalid, a "" .

  12. Let primaryKey be r.

  13. If key is 's and 's is "", a "" .

  14. If key is 's and 's is "", a "" .

  15. If key is 's and primaryKey is or 's and 's is "", a "" .

  16. If key is 's and primaryKey is or 's and 's is "", a "" .

  17. Set 's to false.

  18. Let request be 's .

  19. Set request’s to false.

  20. Set request’s to false.

  21. Let operation be an algorithm to run with , , key, and primaryKey.

  22. Run with 's , operation, and request.

NOTE: Calling this method more than once before new cursor data has been loaded - for example, calling twice from the same onsuccess handler - results in an "" being thrown on the second call because the cursor’s has been set to false.

The following methods throw a "" if called within a , and a "" if called when the is not .
request = cursor . (value)

Updated the pointed at by the cursor with a new value.

Throws a "" if the uses and the would have changed.

If successful, request’s will be the 's .

request = cursor . ()

Delete the pointed at by the cursor with a new value.

If successful, request’s will be undefined.

The method steps are:

  1. Let transaction be 's .

  2. If transaction’s is not , then a "" .

  3. If transaction is a , a "" .

  4. If 's or has been deleted, an "" .

  5. If 's is false, indicating that the cursor is being iterated or has iterated past its end, an "" .

  6. If 's is true, an "" .

  7. Let targetRealm be a user-agent defined .

  8. Let clone be a of value in targetRealm during transaction. 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.
  9. If 's uses , then:

    1. Let kpk be the result of with clone and the of 's . Rethrow any exceptions.

    2. If kpk is failure, invalid, or not 's , a "" .

  10. Let operation be an algorithm to run with 's , clone, 's , and false.

  11. Return the result (an ) of running with and operation.

NOTE: A result of is that if the record has been deleted since the cursor moved to it, a new record will be created.

The method steps are:

  1. Let transaction be 's .

  2. If transaction’s is not , then a "" .

  3. If transaction is a , a "" .

  4. If 's or has been deleted, an "" .

  5. If 's is false, indicating that the cursor is being iterated or has iterated past its end, an "" .

  6. If 's is true, an "" .

  7. Let operation be an algorithm to run with 's and 's .

  8. Return the result (an ) of running with and operation.

A that has its set to false implements the interface as well.

[=(Window,Worker)]
interface  :  {
  readonly attribute  ;
};
cursor .

Returns the 's current .

The getter steps are to return 's current .

NOTE: If returns an object, it returns the same object instance every time it is inspected, until the cursor’s 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 interface

objects implement the following interface:

[=(Window,Worker)]
interface  :  {
  readonly attribute  ;
  readonly attribute  ;
  readonly attribute  ;
  [] readonly attribute  ;
  readonly attribute ? ;

   ( name);
   ();
   ();

  // Event handlers:
  attribute  ;
  attribute  ;
  attribute  ;
};

enum  {
  ,
  ,
  
};
transaction .

Returns a list of the names of in the transaction’s . For an this is all object stores in the .

transaction .

Returns the the transaction was created with ("" or ""), or "" for an .

transaction .

Returns the the transaction was created with ("", ""), or "").

transaction .

Returns the transaction’s .

transaction .

If the transaction was , returns the error (a ) providing the reason.

The getter steps are:

  1. Let names be a of the of the in 's .

  2. Return the result (a ) of with names.

NOTE: The contents of each list returned by this attribute does not change, but subsequent calls to this attribute during an can return lists with different contents as are created and deleted.

The getter steps are to return 's .

The getter steps are to return 's .

🚧 The attribute is new in this edition. It is supported in Chrome 82, Edge 82, and Safari 15. 🚧

The getter steps are to return 's 's associated .

The getter steps are to return 's , or null if none.

NOTE: If this was aborted due to a failed , this will be the same as the 's . If this was aborted due to an uncaught exception in an event handler, the error will be a "" . If the was aborted due to an error while committing, it will reflect the reason for the failure (e.g. "", "", or "" ).

transaction . (name)

Returns an in the 's .

transaction .

Aborts the transaction. All pending will fail with a "" and all changes made to the database will be reverted.

transaction .

Attempts to commit the transaction. All pending 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 events before attempting to commit normally.

The transaction will abort if a pending request fails, for example due to a constraint error. The events for successful requests will still fire, but throwing an exception in an event handler will not abort the transaction. Similarly, events for failed requests will still fire, but calling preventDefault() will not prevent the transaction from aborting.

The method steps are:

  1. If 's is , then an "" .

  2. Let store be the name in 's , or a "" if none.

  3. Return an associated with store and .

NOTE: Each call to this method on the same instance with the same name returns the same instance.

NOTE: The returned instance is specific to this . If this method is called on a different , a different instance is returned.

The method steps are:

  1. If 's is or , then an "" .

  2. Set 's to and run with and null.

The method steps are:

  1. If 's is not , then an "" .

  2. Run with .

🚧 The method is new in this edition. It is supported in Chrome 76, Edge 79, Firefox 74, and Safari 15. 🚧

NOTE: It is not normally necessary to call on a . A transaction will automatically commit when all outstanding requests have been satisfied and no new requests have been made. This call can be used to start the process without waiting for events from outstanding to be dispatched.

The attribute is an whose is .

The attribute is an whose is .

The attribute is an whose is .

NOTE: To determine if a has completed successfully, listen to the 's event rather than the event of a particular , because the can still fail after the event fires.

5. Algorithms

5.1. Opening a database connection

To with storageKey which requested the to be opened, a database name, a database version, and a request, run these steps:

  1. Let queue be the for storageKey and name.

  2. Add request to queue.

  3. Wait until all previous requests in queue have been processed.

  4. Let db be the name in storageKey, or null otherwise.

  5. If version is undefined, let version be 1 if db is null, or db’s otherwise.

  6. If db is null, let db be a new with name, 0 (zero), and with no . If this fails for any reason, return an appropriate error (e.g. a "" or "" ).

  7. If db’s is greater than version, return a newly "" and abort these steps.

  8. Let connection be a new to db.

  9. Set connection’s to version.

  10. If db’s is less than version, then:

    1. Let openConnections be the of all , except connection, associated with db.

    2. entry of openConnections that does not have its set to true, to named at entry with db’s and version.

      NOTE: Firing this event might cause one or more of the other objects in openConnections to be closed, in which case the event is not fired at those objects, even if that hasn’t yet been done.

    3. Wait for all of the events to be fired.

    4. If any of the in openConnections are still not closed, to named at request with db’s and version.

    5. Wait until all in openConnections are .

    6. Run using connection, version and request.

    7. If connection was , return a newly "" and abort these steps.

    8. If the was aborted, run the steps to with connection, return a newly "" and abort these steps.

  11. Return connection.

5.2. Closing a database connection

To with a connection object, and an optional forced flag, run these steps:

  1. Set connection’s to true.

  2. If the forced flag is true, then for each transaction using connection run with transaction and newly "" .

  3. Wait for all transactions using connection to complete. Once they are complete, connection is .

  4. If the forced flag is true, then named at connection.

    NOTE: The event only fires if the connection closes abnormally, e.g. if the 's storage is cleared, or there is corruption or an I/O error. If is called explicitly the event does not fire.

NOTE: Once a 's has been set to true, no new transactions can be using the . All methods that transactions first check the 's first and throw an exception if it is true.

NOTE: Once the is closed, this can unblock the steps to , and the steps to , which both wait for to a given to be closed before continuing.

5.3. Deleting a database

To with the storageKey that requested the to be deleted, a database name, and a request, run these steps:

  1. Let queue be the for storageKey and name.

  2. Add request to queue.

  3. Wait until all previous requests in queue have been processed.

  4. Let db be the name in storageKey, if one exists. Otherwise, return 0 (zero).

  5. Let openConnections be the of all associated with db.

  6. entry of openConnections that does not have its set to true, to named at entry with db’s and null.

    NOTE: Firing this event might cause one or more of the other objects in openConnections to be closed, in which case the event is not fired at those objects, even if that hasn’t yet been done.

  7. Wait for all of the events to be fired.

  8. If any of the in openConnections are still not closed, to named at request with db’s and null.

  9. Wait until all in openConnections are .

  10. Let version be db’s .

  11. Delete db. If this fails for any reason, return an appropriate error (e.g. "" or "" ).

  12. Return version.

5.4. Committing a transaction

To with the transaction to commit, run these steps:

  1. Set transaction’s to .

  2. Run the following steps :

    1. Wait until every item in transaction’s is .

    2. If transaction’s is no longer , then terminate these steps.

    3. Attempt to write any outstanding changes made by transaction to the , considering transaction’s .

    4. If an error occurs while writing the changes to the , then run with transaction and an appropriate type for the error, for example "" or "" , and terminate these steps.

    5. to run these steps:

      1. If transaction is an , then set transaction’s 's associated 's to null.

      2. Set transaction’s to .

      3. named at transaction.

        NOTE: Even if an exception is thrown from one of the event handlers of this event, the transaction is still committed since writing the database changes happens before the event takes place. Only after the transaction has been successfully written is the event fired.

      4. If transaction is an , then let request be the associated with transaction and set request’s to null.

5.5. Aborting a transaction

To with the transaction to abort, and error, run these steps:

  1. All the changes made to the by the are reverted. For this includes changes to the set of and , as well as the change to the . Any and which were created during the transaction are now considered deleted for the purposes of other algorithms.

  2. If transaction is an , run the steps to with transaction.

    NOTE: This reverts changes to all , , and instances associated with transaction.

  3. Set transaction’s to .

  4. If error is not null, set transaction’s to error.

  5. request of transaction’s , abort the steps to for request, set request’s to true, and to run these steps:

    1. Set request’s to true.

    2. Set request’s to undefined.

    3. Set request’s to a newly "" .

    4. named at request with its and attributes initialized to true.

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

  6. to run these steps:

    1. If transaction is an , then set transaction’s 's associated 's to null.

    2. named at transaction with its attribute initialized to true.

    3. If transaction is an , then:

      1. Let request be the associated with transaction.

      2. Set request’s to null.

      3. Set request’s to undefined.

      4. Set request’s to false.

      5. Set request’s to false.

5.6. Asynchronously executing a

To with the source object and an operation to perform on a database, and an optional request, run these steps:

These steps can be aborted at any point if the the created belongs to is using the steps to .

  1. Let transaction be the associated with source.

  2. : transaction’s is .

  3. If request was not given, let request be a new with as source.

  4. Add request to the end of transaction’s .

  5. Run these steps :

    1. Wait until request is the first item in transaction’s that is not .

    2. Let result be the result of performing operation.

    3. If result is an error and transaction’s is , then run with transaction and result, and terminate these steps.

    4. If result is an error, then revert all changes made by operation.

      NOTE: This only reverts the changes done by this request, not any other changes made by the transaction.

    5. Set request’s to true.

    6. to run these steps:

      1. Remove request from transaction’s .

      2. Set request’s to true.

      3. If result is an error, then:

        1. Set request’s to undefined.

        2. Set request’s to result.

        3. at request.

      4. Otherwise:

        1. Set request’s to result.

        2. Set request’s to undefined.

        3. at request.

  6. Return request.

5.7. Upgrading a database

To with connection (a ), a new version, and a request, run these steps:

  1. Let db be connection’s .

  2. Let transaction be a new with connection used as .

  3. Set transaction’s to connection’s .

  4. Set db’s to transaction.

  5. Set transaction’s to .

  6. Start transaction.

    NOTE: Note that until this is finished, no other can be opened to the same .

  7. Let old version be db’s .

  8. Set db’s to version. This change is considered part of the , and so if the transaction is , this change is reverted.

  9. Set request’s to true.

  10. to run these steps:

    1. Set request’s to connection.

    2. Set request’s to transaction.

    3. Set request’s to true.

    4. Set transaction’s to .

    5. Let didThrow be the result of named at request with old version and version.

    6. Set transaction’s to .

    7. If didThrow is true, run with transaction and a newly "" .

  11. Wait for transaction to .

    NOTE: Some of the algorithms invoked during the 's , such as the steps to and the steps to , include steps specific to .

5.8. Aborting an upgrade transaction

To with transaction, run these steps:

NOTE: These steps are run as needed by the steps to , which revert changes to the including the set of associated and , as well as the change to the .

  1. Let connection be transaction’s .

  2. Let database be connection’s .

  3. Set connection’s to database’s if database previously existed, or 0 (zero) if database was newly created.

    NOTE: This reverts the value of returned by the object.

  4. Set connection’s to the set of in database if database previously existed, or the empty set if database was newly created.

    NOTE: This reverts the value of returned by the object.

  5. For each handle associated with transaction, including those for that were created or deleted during transaction:

    1. If handle’s was not newly created during transaction, set handle’s to its 's .

    2. Set handle’s to the set of that reference its .

    NOTE: This reverts the values of and returned by related objects.

    How is this observable? Although script cannot access an by using the method on an instance after the is aborted, it can still have references to instances where the and properties can be queried.
  6. For each handle associated with transaction, including those for that were created or deleted during transaction:

    1. If handle’s was not newly created during transaction, set handle’s to its 's .

    NOTE: This reverts the value of returned by related objects.

    How is this observable? Although script cannot access an by using the method on an instance after the is aborted, it can still have references to instances where the property can be queried.

NOTE: The property of the instance is not modified, even if the aborted was creating a new .

5.9. Firing a success event

To at a request, run these steps:

  1. Let event be the result of using .

  2. Set event’s attribute to "success".

  3. Set event’s and attributes to false.

  4. Let transaction be request’s .

  5. Let legacyOutputDidListenersThrowFlag be initially false.

  6. If transaction’s is , then set transaction’s to .

  7. event at request with legacyOutputDidListenersThrowFlag.

  8. If transaction’s is , then:

    1. Set transaction’s to .

    2. If legacyOutputDidListenersThrowFlag is true, then run with transaction and a newly "" .

    3. If transaction’s is empty, then run with transaction.

5.10. Firing an error event

To at a request, run these steps:

  1. Let event be the result of using .

  2. Set event’s attribute to "error".

  3. Set event’s and attributes to true.

  4. Let transaction be request’s .

  5. Let legacyOutputDidListenersThrowFlag be initially false.

  6. If transaction’s is , then set transaction’s to .

  7. event at with legacyOutputDidListenersThrowFlag.

  8. If transaction’s is , then:

    1. Set transaction’s to .

    2. If legacyOutputDidListenersThrowFlag is true, then run with transaction and a newly "" and terminate these steps. This is done even if event’s is false.

      NOTE: This means that if an error event is fired and any of the event handlers throw an exception, transaction’s property is set to an rather than request’s , even if is never called.

    3. If event’s is false, then run using transaction and 's , and terminate these steps.

    4. If transaction’s is empty, then run with transaction.

5.11. Clone a value

To make a of value in targetRealm during transaction, run these steps:

  1. : transaction’s is .

  2. Set transaction’s to .

    NOTE: The is made so that getters or other side effects triggered by the cloning operation are unable to make additional requests against the transaction.

  3. Let serialized be (value).

  4. Let clone be (serialized, targetRealm).

  5. Set transaction’s to .

  6. Return clone.

6. Database operations

This section describes various operations done on the data in and in a . These operations are run by the steps to .

NOTE: Invocations of () in the operation steps below can be asserted not to throw (as indicated by the prefix) because they operate only on previous output of ().

6.1. Object store storage operation

To with store, value, an optional key, and a no-overwrite flag, run these steps:

  1. If store uses a , then:

    1. If key is undefined, then:

      1. Let key be the result of for store.

      2. If key is failure, then this operation failed with a "" . Abort this algorithm without taking any further steps.

      3. If store also uses , then run with value, key and store’s .

    2. Otherwise, run for store with key.

  2. If the no-overwrite flag was given to these steps and is true, and a already exists in store with its key key, then this operation failed with a "" . Abort this algorithm without taking any further steps.

  3. If a already exists in store with its key key, then remove the from store using .

  4. Store a record in store containing key as its key and (value) as its value. The record is stored in the object store’s such that the list is sorted according to the key of the records in order.

  5. For each index which store:

    1. Let index key be the result of with value, index’s , and index’s .

    2. If index key is an exception, or invalid, or failure, take no further actions for index, and continue these steps for the next index.

      NOTE: An exception thrown in this step is not rethrown.

    3. If index’s is false, or if index key is not an , and if index already contains a with index key, and index’s is true, then this operation failed with a "" . Abort this algorithm without taking any further steps.

    4. If index’s is true and index key is an , and if index already contains a with any of the of index key, and index’s is true, then this operation failed with a "" . Abort this algorithm without taking any further steps.

    5. If index’s is false, or if index key is not an then store a record in index containing index key as its key and key as its value. The record is stored in index’s such that the list is sorted primarily on the records keys, and secondarily on the records values, in order.

    6. If index’s is true and index key is an , then for each subkey of the 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 such that the list is sorted primarily on the records keys, and secondarily on the records values, in order.

      NOTE: It is valid for there to be no . In this case no records are added to the index.

      NOTE: Even if any member of is itself an , the member is used directly as the key for the index record. Nested are not flattened or "unpacked" to produce multiple rows; only the outer-most is.

  6. Return key.

6.2. Object store retrieval operations

To with targetRealm, store and range, run these steps:

  1. Let record be the first in store’s whose is range, if any.

  2. If record was not found, return undefined.

  3. Let serialized be of record’s .

  4. Return (serialized, targetRealm).

To with targetRealm, store, range and optional count, run these steps:

  1. If count is not given or is 0 (zero), let count be infinity.

  2. Let records be a containing the first count in store’s whose is range.

  3. Let list be an empty .

  4. record of records:

    1. Let serialized be record’s .

    2. Let entry be (serialized, targetRealm).

    3. Append entry to list.

  5. Return list converted to a <>.

To with store and range, run these steps:

  1. Let record be the first in store’s whose is range, if any.

  2. If record was not found, return undefined.

  3. Return the result of with record’s key.

To with store, range and optional count, run these steps:

  1. If count is not given or is 0 (zero), let count be infinity.

  2. Let records be a list containing the first count in store’s whose is range.

  3. Let list be an empty .

  4. record of records:

    1. Let entry be the result of with record’s key.

    2. Append entry to list.

  5. Return list converted to a <>.

6.3. Index retrieval operations

To with targetRealm, index and range, run these steps:

  1. Let record be the first in index’s whose is range, if any.

  2. If record was not found, return undefined.

  3. Let serialized be record’s .

  4. Return (serialized, targetRealm).

To with targetRealm, index, range and optional count, run these steps:

  1. If count is not given or is 0 (zero), let count be infinity.

  2. Let records be a list containing the first count in index’s whose is range.

  3. Let list be an empty .

  4. record of records:

    1. Let serialized be record’s .

    2. Let entry be (serialized, targetRealm).

    3. Append entry to list.

  5. Return list converted to a <>.

NOTE: The of an in an index are the keys of in the object store.

To with index and range, run these steps:

  1. Let record be the first in index’s whose is range, if any.

  2. If record was not found, return undefined.

  3. Return the result of with record’s .

To with index, range and optional count, run these steps:

  1. If count is not given or is 0 (zero), let count be infinity.

  2. Let records be a list containing the first count in index’s whose is range.

  3. Let list be an empty .

  4. record of records:

    1. Let entry be the result of with record’s value.

    2. Append entry to list.

  5. Return list converted to a <>.

6.4. Object store deletion operation

To with store and range, run these steps:

  1. Remove all records, if any, from store’s with key range.

  2. For each index which store, remove every from index’s whose value is range, if any such records exist.

  3. Return undefined.

6.5. Record counting operation

To with source and range, run these steps:

  1. Let count be the number of records, if any, in source’s list of records with key range.

  2. Return count.

6.6. Object store clear operation

To with store, run these steps:

  1. Remove all records from store.

  2. In all which store, remove all .

  3. Return undefined.

6.7. Cursor iteration operation

To with targetRealm, cursor, an optional key and primaryKey to iterate to, and an optional count, run these steps:

  1. Let source be cursor’s .

  2. Let direction be cursor’s .

  3. : if primaryKey is given, source is an and direction is "" or "".

  4. Let records be the list of in source.

    NOTE: records is always sorted in order. In the case of source being an , records is secondarily sorted in order (where the value in an is the of the in the referenced ).

  5. Let range be cursor’s .

  6. Let position be cursor’s .

  7. Let object store position be cursor’s .

  8. If count is not given, let count be 1.

  9. While count is greater than 0:

    1. Switch on direction:

      ""

      Let found record be the first record in records which satisfy all of the following requirements:

      ""

      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 or key.

      • If position is defined, the record’s key is position.

      • The record’s key is range.

      ""

      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 or key.

      • If primaryKey is defined, the record’s key is key and the record’s value is or primaryKey, or the record’s key is key.

      • If position is defined, and source is an , the record’s key is position.

      • If position is defined, and source is an , the record’s key is position and the record’s value is object store position or the record’s key is position.

      • The record’s key is range.

      ""

      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 or key.

      • If position is defined, the record’s key is position.

      • The record’s key is range.

      If temp record is defined, let found record be the first record in records whose is temp record’s .

      NOTE: Iterating with "" visits the same records that "" visits, but in reverse order.

    2. If found record is not defined, then:

      1. Set cursor’s to undefined.

      2. If source is an , set cursor’s to undefined.

      3. If cursor’s is false, set cursor’s to undefined.

      4. Return null.

    3. Let position be found record’s key.

    4. If source is an , let object store position be found record’s value.

    5. Decrease count by 1.

  10. Set cursor’s to position.

  11. If source is an , set cursor’s to object store position.

  12. Set cursor’s to found record’s key.

  13. If cursor’s is false, then:

    1. Let serialized be found record’s .

    2. Set cursor’s to (serialized, targetRealm)

  14. Set cursor’s to true.

  15. Return cursor.

7. ECMAScript binding

This section defines how 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 . 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

To with value, keyPath and an optional multiEntry flag, run the following steps. The result of these steps is a , invalid, or failure, or the steps may throw an exception.

  1. Let r be the result of with value and keyPath. Rethrow any exceptions.

  2. If r is failure, return failure.

  3. Let key be the result of with r if the multiEntry flag is false, and the result of with r otherwise. Rethrow any exceptions.

  4. If key is invalid, return invalid.

  5. Return key.

To with value and keyPath, run the following steps. The result of these steps is an ECMAScript value or failure, or the steps may throw an exception.

  1. If keyPath is a of strings, then:

    1. Let result be a new object created as if by the expression [].

    2. Let i be 0.

    3. item of keyPath:

      1. Let key be the result of recursively with item and value.

      2. : key is not an .

      3. If key is failure, abort the overall algorithm and return failure.

      4. Let p be (i).

      5. Let status be (result, p, key).

      6. : status is true.

      7. Increase i by 1.

    4. Return result.

      NOTE: This will only ever "recurse" one level since sequences can’t ever be nested.

  2. If keyPath is the empty string, return value and skip the remaining steps.

  3. Let identifiers be the result of keyPath on U+002E FULL STOP characters (.).

  4. identifier of identifiers, jump to the appropriate step below:

    If (value) is String, and identifier is "length"

    Let value be a Number equal to the number of elements in value.

    If value is an and identifier is "length"

    Let value be ( (value, "length")).

    If value is a and identifier is "size"

    Let value be a Number equal to value’s .

    If value is a and identifier is "type"

    Let value be a String equal to value’s .

    If value is a and identifier is "name"

    Let value be a String equal to value’s .

    If value is a and identifier is "lastModified"

    Let value be a Number equal to value’s .

    Otherwise
    1. If (value) is not Object, return failure.

    2. Let hop be (value, identifier).

    3. If hop is false, return failure.

    4. Let value be (value, identifier).

    5. If value is undefined, return failure.

  5. : value is not an .

  6. Return value.

NOTE: Assertions can be made in the above steps because this algorithm is only applied to values that are the output of and only access "own" properties.

7.2. Inject a key into a value

NOTE: The used in this section are always strings and never sequences, since it is not possible to create a which has a and also has a that is a sequence.

To with value and a keyPath, run the following steps. The result of these steps is either true or false.

  1. Let identifiers be the result of keyPath on U+002E FULL STOP characters (.).

  2. : identifiers is not empty.

  3. Remove the last of identifiers.

  4. remaining identifier of identifiers, if any:

    1. If value is not an or an , return false.

    2. Let hop be (value, identifier).

    3. If hop is false, return true.

    4. Let value be (value, identifier).

  5. Return true if value is an or an , or false otherwise.

NOTE: Assertions can be made in the above steps because this algorithm is only applied to values that are the output of .

To with value, a key and a keyPath, run these steps:

  1. Let identifiers be the result of keyPath on U+002E FULL STOP characters (.).

  2. : identifiers is not empty.

  3. Let last be the last of identifiers and remove it from the list.

  4. remaining identifier of identifiers:

    1. : value is an or an .

    2. Let hop be (value, identifier).

    3. If hop is false, then:

      1. Let o be a new created as if by the expression ({}).

      2. Let status be (value, identifier, o).

      3. : status is true.

    4. Let value be (value, identifier).

  5. : value is an or an .

  6. Let keyValue be the result of with key.

  7. Let status be (value, last, keyValue).

  8. : status is true.

NOTE: Assertions can be made in the above steps because this algorithm is only applied to values that are the output of , and the steps to have been run.

7.3. Convert a key to a value

To with key, run the following steps. The steps return an ECMAScript value.

  1. Let type be key’s .

  2. Let value be key’s .

  3. Switch on type:

    number

    Return an ECMAScript Number value equal to value

    string

    Return an ECMAScript String value equal to value

    date
    1. Let date be the result of executing the ECMAScript Date constructor with the single argument value.

    2. : date is not an .

    3. Return date.

    binary
    1. Let len be value’s .

    2. Let buffer be the result of executing the ECMAScript ArrayBuffer constructor with len.

    3. : buffer is not an .

    4. Set the entries in buffer’s [[ArrayBufferData]] internal slot to the entries in value.

    5. Return buffer.

    array
    1. Let array be the result of executing the ECMAScript Array constructor with no arguments.

    2. : array is not an .

    3. Let len be value’s .

    4. Let index be 0.

    5. While index is less than len:

      1. Let entry be the result of with value[index].

      2. Let status be (array, index, entry).

      3. : status is true.

      4. Increase index by 1.

    6. Return array.

7.4. Convert a value to a key

To with an ECMAScript value input, and an optional seen, run the following steps. The result of these steps is a or invalid, or the steps may throw an exception.

  1. If seen was not given, then let seen be a new empty .

  2. If seen input, then return invalid.

  3. Jump to the appropriate step below:

    If (input) is Number
    1. If input is NaN then return invalid.

    2. Otherwise, return a new with number and input.

    If input is a (has a [[DateValue]] internal slot)
    1. Let ms be the value of input’s [[DateValue]] internal slot.

    2. If ms is NaN then return invalid.

    3. Otherwise, return a new with date and ms.

    If (input) is String
    1. Return a new with string and input.

    If input is a
    1. Let bytes be the result of input. Rethrow any exceptions.

    2. Return a new with binary and bytes.

    If input is an
    1. Let len be ( (input, "length")).

    2. input to seen.

    3. Let keys be a new empty list.

    4. Let index be 0.

    5. While index is less than len:

      1. Let hop be (input, index).

      2. If hop is false, return invalid.

      3. Let entry be (input, index).

      4. Let key be the result of with arguments entry and seen.

      5. (key).

      6. If key is invalid abort these steps and return invalid.

      7. key to keys.

      8. Increase index by 1.

    6. Return a new with keys.

    Otherwise

    Return invalid.

To with an ECMAScript value input, run the following steps. The result of these steps is a or invalid, or the steps may throw an exception.

  1. If input is an , then:

    1. Let len be ToLength( (input, "length")).

    2. Let seen be a new containing only input.

    3. Let keys be a new empty .

    4. Let index be 0.

    5. While index is less than len:

      1. Let entry be (input, index).

      2. If entry is not an , then:

        1. Let key be the result of with arguments entry and seen.

        2. If key is not invalid or an , and there is no in keys key, then key to keys.

      3. Increase index by 1.

    6. Return a new with set to keys.

  2. Otherwise, return the result of with argument input. Rethrow any exceptions.

NOTE: These steps are similar to those to but if the top-level value is an then members which can not be converted to keys are ignored, and duplicates are removed.

For example, the value [10, 20, null, 30, 20] is converted to an with 10, 20, 30.

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

Expiring stored data

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

This can restrict the ability of a site to track a user, as the site would then only be able to track the user across multiple sessions when 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.

Attribution of third-party storage

User agents may record the of sites that contained content from third-party 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.

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.

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

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 storage key partitioning model described in this specification is important for user security.

If host names 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 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 type. The operation allows serializing 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. Accessibility considerations

This section is non-normative.

The API described by this specification has limited accesibility considerations:

The API does allow storage of structured content. Textual content can be stored as strings. Support exists in the API for developers to store alternative non-textual content such as images or audio as , , or objects. Developers producing dynamic content applications using the API should ensure that the content is accessible to users with a variety of technologies and needs.

While the API itself does not define a specific mechanism for it, storage of structured content also allows developers to store internationalized content, using different records or structure within records to hold language alternatives.

The API does not define or require any a user agent to generate a user interface to enable interaction with the API. User agents may optionally provide user interface elements to support the API. Examples include prompts to users when additional storage quota is required, functionality to observe storage used by particular web sites, or tools specific to the API’s storage such as inspecting, modifying, or deleting records. Any such user interface elements must be designed with accessibility tools in mind. For example, a user interface presenting the fraction of storage quota used in graphical form must also provide the same data to tools such as screen readers.

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

12. 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 Adam Klein, Addison Phillips, Adrienne Walker, Alec Flett, Andrea Marchesini, Andreas Butler, Andrew Sutherland, Anne van Kesteren, Anthony Ramine, Ari Chivukula, Arun Ranganathan, Ben Dilts, Ben Turner, Bevis Tseng, Boris Zbarsky, Brett Zamir, Chris Anderson, Dana Florescu, Danillo Paiva, David Grogan, Domenic Denicola, Dominique Hazael-Massieux, Evan Stade, Glenn Maynard, Hans Wennborg, Isiah Meadows, Israel Hilerio, Jake Archibald, Jake Drew, Jerome Hode, Josh Matthews, João Eiras, Kagami Sascha Rosylight, Kang-Hao Lu, Kris Zyp, Kristof Degrave, Kyaw Tun, Kyle Huey, Laxminarayan G Kamath A, Maciej Stachowiak, Marcos Cáceres, Margo Seltzer, Marijn Kruisselbrink, Ms2ger, Odin Omdal, Olli Pettay, Pablo Castro, Philip Jägenstedt, Shawn Wilsher, Simon Pieters, Tobie Langel, Victor Costan, Xiaoqian Wu, Yannic Bonenberger, Yaron Tausky, Yonathan Randolph, and Zhiqiang Zhang, all of whose feedback and suggestions have led to improvements to this specification.

Conformance

Document conventions

Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification.

All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. [RFC2119]

Examples in this specification are introduced with the words “for example” or are set apart from the normative text with class="example", like this:

This is an example of an informative example.

Informative notes begin with the word “Note” and are set apart from the normative text with class="note", like this:

Note, this is an informative note.

Conformant Algorithms

Requirements phrased in the imperative as part of algorithms (such as "strip any leading space characters" or "return false and abort these steps") are to be interpreted with the meaning of the key word ("must", "should", "may", etc) used in introducing the algorithm.

Conformance requirements phrased as algorithms or specific steps can be implemented in any manner, so long as the end result is equivalent. In particular, the algorithms defined in this specification are intended to be easy to understand and are not intended to be performant. Implementers are encouraged to optimize.

Index

Terms defined by this specification

Terms defined by reference

References

Normative References

[DOM]
Anne van Kesteren. DOM Standard. Living Standard. URL: https://dom.spec.whatwg.org/
[ECMA-262]
ECMAScript Language Specification. URL: https://tc39.es/ecma262/multipage/
[FileAPI]
Marijn Kruisselbrink. File API. 6 February 2023. WD. URL: https://www.w3.org/TR/FileAPI/
[HTML]
Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra Standard. Living Standard. URL: https://infra.spec.whatwg.org/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
[STORAGE]
Anne van Kesteren. Storage Standard. Living Standard. URL: https://storage.spec.whatwg.org/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL Standard. Living Standard. URL: https://webidl.spec.whatwg.org/

Informative References

[Charmod-Norm]
Addison Phillips; et al. Character Model for the World Wide Web: String Matching. 11 August 2021. NOTE. URL: https://www.w3.org/TR/charmod-norm/
[COOKIES]
A. Barth. HTTP State Management Mechanism. April 2011. Proposed Standard. URL: https://httpwg.org/specs/rfc6265.html
[WEBSTORAGE]
Ian Hickson. Web Storage (Second Edition). 28 January 2021. REC. URL: https://www.w3.org/TR/webstorage/

IDL Index

[=(Window,Worker)]
interface  :  {
  readonly attribute  ;
  readonly attribute ? ;
  readonly attribute ( or  or )? ;
  readonly attribute ? ;
  readonly attribute  ;

  // Event handlers:
  attribute  ;
  attribute  ;
};

enum  {
  ,
  
};

[=(Window,Worker)]
interface  :  {
  // Event handlers:
  attribute  ;
  attribute  ;
};

[=(Window,Worker)]
interface  :  {
  constructor( type, optional  eventInitDict = {});
  readonly attribute  ;
  readonly attribute ? ;
};

dictionary  :  {
   oldVersion = 0;
  ? newVersion = null;
};

partial interface mixin  {
  [] readonly attribute  ;
};

[=(Window,Worker)]
interface  {
  []  ( name,
                                    optional []  version);
  []  ( name);

  <<>> ();

   ( first,  second);
};

dictionary  {
   ;
   ;
};

[=(Window,Worker)]
interface  :  {
  readonly attribute  ;
  readonly attribute  ;
  readonly attribute  ;

  []  (( or <>) storeNames,
                                         optional  mode = "readonly",
                                         optional  options = {});
   ();

  []  (
     name,
    optional  options = {});
   ( name);

  // Event handlers:
  attribute  ;
  attribute  ;
  attribute  ;
  attribute  ;
};

enum  { , ,  };

dictionary  {
    = "default";
};

dictionary  {
  ( or <>)?  = null;
    = false;
};

[=(Window,Worker)]
interface  {
  attribute  ;
  readonly attribute  ;
  readonly attribute  ;
  [] readonly attribute  ;
  readonly attribute  ;

  []  ( value, optional  key);
  []  ( value, optional  key);
  []  ( query);
  []  ();
  []  ( query);
  []  ( query);
  []  (optional  query,
                                optional []  count);
  []  (optional  query,
                                    optional []  count);
  []  (optional  query);

  []  (optional  query,
                                    optional  direction = "next");
  []  (optional  query,
                                       optional  direction = "next");

   ( name);

  []  ( name,
                                   ( or <>) keyPath,
                                   optional  options = {});
   ( name);
};

dictionary  {
    = false;
    = false;
};

[=(Window,Worker)]
interface  {
  attribute  ;
  [] readonly attribute  ;
  readonly attribute  ;
  readonly attribute  ;
  readonly attribute  ;

  []  ( query);
  []  ( query);
  []  (optional  query,
                                optional []  count);
  []  (optional  query,
                                    optional []  count);
  []  (optional  query);

  []  (optional  query,
                                    optional  direction = "next");
  []  (optional  query,
                                       optional  direction = "next");
};

[=(Window,Worker)]
interface  {
  readonly attribute  ;
  readonly attribute  ;
  readonly attribute  ;
  readonly attribute  ;

  // Static construction methods:
  [] static  ( value);
  [] static  ( lower, optional  open = false);
  [] static  ( upper, optional  open = false);
  [] static  ( lower,
                                        upper,
                                       optional  lowerOpen = false,
                                       optional  upperOpen = false);

   ( key);
};

[=(Window,Worker)]
interface  {
  readonly attribute ( or ) ;
  readonly attribute  ;
  readonly attribute  ;
  readonly attribute  ;
  [] readonly attribute  ;

   ([]  count);
   (optional  key);
   ( key,  primaryKey);

  []  ( value);
  []  ();
};

enum  {
  ,
  ,
  ,
  
};

[=(Window,Worker)]
interface  :  {
  readonly attribute  ;
};

[=(Window,Worker)]
interface  :  {
  readonly attribute  ;
  readonly attribute  ;
  readonly attribute  ;
  [] readonly attribute  ;
  readonly attribute ? ;

   ( name);
   ();
   ();

  // Event handlers:
  attribute  ;
  attribute  ;
  attribute  ;
};

enum  {
  ,
  ,
  
};

MDN

IDBCursor/advance

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBCursor/continue

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBCursor/continuePrimaryKey

In all current engines.

Firefox10+Safari10.1+Chrome58+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android51+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBCursor/delete

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBCursor/direction

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBCursor/key

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBCursor/primaryKey

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBCursor/request

In all current engines.

Firefox77+Safari15+Chrome76+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBCursor/source

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBCursor/update

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBCursor

In all current engines.

Firefox16+Safari8+Chrome24+
Opera44+Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView4.4+Samsung Internet?Opera Mobile43+
MDN

IDBCursorWithValue/value

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBCursorWithValue

In all current engines.

Firefox16+Safari8+Chrome24+
Opera15+Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView4.4+Samsung Internet?Opera Mobile14+
MDN

IDBDatabase/close

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBDatabase/close_event

In all current engines.

Firefox50+Safari10.1+Chrome30+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView37+Samsung Internet?Opera Mobile?
MDN

IDBDatabase/close_event

In all current engines.

Firefox50+Safari10.1+Chrome30+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView37+Samsung Internet?Opera Mobile?
MDN

IDBDatabase/createObjectStore

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBDatabase/deleteObjectStore

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBDatabase/name

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBDatabase/objectStoreNames

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBDatabase/transaction

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBDatabase/version

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBDatabase/versionchange_event

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBDatabase/versionchange_event

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBDatabase

In all current engines.

Firefox16+Safari8+Chrome24+
Opera15+Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView4.4+Samsung Internet?Opera Mobile14+
MDN

IDBFactory/cmp

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBFactory/databases

FirefoxNoneSafari14+Chrome72+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBFactory/deleteDatabase

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBFactory/open

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBFactory

In all current engines.

Firefox16+Safari8+Chrome24+
Opera15+Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView4.4+Samsung Internet?Opera Mobile14+
MDN

IDBIndex/count

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBIndex/get

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBIndex/getAll

In all current engines.

Firefox44+Safari10.1+Chrome48+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBIndex/getAllKeys

In all current engines.

Firefox44+Safari10.1+Chrome48+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBIndex/getKey

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBIndex/keyPath

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBIndex/multiEntry

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBIndex/name

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBIndex/objectStore

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBIndex/openCursor

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBIndex/openKeyCursor

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBIndex/unique

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBIndex

In all current engines.

Firefox16+Safari8+Chrome24+
Opera15+Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView4.4+Samsung Internet?Opera Mobile14+
MDN

IDBKeyRange/bound_static

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBKeyRange/includes

In all current engines.

Firefox47+Safari10.1+Chrome52+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBKeyRange/lower

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBKeyRange/lowerBound_static

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBKeyRange/lowerOpen

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBKeyRange/only_static

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBKeyRange/upper

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBKeyRange/upperBound_static

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBKeyRange/upperOpen

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBKeyRange

In all current engines.

Firefox16+Safari8+Chrome24+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView4.4+Samsung Internet?Opera Mobile14+
MDN

IDBObjectStore/add

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBObjectStore/autoIncrement

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)?IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBObjectStore/clear

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBObjectStore/count

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBObjectStore/createIndex

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBObjectStore/delete

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBObjectStore/deleteIndex

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBObjectStore/get

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBObjectStore/getAll

In all current engines.

Firefox44+Safari10.1+Chrome48+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android48+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBObjectStore/getAllKeys

In all current engines.

Firefox44+Safari10.1+Chrome48+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android48+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBObjectStore/getKey

In all current engines.

Firefox51+Safari10.1+Chrome48+
Opera45+Edge79+
Edge (Legacy)?IENone
Firefox for Android58+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile43+
MDN

IDBObjectStore/index

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBObjectStore/indexNames

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBObjectStore/keyPath

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBObjectStore/name

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBObjectStore/openCursor

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBObjectStore/openKeyCursor

In all current engines.

Firefox44+Safari10.1+Chrome23+
Opera?Edge79+
Edge (Legacy)?IE10+
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBObjectStore/put

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBObjectStore/transaction

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBObjectStore

In all current engines.

Firefox16+Safari8+Chrome24+
Opera15+Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView4.4+Samsung Internet?Opera Mobile14+
MDN

IDBOpenDBRequest/blocked_event

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBOpenDBRequest/upgradeneeded_event

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBOpenDBRequest

In all current engines.

Firefox16+Safari8+Chrome24+
Opera15+Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView4.4+Samsung Internet?Opera Mobile14+
MDN

IDBRequest/error

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBRequest/error_event

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?

IDBTransaction/error_event

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBRequest/readyState

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBRequest/result

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBRequest/source

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBRequest/success_event

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBRequest/transaction

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBRequest

In all current engines.

Firefox16+Safari8+Chrome24+
Opera15+Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android25+Android WebView4.4+Samsung Internet?Opera Mobile14+
MDN

IDBTransaction/abort

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBTransaction/abort_event

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBTransaction/commit

In all current engines.

Firefox74+Safari15+Chrome76+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBTransaction/complete_event

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBTransaction/db

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBTransaction/durability

FirefoxNoneSafari15+Chrome83+
Opera70+Edge83+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBTransaction/error

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBTransaction/mode

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBTransaction/objectStore

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBTransaction/objectStoreNames

In all current engines.

Firefox10+Safari10.1+Chrome48+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBTransaction

In all current engines.

Firefox16+Safari8+Chrome24+
Opera15+Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView4.4+Samsung Internet?Opera Mobile14+
MDN

IDBVersionChangeEvent/IDBVersionChangeEvent

In all current engines.

Firefox25+Safari10+Chrome41+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBVersionChangeEvent/newVersion

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBVersionChangeEvent/oldVersion

In all current engines.

Firefox10+Safari8+Chrome23+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

IDBVersionChangeEvent

In all current engines.

Firefox16+Safari8+Chrome24+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView4.4+Samsung Internet?Opera Mobile?
MDN

indexedDB

In all current engines.

Firefox16+Safari8+Chrome24+
Opera?Edge79+
Edge (Legacy)12+IE10+
Firefox for Android22+iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?