From 6c2b3f18c5aad509635bd81f4931132c26514bb6 Mon Sep 17 00:00:00 2001 From: Yutaka Hirano Date: Thu, 21 Jul 2016 17:49:40 +0900 Subject: [PATCH] Create a new ReadableStream in respondWith functions The current description pretends that a ReadableStream can be passed from one realm to another, which is wrong. This change changes the description so that it creates a new ReadableStream and passes Uint8Array objects from the old ReadableStream to the new one. This is discussed at whatwg/fetch#330. This change fixes #850 as well. --- spec/service_worker/index.bs | 87 +++++++++++++++++++++++----- spec/service_worker/index.html | 103 +++++++++++++++++++++++---------- 2 files changed, 145 insertions(+), 45 deletions(-) diff --git a/spec/service_worker/index.bs b/spec/service_worker/index.bs index 939b868a..0933af62 100644 --- a/spec/service_worker/index.bs +++ b/spec/service_worker/index.bs @@ -132,9 +132,15 @@ spec: csp2; urlPrefix: https://w3c.github.io/webappsec-csp/2/ spec: fetch; urlPrefix: https://fetch.spec.whatwg.org/ type: dfn text: basic filtered response; url: concept-filtered-response-basic + text: cancel a reader; url: concept-cancel-stream-reader + text: close ReadableStream; url: concept-close-readablestream + text: construct a ReadableStream; url: concept-construct-readablestream text: CORS filtered response; url: concept-filtered-response-cors text: disturbed; url: concept-body-disturbed text: empty; url: concept-empty-readablestream + text: enqueue a chunk to ReadableStream; url: concept-enqueue-readablestream + text: error ReadableStream; url: concept-error-readablestream + text: errored; url: concept-readablestream-errored text: extract a mime type; url: concept-header-extract-mime-type text: fetch; url: concept-fetch text: filtered response; url: concept-filtered-response @@ -152,6 +158,7 @@ spec: fetch; urlPrefix: https://fetch.spec.whatwg.org/ text: potential-navigation-or-subresource request text: process response text: process response end-of-file + text: read a chunk from a reader; url: concept-read-chunk-from-reader text: read all bytes; url: concept-read-all-bytes-from-readablestream text: ReadableStream; url: concept-readablestream text: request; for: fetch; url: concept-request @@ -216,6 +223,7 @@ spec: html; urlPrefix: https://html.spec.whatwg.org/multipage/ text: https state; for: environment settings object text: module script text: realm execution context + text: relevant Realm; url: concept-relevant-realm text: relevant global object; url: concept-relevant-global text: report the error text: run a classic script @@ -1753,6 +1761,7 @@ spec: webidl; urlPrefix: https://heycam.github.io/webidl/
  • Set the stop propagation flag and stop immediate propagation flag.
  • Set the respond-with entered flag.
  • Set the wait to respond flag.
  • +
  • Let targetRealm be the relevant Realm of the context object.
  • Run the following substeps in parallel:
    1. Wait until r settles.
    2. @@ -1772,17 +1781,41 @@ spec: webidl; urlPrefix: https://heycam.github.io/webidl/
    3. Else:
        -
      1. Let potentialResponse be a copy of response's associated response, except for its body.
      2. +
      3. Let bytes be an empty byte sequence. +
      4. Let end-of-body be false. +
      5. Let done be false. +
      6. Let potentialResponse be a copy of response's associated response, except for its body.
      7. If response's body is non-null, run these substeps:
          -
        1. Set potentialResponse's body to response's body.
        2. -
        3. Let dummyStream be an empty ReadableStream object.
        4. -
        5. Set response's body to a new body whose stream is dummyStream.
        6. -
        7. Let reader be the result of getting a reader from dummyStream.
        8. -
        9. Read all bytes from dummyStream with reader.
        10. +
        11. Let reader be the result of getting a reader from response's body's stream.
        12. +
        13. Let strategy be an object created in targetRealm. The user agent may choose any object.
        14. +
        15. Let pull be an action that runs these subsubsteps: +
            +
          1. Let promise be the result of reading a chunk from response's body's stream with reader.
          2. +
          3. When promise is fulfilled with an object whose done property is false and whose value property is a Uint8Array object, append the bytes represented by the value property to bytes and perform ! DetachArrayBuffer with the ArrayBuffer object wrapped by the value property.
          4. +
          5. When promise is fulfilled with an object whose done property is true, set end-of-body to true.
          6. +
          7. When promise is fulfilled with a value that matches with neither of the above patterns, or promise is rejected, error newStream with a TypeError.
          8. +
          +
        16. +
        17. Let cancel be an action that cancels response's body's stream with reader.
        18. +
        19. Let newStream be the result of constructing a ReadableStream object with strategy, pull and cancel in targetRealm.
        20. +
        21. Set potentialResponse's body to a new body whose stream is newStream.
        22. +
        23. Run these subsubsteps repeatedly in parallel while done is false:
        24. +
            +
          1. If newStream is errored, then set done to true.
          2. +
          3. Otherwise, if bytes is empty and end-of-body is true, then close newStream and set done to true.
          4. +
          5. Otherwise, if bytes is not empty, run these subsubsubsteps: +
              +
            1. Let chunk be a subsequence of bytes starting from the beginning of bytes.
            2. +
            3. Remove chunk from bytes. +
            4. Let buffer be an ArrayBuffer object created in targetRealm and containing chunk. +
            5. Enqueue a Uint8Array object created in targetRealm and wrapping buffer to newStream. +
            +
          6. +
          +
        -

        These substeps are meant to produce the observable equivalent of "piping" response's body's stream into potentialResponse. That is, response is left with a body with a ReadableStream object that is disturbed and locked, while the data readable from potentialResponse's body's stream is now equal to what used to be response's, if response's original body is non-null.

        -

        These substeps will be replaced by using pipe when the algorithm for pipeTo becomes stable.

        +

        These substeps are meant to produce the observable equivalent of "piping" response's body's stream into potentialResponse.

      8. Set the potential response to potentialResponse.
      @@ -1874,6 +1907,7 @@ spec: webidl; urlPrefix: https://heycam.github.io/webidl/
    4. Set the stop propagation flag and stop immediate propagation flag.
    5. Set the respond-with entered flag.
    6. Set the wait to respond flag.
    7. +
    8. Let targetRealm be the relevant Realm of the context object.
    9. Run the following substeps in parallel:
      1. Wait until r settles.
      2. @@ -1895,17 +1929,40 @@ spec: webidl; urlPrefix: https://heycam.github.io/webidl/
      3. Else:
          +
        1. Let bytes be an empty byte sequence. +
        2. Let end-of-body be false. +
        3. Let done be false.
        4. Let potentialResponse be a copy of response.{{ForeignFetchResponse/response}}'s associated response, except for its body.
        5. If response.{{ForeignFetchResponse/response}}'s body is non-null, run these substeps:
            -
          1. Set potentialResponse's body to response.{{ForeignFetchResponse/response}}'s body.
          2. -
          3. Let dummyStream be an empty ReadableStream object.
          4. -
          5. Set response.{{ForeignFetchResponse/response}}'s body to a new body whose stream is dummyStream.
          6. -
          7. Let reader be the result of getting a reader from dummyStream.
          8. -
          9. Read all bytes from dummyStream with reader.
          10. +
          11. Let reader be the result of getting a reader from response.{{ForeignFetchResponse/response}}'s body's stream.
          12. +
          13. Let strategy be an object created in targetRealm. The user agent may choose any object.
          14. +
          15. Let pull be an action that runs these subsubsteps: +
              +
            1. Let promise be the result of reading a chunk from response.{{ForeignFetchResponse/response}}'s body's stream with reader.
            2. +
            3. When promise is fulfilled with an object whose done property is false and whose value property is a Uint8Array object, append the bytes represented by the value property to bytes and perform ! DetachArrayBuffer with the ArrayBuffer object wrapped by the value property.
            4. +
            5. When promise is fulfilled with an object whose done property is true, set end-of-body to true.
            6. +
            7. When promise is fulfilled with a value that matches with neither of the above patterns, or promise is rejected, error newStream with a TypeError.
            8. +
            +
          16. +
          17. Let cancel be an action that cancels response.{{ForeignFetchResponse/response}}'s body's stream with reader.
          18. +
          19. Let newStream be the result of constructing a ReadableStream object with strategy, pull and cancel in targetRealm.
          20. +
          21. Set potentialResponse's body to a new body whose stream is newStream.
          22. +
          23. Run these subsubsteps repeatedly in parallel while done is false:
          24. +
              +
            1. If newStream is errored, then set done to true.
            2. +
            3. Otherwise, if bytes is empty and end-of-body is true, then close newStream and set done to true.
            4. +
            5. Otherwise, if bytes is not empty, run these subsubsubsteps: +
                +
              1. Let chunk be a subsequence of bytes starting from the beginning of bytes.
              2. +
              3. Remove chunk from bytes. +
              4. Let buffer be an ArrayBuffer object created in targetRealm and containing chunk. +
              5. Enqueue a Uint8Array object created in targetRealm and wrapping buffer to newStream. +
              +
            6. +
            +
          -

          These substeps are meant to produce the observable equivalent of "piping" response's body's stream into potentialResponse. That is, response is left with a body with a ReadableStream object that is disturbed and locked, while the data readable from potentialResponse's body's stream is now equal to what used to be response's, if response's original body is non-null.

          -

          These substeps will be replaced by using pipe when the algorithm for pipeTo becomes stable.

        6. Set the potential response to potentialResponse.
        diff --git a/spec/service_worker/index.html b/spec/service_worker/index.html index 973da72e..caa50d47 100644 --- a/spec/service_worker/index.html +++ b/spec/service_worker/index.html @@ -35,7 +35,6 @@ * - .note for informative notes (div, p, span, aside, details) * - .example for informative examples (div, p, pre, span) * - .issue for issues (div, p, span) - * - .assertion for assertions (div, p, span) * - .advisement for loud normative statements (div, p, strong) * - .annoying-warning for spec obsoletion notices (div, aside, details) * @@ -599,7 +598,7 @@ /* Colored Boxes */ /******************************************************************************/ - .issue, .note, .example, .assertion, .advisement, blockquote { + .issue, .note, .example, .advisement, blockquote { padding: .5em; border: .5em; border-left-style: solid; @@ -614,7 +613,6 @@ .note, .example, .advisement, - .assertion, blockquote { margin: 1em auto; } @@ -694,14 +692,6 @@ border-bottom: 1px silver solid; } -/** Assertion Box *************************************************************/ - /* for assertions in algorithms */ - - .assertion { - border-color: #AAA; - background: #EEE; - } - /** Advisement Box ************************************************************/ /* for attention-grabbing normative statements */ @@ -1409,7 +1399,7 @@

        Service Workers Nightly

        -

        Editor’s Draft,

        +

        Editor’s Draft,

        This version: @@ -2904,6 +2894,7 @@

        Set the stop propagation flag and stop immediate propagation flag.
      4. Set the respond-with entered flag.
      5. Set the wait to respond flag. +
      6. Let targetRealm be the relevant Realm of the context object.
      7. Run the following substeps in parallel:
          @@ -2927,18 +2918,41 @@

          Else:
            -
          1. Let potentialResponse be a copy of response’s associated response, except for its body. +
          2. Let bytes be an empty byte sequence. +
          3. Let end-of-body be false. +
          4. Let done be false. +
          5. Let potentialResponse be a copy of response’s associated response, except for its body.
          6. If response’s body is non-null, run these substeps:
              -
            1. Set potentialResponse’s body to response’s body. -
            2. Let dummyStream be an empty ReadableStream object. -
            3. Set response’s body to a new body whose stream is dummyStream. -
            4. Let reader be the result of getting a reader from dummyStream. -
            5. Read all bytes from dummyStream with reader. +
            6. Let reader be the result of getting a reader from response’s body’s stream. +
            7. Let strategy be an object created in targetRealm. The user agent may choose any object. +
            8. + Let pull be an action that runs these subsubsteps: +
                +
              1. Let promise be the result of reading a chunk from response’s body’s stream with reader. +
              2. When promise is fulfilled with an object whose done property is false and whose value property is a Uint8Array object, append the bytes represented by the value property to bytes and perform ! DetachArrayBuffer with the ArrayBuffer object wrapped by the value property. +
              3. When promise is fulfilled with an object whose done property is true, set end-of-body to true. +
              4. When promise is fulfilled with a value that matches with neither of the above patterns, or promise is rejected, error newStream with a TypeError. +
              +
            9. Let cancel be an action that cancels response’s body’s stream with reader. +
            10. Let newStream be the result of constructing a ReadableStream object with strategy, pull and cancel in targetRealm. +
            11. Set potentialResponse’s body to a new body whose stream is newStream. +
            12. Run these subsubsteps repeatedly in parallel while done is false: +
                +
              1. If newStream is errored, then set done to true. +
              2. Otherwise, if bytes is empty and end-of-body is true, then close newStream and set done to true. +
              3. + Otherwise, if bytes is not empty, run these subsubsubsteps: +
                  +
                1. Let chunk be a subsequence of bytes starting from the beginning of bytes. +
                2. Remove chunk from bytes. +
                3. Let buffer be an ArrayBuffer object created in targetRealm and containing chunk. +
                4. Enqueue a Uint8Array object created in targetRealm and wrapping buffer to newStream. +
                +
            -

            These substeps are meant to produce the observable equivalent of "piping" response’s body’s stream into potentialResponse. That is, response is left with a body with a ReadableStream object that is disturbed and locked, while the data readable from potentialResponse’s body’s stream is now equal to what used to be response’s, if response’s original body is non-null.

            -

            These substeps will be replaced by using pipe when the algorithm for pipeTo becomes stable.

            +

            These substeps are meant to produce the observable equivalent of "piping" response’s body’s stream into potentialResponse.

          7. Set the potential response to potentialResponse.

        @@ -3012,6 +3026,7 @@
      @@ -5754,12 +5791,18 @@

      body
    10. cache mode
    11. cache state +
    12. cancel a reader
    13. client +
    14. close readablestream +
    15. construct a readablestream
    16. cors filtered response
    17. cors-exposed header-names list
    18. destination
    19. disturbed
    20. empty +
    21. enqueue a chunk to readablestream +
    22. error readablestream +
    23. errored
    24. extract a mime type
    25. fetch
    26. fetch(input, init) @@ -5787,6 +5830,7 @@

      potential-navigation-or-subresource request
    27. process response
    28. process response end-of-file +
    29. read a chunk from a reader
    30. read all bytes
    31. readablestream
    32. redirect mode @@ -5866,6 +5910,7 @@

      queue a task
    33. realm execution context
    34. relevant global object +
    35. relevant realm
    36. relevant settings object
    37. replacement enabled
    38. responsible browsing context @@ -6273,8 +6318,6 @@

      I

      Issues Index

      -
      These substeps will be replaced by using pipe when the algorithm for pipeTo becomes stable.
      -
      These substeps will be replaced by using pipe when the algorithm for pipeTo becomes stable.
      Remove this definition after sorting out the referencing sites.
      This needs an extra step in the HTTP fetch algorithm in between step 3 and 4, to call this algorithm for all requests if response is null at that point.
      @@ -7525,7 +7568,7 @@

      #dom-foreignfetchresponse-responseReferenced in: