0dafe450af5a34771563598e5457deba533d22ad
[WebKit-https.git] / Source / WebCore / Modules / streams / ReadableStream.cpp
1 /*
2  * Copyright (C) 2015 Canon Inc.
3  * Copyright (C) 2015 Igalia S.L.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted, provided that the following conditions
7  * are required to be met:
8  *
9  * 1.  Redistributions of source code must retain the above copyright
10  *     notice, this list of conditions and the following disclaimer.
11  * 2.  Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution.
14  * 3.  Neither the name of Canon Inc. nor the names of
15  *     its contributors may be used to endorse or promote products derived
16  *     from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY CANON INC. AND ITS CONTRIBUTORS "AS IS" AND ANY
19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  * DISCLAIMED. IN NO EVENT SHALL CANON INC. AND ITS CONTRIBUTORS BE LIABLE FOR
22  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include "config.h"
31 #include "ReadableStream.h"
32
33 #if ENABLE(STREAMS_API)
34
35 #include "NotImplemented.h"
36 #include "ReadableStreamReader.h"
37 #include <runtime/JSCJSValueInlines.h>
38 #include <wtf/RefCountedLeakCounter.h>
39
40 namespace WebCore {
41
42 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, readableStreamCounter, ("ReadableStream"));
43
44 ReadableStream::ReadableStream(ScriptExecutionContext& scriptExecutionContext)
45     : ActiveDOMObject(&scriptExecutionContext)
46 {
47 #ifndef NDEBUG
48     readableStreamCounter.increment();
49 #endif
50     suspendIfNeeded();
51 }
52
53 ReadableStream::~ReadableStream()
54 {
55 #ifndef NDEBUG
56     readableStreamCounter.decrement();
57 #endif
58 }
59
60 void ReadableStream::clearCallbacks()
61 {
62     m_closedSuccessCallback = nullptr;
63     m_closedFailureCallback = nullptr;
64
65     m_readRequests.clear();
66 }
67
68 void ReadableStream::changeStateToClosed()
69 {
70     ASSERT(!m_closeRequested);
71     ASSERT(m_state != State::Errored);
72
73     m_closeRequested = true;
74
75     if (m_state != State::Readable || hasValue())
76         return;
77     close();
78 }
79
80 void ReadableStream::close()
81 {
82     m_state = State::Closed;
83
84     if (m_reader)
85         m_releasedReaders.append(WTF::move(m_reader));
86
87     if (m_closedSuccessCallback)
88         m_closedSuccessCallback();
89
90     for (auto& request : m_readRequests)
91         request.endCallback();
92
93     clearCallbacks();
94 }
95
96 void ReadableStream::changeStateToErrored()
97 {
98     if (m_state != State::Readable)
99         return;
100     m_state = State::Errored;
101
102     if (m_reader)
103         m_releasedReaders.append(WTF::move(m_reader));
104
105     JSC::JSValue error = this->error();
106     if (m_closedFailureCallback)
107         m_closedFailureCallback(error);
108
109     for (auto& request : m_readRequests)
110         request.failureCallback(error);
111
112     clearCallbacks();
113 }
114
115 ReadableStreamReader& ReadableStream::getReader()
116 {
117     ASSERT(!m_reader);
118
119     std::unique_ptr<ReadableStreamReader> newReader = std::make_unique<ReadableStreamReader>(*this);
120     ReadableStreamReader& reader = *newReader.get();
121
122     if (m_state == State::Readable) {
123         m_reader = WTF::move(newReader);
124         return reader;
125     }
126
127     m_releasedReaders.append(WTF::move(newReader));
128     return reader;
129 }
130
131 void ReadableStream::closed(ClosedSuccessCallback&& successCallback, FailureCallback&& failureCallback)
132 {
133     if (m_state == State::Closed) {
134         successCallback();
135         return;
136     }
137     if (m_state == State::Errored) {
138         failureCallback(error());
139         return;
140     }
141     m_closedSuccessCallback = WTF::move(successCallback);
142     m_closedFailureCallback = WTF::move(failureCallback);
143 }
144
145 void ReadableStream::read(ReadSuccessCallback&& successCallback, ReadEndCallback&& endCallback, FailureCallback&& failureCallback)
146 {
147     if (m_state == State::Closed) {
148         endCallback();
149         return;
150     }
151     if (m_state == State::Errored) {
152         failureCallback(error());
153         return;
154     }
155     if (hasValue()) {
156         successCallback(read());
157         if (m_closeRequested && !hasValue())
158             close();
159         return;
160     }
161     m_readRequests.append({ WTF::move(successCallback), WTF::move(endCallback), WTF::move(failureCallback) });
162     // FIXME: We should try to pull.
163 }
164
165 bool ReadableStream::resolveReadCallback(JSC::JSValue value)
166 {
167     if (m_readRequests.isEmpty())
168         return false;
169
170     m_readRequests.takeFirst().successCallback(value);
171     return true;
172 }
173
174 void ReadableStream::start()
175 {
176     notImplemented();
177 }
178
179 const char* ReadableStream::activeDOMObjectName() const
180 {
181     return "ReadableStream";
182 }
183
184 bool ReadableStream::canSuspendForPageCache() const
185 {
186     // FIXME: We should try and do better here.
187     return false;
188 }
189
190 }
191
192 #endif