From d13c89772875007a1ee15f4f896f737323ade1d8 Mon Sep 17 00:00:00 2001 From: Anne van Kesteren Date: Fri, 10 Jul 2020 19:28:41 +0200 Subject: [PATCH] Refactor Web storage Use the new primitives in the Storage Standard. Closes #3209, closes #3210, closes #3283, closes #4650, closes #5463, and closes #5498. --- source | 518 ++++++++++++++++++++++++++++++--------------------------- 1 file changed, 269 insertions(+), 249 deletions(-) diff --git a/source b/source index d2df3586a75..04596540ed8 100644 --- a/source +++ b/source @@ -2230,7 +2230,9 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute getting the value of an entry, setting the value of an entry, removing an entry, - getting the keys, and + clear, + getting the keys, + size, and iterate
  • The list data structure and the associated definitions for append, @@ -3967,6 +3969,17 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute +
    Storage
    +
    +

    The following terms are defined in Storage:

    + +
      +
    • obtain a local storage bottle map
    • +
    • obtain a session storage bottle map
    • +
    • storage proxy map
    • +
    • legacy-clone a browsing session storage shed
    • +
    +

    @@ -76917,17 +76930,10 @@ popup4.close();
  • Set browsingContext's opener browsing context to opener.

  • -
  • Assert: browsingContext's creator origin is non-null.

  • - -
  • If browsingContext's creator origin is - same origin with browsingContext's active document's - origin, then copy the sessionStorage - storage area of opener into browsingContext's set of session storage areas. - These areas must be considered separate, not affecting each other in any way.

  • - +
  • Legacy-clone a browsing session storage shed with + opener's browsing session and + browsingContext's browsing session.

  • Return browsingContext.

  • @@ -100254,12 +100260,10 @@ interface WorkerLocation { to buy two tickets for the same flight without really noticing.

    To address this, this specification introduces the sessionStorage IDL attribute. Sites can add data to the session - storage, and it will be accessible to any page from the same site opened in that window.

    + data-x="dom-sessionStorage">sessionStorage getter. Sites can add data to the session + storage, and it will be accessible to any page from the same site opened in that window.

    -

    For example, a page could have a checkbox that the user ticks to indicate that they want insurance:

    @@ -100275,7 +100279,6 @@ interface WorkerLocation {

    If the user had multiple windows opened on the site, each one would have its own individual copy of the session storage object.

    -
    If n is - greater than or equal to the number of key/value pairs - in the object, then this method must return null.

    +
    +
    map +
    A storage proxy map.
    -

    The supported property names on a Storage object are the keys of each - key/value pair currently present in the list associated with the object, in the order that the - keys were last added to the storage area.

    +
    type +
    "local" or "session". +
    -

    The getItem(key) method - must return the current value associated with the given key. If the given key does not exist in the list associated with the object then this method must - return null.

    +

    To reorder a Storage object + storage, reorder storage's map's + entries in an implementation-defined manner.

    -

    The setItem(key, value) method must first check if a key/value pair with the given key already exists in the list associated with the object.

    +

    Unfortunate as it is, iteration order is not defined and can change upon most + mutations.

    -

    If it does not, then a new key/value pair must be added to the list, with the given key and with its value set to value.

    +

    To broadcast a Storage object + storage, given a key, oldValue, and newValue, run + these steps:

    -

    If the given key does exist in the list, and its value is not - equal to value, then it must have its value updated to value. If its previous value is equal to value, then - the method must do nothing.

    +
      +
    1. Let url be storage's relevant global object's associated Document's URL.

    2. -

      If it couldn't set the new value, the method must throw a - "QuotaExceededError" DOMException exception.

      +
    3. +

      Let remoteStorages be all Storage objects excluding + storage whose:

      -

      The removeItem(key) - method must cause the key/value pair with the given key to be removed from the - list associated with the object, if it exists. If no item with that key exists, the method must do - nothing.

      +
        +
      • type is storage's type
      • -

        The setItem() and removeItem() methods must be atomic with respect to failure. - In the case of failure, the method does nothing. That is, changes to the data storage area must - either be successful, or the data storage area must not be changed at all.

        +
      • relevant settings object's origin is same origin + with storage's relevant settings object's origin.
      • +
      -

      The clear() method must atomically cause the - list associated with the object to be emptied of all key/value pairs, if there are any. If there - are none, then the method must do nothing.

      +

      and, if type is "session", + whose relevant settings object's browsing session is storage's relevant settings object's + browsing session.

      +
    4. - +
    5. +

      For each remoteStorage of + remoteStorages: queue a global task on the DOM manipulation task + source given remoteStorage's relevant global object to fire an event named storage at remoteStorage's relevant global + object, using StorageEvent, with key initialized to key, oldValue initialized to oldValue, newValue initialized to newValue, url initialized to url, and storageArea initialized to + remoteStorage.

      + -

      When the setItem(), removeItem(), and clear() methods are invoked, events are fired on the - relevant global objects of other - Document objects that can access the newly stored or removed data, as defined in the - sections on the sessionStorage and localStorage attributes.

      +

      The Document object associated with the resulting task is not necessarily fully active, but events fired + on such objects are ignored by the event loop until the Document + becomes fully active again.

      +
    6. +
    -

    This specification does not require that the above methods wait until the data has - been physically written to disk. Only consistency in what different scripts accessing the same - underlying list of key/value pairs see is required.

    +
    +

    The length getter steps are to return + this's map's size.

    -

    The sessionStorage attribute

    +

    The key(n) method steps are:

    -
    interface mixin WindowSessionStorage {
    -  readonly attribute Storage sessionStorage;
    -};
    -Window includes WindowSessionStorage;
    +
      +
    1. If n is greather than or equal to this's map's size, then return + null.

    2. -

      The sessionStorage attribute represents the - set of storage areas specific to the current top-level browsing context.

      +
    3. Let keys be the result of running get the + keys on this's map. -

      -
      window . sessionStorage
      -

      Returns the Storage object associated with that origin's session storage - area.

      -
      +
    4. Return keys[n].

    5. +
    -

    Each top-level browsing context has a unique set of session storage areas, one for - each origin.

    +

    The supported property names on a Storage object storage + are the result of running get the keys on + storage's map.

    -

    User agents should not expire data from a browsing context's session storage areas, but may do - so when the user requests that such data be deleted, or when the UA detects that it has limited - storage space, or for security reasons. User agents should always avoid deleting data while a - script that could access that data is running. When a top-level browsing context is destroyed (and - therefore permanently inaccessible to the user) the data stored in its session storage areas can - be discarded with it, as the API described in this specification provides no way for that data to - ever be subsequently retrieved.

    +

    The getItem(key) method steps + are:

    -
    +
      +
    1. If this's map[key] does + not exist, then return null.

    2. -

      The lifetime of a browsing context can be unrelated to the lifetime of the actual - user agent process itself, as the user agent can support resuming sessions after a restart.

      +
    3. Return this's map[key].

    4. +
    -

    When a new Document is created in a browsing context which has a - top-level browsing context, the user agent must check to see if that top-level - browsing context has a session storage area for that document's origin. If it - does, then that is the Document's assigned session storage area. If it does not, a - new storage area for that document's origin must be created, and then that - is the Document's assigned session storage area. A Document's assigned - storage area does not change during the lifetime of a Document.

    +

    The setItem(key, + value) method are:

    -

    In the case of an iframe being moved to another - Document, its nested browsing context is destroyed and a new one created.

    +
      +
    1. Let oldValue be null.

    2. -

      The sessionStorage attribute must return a - Storage object associated with the Document's assigned session storage - area. Each Document object must have a separate object for its relevant global - object's sessionStorage attribute.

      +
    3. Let reorder be true.

    4. -

      While creating a new auxiliary browsing context, the session storage area is copied over.

      +
    5. +

      If this's map[key] + exists:

      -
    +
      +
    1. Set oldValue to this's map[key].

    2. -

      When the setItem(), removeItem(), and clear() methods are called on a Storage object x that is associated with a session storage area, if the methods did not throw an - exception or "do nothing" as defined above, then for every Document object whose - relevant global object's sessionStorage - attribute's Storage object is associated with the same storage area, other than - x, user agents send a storage notification.

      +
    3. If oldValue is value, then return.

    4. +
    5. Set reorder to false.

    6. +
    + -

    The localStorage attribute

    +
  • If value cannot be stored, then throw a + "QuotaExceededError" DOMException exception.

  • -
    interface mixin WindowLocalStorage {
    -  readonly attribute Storage localStorage;
    -};
    -Window includes WindowLocalStorage;
    +
  • Set this's map[key] to value.

  • -

    - - The localStorage object provides a - Storage object for an origin.

    +
  • If reorder is true, then reorder + this.

  • + +
  • Broadcast this with + key, oldValue, and value.

  • + + +

    The removeItem(key) method + steps are:

    + +
      +
    1. If this's map[key] does + not exist, then return null.

    2. + +
    3. Set oldValue to this's map[key].

    4. + +
    5. Remove this's map[key].

    6. + +
    7. Reorder this.

    8. + +
    9. Broadcast this with + key, oldValue, and null.

    10. +
    + +

    The clear() method steps are:

    + +
      +
    1. Clear this's map.

    2. + +
    3. Broadcast this with null, + null, and null.

    4. +
    + + + + +

    The sessionStorage getter

    + +
    interface mixin WindowSessionStorage {
    +  readonly attribute Storage sessionStorage;
    +};
    +Window includes WindowSessionStorage;
    -
    window . localStorage
    +
    window . sessionStorage
    -

    Returns the Storage object associated with that origin's local storage - area.

    -

    Throws a "SecurityError" DOMException if the - Document's origin is an opaque - origin or if the request violates a policy decision (e.g. if the user agent is - configured to not allow the page to persist data).

    +

    Returns the Storage object associated with that window's origin's + session storage area.

    + +

    Throws a "SecurityError" DOMException if the + Document's origin is an opaque + origin or if the request violates a policy decision (e.g., if the user agent is + configured to not allow the page to persist data).

    -

    User agents must have a set of local storage areas, one for each origin.

    +

    A Document object has an associated session storage holder, which is + null or a Storage object. It is initially null.

    -

    User agents should expire data from the local storage areas only for security reasons or when - requested to do so by the user. User agents should always avoid deleting data while a script that - could access that data is running.

    - -

    When the localStorage attribute is accessed, the user - agent must run the following steps, which are known as the - Storage object - initialization steps:

    +

    + + The sessionStorage getter steps are:

      -
    1. If the request violates a policy decision (e.g. if the user agent is configured to not - allow the page to persist data), the user agent may throw a - "SecurityError" DOMException instead of returning a - Storage object

    2. +
    3. If this's associated + Document's session storage holder is non-null, then return + this's associated + Document's session storage holder.

    4. -
    5. If the Document's origin is an opaque origin, then throw a - "SecurityError" DOMException.

    6. +
    7. Let map be the result of running obtain a session storage bottle + map with this's relevant settings object and "sessionStorage".

    8. + +
    9. If map is failure, then throw a "SecurityError" + DOMException.

    10. -
    11. Check to see if the user agent has allocated a local storage area for the - origin of the associated - Document of the Window object on which the attribute was - accessed. If it has not, create a new storage area for that origin.

    12. +
    13. Let storage be a new Storage object whose map is map. -

    14. Return the Storage object associated with that origin's local storage area. - Each Document object must have a separate object for its relevant global - object's localStorage attribute.

      +
    15. Set this's associated + Document's session storage holder to + storage.

    16. + +
    17. Return storage.

    +

    While creating a new auxiliary browsing context, the session storage + is copied over.

    +
    -

    When the setItem(), removeItem(), and clear() methods are called on a Storage object x that is associated with a local storage area, if the methods did not throw an - exception or "do nothing" as defined above, then for every Document object whose - relevant global object's localStorage - attribute's Storage object is associated with the same storage area, other than - x, user agents send a storage notification. -

    The localStorage attribute provides - access to shared state. This specification does not define the interaction with other browsing - contexts in a multiprocess user agent, and authors are encouraged to assume that there is no - locking mechanism. A site could, for instance, try to read the value of a key, increment its - value, then write it back out, using the new value as a unique identifier for the session; if the - site does this twice in two different browser windows at the same time, it might end up using the - same "unique" identifier for both sessions, with potentially disastrous effects.

    +

    The localStorage getter

    + +
    interface mixin WindowLocalStorage {
    +  readonly attribute Storage localStorage;
    +};
    +Window includes WindowLocalStorage;
    -

    The storage event

    +
    +
    window . localStorage
    +
    +

    Returns the Storage object associated with window's origin's local + storage area.

    -

    The storage event is fired on a Document object's - relevant global object when a storage area changes, as described in the - previous two sections (for session storage, for local storage).

    +

    Throws a "SecurityError" DOMException if the + Document's origin is an opaque + origin or if the request violates a policy decision (e.g., if the user agent is + configured to not allow the page to persist data).

    +
    +
    -

    When a user agent is to send a storage notification for a Document, the - user agent must queue a task to fire an - event named storage at the Document object's relevant - global object, using StorageEvent.

    +

    A Document object has an associated local storage holder, which is null + or a Storage object. It is initially null.

    + +

    + + The localStorage getter steps are:

    + +
      +
    1. If this's associated + Document's local storage holder is non-null, then return + this's associated + Document's local storage holder.

    2. -

      Such a Document object is not necessarily fully active, - but events fired on such objects are ignored by the event loop until the - Document becomes fully active again.

      +
    3. Let map be the result of running obtain a local storage bottle map + with this's relevant settings object and "localStorage".

    4. -

      The task source for these tasks is the DOM manipulation task - source.

      +
    5. If map is failure, then throw a "SecurityError" + DOMException.

    6. -

      If the event is being fired due to an invocation of the setItem() or removeItem() methods, the event must have its key attribute initialized to the name of the key in question, - its oldValue attribute initialized to the old - value of the key in question, or null if the key is newly added, and its newValue attribute initialized to the new value of the - key in question, or null if the key was removed.

      +
    7. Let storage be a new Storage object whose map is map. -

      Otherwise, if the event is being fired due to an invocation of the clear() method, the event must have its key, oldValue, - and newValue attributes initialized to null.

      +
    8. Set this's associated + Document's local storage holder to storage.

    9. -

      In addition, the event must have its url attribute - initialized to the URL of the document whose - Storage object was affected; and its storageArea attribute initialized to the - Storage object from the relevant global object of the target - Document that represents the same kind of Storage area as was affected - (i.e. session or local).

      +
    10. Return storage.

    11. +
    -
    The StorageEvent interface
    +

    The StorageEvent interface

    [Exposed=Window]
     interface StorageEvent : Event {
    @@ -100698,31 +100740,6 @@ dictionary StorageEventInit : EventInit {
       
     
     
    -  

    Disk space

    - -

    User agents should limit the total amount of space allowed for storage areas, because hostile - authors could otherwise use this feature to exhaust the user's available disk space.

    - -

    User agents should guard against sites storing data under their origin's other affiliated - sites, e.g. storing up to the limit in a1.example.com, a2.example.com, a3.example.com, etc, - circumventing the main example.com storage limit.

    - -

    User agents may prompt the user when quotas are reached, allowing the user to grant a site more - space. This enables sites to store many user-created documents on the user's computer, for - instance.

    - -

    User agents should allow users to see how much space each domain is using.

    - - - -

    A mostly arbitrary limit of five megabytes per origin is suggested. Implementation - feedback is welcome and will be used to update this suggestion in the future.

    - -

    For predictability, quotas should be based on the uncompressed size of data stored.

    - - -

    Privacy

    User tracking

    @@ -122129,6 +122146,9 @@ INSERT INTERFACES HERE
    [SRI]
    Subresource Integrity, D. Akhawe, F. Braun, F. Marier, J. Weinberger. W3C.
    +
    [STORAGE]
    +
    Storage, A. van Kesteren. WHATWG.
    +
    [SVG]
    Scalable Vector Graphics (SVG) 2, N Andronikos, R. Atanassov, T. Bah, B. Birtles, B. Brinza, C. Concolato, E. Dahlström, C. Lilley, C. McCormack, D. Schepers, R. Schwerdtfeger, D. Storey, S. Takagi, J. Watt. W3C.