Changeset 205110 in webkit


Ignore:
Timestamp:
Aug 28, 2016 11:49:42 PM (8 years ago)
Author:
commit-queue@webkit.org
Message:

[Fetch API] Ensure response cloning works when data is loading
https://bugs.webkit.org/show_bug.cgi?id=161137

Patch by Youenn Fablet <youenn@apple.com> on 2016-08-28
Reviewed by Darin Adler.

LayoutTests/imported/w3c:

  • web-platform-tests/fetch/api/response/response-clone-expected.txt:
  • web-platform-tests/fetch/api/response/response-clone.html: New tests highly inspired from Chromium similar tests.

Source/WebCore:

Test: http/tests/fetch/clone-after-load-is-finished.html and updated wpt test

FetchBody is only able to clone data when requested by Response in case the data is already there.
If data is loaded from FetchLoader, each received chunk should be given to each cloned response.
The simplest approach is to create a ReadableStream body for the cloned Response and use it for the teeing.

  • Modules/fetch/FetchResponse.cpp:

(WebCore::FetchResponse::BodyLoader::didSucceed): Postpone stream closing if there is still data to enqueue in the FetchBody.

  • Modules/fetch/FetchResponse.h:
  • Modules/fetch/FetchResponse.idl:
  • Modules/fetch/FetchResponse.js:

(clone): If response is being loaded, create a ReadableStream body so that loaded data cloning is handled by ReadableStream tee.

  • Modules/streams/ReadableStreamInternals.js: Restrict firstReadCallback to the case of a readable ReadableStream.

If stream is errored or closed, FetchResponse will already have disposed of its source.
(readFromReadableStreamDefaultReader):

  • bindings/js/WebCoreBuiltinNames.h:

LayoutTests:

  • http/tests/fetch/clone-response-body-expected.txt: Added.
  • http/tests/fetch/clone-response-body.html: Added.
