Changeset 182794 in webkit


Ignore:
Timestamp:
Apr 14, 2015, 6:52:59 AM (10 years ago)
Author:
youenn.fablet@crf.canon.fr
Message:

[Streams API] ReadableStream constructor start function should be able to close the stream
https://bugs.webkit.org/show_bug.cgi?id=143363

Reviewed by Benjamin Poulain.

Source/WebCore:

Implements https://streams.spec.whatwg.org/#close-readable-stream.
When the "close" JS function is called, the stream is getting closed.
The stream state is changed to close and if it has a reader, the reader gets closed as well:
The reader resolves the closed promise and release the stream.

Enabled the possibility to resolve a promise with any JS value.
This is used to resolve closed promise with jsUndefined and will be used for read promises.

Covered by reference tests that are now passing.

  • Modules/streams/ReadableStream.cpp:

(WebCore::ReadableStream::changeStateToClosed): Called by the JS function 'close'.

  • Modules/streams/ReadableStream.h:
  • Modules/streams/ReadableStreamReader.cpp:

(WebCore::ReadableStreamReader::ReadableStreamReader):
(WebCore::ReadableStreamReader::initialize): Added to handle state change at constructor time (in particular closed/errored state).
(WebCore::ReadableStreamReader::releaseStream):
(WebCore::ReadableStreamReader::closed): Storing the closed promise callbacks.
(WebCore::ReadableStreamReader::changeStateToClosed): Resolution of closed promise.

  • Modules/streams/ReadableStreamReader.h:
  • bindings/js/JSDOMPromise.h:

(WebCore::DeferredWrapper::resolve<JSC::JSValue>):

  • bindings/js/JSReadableStreamReaderCustom.cpp:

(WebCore::JSReadableStreamReader::closed):

  • bindings/js/ReadableStreamJSSource.cpp:

(WebCore::readableStreamSlotName):
(WebCore::getReadableJSStream): Helper function to retrieve the stream from the exec state.
(WebCore::closeReadableStreamFunction):
(WebCore::createReadableStreamCloseFunction):
(WebCore::createReadableStreamController):
(WebCore::ReadableStreamJSSource::start):
(WebCore::ReadableJSStreamReader::ReadableJSStreamReader): Deleted.

LayoutTests:

Rebased tests as some are now passing.

  • streams/reference-implementation/readable-stream-reader-expected.txt:
  • streams/reference-implementation/readable-stream-templated-expected.txt:
Location:
trunk
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r182793 r182794  
     12015-04-14  Xabier Rodriguez Calvar  <calvaris@igalia.com> and Youenn Fablet  <youenn.fablet@crf.canon.fr>
     2
     3        [Streams API] ReadableStream constructor start function should be able to close the stream
     4        https://bugs.webkit.org/show_bug.cgi?id=143363
     5
     6        Reviewed by Benjamin Poulain.
     7
     8        Rebased tests as some are now passing.
     9
     10        * streams/reference-implementation/readable-stream-reader-expected.txt:
     11        * streams/reference-implementation/readable-stream-templated-expected.txt:
     12
    1132015-04-14  Marcos Chavarría Teijeiro  <chavarria1991@gmail.com>
    214
  • trunk/LayoutTests/streams/reference-implementation/readable-stream-reader-expected.txt

    r182783 r182794  
    1212FAIL Reading from a reader for an empty stream will wait until a chunk is available read is not implemented
    1313FAIL cancel() on a reader releases the reader before calling through cancel is not implemented
    14 TIMEOUT closed should be fulfilled after stream is closed (.closed access before acquiring) Test timed out
     14PASS closed should be fulfilled after stream is closed (.closed access before acquiring)
    1515FAIL closed should be fulfilled after reader releases its lock (multiple stream locks) releaseLock is not implemented
    1616FAIL Multiple readers can access the stream in sequence read is not implemented
  • trunk/LayoutTests/streams/reference-implementation/readable-stream-templated-expected.txt

    r182625 r182794  
    1616FAIL cancel() should return a distinct fulfilled promise each time cancel is not implemented
    1717PASS getReader() should be OK
    18 FAIL should be able to acquire multiple readers, since they are all auto-released ReadableStream is locked
     18PASS should be able to acquire multiple readers, since they are all auto-released
    1919PASS Running templatedRSClosedReader with ReadableStream (closed via call in start) reader
    2020FAIL read() should fulfill with { value: undefined, done: true } read is not implemented
    21 TIMEOUT closed should fulfill with undefined Test timed out
     21PASS closed should fulfill with undefined
    2222FAIL cancel() should return a distinct fulfilled promise each time cancel is not implemented
    2323PASS Running templatedRSClosed with ReadableStream (closed via cancel)
  • trunk/Source/WebCore/ChangeLog

    r182782 r182794  
     12015-04-14  Xabier Rodriguez Calvar  <calvaris@igalia.com> and Youenn Fablet  <youenn.fablet@crf.canon.fr>
     2
     3        [Streams API] ReadableStream constructor start function should be able to close the stream
     4        https://bugs.webkit.org/show_bug.cgi?id=143363
     5
     6        Reviewed by Benjamin Poulain.
     7
     8        Implements https://streams.spec.whatwg.org/#close-readable-stream.
     9        When the "close" JS function is called, the stream is getting closed.
     10        The stream state is changed to close and if it has a reader, the reader gets closed as well:
     11        The reader resolves the closed promise and release the stream.
     12
     13        Enabled the possibility to resolve a promise with any JS value.
     14        This is used to resolve closed promise with jsUndefined and will be used for read promises.
     15
     16        Covered by reference tests that are now passing.
     17
     18        * Modules/streams/ReadableStream.cpp:
     19        (WebCore::ReadableStream::changeStateToClosed): Called by the JS function 'close'.
     20        * Modules/streams/ReadableStream.h:
     21        * Modules/streams/ReadableStreamReader.cpp:
     22        (WebCore::ReadableStreamReader::ReadableStreamReader):
     23        (WebCore::ReadableStreamReader::initialize): Added to handle state change at constructor time (in particular closed/errored state).
     24        (WebCore::ReadableStreamReader::releaseStream):
     25        (WebCore::ReadableStreamReader::closed): Storing the closed promise callbacks.
     26        (WebCore::ReadableStreamReader::changeStateToClosed): Resolution of closed promise.
     27        * Modules/streams/ReadableStreamReader.h:
     28        * bindings/js/JSDOMPromise.h:
     29        (WebCore::DeferredWrapper::resolve<JSC::JSValue>):
     30        * bindings/js/JSReadableStreamReaderCustom.cpp:
     31        (WebCore::JSReadableStreamReader::closed):
     32        * bindings/js/ReadableStreamJSSource.cpp:
     33        (WebCore::readableStreamSlotName):
     34        (WebCore::getReadableJSStream): Helper function to retrieve the stream from the exec state.
     35        (WebCore::closeReadableStreamFunction):
     36        (WebCore::createReadableStreamCloseFunction):
     37        (WebCore::createReadableStreamController):
     38        (WebCore::ReadableStreamJSSource::start):
     39        (WebCore::ReadableJSStreamReader::ReadableJSStreamReader): Deleted.
     40
    1412015-04-13  Joonghun Park  <jh718.park@samsung.com>
    242
  • trunk/Source/WebCore/Modules/streams/ReadableStream.cpp

    r182591 r182794  
    5959}
    6060
     61void ReadableStream::changeStateToClosed()
     62{
     63    if (m_state != State::Readable)
     64        return;
     65    m_state = State::Closed;
     66    if (m_reader)
     67        m_reader->changeStateToClosed();
     68    ASSERT(!m_reader);
     69}
     70
    6171void ReadableStream::start()
    6272{
  • trunk/Source/WebCore/Modules/streams/ReadableStream.h

    r182591 r182794  
    6969
    7070    void start();
     71    void changeStateToClosed();
    7172
    7273protected:
  • trunk/Source/WebCore/Modules/streams/ReadableStreamReader.cpp

    r182544 r182794  
    4242ReadableStreamReader::ReadableStreamReader(ReadableStream& stream)
    4343    : ActiveDOMObject(stream.scriptExecutionContext())
     44    , m_stream(&stream)
    4445{
    4546#ifndef NDEBUG
     
    4748#endif
    4849    suspendIfNeeded();
    49     ASSERT_WITH_MESSAGE(!stream.reader(), "A ReadableStream cannot be locked by two readers at the same time.");
    50     m_stream = &stream;
    51     stream.lock(*this);
     50    initialize();
    5251}
    5352
     
    6362}
    6463
    65 void ReadableStreamReader::closed(ClosedSuccessCallback, ClosedErrorCallback)
     64void ReadableStreamReader::initialize()
    6665{
    67     notImplemented();   
     66    ASSERT_WITH_MESSAGE(!m_stream->isLocked(), "A ReadableStream cannot be locked by two readers at the same time.");
     67    m_stream->lock(*this);
     68    if (m_stream->internalState() == ReadableStream::State::Closed) {
     69        changeStateToClosed();
     70        return;
     71    }
     72}
     73
     74void ReadableStreamReader::releaseStream()
     75{
     76    ASSERT(m_stream);
     77    m_stream->release();
     78    m_stream = nullptr;
     79}
     80
     81void ReadableStreamReader::closed(ClosedSuccessCallback successCallback, ClosedErrorCallback)
     82{
     83    if (m_state == State::Closed) {
     84        successCallback();
     85        return;
     86    }
     87    m_closedSuccessCallback = WTF::move(successCallback);
     88}
     89
     90void ReadableStreamReader::changeStateToClosed()
     91{
     92    ASSERT(m_state == State::Readable);
     93    m_state = State::Closed;
     94
     95    if (m_closedSuccessCallback) {
     96        ClosedSuccessCallback closedSuccessCallback = WTF::move(m_closedSuccessCallback);
     97        closedSuccessCallback();
     98    }
     99    ASSERT(!m_closedSuccessCallback);
     100    releaseStream();
     101    // FIXME: Implement read promise fulfilling.
    68102}
    69103
  • trunk/Source/WebCore/Modules/streams/ReadableStreamReader.h

    r182544 r182794  
    4747class ReadableStreamReader : public ActiveDOMObject, public ScriptWrappable, public RefCounted<ReadableStreamReader> {
    4848public:
     49    enum class State {
     50        Readable,
     51        Closed,
     52        Errored
     53    };
     54
    4955    virtual ~ReadableStreamReader();
    5056
     
    5561    void closed(ClosedSuccessCallback, ClosedErrorCallback);
    5662
     63    void changeStateToClosed();
     64
    5765protected:
    5866    ReadableStreamReader(ReadableStream&);
     67
     68    void releaseStream();
    5969
    6070private:
     
    6272    const char* activeDOMObjectName() const override;
    6373    bool canSuspendForPageCache() const override;
     74    void initialize();
    6475
    6576    RefPtr<ReadableStream> m_stream;
     77    State m_state { State::Readable };
     78
     79    ClosedSuccessCallback m_closedSuccessCallback;
    6680};
    6781
  • trunk/Source/WebCore/bindings/js/JSDOMPromise.h

    r182141 r182794  
    9999
    100100template<>
     101inline void DeferredWrapper::resolve<JSC::JSValue>(const JSC::JSValue& value)
     102{
     103    JSC::ExecState* exec = m_globalObject->globalExec();
     104    JSC::JSLockHolder locker(exec);
     105    resolve(exec, value);
     106}
     107template<>
    101108inline void DeferredWrapper::resolve<Vector<unsigned char>>(const Vector<unsigned char>& result)
    102109{
  • trunk/Source/WebCore/bindings/js/JSReadableStreamReaderCustom.cpp

    r182344 r182794  
    7272    JSPromiseDeferred* promiseDeferred = getOrCreatePromiseDeferredFromObject(exec, this, globalObject(), closedPromiseSlotName());
    7373    DeferredWrapper wrapper(exec, globalObject(), promiseDeferred);
    74     auto successCallback = [this, wrapper]() mutable {
    75         // FIXME: return jsUndefined().
    76         wrapper.resolve(&impl());
     74    auto successCallback = [wrapper]() mutable {
     75        wrapper.resolve(jsUndefined());
    7776    };
    7877    auto failureCallback = [this, wrapper]() mutable {
  • trunk/Source/WebCore/bindings/js/ReadableStreamJSSource.cpp

    r182591 r182794  
    6565}
    6666
     67// This slot name is used to store the JSReadableStream in created JS functions (enqueue, close...).
     68// This allows retrieving the corresponding JSReadableStream when executing the JS function.
     69static JSC::PrivateName& readableStreamSlotName()
     70{
     71    static NeverDestroyed<JSC::PrivateName> readableStreamSlotName("readableStream");
     72    return readableStreamSlotName;
     73}
     74
     75static ReadableJSStream& getReadableJSStream(ExecState* exec)
     76{
     77    JSReadableStream* jsReadableStream = jsDynamicCast<JSReadableStream*>(getInternalSlotFromObject(exec, exec->callee(), readableStreamSlotName()));
     78    ASSERT(jsReadableStream);
     79    return static_cast<ReadableJSStream&>(jsReadableStream->impl());
     80}
     81
    6782static inline JSValue getPropertyFromObject(ExecState* exec, JSObject* object, const char* identifier)
    6883{
     
    107122}
    108123
    109 static inline JSFunction* createReadableStreamCloseFunction(ExecState* exec)
    110 {
    111     return JSFunction::create(exec->vm(), exec->callee()->globalObject(), 0, String(), notImplementedFunction);
     124static EncodedJSValue JSC_HOST_CALL closeReadableStreamFunction(ExecState* exec)
     125{
     126    getReadableJSStream(exec).changeStateToClosed();
     127    return JSValue::encode(jsUndefined());
     128}
     129
     130static inline JSFunction* createReadableStreamCloseFunction(ExecState* exec, JSReadableStream* readableStream)
     131{
     132    JSFunction* closeFunction = JSFunction::create(exec->vm(), exec->callee()->globalObject(), 0, String(), closeReadableStreamFunction);
     133    setInternalSlotToObject(exec, closeFunction, readableStreamSlotName(), readableStream);
     134    return closeFunction;
    112135}
    113136
     
    125148}
    126149
    127 static inline JSObject* createReadableStreamController(JSC::ExecState* exec)
     150static inline JSObject* createReadableStreamController(JSC::ExecState* exec, JSReadableStream* readableStream)
    128151{
    129152    JSFunction* enqueueFunction = createReadableStreamEnqueueFunction(exec);
    130     JSFunction* closeFunction = createReadableStreamCloseFunction(exec);
     153    JSFunction* closeFunction = createReadableStreamCloseFunction(exec, readableStream);
    131154    JSFunction* errorFunction = createReadableStreamErrorFunction(exec);
    132155
     
    142165    JSLockHolder lock(exec);
    143166
    144     m_controller.set(exec->vm(), createReadableStreamController(exec));
     167    m_controller.set(exec->vm(), createReadableStreamController(exec, readableStream));
    145168
    146169    JSValue startFunction = getPropertyFromObject(exec, m_source.get(), "start");
Note: See TracChangeset for help on using the changeset viewer.