From 349e066d935428eb9f47fcb04e666cd7c8997da1 Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Wed, 30 Aug 2017 14:26:48 +0100 Subject: [PATCH 1/6] Abortable fetch --- fetch.bs | 1410 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 805 insertions(+), 605 deletions(-) diff --git a/fetch.bs b/fetch.bs index c135722ab..a54412751 100644 --- a/fetch.bs +++ b/fetch.bs @@ -1189,38 +1189,45 @@ or "worker".

In parallel, while true:

    -
  1. Wait for read to be fulfilled or rejected. -

  2. -

    If read is fulfilled with an object whose done property is false - and whose value property is a Uint8Array object, then run these steps: +

    Run these steps, but abort if the ongoing fetch is terminated:

      -
    1. Let bs be the byte sequence represented by the Uint8Array - object. +

    2. Wait for read to be fulfilled or rejected.

    3. -

      Transmit bs. Whenever one or more bytes are transmitted, increase - body's transmitted bytes by the number of transmitted bytes and - queue a fetch task on request to process request body - for request. +

      If read is fulfilled with an object whose done property is false + and whose value property is a Uint8Array object, then run these + steps: -

      This step blocks until bs is fully transmitted. +

        +
      1. Let bs be the byte sequence represented by the + Uint8Array object. -

      2. Set read to the result of reading a - chunk from body's stream with reader. -

      +
    4. +

      Transmit bs. Whenever one or more bytes are transmitted, increase + body's transmitted bytes by the number of transmitted bytes and + queue a fetch task on request to process request body + for request. + +

      This step blocks until bs is fully transmitted. -

    5. Otherwise, if read is fulfilled with an object whose done property - is true, then queue a fetch task on request to - process request end-of-body for request and abort these steps. +

    6. Set read to the result of reading a + chunk from body's stream with reader. +

    -
  3. Otherwise, terminate the ongoing fetch with reason - fatal and abort these steps. +

  4. Otherwise, if read is fulfilled with an object whose done + property is true, then queue a fetch task on request to + process request end-of-body for request and abort these in-parallel steps. + +

  5. Otherwise, terminate the ongoing fetch with reason + fatal. +

+ +
  • If the ongoing fetch is terminated, then abort these in-parallel steps. -

    Responses

    The result of fetch is a @@ -1488,21 +1495,38 @@ for each associated fetch record whose origin and credentials, run these steps:

      -
    1. If connection pool contains a - connection whose origin is origin and - credentials is credentials, return that +

    2. If connection pool contains a connection whose origin is + origin and credentials is credentials, then return that connection. +

    3. Let connection be null. + +

    4. +

      Run these steps, but abort if the ongoing fetch is terminated:

      + +
        +
      1. +

        Set connection to the result of establishing an HTTP connection to + origin. [[!HTTP]] [[!HTTP-SEMANTICS]] [[!HTTP-COND]] [[!HTTP-CACHING]] [[!HTTP-AUTH]] + [[!TLS]] + +

        If credentials is false, then do not send a TLS client certificate. + +

        If establishing a connection does not succeed (e.g., a DNS, TCP, or TLS error), then return + failure. +

      +
    5. -

      Let connection be the result of establishing an HTTP connection to - origin. [[!HTTP]] [[!HTTP-SEMANTICS]] [[!HTTP-COND]] [[!HTTP-CACHING]] [[!HTTP-AUTH]] [[!TLS]] +

      If the ongoing fetch is terminated, then: -

      If credentials is false, do not send a TLS client certificate. +

        +
      1. If connection is not null, close connection. -

        If establishing a connection does not succeed (e.g., a DNS, TCP, or TLS error), return failure. +

      2. Return failure. +

      -
    6. Add connection to the connection pool - with origin being origin and credentials being credentials. +

    7. Add connection to the connection pool with origin + being origin and credentials being credentials.

    8. Return connection.

    @@ -1776,11 +1800,8 @@ from a {{ReadableStream}} object with reader, run these steps:

    To cancel a -{{ReadableStream}} object with reader and reason, return the result of calling -ReadableStreamCancel(reader, reason). - -

    Because the reader grants exclusive access, the actual mechanism of how -to read cannot be observed. Implementations could use more direct mechanism if convenient. +{{ReadableStream}} object stream with reason, return the result of calling +ReadableStreamCancel(stream, reason).

    To tee a {{ReadableStream}} object stream, run these steps: @@ -2295,127 +2316,136 @@ the request. [[!HTTP-CACHING]]

      -
    1. If request's window is - "client", set request's - window to request's - client, if request's - client's - global object is a - {{Window}} object, and to "no-window" - otherwise. - -

    2. If request's origin is - "client", set request's - origin to request's - client's origin. -

    3. -

      If request's header list - does not contain `Accept`, then: +

      Run these steps, but abort if the ongoing fetch is terminated:

        -
      1. Let value be `*/*`. +

      2. If request's window is + "client", set request's + window to request's + client, if request's + client's + global object is a + {{Window}} object, and to "no-window" + otherwise. -

      3. If request is a navigation request, a user agent should set - value to - `text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8`. +

      4. If request's origin is + "client", set request's + origin to request's + client's origin.

      5. -

        Otherwise, a user agent should set value to the first matching statement, if any, - switching on request's destination: - +

        If request's header list + does not contain `Accept`, then: -

        -
        "image" -
        `image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5` +
          +
        1. Let value be `*/*`. -

          "style" -
          `text/css,*/*;q=0.1` -
        +
      6. If request is a navigation request, a user agent should set + value to + `text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8`. -

      7. Append - `Accept`/value to request's - header list. -

      +
    4. +

      Otherwise, a user agent should set value to the first matching statement, if + any, switching on request's destination: + -

    5. If request's header list - does not contain `Accept-Language`, user agents should - append - `Accept-Language`/an appropriate value - to request's header list. +

      +
      "image" +
      `image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5` -
    6. -

      If request's priority is null, then use request's - initiator and destination appropriately in setting - request's priority to a user-agent-defined object. +

      "style" +
      `text/css,*/*;q=0.1` +
    7. -

      The user-agent-defined object could encompass stream weight and dependency - for HTTP/2, and equivalent information used to prioritize dispatch and processing of - HTTP/1 fetches. +

    8. Append + `Accept`/value to request's + header list. +

    -
  • -

    If request is a navigation request, a user agent should, for each - header name (hintName) in the first column of the - following table, if request's header list - does not contain hintName, then - append - hintName/the value given in the same row on the second column, to request's - header list. - - - - - - -
    Name - Value -
    `dpr` - a suitable dpr value -
    `save-data` - a suitable save-data value -
    `viewport-width` - a suitable viewport-width value -
    +

  • If request's header list + does not contain `Accept-Language`, user agents should + append + `Accept-Language`/an appropriate value + to request's header list. -

  • -

    If request is a subresource request, run these substeps: +

  • +

    If request's priority is null, then use request's + initiator and destination appropriately in setting + request's priority to a user-agent-defined object. + +

    The user-agent-defined object could encompass stream weight and dependency + for HTTP/2, and equivalent information used to prioritize dispatch and processing of + HTTP/1 fetches. -

    1. -

      If request's client hints list is not empty, then run these - substeps for each hintName in the list: +

      If request is a navigation request, a user agent should, for each + header name (hintName) in the first column of the + following table, if request's header list + does not contain hintName, then + append + hintName/the value given in the same row on the second column, to + request's header list. + + + + + + +
      Name + Value +
      `dpr` + a suitable dpr value +
      `save-data` + a suitable save-data value +
      `viewport-width` + a suitable viewport-width value +
      + +

    2. +

      If request is a subresource request, run these substeps:

      1. -

        Set value to the first matching statement, if any, switching on - hintName: - -

        -
        "dpr" -
        a suitable dpr value -
        "save-data" -
        a suitable save-data value -
        "viewport-width" -
        a suitable viewport-width value -
        "width" -
        a suitable width value -
        - -
      2. Append hintName/value to - request's header list. +

        If request's client hints list is not empty, then run these + substeps for each hintName in the list: + +

          +
        1. +

          Set value to the first matching statement, if any, switching on + hintName: + +

          +
          "dpr" +
          a suitable dpr value +
          "save-data" +
          a suitable save-data value +
          "viewport-width" +
          a suitable viewport-width value +
          "width" +
          a suitable width value +
          + +
        2. Append hintName/value to + request's header list. +

        + +
      3. Let record be a new + fetch record consisting of + request and this instance of the + fetch algorithm. + +

      4. Append record to request's + client's + fetch group list of + fetch records.

      - -
    3. Let record be a new - fetch record consisting of - request and this instance of the - fetch algorithm. - -

    4. Append record to request's - client's - fetch group list of - fetch records.

    +
  • If the ongoing fetch is terminated, then let reason be the + provided termination reason, and return a network error with + termination reason set to reason. +

  • Return the result of performing a main fetch using request. @@ -2432,81 +2462,91 @@ with a CORS flag and recursive flag, run these steps:

    1. Let response be null. -

    2. If request's local-URLs-only flag is set and - request's current url is - not local, set - response to a network error. +

    3. +

      Run these steps, but abort if the ongoing fetch is terminated:

      -
    4. Execute Report Content Security Policy violations for request. - [[!CSP]] +

        -
      1. Upgrade request to a potentially secure URL, if appropriate. - [[!UPGRADE]] +

      2. If request's local-URLs-only flag is set and + request's current url is + not local, set + response to a network error. -

      3. If - should fetching request be blocked due to a bad port, - should fetching request be blocked as mixed content, - or - should fetching request be blocked by Content Security Policy - returns blocked, set response to a - network error. - [[!MIX]] - [[!CSP]] +

      4. Execute Report Content Security Policy violations for request. + [[!CSP]] -

      5. If request's referrer policy is the empty string and - request's client is non-null, then set request's - referrer policy to request's client's - referrer policy. - [[!REFERRER]] +

      6. Upgrade request to a potentially secure URL, if appropriate. + [[!UPGRADE]] -

      7. -

        If request's referrer policy - is the empty string, then set request's - referrer policy to - "no-referrer-when-downgrade". +

      8. If + should fetching request be blocked due to a bad port, + should fetching request be blocked as mixed content, + or + should fetching request be blocked by Content Security Policy + returns blocked, set response to a + network error. + [[!MIX]] + [[!CSP]] -

        We use "no-referrer-when-downgrade" because it is the - historical default. +

      9. If request's referrer policy is the empty string and + request's client is non-null, then set request's + referrer policy to request's client's + referrer policy. + [[!REFERRER]] -

      10. -

        If request's referrer - is not "no-referrer", set request's - referrer to the result of invoking - determine request's referrer. - [[!REFERRER]] +

      11. +

        If request's referrer policy + is the empty string, then set request's + referrer policy to + "no-referrer-when-downgrade". -

        As stated in Referrer Policy, user agents can - provide the end user with options to override request's - referrer to "no-referrer" or - have it expose less sensitive information. +

        We use "no-referrer-when-downgrade" because it is the + historical default. -

      12. -

        If request's current URL's scheme is - "ftp", request's client's - creation URL's scheme is not "ftp", and - request's reserved client is either null or an environment - whose target browsing context is a nested browsing context, then set - response to a network error. +

      13. +

        If request's referrer + is not "no-referrer", set request's + referrer to the result of invoking + determine request's referrer. + [[!REFERRER]] -

      14. -

        Set request's current url's - scheme to "https" if - all of the following conditions are true: +

        As stated in Referrer Policy, user agents can + provide the end user with options to override request's + referrer to "no-referrer" or + have it expose less sensitive information. -

        - +
      15. +

        If request's current URL's scheme is + "ftp", request's client's + creation URL's scheme is not "ftp", and + request's reserved client is either null or an environment + whose target browsing context is a nested browsing context, then + set response to a network error. + +

      16. +

        Set request's current url's + scheme to "https" if + all of the following conditions are true: + +

        + +
      + +
    5. If the ongoing fetch is terminated, then let reason be the + provided termination reason, and return a network error with + termination reason set to reason.

    6. If request's synchronous flag is unset and recursive flag is unset, run the remaining steps @@ -2788,44 +2828,55 @@ steps:

      "blob"
        -
      1. Let blob be request's - current url's - object. -

      2. -

        If request's method is not - `GET` or blob is null, then return a - network error. +

        Run these steps, but abort if the ongoing fetch is terminated: -

        The `GET` method restriction - serves no useful purpose other than being interoperable. +

          +
        1. Let blob be request's + current url's + object. -

        2. Let response be a new - response. +

        3. +

          If request's method is not + `GET` or blob is null, then return a + network error. -

        4. Append - `Content-Length`/blob's - {{Blob/size}} attribute value to - response's - header list. +

          The `GET` method restriction + serves no useful purpose other than being interoperable. -

        5. Append - `Content-Type`/blob's - {{Blob/type}} attribute value to - response's - header list. +

        6. Let response be a new + response. -

        7. Set response's - HTTPS state to request's - client's HTTPS state - if request's client is non-null. +

        8. Append + `Content-Length`/blob's + {{Blob/size}} attribute value to + response's + header list. + +

        9. Append + `Content-Type`/blob's + {{Blob/type}} attribute value to + response's + header list. -

        10. Set response's body to - the result of performing the read operation on - blob. - +

        11. Set response's + HTTPS state to request's + client's HTTPS state + if request's client is non-null. -

        12. Return response. +

        13. Set response's body to + the result of performing the read operation on + blob. + + + +

        14. Return response. +

        + +
      3. Let reason be the provided termination reason. + +

      4. Return a network error with termination reason set to + reason.

      "data" @@ -2936,8 +2987,7 @@ optional CORS flag and CORS-preflight flag, run these steps: url list has more than one item. -
    7. Execute - set response's CSP list +

    8. Execute set response's CSP list on actualResponse. [[!CSP]]

    @@ -3177,280 +3227,288 @@ Range Requests. [[HTTP-RANGE]] However, this is not widely supported by b
    1. Let httpRequest be null. -

    2. If request's window is "no-window" and - request's redirect mode is "error", then set - httpRequest to request. -

    3. -

      Otherwise, run these substeps: +

      Run these steps, but abort if the ongoing fetch is terminated:

        -
      1. Set httpRequest to a copy of request except for its - body. - -

      2. Let body be request's body. +

      3. If request's window is "no-window" and + request's redirect mode is "error", then set + httpRequest to request. -

      4. Set httpRequest's body to body. - -

      5. If body is non-null, then set request's body to a - new body whose stream is null and whose source is - body's source. -

      +
    4. +

      Otherwise, run these substeps: -

      request is copied as httpRequest here as we need - to be able to add headers to httpRequest and read its body without - affecting request. Namely, request can be reused with redirects, - authentication, and proxy authentication. We copy rather than clone in order to reduce memory - consumption. In case request's body's source is - null, redirects and authentication will end up failing the fetch. +

        +
      1. Set httpRequest to a copy of request except for its + body. -

      2. -

        Let credentials flag be set if one of +

      3. Let body be request's body. -

        +
      4. Set httpRequest's body to body. -

        is true, and unset otherwise. +

      5. If body is non-null, then set request's body to + a new body whose stream is null and whose source + is body's source. +

      -
    5. Let contentLengthValue be null. +

      request is copied as httpRequest here as we + need to be able to add headers to httpRequest and read its body + without affecting request. Namely, request can be reused with redirects, + authentication, and proxy authentication. We copy rather than clone in order to reduce memory + consumption. In case request's body's source is + null, redirects and authentication will end up failing the fetch. -

    6. If httpRequest's body is null and - httpRequest's method is - `POST` or `PUT`, then set contentLengthValue to - `0`. - +

    7. +

      Let credentials flag be set if one of -

    8. If httpRequest's body is non-null and httpRequest's - body's source is non-null, then set - contentLengthValue to httpRequest's body's - total bytes, UTF-8 encoded. +

      -
    9. If contentLengthValue is non-null, - append - `Content-Length`/contentLengthValue to - httpRequest's - header list. +

      is true, and unset otherwise. -

    10. -

      If contentLengthValue is non-null and httpRequest's - keepalive flag is set, then: +

    11. Let contentLengthValue be null. -

        -
      1. Let inflightKeepaliveBytes be zero. +

      2. If httpRequest's body is null and + httpRequest's method is + `POST` or `PUT`, then set contentLengthValue to + `0`. + -

      3. Let group be httpRequest's client's fetch group. +

      4. If httpRequest's body is non-null and httpRequest's + body's source is non-null, then set + contentLengthValue to httpRequest's body's + total bytes, UTF-8 encoded. -

      5. Let inflightRecords be the set of fetch records in - group whose request has its - keepalive flag set and done flag unset. +

      6. If contentLengthValue is non-null, + append + `Content-Length`/contentLengthValue to + httpRequest's + header list.

      7. -

        For each fetchRecord in inflightRecords: +

        If contentLengthValue is non-null and httpRequest's + keepalive flag is set, then:

          -
        1. Let inflightRequest be fetchRecord's - request. +

        2. Let inflightKeepaliveBytes be zero. -

        3. Increment inflightKeepaliveBytes by inflightRequest's - body's total bytes. -

        +
      8. Let group be httpRequest's client's fetch group. -

      9. If the sum of contentLengthValue and inflightKeepaliveBytes is - greater than 64 kibibytes, then return a network error. -

      +
    12. Let inflightRecords be the set of fetch records in + group whose request has its + keepalive flag set and done flag unset. -

      The above limit ensures that requests that are allowed to outlive the - environment settings object and contain a body, have a bounded size and are not allowed to - stay alive indefinitely. - -

    13. If httpRequest's referrer is a URL, then - append `Referer`/httpRequest's - referrer, serialized and UTF-8 encoded, to - httpRequest's header list. - - -

    14. If the CORS flag is set, httpRequest's method is - neither `GET` nor `HEAD`, or httpRequest's - mode is "websocket", then append - `Origin`/httpRequest's origin, - serialized and UTF-8 encoded, to - httpRequest's header list. - +

    15. +

      For each fetchRecord in inflightRecords: -

    16. If httpRequest's header list - does not contain `User-Agent`, then user agents should - append - `User-Agent`/default `User-Agent` value - to httpRequest's header list. +

        +
      1. Let inflightRequest be fetchRecord's + request. -

      2. If httpRequest's cache mode is "default" and - httpRequest's header list contains - `If-Modified-Since`, - `If-None-Match`, - `If-Unmodified-Since`, - `If-Match`, or - `If-Range`, then set httpRequest's - cache mode to "no-store". +

      3. Increment inflightKeepaliveBytes by inflightRequest's + body's total bytes. +

      -
    17. If httpRequest's cache mode is "no-cache" and - httpRequest's header list does not contain - `Cache-Control`, then append - `Cache-Control`/`max-age=0` to - httpRequest's header list. +

    18. If the sum of contentLengthValue and inflightKeepaliveBytes is + greater than 64 kibibytes, then return a network error. +

    -
  • -

    If httpRequest's cache mode is - "no-store" or "reload", run these substeps: +

    The above limit ensures that requests that are allowed to outlive the + environment settings object and contain a body, have a bounded size and are not allowed + to stay alive indefinitely. -

      -
    1. If httpRequest's header list - does not contain `Pragma`, then - append `Pragma`/`no-cache` to +

    2. If httpRequest's referrer is a URL, then + append `Referer`/httpRequest's + referrer, serialized and UTF-8 encoded, to + httpRequest's header list. + + +

    3. If the CORS flag is set, httpRequest's method is + neither `GET` nor `HEAD`, or httpRequest's + mode is "websocket", then append + `Origin`/httpRequest's origin, + serialized and UTF-8 encoded, to httpRequest's header list. +

    4. If httpRequest's header list - does not contain `Cache-Control`, then - append `Cache-Control`/`no-cache` to + does not contain `User-Agent`, then user agents should + append + `User-Agent`/default `User-Agent` value + to httpRequest's header list. + +

    5. If httpRequest's cache mode is "default" and + httpRequest's header list contains + `If-Modified-Since`, + `If-None-Match`, + `If-Unmodified-Since`, + `If-Match`, or + `If-Range`, then set httpRequest's + cache mode to "no-store". + +

    6. If httpRequest's cache mode is "no-cache" and + httpRequest's header list does not contain + `Cache-Control`, then append + `Cache-Control`/`max-age=0` to httpRequest's header list. - -

    - -
  • -

    Modify httpRequest's - header list per HTTP. - -

    It would be great if we could make this more normative - somehow. At this point headers such as - `Accept-Encoding`, - `Connection`, - `DNT`, and - `Host`, - are to be appended if necessary. - -

    `Accept`, - `Accept-Charset`, and - `Accept-Language` must not be included at this point. - -

    `Accept` and - `Accept-Language` are already included (unless - fetch() is used, which does not include the latter by - default), and `Accept-Charset` is a waste of bytes. See - HTTP header layer division for more details. - -

  • -

    If credentials flag is set, run these substeps: -

    1. -

      If the user agent is not configured to block cookies for httpRequest (see - section 7 of - [[!COOKIES]]), then run these substeps: +

      If httpRequest's cache mode is + "no-store" or "reload", run these substeps:

        -
      1. Let cookies be the result of running the "cookie-string" algorithm (see - section 5.4 of - [[!COOKIES]]) with the user agent's cookie store and - httpRequest's current url. +

      2. If httpRequest's header list + does not contain `Pragma`, then + append `Pragma`/`no-cache` to + httpRequest's header list. -

      3. If cookies is not the empty string, append - `Cookie`/cookies to httpRequest's - header list. +
      4. If httpRequest's header list + does not contain `Cache-Control`, then + append `Cache-Control`/`no-cache` to + httpRequest's header list. +

      -
    2. If httpRequest's header list - contains `Authorization`, then terminate these substeps. - - -

    3. Let authorizationValue be null. - -

    4. If there's an authentication entry for httpRequest - and either httpRequest's - use-URL-credentials flag is - unset or httpRequest's - current url does not - include credentials, set - authorizationValue to authentication entry. - - -

    5. Otherwise, if httpRequest's - current url does - include credentials and authentication-fetch flag is - set, then set authorizationValue to httpRequest's - current url, - converted to an `Authorization` value. - -

    6. If authorizationValue is non-null, - append - `Authorization`/authorizationValue to - httpRequest's - header list. -

    - -
  • -

    If there's a proxy-authentication entry, use it as appropriate. - -

    This intentionally does not depend on - httpRequest's - credentials mode. - -

  • Let response and storedResponse be null. +

  • +

    Modify httpRequest's + header list per HTTP. + +

    It would be great if we could make this more normative + somehow. At this point headers such as + `Accept-Encoding`, + `Connection`, + `DNT`, and + `Host`, + are to be appended if necessary. + +

    `Accept`, + `Accept-Charset`, and + `Accept-Language` must not be included at this point. + +

    `Accept` and + `Accept-Language` are already included (unless + fetch() is used, which does not include the latter by + default), and `Accept-Charset` is a waste of bytes. See + HTTP header layer division for more details. -

  • Let the revalidatingFlag be unset. +

  • +

    If credentials flag is set, run these substeps: -

  • -

    If httpRequest's cache mode is neither "no-store" - nor "reload", run these substeps: +

      +
    1. +

      If the user agent is not configured to block cookies for httpRequest (see + section 7 of + [[!COOKIES]]), then run these substeps: + +

        +
      1. Let cookies be the result of running the "cookie-string" algorithm (see + section 5.4 of + [[!COOKIES]]) with the user agent's cookie store and + httpRequest's current url. + +

      2. If cookies is not the empty string, append + `Cookie`/cookies to httpRequest's + header list. +
      + +
    2. If httpRequest's header list + contains `Authorization`, then terminate these substeps. + + +

    3. Let authorizationValue be null. + +

    4. If there's an authentication entry for httpRequest + and either httpRequest's + use-URL-credentials flag is + unset or httpRequest's + current url does not + include credentials, set + authorizationValue to authentication entry. + + +

    5. Otherwise, if httpRequest's + current url does + include credentials and authentication-fetch flag is + set, then set authorizationValue to httpRequest's + current url, + converted to an `Authorization` value. + +

    6. If authorizationValue is non-null, + append + `Authorization`/authorizationValue to + httpRequest's + header list. +

    -
    1. -

      Set storedResponse to the result of selecting a response from the HTTP cache, - possibly needing validation, as per the - "Constructing Responses from Caches" - chapter of HTTP Caching [[!HTTP-CACHING]], if any. +

      If there's a proxy-authentication entry, use it as appropriate. -

    2. If storedResponse is null, then abort these substeps. +

      This intentionally does not depend on + httpRequest's + credentials mode. - -

    3. If storedResponse requires validation (i.e., it is not fresh), then set the - revalidatingFlag. +

    4. Let response and storedResponse be null. -

    5. -

      If httpRequest's cache mode is "force-cache" or - "only-if-cached", then set response to storedResponse and - abort these substeps. - -

      As mandated by HTTP, this still takes the `Vary` header - into account. +

    6. Let the revalidatingFlag be unset.

    7. -

      If the revalidatingFlag is set, then: +

      If httpRequest's cache mode is neither "no-store" + nor "reload", run these substeps:

        -
      1. If storedResponse's header list - contains `ETag`, then append - `If-None-Match` with its value to httpRequest's - header list. +

      2. Set storedResponse to the result of selecting a response from the HTTP cache, + possibly needing validation, as per the + "Constructing Responses from Caches" + chapter of HTTP Caching [[!HTTP-CACHING]], if any. -

      3. If storedResponse's header list - contains `Last-Modified`, then - append `If-Modified-Since` with its value to - httpRequest's header list. -

      +
    8. If storedResponse is null, then abort these substeps. + + +

    9. If storedResponse requires validation (i.e., it is not fresh), then set the + revalidatingFlag. -

      See also the - "Sending a Validation Request" - chapter of HTTP Caching [[!HTTP-CACHING]]. +

    10. +

      If httpRequest's cache mode is "force-cache" or + "only-if-cached", then set response to storedResponse and + abort these substeps. -

    11. Otherwise, if the revalidatingFlag is unset, then set response to - storedResponse. +

      As mandated by HTTP, this still takes the `Vary` + header into account. + +

    12. +

      If the revalidatingFlag is set, then: + +

        +
      1. If storedResponse's header list + contains `ETag`, then append + `If-None-Match` with its value to httpRequest's + header list. + +

      2. If storedResponse's header list + contains `Last-Modified`, then + append `If-Modified-Since` with its value to + httpRequest's header list. +

      + +

      See also the + "Sending a Validation Request" + chapter of HTTP Caching [[!HTTP-CACHING]]. + +

    13. Otherwise, if the revalidatingFlag is unset, then set response to + storedResponse. +

    +
  • If the ongoing fetch is terminated, then let reason be the + provided termination reason, and return a network error with + termination reason set to reason. +

  • If response is null, then run these substeps: @@ -3534,6 +3592,10 @@ Range Requests. [[HTTP-RANGE]] However, this is not widely supported by b authentication-fetch flag is set, then run these subsubsteps:

      +
    1. If the ongoing fetch is terminated, then let reason be the + provided termination reason, and return a network error with + termination reason set to reason. +

    2. Let username and password be the result of prompting the end user for a username and password, respectively, in request's window. @@ -3561,6 +3623,10 @@ Range Requests. [[HTTP-RANGE]] However, this is not widely supported by b

    3. Needs testing: multiple `Proxy-Authenticate` headers, missing, parsing issues. +

    4. If the ongoing fetch is terminated, then let reason be the + provided termination reason, and return a network error with + termination reason set to reason. +

    5. Prompt the end user as appropriate in request's window and store the result as a @@ -3606,70 +3672,86 @@ Range Requests. [[HTTP-RANGE]] However, this is not widely supported by b origin and credentials. -

    6. If connection is failure, return a - network error. - -

    7. If connection is not an HTTP/2 connection, request's - body is non-null, and request's body's - source is null, then append - `Transfer-Encoding`/`chunked` to request's - header list.

    8. -

      Let response be the result of making an HTTP request over connection - using request with the following caveats: +

      Run these steps, but abort if the ongoing fetch is terminated:

      -
        -
      • Follow the relevant requirements from HTTP. [[!HTTP]] [[!HTTP-SEMANTICS]] [[!HTTP-COND]] [[!HTTP-CACHING]] [[!HTTP-AUTH]] +

          +
        1. If connection is failure, return a + network error. -

        2. Wait until all the headers are transmitted or - fetch is being - terminated with reason reason. If - fetch is being - terminated, then set response's - termination reason to reason. +

        3. If connection is not an HTTP/2 connection, request's + body is non-null, and request's body's + source is null, then append + `Transfer-Encoding`/`chunked` to request's + header list.

        4. -

          Any responses whose - status is in the range 100 to - 199, inclusive, and is not 101, are to be ignored. +

          Let response be the result of making an HTTP request over connection + using request with the following caveats: -

          These kind of responses are - eventually followed by a "final" response. -

      +
        +
      • Follow the relevant requirements from HTTP. [[!HTTP]] [[!HTTP-SEMANTICS]] [[!HTTP-COND]] [[!HTTP-CACHING]] [[!HTTP-AUTH]] -

        The exact layering between Fetch and HTTP still needs to be sorted through and - therefore response represents both a response and - an HTTP response here. +

      • Wait until all the headers are transmitted. -

        If request's header list contains - `Transfer-Encoding`/`chunked` and response is transferred - via HTTP/1.0 or older, then return a network error. +

      • +

        Any responses whose + status is in the range 100 to + 199, inclusive, and is not 101, are to be ignored. -

        If the HTTP request results in a TLS client certificate dialog, run these substeps: +

        These kind of responses are + eventually followed by a "final" response. +

      -
        -
      1. If request's window - is an environment settings object, make the dialog - available in request's - window. +

        The exact layering between Fetch and HTTP still needs to be sorted through and + therefore response represents both a response and + an HTTP response here. + +

        If request's header list contains + `Transfer-Encoding`/`chunked` and response is transferred + via HTTP/1.0 or older, then return a network error. + +

        If the HTTP request results in a TLS client certificate dialog, run these substeps: -

      2. Otherwise, return a network error. +

          +
        1. If request's window + is an environment settings object, make the dialog + available in request's + window. + +

        2. Otherwise, return a network error. +

        + +

        If response was retrieved over HTTPS, set its + HTTPS state to either + "deprecated" or "modern". + [[!TLS]] + +

        The exact determination here is up to user agents for the + time being. User agents are strongly encouraged to only succeed HTTPS connections with + strong security properties and return + network errors otherwise. Using the + "deprecated" state value ought to be a temporary and last resort kind + of option. + +

        Transmit body for request.

      -

      If response was retrieved over HTTPS, set its - HTTPS state to either - "deprecated" or "modern". - [[!TLS]] +

    9. +

      If the ongoing fetch is terminated, then: + +

        +
      1. Let reason be the provided termination reason. + +

      2. If connection is an HTTP/2 connection, then transmit an + "RST_STREAM" to cancel the underlying stream. -

        The exact determination here is up to user agents for the - time being. User agents are strongly encouraged to only succeed HTTPS connections with - strong security properties and return - network errors otherwise. Using the - "deprecated" state value ought to be a temporary and last resort kind - of option. +

      3. Otherwise, close connection. -

        Transmit body for request. +

      4. Return a network error with termination reason set to + reason. +

    10. Let strategy be an object. The user agent may choose any object. @@ -3677,12 +3759,11 @@ Range Requests. [[HTTP-RANGE]] However, this is not widely supported by b

      strategy is used to control the queuing strategy of stream constructed below. -

    11. Let pull be an action that resumes the - ongoing fetch if it is suspended. +

    12. Let pull be an action that resumes the ongoing fetch + if it is suspended. -

    13. Let cancel be an action that - terminates the ongoing fetch with reason - end-user abort. +

    14. Let cancel be an action that terminates the + ongoing fetch with reason fatal.

    15. Let stream be the result of @@ -3691,132 +3772,153 @@ Range Requests. [[HTTP-RANGE]] However, this is not widely supported by b pull and cancel.

      This construction operation will not throw an exception. -

    16. Set response's body to a new - body whose stream is - stream. +

    17. +

      Run these steps, but abort if the ongoing fetch is terminated:

      -
    18. If response has a payload body length, then set response's - body's - total bytes to that payload body length. - +

        +
      1. Set response's body to a new + body whose stream is + stream. -

      2. -

        Delete - `Content-Encoding` from response's - header list if one of the following - conditions is true: +

      3. If response has a payload body length, then set response's + body's + total bytes to that payload body length. + -

        +
      4. +

        Delete + `Content-Encoding` from response's + header list if one of the following + conditions is true: + +

        -

        This deals with broken Apache configurations. Ideally HTTP would define - this. - +

        This deals with broken Apache configurations. Ideally HTTP would define + this. + -

        Gecko - bug 1030660 looks - into whether this quirk can be removed. +

        Gecko + bug 1030660 looks + into whether this quirk can be removed. -

      5. Execute - set response's CSP list - on response. [[!CSP]] +

      6. Execute + set response's CSP list + on response. [[!CSP]] -

      7. If response is not a - network error and request's - cache mode is not "no-store", - update response in the HTTP cache for request. - +

      8. If response is not a + network error and request's + cache mode is not "no-store", + update response in the HTTP cache for request. + + +

      9. +

        If credentials flag is set and the user agent is not configured to block cookies for + request (see section 7 of + [[!COOKIES]]), then run the "set-cookie-string" parsing algorithm (see section 5.2 of [[!COOKIES]]) on the value of each header whose name is a + byte-case-insensitive match for `Set-Cookie` in response's header list, if any, and request's current url. + +

        This is a fingerprinting vector. +

    19. -

      If credentials flag is set and the user agent is not configured to block cookies for - request (see section 7 of - [[!COOKIES]]), then run the "set-cookie-string" parsing algorithm (see - section 5.2 of - [[!COOKIES]]) on the value - of each header whose name is a byte-case-insensitive match for - `Set-Cookie` in response's header list, if any, and - request's current url. +

      If the ongoing fetch is terminated, then: + +

        +
      1. Let reason be the provided termination reason. + +

      2. Set response's termination reason to reason. -

        This is a fingerprinting vector. +

      3. Return response. +

    20. Run these substeps in parallel:

      1. -

        Whenever one or more bytes are transmitted from response's message body, let - bytes be the transmitted bytes and run these subsubsteps: - +

        While true, breaking if the ongoing fetch terminates:

          -
        1. Increase response's - body's - transmitted bytes with bytes' - length. +

        2. +

          If one or more bytes have been transmitted from response's message body, then: -

        3. Let codings be the result of extracting header list values given - `Content-Encoding` and response's header list. +

            +
          1. Let bytes be the transmitted bytes. -

          2. -

            Set bytes to the result of handling - content codings given codings and bytes. +

          3. Increase response's body's transmitted + bytes with bytes' length. -

            This makes the `Content-Length` - header unreliable to the extent that it was reliable - to begin with. +

          4. Let codings be the result of extracting header list values given + `Content-Encoding` and response's header list. -

          5. -

            Enqueue a Uint8Array - object wrapping an ArrayBuffer containing bytes to stream. - If that threw an exception, terminate the ongoing - fetch with fatal, error - stream with that exception and abort these subsubsteps. - -

          6. If stream doesn't need more - data and request's synchronous flag is unset, ask the user agent - to suspend the ongoing fetch. -

          +
        4. +

          Set bytes to the result of handling content + codings given codings and bytes. -

        5. If at any point the bytes transmission for response's message body is done - normally and stream is readable, - then close stream. - +

          This makes the `Content-Length` header + unreliable to the extent that it was reliable to begin with. -

        6. -

          If at any point fetch is - terminated with reason reason, - run these subsubsteps: +

        7. +

          Enqueue a Uint8Array object wrapping an + ArrayBuffer containing bytes to stream. If that threw an + exception, terminate the ongoing fetch with fatal, error stream with that exception. -

            -
          1. Set response's termination - reason to reason. +

          2. If stream doesn't need more + data and request's synchronous flag is unset, ask the user agent to suspend the ongoing fetch. +

          -
        8. If stream is readable, - error stream with a - TypeError. +

        9. Otherwise, if the bytes transmission for response's message body is done + normally and stream is readable, then + close stream and abort these steps.

        + +

        The following steps can only occur if the ongoing fetch terminates. + +

      2. Let reason be the provided termination reason. + +

      3. Set response's termination reason + to reason. + +

      4. If stream is readable, error + stream with a TypeError. + +

      5. If connection is an HTTP/2 connection, then transmit an + "RST_STREAM" to cancel the underlying stream. + +

      6. +

        Otherwise, the user agent should close connection unless it would be bad for + performance to do so. + +

        For instance, the user agent could keep the connection open if it knows there's + only a few bytes of transfer remaining on a reusable connection. In this case it could be worse + to close the connection and go through the handshake process again for the next fetch.

      -

      These are run in parallel - as at this point it is unclear whether response's - body is relevant (response - might be a redirect). +

      These are run in parallel as at this point it is unclear whether + response's body is relevant (response might be a + redirect). -

    21. Return response. Typically - response's body's - stream is still being enqueued to after returning. +

    22. Return response. Typically response's + body's stream is still being enqueued to after + returning.

    @@ -4066,9 +4168,12 @@ Entries may be removed before that moment arrives. request and response, run these steps:
      -
    1. Let origin be the result of extracting header list values given - `Access-Control-Allow-Origin` and response's - header list. +

    2. +

      Let origin be the result of extracting header list values given + `Access-Control-Allow-Origin` and response's + header list. + +

      The above will fail for network errors, as they have no headers.

    3. If origin is null or failure, return failure. @@ -4679,6 +4784,7 @@ interface Request { readonly attribute RequestRedirect redirect; readonly attribute DOMString integrity; readonly attribute boolean keepalive; + readonly attribute AbortSignal signal; [NewObject] Request clone(); }; @@ -4695,6 +4801,7 @@ dictionary RequestInit { RequestRedirect redirect; DOMString integrity; boolean keepalive; + AbortSignal? signal; any window; // can only be set to null }; @@ -4716,6 +4823,9 @@ omitted from RequestMode as it cannot be used nor obser

      A {{Request}} object also has an associated headers (null or a {{Headers}} object), initially null. +

      A {{Request}} object has an associated signal (an {{AbortSignal}} object), +initially a new {{AbortSignal}} object. +

      A {{Request}} object's body is its request's body. @@ -4736,6 +4846,8 @@ constructor must run these steps:

    4. Let baseURL be current settings object's API base URL. +

    5. Let signal be null. +

    6. If input is a string, then run these substeps: @@ -4766,6 +4878,8 @@ constructor must run these steps:

    7. Set request to input's request. + +

    8. Set signal to input's signal.

  • Let origin be current settings object's @@ -4935,12 +5049,23 @@ constructor must run these steps: to method. +

  • If init's signal member is present, then set signal to + it. +

  • Let r be a new {{Request}} object associated with request.

  • Set r's headers to a new {{Headers}} object, whose header list is request's header list, and guard is "request". +

  • +

    If signal is not null, then + add the following abort steps to signal: + +

      +
    1. Signal abort on r's signal. +

    +
  • Let headers be a copy of r's headers and its associated header list. @@ -5099,6 +5224,9 @@ must return request's must return true if request's keepalive flag is set, and false otherwise. +

    The signal attribute's getter must return the +associated signal. +


    The clone() method, when invoked, must @@ -5120,6 +5248,19 @@ run these steps: header list, and guard is context object's headers' guard. +

  • If context object's signal's aborted flag + is set, set clonedRequestObject signal's + aborted flag. + +

  • +

    Otherwise, add the following abort steps to context object's + signal: + +

      +
    1. Signal abort on clonedRequestObject + signal. +

    +
  • Return clonedRequestObject. @@ -5367,11 +5508,21 @@ method, must run these steps:

    1. Let p be a new promise. -

    2. Let request be the associated - request of the result of invoking the initial value of - {{Request}} as constructor with input and - init as arguments. If this throws an exception, reject - p with it and return p. +

    3. Let requestObject be the result of invoking the initial value of {{Request}} as + constructor with input and init as arguments. If this throws an exception, + reject p with it and return p + +

    4. Let request be requestObject's request. + +

    5. +

      If requestObject's signal's aborted flag + is set, then: + +

        +
      1. Abort fetch with p, request, and null. + +

      2. Return p. +

    6. If request's client's global object is a {{ServiceWorkerGlobalScope}} object, @@ -5381,6 +5532,21 @@ method, must run these steps: {{Headers}} object whose guard is "immutable". +
    7. Let aborted be false. + +

    8. +

      Add the following abort steps to requestObject's + signal: + +

        +
      1. Set aborted to true. + +

      2. Abort fetch with p, request, and + responseObject. + +

      3. Terminate the ongoing fetch with reason fatal. +

      +
    9. Run the following in parallel: @@ -5389,6 +5555,8 @@ method, must run these steps:

      To process response for response, run these substeps:

        +
      1. If aborted is true, terminate these substeps. +

      2. If response's type is "error", reject p with a TypeError and terminate these substeps. @@ -5401,6 +5569,8 @@ method, must run these steps:

        To process response done for response, run these substeps:

          +
        1. If aborted is true, terminate these substeps. +

        2. Let trailerObject be a new {{Headers}} object whose guard is "immutable". @@ -5415,6 +5585,36 @@ method, must run these steps:

        3. Return p.

        +

        To abort fetch with a promise, request, and +responseObject, run these steps: + +

          +
        1. Let error be an "AbortError" {{DOMException}}. + +

        2. +

          Reject promise with error. + +

          This is a no-op if promise has already fulfilled. + +

        3. If request's body is not null and is + readable, then cancel request's + body with error. + +

        4. If responseObject is null, then return. + +

        5. +

          Reject responseObject's trailer promise with error. + +

          This is a no-op if responseObject's trailer promise + has already fulfilled. + +

        6. Let response be responseObject's response. + +

        7. If response's body is not null and is + readable, then error + response's body with error. +

        +

        Garbage collection

        From a9938251e44ad0b29ef18e3a2e69c14e96d6eedf Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Tue, 5 Sep 2017 13:03:53 +0100 Subject: [PATCH 2/6] Adding note back --- fetch.bs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fetch.bs b/fetch.bs index a54412751..c1d125a72 100644 --- a/fetch.bs +++ b/fetch.bs @@ -1803,6 +1803,9 @@ from a {{ReadableStream}} object with reader, run these steps: {{ReadableStream}} object stream with reason, return the result of calling ReadableStreamCancel(stream, reason). +

        Because the reader grants exclusive access, the actual mechanism of how +to read cannot be observed. Implementations could use more direct mechanism if convenient. +

        To tee a {{ReadableStream}} object stream, run these steps: From e8f712966a59e95dfe371d000554ae417493f8ab Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Tue, 5 Sep 2017 15:08:34 +0100 Subject: [PATCH 3/6] Replacing termination reason with aborted flag --- fetch.bs | 178 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 118 insertions(+), 60 deletions(-) diff --git a/fetch.bs b/fetch.bs index c1d125a72..c562cbcbd 100644 --- a/fetch.bs +++ b/fetch.bs @@ -1220,8 +1220,11 @@ or "worker". property is true, then queue a fetch task on request to process request end-of-body for request and abort these in-parallel steps. -

      3. Otherwise, terminate the ongoing fetch with reason - fatal. +

      4. Otherwise, if read is rejected with an + "AbortError" {{DOMException}}, + terminate the ongoing fetch with the aborted flag set. + +

      5. Otherwise, terminate the ongoing fetch.

    10. If the ongoing fetch is terminated, then abort these in-parallel steps. @@ -1245,8 +1248,11 @@ evolves over time. That is, not all its fields are available straight away. Unless stated otherwise, it is "default".

      A response can have an associated -termination reason -which is end-user abort, fatal, or timeout. +aborted flag +which is initially unset. + +

      This is set for network errors that should appear as "aborted" to developers. +This should be limited to requests that are intentionally aborted by the developer or end-user.

      A response has an associated url. It is a pointer to the @@ -1317,6 +1323,10 @@ navigate algorithm. It ensures `Location` has


      +

      A response whose +type is "error" and aborted flag is set is +known as a aborted network error. +

      A response whose type is "error" is known as a network error. @@ -1479,7 +1489,7 @@ for each associated fetch record whose keepalive flag is unset, terminate the fetch record's -fetch with reason fatal. +fetch.

      Connections

      @@ -2302,9 +2312,8 @@ pertain to them. Also, considering "image" was not compatible with

      To perform a fetch using request, run the steps below. An ongoing fetch can be -terminated with reason -reason, which must be end-user abort, fatal, -timeout, or garbage collection. +terminated with flag aborted, +which is unset unless otherwise specified.

      The user agent may be asked to suspend the ongoing fetch. @@ -2445,9 +2454,16 @@ the request.

    -
  • If the ongoing fetch is terminated, then let reason be the - provided termination reason, and return a network error with - termination reason set to reason. +

  • +

    If the ongoing fetch is terminated, then: + +

      +
    1. Let aborted be the termination's aborted flag. + +

    2. If aborted is set, then return an aborted network error. + +

    3. Return a network error. +

  • Return the result of performing a main fetch using request. @@ -2547,9 +2563,16 @@ with a CORS flag and recursive flag, run these steps: -

  • If the ongoing fetch is terminated, then let reason be the - provided termination reason, and return a network error with - termination reason set to reason. +

  • +

    If the ongoing fetch is terminated, then: + +

      +
    1. Let aborted be the termination's aborted flag. + +

    2. If aborted is set, then return an aborted network error. + +

    3. Return a network error. +

  • If request's synchronous flag is unset and recursive flag is unset, run the remaining steps @@ -2739,13 +2762,11 @@ with a CORS flag and recursive flag, run these steps:

  • Wait for response's body. -

  • If response does not have a - termination reason and - response does not +

  • If response's body's stream has not + errored, and response does not match - request's integrity metadata, - set response and internalResponse to a - network error. + request's integrity metadata, set response and + internalResponse to a network error. [[!SRI]] @@ -2876,10 +2897,11 @@ steps:

  • Return response. -

  • Let reason be the provided termination reason. +

  • Let aborted be the termination's aborted flag. -

  • Return a network error with termination reason set to - reason. +

  • If aborted is set, then return an aborted network error. + +

  • Return a network error.

    "data" @@ -3508,9 +3530,16 @@ Range Requests. [[HTTP-RANGE]] However, this is not widely supported by b -
  • If the ongoing fetch is terminated, then let reason be the - provided termination reason, and return a network error with - termination reason set to reason. +

  • +

    If the ongoing fetch is terminated, then: + +

      +
    1. Let aborted be the termination's aborted flag. + +

    2. If aborted is set, then return an aborted network error. + +

    3. Return a network error. +

  • @@ -3595,9 +3624,16 @@ Range Requests. [[HTTP-RANGE]] However, this is not widely supported by b authentication-fetch flag is set, then run these subsubsteps:
      -
    1. If the ongoing fetch is terminated, then let reason be the - provided termination reason, and return a network error with - termination reason set to reason. +

    2. +

      If the ongoing fetch is terminated, then: + +

        +
      1. Let aborted be the termination's aborted flag. + +

      2. If aborted is set, then return an aborted network error. + +

      3. Return a network error. +

    3. Let username and password be the result of prompting the end user for a username and password, respectively, in request's @@ -3626,9 +3662,16 @@ Range Requests. [[HTTP-RANGE]] However, this is not widely supported by b

    4. Needs testing: multiple `Proxy-Authenticate` headers, missing, parsing issues. -

    5. If the ongoing fetch is terminated, then let reason be the - provided termination reason, and return a network error with - termination reason set to reason. +

    6. +

      If the ongoing fetch is terminated, then: + +

        +
      1. Let aborted be the termination's aborted flag. + +

      2. If aborted is set, then return an aborted network error. + +

      3. Return a network error. +

    7. Prompt the end user as appropriate in request's @@ -3659,6 +3702,8 @@ Range Requests. [[HTTP-RANGE]] However, this is not widely supported by b

      1. Let credentials be true if credentials flag is set, and false otherwise. +

      2. Let response be null. +

      3. Switch on request's mode: @@ -3690,7 +3735,7 @@ Range Requests. [[HTTP-RANGE]] However, this is not widely supported by b header list.

      4. -

        Let response be the result of making an HTTP request over connection +

        Set response to the result of making an HTTP request over connection using request with the following caveats:

          @@ -3745,15 +3790,14 @@ Range Requests. [[HTTP-RANGE]] However, this is not widely supported by b

          If the ongoing fetch is terminated, then:

            -
          1. Let reason be the provided termination reason. +

          2. Let aborted be the termination's aborted flag.

          3. If connection is an HTTP/2 connection, then transmit an "RST_STREAM" to cancel the underlying stream. -

          4. Otherwise, close connection. +

          5. If aborted is set, then return an aborted network error. -

          6. Return a network error with termination reason set to - reason. +

          7. Return a network error.

        • @@ -3766,7 +3810,7 @@ Range Requests. [[HTTP-RANGE]] However, this is not widely supported by b if it is suspended.
        • Let cancel be an action that terminates the - ongoing fetch with reason fatal. + ongoing fetch with the aborted flag set.

        • Let stream be the result of @@ -3843,9 +3887,10 @@ Range Requests. [[HTTP-RANGE]] However, this is not widely supported by b

          If the ongoing fetch is terminated, then:

            -
          1. Let reason be the provided termination reason. +

          2. Let aborted be the termination's aborted flag. -

          3. Set response's termination reason to reason. +

          4. If aborted is set, then set response's + aborted flag.

          5. Return response.

          @@ -3877,11 +3922,10 @@ Range Requests. [[HTTP-RANGE]] However, this is not widely supported by b

          This makes the `Content-Length` header unreliable to the extent that it was reliable to begin with. -

        • -

          Enqueue a Uint8Array object wrapping an - ArrayBuffer containing bytes to stream. If that threw an - exception, terminate the ongoing fetch with fatal, error stream with that exception. +

        • Enqueue a Uint8Array object wrapping an + ArrayBuffer containing bytes to stream. If that threw an + exception, terminate the ongoing fetch, and + error stream with that exception.

        • If stream doesn't need more data and request's synchronous flag is unset, ask the user agent to . [[HTTP-RANGE]] However, this is not widely supported by b

          The following steps can only occur if the ongoing fetch terminates. -

        • Let reason be the provided termination reason. +

        • Let aborted be the termination's aborted flag. -

        • Set response's termination reason - to reason. +

        • +

          If aborted is set, then: -

        • If stream is readable, error - stream with a TypeError. +

            +
          1. Set response's aborted flag. + +

          2. If stream is readable, error + stream with an "AbortError" {{DOMException}}. +

          + +
        • Otherwise, if stream is readable, + error stream with a TypeError.

        • If connection is an HTTP/2 connection, then transmit an "RST_STREAM" to cancel the underlying stream. @@ -5535,19 +5586,23 @@ method, must run these steps: {{Headers}} object whose guard is "immutable". -

        • Let aborted be false. +

        • +

          Let locallyAborted be false. + +

          This lets us reject promises with predictable timing, when the request to abort + comes from the same thread as the call to fetch.

        • Add the following abort steps to requestObject's signal:

            -
          1. Set aborted to true. +

          2. Set locallyAborted to true.

          3. Abort fetch with p, request, and responseObject. -

          4. Terminate the ongoing fetch with reason fatal. +

          5. Terminate the ongoing fetch with the aborted flag set.

        • @@ -5558,11 +5613,14 @@ method, must run these steps:

          To process response for response, run these substeps:

            -
          1. If aborted is true, terminate these substeps. +

          2. If locallyAborted is true, terminate these substeps. + +

          3. If response's aborted flag is set, then abort fetch + with p, request, and responseObject, and terminate these + substeps. -

          4. If response's type is - "error", reject p with a TypeError and terminate - these substeps. +

          5. If response is a network error, then reject p with a + TypeError and terminate these substeps.

          6. Associate responseObject with response. @@ -5572,7 +5630,7 @@ method, must run these steps:

            To process response done for response, run these substeps:

              -
            1. If aborted is true, terminate these substeps. +

            2. If locallyAborted is true, terminate these substeps.

            3. Let trailerObject be a new {{Headers}} object whose guard is "immutable". @@ -5621,8 +5679,8 @@ method, must run these steps:

              Garbage collection

              -

              The user agent may terminate an ongoing fetch with -reason garbage collection if that termination is not observable through script. +

              The user agent may terminate an ongoing fetch with if that +termination is not observable through script.

              "Observable through script" means observable through fetch()'s arguments and return value. Other ways, such as From a66142fe3cf6bd81cd85bd54144e74ad21cc3724 Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Tue, 5 Sep 2017 15:09:28 +0100 Subject: [PATCH 4/6] Be specific about which steps to abort --- fetch.bs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fetch.bs b/fetch.bs index c562cbcbd..c066cf812 100644 --- a/fetch.bs +++ b/fetch.bs @@ -3934,7 +3934,7 @@ Range Requests. [[HTTP-RANGE]] However, this is not widely supported by b

            4. Otherwise, if the bytes transmission for response's message body is done normally and stream is readable, then - close stream and abort these steps. + close stream and abort these in-parallel steps.

            The following steps can only occur if the ongoing fetch terminates. From 185a0c9e9567890f1d6e98338e06f0fefa9a6f1a Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Thu, 7 Sep 2017 13:47:06 +0100 Subject: [PATCH 5/6] Allow the trailer promise to reject if the fetch is terminated in another thread. --- fetch.bs | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/fetch.bs b/fetch.bs index c066cf812..efabfc76a 100644 --- a/fetch.bs +++ b/fetch.bs @@ -1248,11 +1248,10 @@ evolves over time. That is, not all its fields are available straight away. Unless stated otherwise, it is "default".

            A response can have an associated -aborted flag -which is initially unset. +aborted flag, which is initially unset. -

            This is set for network errors that should appear as "aborted" to developers. -This should be limited to requests that are intentionally aborted by the developer or end-user. +

            This indicates that the request was intentionally aborted by the developer or +end-user.

            A response has an associated url. It is a pointer to the @@ -1290,6 +1289,10 @@ Unless stated otherwise it is `OK`. trailer (a header list). Unless stated otherwise it is empty. +

            A response has an associated +trailer failed flag, which is +initially unset. +

            A response has an associated HTTPS state (an HTTPS state value). Unless stated otherwise, it is @@ -2805,11 +2808,14 @@ with a CORS flag and recursive flag, run these steps:

          7. Queue a fetch task on request to process response end-of-body for response. -

          8. Wait for internalResponse's trailer, - if any. See +

          9. Wait for either internalResponse's trailer, + if any, or for the ongoing fetch to terminate. See section 4.1.2 of [[!HTTP]]. +

          10. If the ongoing fetch is terminated, then set internalResponse's + trailer failed flag. +

          11. Set request's done flag.

          12. Queue a fetch task on request to process response done @@ -5635,6 +5641,20 @@ method, must run these steps:

          13. Let trailerObject be a new {{Headers}} object whose guard is "immutable". +

          14. +

            If response's trailer failed flag is set, then: + +

              +
            1. If response's aborted flag is set, reject + responseObject's trailer promise with an + "AbortError" {{DOMException}}. + +

            2. Otherwise, reject responseObject's trailer promise with + a TypeError. + +

            3. Terminate these substeps. +

            +
          15. Associate trailerObject with response's trailer. From 8e1d2d5fdc4011ed258f1287a3f30be511c35e0e Mon Sep 17 00:00:00 2001 From: Jake Archibald Date: Thu, 14 Sep 2017 14:20:26 +0100 Subject: [PATCH 6/6] Nits --- fetch.bs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fetch.bs b/fetch.bs index efabfc76a..0d19e5c82 100644 --- a/fetch.bs +++ b/fetch.bs @@ -1328,7 +1328,7 @@ navigate algorithm. It ensures `Location` has

            A response whose type is "error" and aborted flag is set is -known as a aborted network error. +known as an aborted network error.

            A response whose type is "error" is known as a @@ -1533,7 +1533,7 @@ for each associated fetch record whose

            If the ongoing fetch is terminated, then:

              -
            1. If connection is not null, close connection. +

            2. If connection is not null, then close connection.

            3. Return failure.