diff --git a/index.bs b/index.bs index d13da4a..a4530e8 100644 --- a/index.bs +++ b/index.bs @@ -28,11 +28,6 @@ spec: html; urlPrefix: https://html.spec.whatwg.org/multipage/ urlPrefix: dom.html type: interface text: Document; url: document - urlPrefix: infrastructure.html - type: abstract-op - text: StructuredClone; url: structuredclone - type: dfn - text: cloneable objects; url: cloneable-objects spec: ecma262; urlPrefix: https://tc39.github.io/ecma262/ type: dfn url: sec-algorithm-conventions @@ -61,6 +56,7 @@ spec: ecma262; urlPrefix: https://tc39.github.io/ecma262/ text: Realm; url: realm text: current Realm; url: current-realm text: Array.prototype.sort; url: sec-array.prototype.sort + text: Record; url: sec-list-and-record-specification-type spec: webidl; urlPrefix: https://heycam.github.io/webidl/ type: dfn text: sequence; url: idl-sequence @@ -576,13 +572,16 @@ transaction=] is running. Each record is associated with a value. User agents must -support any [=cloneable object=]. This includes simple types +support any [=serializable object=]. This includes simple types such as [=String=] primitive values and [=Date=] objects as well as [=Object=] and [=Array=] instances, {{File}} objects, {{Blob}} objects, {{ImageData}} objects, and so on. Record [=/values=] are stored and retrieved by value rather than by reference; later changes to a value have no effect on the record stored in the database. +Record [=/values=] are [=/Records=] output by the +StructuredSerialize operation. +

Keys