Location:
trunk
Files:
2 added
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r205109 r205110  
     12016-08-28  Youenn Fablet  <youenn@apple.com>
     2
     3        [Fetch API] Ensure response cloning works when data is loading
     4        https://bugs.webkit.org/show_bug.cgi?id=161137
     5
     6        Reviewed by Darin Adler.
     7
     8        * http/tests/fetch/clone-response-body-expected.txt: Added.
     9        * http/tests/fetch/clone-response-body.html: Added.
     10
    1112016-08-28  Jiewen Tan  <jiewen_tan@apple.com>
    212
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r205082 r205110  
     12016-08-28  Youenn Fablet  <youenn@apple.com>
     2
     3        [Fetch API] Ensure response cloning works when data is loading
     4        https://bugs.webkit.org/show_bug.cgi?id=161137
     5
     6        Reviewed by Darin Adler.
     7
     8        * web-platform-tests/fetch/api/response/response-clone-expected.txt:
     9        * web-platform-tests/fetch/api/response/response-clone.html: New tests highly inspired from Chromium similar tests.
     10
    1112016-08-27  Youenn Fablet  <youenn@apple.com>
    212
  • trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/response/response-clone-expected.txt

    r203408 r205110  
    55PASS Check cloned response's body
    66PASS Cannot clone a disturbed response
     7PASS Cloned responses should provide the same data
     8PASS Cancelling stream should not affect cloned one
    79
  • trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/response/response-clone.html

    r203408 r205110  
    6262        });
    6363      }, "Cannot clone a disturbed response");
     64
     65    promise_test(function(t) {
     66        var clone;
     67        var result;
     68        var response;
     69        return fetch('../resources/trickle.py?count=2&delay=100').then(function(res) {
     70            clone = res.clone();
     71            response = res;
     72            return clone.arrayBuffer();
     73        }).then(function(r) {
     74            assert_equals(r.byteLength, 26);
     75            result = r;
     76            return response.arrayBuffer();
     77        }).then(function(r) {
     78            assert_array_equals(r, result, "cloned responses should provide the same data");
     79        });
     80     }, 'Cloned responses should provide the same data');
     81
     82    promise_test(function(t) {
     83        var clone;
     84        return fetch('../resources/trickle.py?count=2&delay=100').then(function(res) {
     85            clone = res.clone();
     86            res.body.cancel();
     87            assert_true(res.bodyUsed);
     88            assert_false(clone.bodyUsed);
     89            return clone.arrayBuffer();
     90        }).then(function(r) {
     91            assert_equals(r.byteLength, 26);
     92            assert_true(clone.bodyUsed);
     93        });
     94    }, 'Cancelling stream should not affect cloned one');
     95
    6496    </script>
    6597  </body>
  • trunk/Source/WebCore/ChangeLog

    r205106 r205110  
     12016-08-28  Youenn Fablet  <youenn@apple.com>
     2
     3        [Fetch API] Ensure response cloning works when data is loading
     4        https://bugs.webkit.org/show_bug.cgi?id=161137
     5
     6        Reviewed by Darin Adler.
     7
     8        Test: http/tests/fetch/clone-after-load-is-finished.html and updated wpt test
     9
     10        FetchBody is only able to clone data when requested by Response in case the data is already there.
     11        If data is loaded from FetchLoader, each received chunk should be given to each cloned response.
     12        The simplest approach is to create a ReadableStream body for the cloned Response and use it for the teeing.
     13
     14        * Modules/fetch/FetchResponse.cpp:
     15        (WebCore::FetchResponse::BodyLoader::didSucceed): Postpone stream closing if there is still data to enqueue in the FetchBody.
     16        * Modules/fetch/FetchResponse.h:
     17        * Modules/fetch/FetchResponse.idl:
     18        * Modules/fetch/FetchResponse.js:
     19        (clone): If response is being loaded, create a ReadableStream body so that loaded data cloning is handled by ReadableStream tee.
     20        * Modules/streams/ReadableStreamInternals.js: Restrict firstReadCallback to the case of a readable ReadableStream.
     21        If stream is errored or closed, FetchResponse will already have disposed of its source.
     22        (readFromReadableStreamDefaultReader):
     23        * bindings/js/WebCoreBuiltinNames.h:
     24
    1252016-08-28  Andreas Kling  <akling@apple.com>
    226
  • trunk/Source/WebCore/Modules/fetch/FetchResponse.cpp

    r205076 r205110  
    128128{
    129129    ASSERT(m_response.hasPendingActivity());
     130    m_response.m_body.loadingSucceeded();
     131
    130132#if ENABLE(STREAMS_API)
    131     if (m_response.m_readableStreamSource) {
     133    if (m_response.m_readableStreamSource && m_response.m_body.type() != FetchBody::Type::Loaded) {
     134        // We only close the stream if FetchBody already enqueued data.
     135        // Otherwise, FetchBody will close the stream when enqueuing data.
    132136        m_response.m_readableStreamSource->close();
    133137        m_response.m_readableStreamSource = nullptr;
    134138    }
    135139#endif
    136     m_response.m_body.loadingSucceeded();
    137140
    138141    if (m_loader->isStarted())
  • trunk/Source/WebCore/Modules/fetch/FetchResponse.h

    r203767 r205110  
    8686    void cancel();
    8787#endif
     88    bool isLoading() const { return body().type() == FetchBody::Type::Loading; }
    8889
    8990private:
  • trunk/Source/WebCore/Modules/fetch/FetchResponse.idl

    r203767 r205110  
    7171
    7272    [PrivateIdentifier] Promise consume(unsigned short type);
     73    [PrivateIdentifier] boolean isLoading();
    7374    [PrivateIdentifier, RaisesException] void setStatus(unsigned short status, DOMString statusText);
    7475    [CallWith=ScriptState, PrivateIdentifier] void initializeWith(any body);
  • trunk/Source/WebCore/Modules/fetch/FetchResponse.js

    r203961 r205110  
    8888
    8989    var cloned = @Response.prototype.@cloneForJS.@call(this);
     90
     91    // Let's create @body if response body is loading to provide data to both clones.
     92    if (@Response.prototype.@isLoading.@call(this) && !this.@body) {
     93        var source = @Response.prototype.@createReadableStreamSource.@call(this);
     94        @assert(!!source);
     95        this.@body = new @ReadableStream(source);
     96    }
     97
    9098    if (this.@body) {
    9199        var teedReadableStreams = @teeReadableStream(this.@body, false);
  • trunk/Source/WebCore/Modules/streams/ReadableStreamInternals.js

    r203818 r205110  
    344344
    345345    // Native sources may want to start enqueueing at the time of the first read request.
    346     if (!stream.@disturbed && stream.@underlyingSource.@firstReadCallback)
     346    if (!stream.@disturbed && stream.@state === @streamReadable && stream.@underlyingSource.@firstReadCallback)
    347347        stream.@underlyingSource.@firstReadCallback();
    348348
  • trunk/Source/WebCore/bindings/js/WebCoreBuiltinNames.h

    r203818 r205110  
    5555    macro(initializeWith) \
    5656    macro(isDisturbed) \
     57    macro(isLoading) \
    5758    macro(localStreams) \
    5859    macro(makeThisTypeError) \
Note: See TracChangeset for help on using the changeset viewer.