@@ -793,7 +792,7 @@ from a [=/value=]. A valid key path is one of: [=/Key path=] values can only be accessed from properties explicitly -copied by StructuredClone, as well as the +copied by StructuredSerialize, as well as the following type-specific properties: @@ -2969,9 +2968,17 @@ when invoked, must run these steps: 9. Let |targetRealm| be a user-agent defined [=Realm=]. -10. Let |clone| be StructuredClone(|value|, |targetRealm|). +10. Let |clone| be a [=clone=] of |value| in |targetRealm|. Rethrow any exceptions. +
+ Why create a copy of the value? + The value must be serialized when stored. Treating it as a copy + here allows other algorithms in this specification to treat it as + an ECMAScript value, but implementations may optimize this + if the difference in behavior is not observable. +
+ 11. If |store| uses [=in-line keys=], run these substeps: 1. Let |kpk| be the result of running the steps to [=extract a @@ -3040,9 +3047,17 @@ when invoked, must run these steps: 9. Let |targetRealm| be a user-agent defined [=Realm=]. -10. Let |clone| be StructuredClone(|value|, |targetRealm|). +10. Let |clone| be a [=clone=] of |value| in |targetRealm|. Rethrow any exceptions. +
+ Why create a copy of the value? + The value must be serialized when stored. Treating it as a copy + here allows other algorithms in this specification to treat it as + an ECMAScript value, but implementations may optimize this + if the difference in behavior is not observable. +
+ 11. If |store| uses [=in-line keys=], run these substeps: 1. Let |kpk| be the result of running the steps to [=extract a @@ -4904,9 +4919,17 @@ invoked, must run these steps: 7. Let |targetRealm| be a user-agent defined [=Realm=]. -8. Let |clone| be StructuredClone(|value|, |targetRealm|). +8. Let |clone| be a [=clone=] of |value| in |targetRealm|. Rethrow any exceptions. +
+ Why create a copy of the value? + The value must be serialized when stored. Treating it as a copy + here allows other algorithms in this specification to treat it as + an ECMAScript value, but implementations may optimize this + if the difference in behavior is not observable. +
+ 9. If the [=effective object store=] of this cursor uses [=in-line keys=], run these substeps: @@ -5775,6 +5798,23 @@ the implementation must run the following steps: + +

Clone a value

+ + +
+ + To make a clone of |value| in |targetRealm|, + the implementation must run the following steps: + + 1. Let |serialized| be [=?=] StructuredSerialize(|value|). + + 2. Let |clone| be [=?=] StructuredDeserialize(|serialized|, |targetRealm|). + + 3. Return |clone|. + +
+

Database operations

@@ -5786,9 +5826,10 @@ These operations are run by the steps to [=asynchronously execute a request=]. @@ -5829,7 +5870,8 @@ follows. to=] |key|, then remove the [=object-store/record=] from |store| using the steps to [=delete records from an object store=]. -4. Store a record in |store| containing |key| as its key and |value| +4. Store a record in |store| containing |key| as its key and + [=!=] StructuredSerialize(|value|) as its value. The record is stored in the object store's [=object-store/list of records=] such that the list is sorted according to the key of the records in [=ascending=] order. @@ -5912,9 +5954,9 @@ The steps to retrieve a value from an object store with 2. If |record| was not found, return undefined. -3. Let |value| be of |record|'s [=/value=]. +3. Let |serialized| be of |record|'s [=/value=]. -4. Return [=!=] StructuredClone(|value|, |targetRealm|). +4. Return [=!=] StructuredDeserialize(|serialized|, |targetRealm|). @@ -5934,8 +5976,8 @@ store with |targetRealm|, |store|, |range| and optional |count| are as fol 4. For each |record| in |records|, run these substeps: - 1. Let |value| be |record|'s [=/value=]. - 2. Let |entry| be [=!=] StructuredClone(|value|, |targetRealm|). + 1. Let |serialized| be |record|'s [=/value=]. + 2. Let |entry| be [=!=] StructuredDeserialize(|serialized|, |targetRealm|). 3. Append |entry| to |list|. 5. Return |list| converted to a [=sequence<any>=]. @@ -5998,9 +6040,9 @@ with |targetRealm|, |index| and |range| are as follows. 2. If |record| was not found, return undefined. -3. Let |value| be |record|'s [=referenced value=]. +3. Let |serialized| be |record|'s [=referenced value=]. -4. Return [=!=] StructuredClone(|value|, |targetRealm|). +4. Return [=!=] StructuredDeserialize(|serialized|, |targetRealm|). @@ -6019,8 +6061,8 @@ index with |targetRealm|, |index|, |range| and optional |count| are as fol 4. For each |record| in |records|, run these substeps: - 1. Let |value| be |record|'s [=referenced value=]. - 2. Let |entry| be [=!=] StructuredClone(|value|, |targetRealm|). + 1. Let |serialized| be |record|'s [=referenced value=]. + 2. Let |entry| be [=!=] StructuredDeserialize(|serialized|, |targetRealm|). 3. Append |entry| to |list|. 5. Return |list| converted to a [=sequence<any>=]. @@ -6294,9 +6336,9 @@ follows. 13. If |cursor|'s [=key only flag=] is unset, run these substeps: - 1. Let |value| be |found record|'s [=referenced value=]. + 1. Let |serialized| be |found record|'s [=referenced value=]. 2. Set |cursor|'s [=cursor/value=] to - [=!=] StructuredClone(|value|, |targetRealm|) + [=!=] StructuredDeserialize(|serialized|, |targetRealm|) 14. Set |cursor|'s [=got value flag=]. @@ -6441,7 +6483,7 @@ ECMAScript value or failure, or the steps may throw an exception. @@ -6489,7 +6531,7 @@ true or false.
@@ -6537,7 +6579,7 @@ as follows. The algorithm takes a |value|, a |key| and a |keyPath|. @@ -6970,7 +7012,7 @@ basic serialization concerns, serialized data could encode assumptions which are not valid in newer versions of the user agent. A practical example of this is the [=RegExp=] type. The StructuredClone operation allows cloning [=RegExp=] +abstract-op>StructuredSerialize operation allows serializing [=RegExp=] objects. A typical user agent will compile a regular expression into native machine instructions, with assumptions about how the input data is passed and results returned. If this internal state was serialized @@ -7077,9 +7119,6 @@ document's Revision History. * Add non-normative documentation for every method. (bug #110) -* Use [[HTML]]'s StructuredClone hook. - (bug #135) - * Throw {{SecurityError}} if {{IDBFactory/open()}} or {{IDBFactory/deleteDatabase()}} is called from an opaque origin. (bug #148) @@ -7095,6 +7134,10 @@ document's Revision History. * Fix handling of edge cases in key generation algorithm. (bug #147) +* Use [[HTML]]'s StructuredSerialize and + StructuredDeserialize hooks. + (bug #170) +

Acknowledgements

diff --git a/index.html b/index.html index 1e02539..9ae4e00 100644 --- a/index.html +++ b/index.html @@ -1455,7 +1455,7 @@

Indexed Database API 2.0

-

Editor’s Draft,

+

Editor’s Draft,

This version: @@ -1573,6 +1573,7 @@

Table of Contents

  • 5.8 Aborting an upgrade transaction
  • 5.9 Firing a success event
  • 5.10 Firing an error event +
  • 5.11 Clone a value
  • 6 Database operations @@ -1973,10 +1974,11 @@

    2.3. Values

    Each record is associated with a value. User agents must -support any cloneable object. This includes simple types +support any serializable object. This includes simple types such as String primitive values and Date objects as well as Object and Array instances, File objects, Blob objects, ImageData objects, and so on. Record values are stored and retrieved by value rather than by reference; later changes to a value have no effect on the record stored in the database.

    +

    Record values are Records output by the StructuredSerialize operation.

    2.4. Keys

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

    @@ -2164,7 +2166,7 @@

    2.5. Key Path

    A key path is a string or list of strings -that defines how to extract a key from a value. A valid key path is one of:

    +that defines how to extract a key from a value. A valid key path is one of:

    • An empty string.

      @@ -2180,7 +2182,7 @@

      Key path values can only be accessed from properties explicitly -copied by StructuredClone, as well as the +copied by StructuredSerialize, as well as the following type-specific properties:

  • @@ -2201,7 +2203,7 @@

    length

    2.6. Index

    -

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

    +

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

    An index is a specialized persistent key-value storage and has a referenced object store. The index has a list of records which hold the data stored in @@ -2211,7 +2213,7 @@

    object store, in which changes to the object store cause all such indexes to get updated.

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

    @@ -2626,11 +2628,11 @@

    the one previously returned.

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

    A cursor has a key and a value which -represent the key and the value of the last iterated record.

    +represent the key and the value of the last iterated record.

    A cursor has a got value flag. When this flag unset, the cursor is either in the process of loading the next value or it has reached the end of its range. When it is set, it indicates @@ -3636,8 +3638,15 @@

    Let targetRealm be a user-agent defined Realm.

  • -

    Let clone be StructuredClone(value, targetRealm). +

    Let clone be a clone of value in targetRealm. Rethrow any exceptions.

    +
    + Why create a copy of the value? + The value must be serialized when stored. Treating it as a copy + here allows other algorithms in this specification to treat it as + an ECMAScript value, but implementations may optimize this + if the difference in behavior is not observable. +
  • If store uses in-line keys, run these substeps:

      @@ -3703,8 +3712,15 @@

      Let targetRealm be a user-agent defined Realm.

    1. -

      Let clone be StructuredClone(value, targetRealm). +

      Let clone be a clone of value in targetRealm. Rethrow any exceptions.

      +
      + Why create a copy of the value? + The value must be serialized when stored. Treating it as a copy + here allows other algorithms in this specification to treat it as + an ECMAScript value, but implementations may optimize this + if the difference in behavior is not observable. +
    2. If store uses in-line keys, run these substeps:

        @@ -3791,9 +3807,9 @@

        request = store . get(query)
        - Retrieves the value of the first record matching the + Retrieves the value of the first record matching the given key or key range in query. -

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

        +

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

        request = store . getKey(query)
        Retrieves the key of the first record matching the @@ -3801,10 +3817,10 @@

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

        request = store . getAll(query [, count])
        - Retrieves the values of the records matching the + Retrieves the values of the records matching the given key or key range in query (up to count if given).

        If successful, request’s result will - be an Array of the values.

        + be an Array of the values.

        request = store . getAllKeys(query [, count])
        Retrieves the keys of records matching the @@ -4305,9 +4321,9 @@

        request = store . get(query)
        - Retrieves the value of the first record matching the + Retrieves the value of the first record matching the given key or key range in query. -

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

        +

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

        request = store . getKey(query)
        Retrieves the key of the first record matching the @@ -4315,8 +4331,8 @@

        result will be the key, or undefined if there was no matching record.

        request = store . getAll(query [, count])
        - Retrieves the values of the records matching the given key or key range in query (up to count if given). -

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

        + Retrieves the values of the records matching the given key or key range in query (up to count if given). +

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

        request = store . getAllKeys(query [, count])
        Retrieves the keys of records matching the given key or key range in query (up to count if given). @@ -4953,8 +4969,15 @@

        Let targetRealm be a user-agent defined Realm.

      1. -

        Let clone be StructuredClone(value, targetRealm). +

        Let clone be a clone of value in targetRealm. Rethrow any exceptions.

        +
        + Why create a copy of the value? + The value must be serialized when stored. Treating it as a copy + here allows other algorithms in this specification to treat it as + an ECMAScript value, but implementations may optimize this + if the difference in behavior is not observable. +
      2. If the effective object store of this cursor uses in-line keys, run these substeps:

        @@ -5581,13 +5604,26 @@

        abort a transaction using transaction and request's error.

  • +

    5.11. Clone a value

    +
    +

    To make a clone of value in targetRealm, + the implementation must run the following steps:

    +
      +
    1. +

      Let serialized be ? StructuredSerialize(value).

      +
    2. +

      Let clone be ? StructuredDeserialize(serialized, targetRealm).

      +
    3. +

      Return clone.

      +
    +

    6. Database operations

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

    - +

    6.1. Object Store Storage Operation

    The steps to store a record into an object store with store, value, an optional key, and a no-overwrite flag are as @@ -5622,7 +5658,8 @@

    key, then remove the record from store using the steps to delete records from an object store.

  • -

    Store a record in store containing key as its key and value as its value. The record is stored in the object store’s list of records such that the list is sorted +

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

  • For each index which reference store, run these substeps:

    @@ -5676,9 +5713,9 @@

    If record was not found, return undefined.

  • -

    Let value be of record’s value.

    +

    Let serialized be of record’s value.

  • -

    Return ! StructuredClone(value, targetRealm).

    +

    Return ! StructuredDeserialize(serialized, targetRealm).

  • @@ -5695,9 +5732,9 @@

    -

    Let value be record’s value.

    +

    Let serialized be record’s value.

  • -

    Let entry be ! StructuredClone(value, targetRealm).

    +

    Let entry be ! StructuredDeserialize(serialized, targetRealm).

  • Append entry to list.

    @@ -5750,9 +5787,9 @@

    If record was not found, return undefined.

  • -

    Let value be record’s referenced value.

    +

    Let serialized be record’s referenced value.

  • -

    Return ! StructuredClone(value, targetRealm).

    +

    Return ! StructuredDeserialize(serialized, targetRealm).

  • @@ -5769,9 +5806,9 @@

    For each record in records, run these substeps:

    1. -

      Let value be record’s referenced value.

      +

      Let serialized be record’s referenced value.

    2. -

      Let entry be ! StructuredClone(value, targetRealm).

      +

      Let entry be ! StructuredDeserialize(serialized, targetRealm).

    3. Append entry to list.

    @@ -5790,7 +5827,7 @@

    If record was not found, return undefined.

  • Return the of running the steps to convert a - key to a value with record’s value.

    + key to a value with record’s value.

  • @@ -5865,7 +5902,7 @@

    Let records be the list of records in source.

  • Let range be cursor’s range.

    @@ -5983,9 +6020,9 @@

    If cursor’s key only flag is unset, run these substeps:

    1. -

      Let value be found record’s referenced value.

      +

      Let serialized be found record’s referenced value.

    2. -

      Set cursor’s value to ! StructuredClone(value, targetRealm)

      +

      Set cursor’s value to ! StructuredDeserialize(serialized, targetRealm)

  • Set cursor’s got value flag.

    @@ -6103,7 +6140,7 @@

  • + only applied to values that are the output of StructuredDeserialize and only access "own" properties.

    7.2. Inject a key into a value

    The steps to inject a key into a value using a key path are as follows. The algorithm takes a value, a key and a keyPath.

    @@ -6184,7 +6221,7 @@

    7.3. Convert a key to a value

    @@ -6534,7 +6571,7 @@

    -

    A practical example of this is the RegExp type. The StructuredClone operation allows cloning RegExp objects. A typical user agent will compile a regular expression into +

    A practical example of this is the RegExp type. The StructuredSerialize operation allows serializing RegExp objects. A typical user agent will compile a regular expression into native machine instructions, with assumptions about how the input data is passed and results returned. If this internal state was serialized as part of the data stored to the database, various problems could @@ -6620,9 +6657,6 @@

    Add non-normative documentation for every method. (bug #110)

    -
  • -

    Use [HTML]'s StructuredClone hook. -(bug #135)

  • Throw SecurityError if open() or deleteDatabase() is called from an opaque origin. (bug #148)

    @@ -6637,6 +6671,9 @@

    Fix handling of edge cases in key generation algorithm. (bug #147)

    +
  • +

    Use [HTML]'s StructuredSerialize and StructuredDeserialize hooks. +(bug #170)

    11. Acknowledgements

    Special thanks to Nikunj Mehta, the original author of the first @@ -6759,6 +6796,7 @@

    cleanup Indexed Database transactions, in §2.7
  • clear(), in §4.5
  • clear an object store, in §6.6 +
  • clone, in §5.11
  • close(), in §4.4
  • close a database connection, in §5.2
  • closed, in §2.1.1 @@ -7243,6 +7281,7 @@

    number
  • object
  • realm +
  • record
  • regexp
  • returnifabrupt
  • string @@ -7269,16 +7308,17 @@

    Document
  • EventHandler
  • ImageData -
  • StructuredClone +
  • StructuredDeserialize +
  • StructuredSerialize
  • WindowOrWorkerGlobalScope
  • browsing context -
  • cloneable objects
  • domain
  • event handler idl attribute
  • event loop
  • opaque origin
  • origin
  • queue a task +
  • serializable objects
  • task queues
  • @@ -7823,15 +7863,15 @@

    I #valueReferenced in: +