Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(340)

Side by Side Diff: Source/core/streams/ReadableStream.cpp

Issue 837673002: Introduce ExclusiveStreamReader. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "config.h" 5 #include "config.h"
6 #include "core/streams/ReadableStream.h" 6 #include "core/streams/ReadableStream.h"
7 7
8 #include "bindings/core/v8/ExceptionState.h" 8 #include "bindings/core/v8/ExceptionState.h"
9 #include "bindings/core/v8/ScriptFunction.h" 9 #include "bindings/core/v8/ScriptFunction.h"
10 #include "bindings/core/v8/ScriptPromiseResolver.h" 10 #include "bindings/core/v8/ScriptPromiseResolver.h"
11 #include "bindings/core/v8/V8Binding.h" 11 #include "bindings/core/v8/V8Binding.h"
12 #include "core/dom/DOMException.h" 12 #include "core/dom/DOMException.h"
13 #include "core/dom/ExceptionCode.h" 13 #include "core/dom/ExceptionCode.h"
14 #include "core/dom/ExecutionContext.h" 14 #include "core/dom/ExecutionContext.h"
15 #include "core/streams/ExclusiveStreamReader.h"
15 #include "core/streams/UnderlyingSource.h" 16 #include "core/streams/UnderlyingSource.h"
16 17
17 namespace blink { 18 namespace blink {
18 19
19 namespace { 20 namespace {
20 21
21 class ConstUndefined : public ScriptFunction { 22 class ConstUndefined : public ScriptFunction {
22 public: 23 public:
23 static v8::Handle<v8::Function> create(ScriptState* scriptState) 24 static v8::Handle<v8::Function> create(ScriptState* scriptState)
24 { 25 {
25 return (new ConstUndefined(scriptState))->bindToV8Function(); 26 return (new ConstUndefined(scriptState))->bindToV8Function();
26 } 27 }
27 28
28 private: 29 private:
29 explicit ConstUndefined(ScriptState* scriptState) : ScriptFunction(scriptSta te) { } 30 explicit ConstUndefined(ScriptState* scriptState) : ScriptFunction(scriptSta te) { }
30 ScriptValue call(ScriptValue value) override 31 ScriptValue call(ScriptValue value) override
31 { 32 {
32 return ScriptValue(scriptState(), v8::Undefined(scriptState()->isolate() )); 33 return ScriptValue(scriptState(), v8::Undefined(scriptState()->isolate() ));
33 } 34 }
34 }; 35 };
35 36
37 class ResolveWithReady : public ScriptFunction {
38 public:
39 static v8::Handle<v8::Function> create(ScriptState* scriptState, ReadableStr eam* stream)
40 {
41 return (new ResolveWithReady(scriptState, stream))->bindToV8Function();
42 }
43
44 void trace(Visitor* visitor)
45 {
46 visitor->trace(m_stream);
47 ScriptFunction::trace(visitor);
48 }
49
50 private:
51 ResolveWithReady(ScriptState* scriptState, ReadableStream* stream)
52 : ScriptFunction(scriptState)
53 , m_stream(stream) { }
54
55 ScriptValue call(ScriptValue value) override
56 {
57 return ScriptValue(scriptState(), m_stream->ready(scriptState()).v8Value ());
58 }
59
60 Member<ReadableStream> m_stream;
61 };
62
36 } // namespace 63 } // namespace
37 64
38 ReadableStream::ReadableStream(ExecutionContext* executionContext, UnderlyingSou rce* source) 65 ReadableStream::ReadableStream(ExecutionContext* executionContext, UnderlyingSou rce* source)
39 : ActiveDOMObject(executionContext) 66 : ActiveDOMObject(executionContext)
40 , m_source(source) 67 , m_source(source)
41 , m_isStarted(false) 68 , m_isStarted(false)
42 , m_isDraining(false) 69 , m_isDraining(false)
43 , m_isPulling(false) 70 , m_isPulling(false)
44 , m_state(Waiting) 71 , m_state(Waiting)
45 , m_ready(new WaitPromise(executionContext, this, WaitPromise::Ready)) 72 , m_ready(new WaitPromise(executionContext, this, WaitPromise::Ready))
46 , m_closed(new ClosedPromise(executionContext, this, ClosedPromise::Closed)) 73 , m_closed(new ClosedPromise(executionContext, this, ClosedPromise::Closed))
47 { 74 {
48 suspendIfNeeded(); 75 suspendIfNeeded();
49 } 76 }
50 77
51 ReadableStream::~ReadableStream() 78 ReadableStream::~ReadableStream()
52 { 79 {
53 } 80 }
54 81
55 String ReadableStream::stateString() const 82 String ReadableStream::stateString() const
56 { 83 {
57 switch (m_state) { 84 if (m_reader)
58 case Readable:
59 return "readable";
60 case Waiting:
61 return "waiting"; 85 return "waiting";
62 case Closed: 86
63 return "closed"; 87 return stateToString(m_state);
64 case Errored:
65 return "errored";
66 }
67 ASSERT(false);
68 return String();
69 } 88 }
70 89
71 bool ReadableStream::enqueuePreliminaryCheck() 90 bool ReadableStream::enqueuePreliminaryCheck()
72 { 91 {
73 // This is a bit different from what spec says: it says we should throw 92 // This is a bit different from what spec says: it says we should throw
74 // an exception here. But sometimes a caller is not in any JavaScript 93 // an exception here. But sometimes a caller is not in any JavaScript
75 // context, and we don't want to throw an exception in such a case. 94 // context, and we don't want to throw an exception in such a case.
76 if (m_state == Errored || m_state == Closed || m_isDraining) 95 if (m_state == Errored || m_state == Closed || m_isDraining)
77 return false; 96 return false;
78 97
(...skipping 22 matching lines...) Expand all
101 } 120 }
102 121
103 return !shouldApplyBackpressure; 122 return !shouldApplyBackpressure;
104 } 123 }
105 124
106 void ReadableStream::close() 125 void ReadableStream::close()
107 { 126 {
108 if (m_state == Waiting) { 127 if (m_state == Waiting) {
109 m_ready->resolve(ToV8UndefinedGenerator()); 128 m_ready->resolve(ToV8UndefinedGenerator());
110 m_closed->resolve(ToV8UndefinedGenerator()); 129 m_closed->resolve(ToV8UndefinedGenerator());
130 if (m_reader)
131 m_reader->releaseLock();
111 m_state = Closed; 132 m_state = Closed;
112 } else if (m_state == Readable) { 133 } else if (m_state == Readable) {
113 m_isDraining = true; 134 m_isDraining = true;
114 } 135 }
115 } 136 }
116 137
117 void ReadableStream::readPreliminaryCheck(ExceptionState& exceptionState) 138 void ReadableStream::readInternalPreliminaryCheck(ExceptionState& exceptionState )
118 { 139 {
119 if (m_state == Waiting) { 140 if (m_state == Waiting) {
120 exceptionState.throwTypeError("read is called while state is waiting"); 141 exceptionState.throwTypeError("read is called while state is waiting");
121 return; 142 return;
122 } 143 }
123 if (m_state == Closed) { 144 if (m_state == Closed) {
124 exceptionState.throwTypeError("read is called while state is closed"); 145 exceptionState.throwTypeError("read is called while state is closed");
125 return; 146 return;
126 } 147 }
127 if (m_state == Errored) { 148 if (m_state == Errored) {
128 exceptionState.throwDOMException(m_exception->code(), m_exception->messa ge()); 149 exceptionState.throwDOMException(m_exception->code(), m_exception->messa ge());
129 return; 150 return;
130 } 151 }
131 } 152 }
132 153
133 void ReadableStream::readPostAction() 154 void ReadableStream::readInternalPostAction()
134 { 155 {
135 ASSERT(m_state == Readable); 156 ASSERT(m_state == Readable);
136 if (isQueueEmpty()) { 157 if (isQueueEmpty()) {
137 if (m_isDraining) { 158 if (m_isDraining) {
138 m_closed->resolve(ToV8UndefinedGenerator()); 159 m_closed->resolve(ToV8UndefinedGenerator());
160 if (m_reader)
161 m_reader->releaseLock();
139 m_state = Closed; 162 m_state = Closed;
tyoshino (SeeGerritForStatus) 2015/02/02 08:38:24 this doesn't cause any real issue, but let's updat
yhirano 2015/02/02 10:21:20 Done.
140 } else { 163 } else {
141 m_ready->reset(); 164 m_ready->reset();
142 m_state = Waiting; 165 m_state = Waiting;
143 } 166 }
144 } 167 }
145 callPullIfNeeded(); 168 callPullIfNeeded();
146 } 169 }
147 170
171 ScriptValue ReadableStream::read(ScriptState* scriptState, ExceptionState& excep tionState)
172 {
173 if (m_reader) {
174 exceptionState.throwTypeError("this stream is locked to an ExclusiveStre amReader");
175 return ScriptValue();
176 }
177 return readInternal(scriptState, exceptionState);
178 }
179
148 ScriptPromise ReadableStream::ready(ScriptState* scriptState) 180 ScriptPromise ReadableStream::ready(ScriptState* scriptState)
149 { 181 {
182 if (m_reader) {
183 return m_reader->released(scriptState).then(ResolveWithReady::create(scr iptState, this));
184 }
185
186 if (m_state == Waiting) {
187 return readyInternal(scriptState).then(ResolveWithReady::create(scriptSt ate, this));
188 }
189 return readyInternal(scriptState);
190 }
191
192 ScriptPromise ReadableStream::readyInternal(ScriptState* scriptState)
193 {
150 return m_ready->promise(scriptState->world()); 194 return m_ready->promise(scriptState->world());
151 } 195 }
152 196
153 ScriptPromise ReadableStream::cancel(ScriptState* scriptState, ScriptValue reaso n) 197 ScriptPromise ReadableStream::cancel(ScriptState* scriptState, ScriptValue reaso n)
154 { 198 {
199 if (m_reader)
200 return ScriptPromise::reject(scriptState, V8ThrowException::createTypeEr ror(scriptState->isolate(), "this stream is locked to an ExclusiveStreamReader") );
155 if (m_state == Closed) 201 if (m_state == Closed)
156 return ScriptPromise::cast(scriptState, v8::Undefined(scriptState->isola te())); 202 return ScriptPromise::cast(scriptState, v8::Undefined(scriptState->isola te()));
157 if (m_state == Errored) 203 if (m_state == Errored)
158 return ScriptPromise::rejectWithDOMException(scriptState, m_exception); 204 return ScriptPromise::rejectWithDOMException(scriptState, m_exception);
159 205
160 ASSERT(m_state == Readable || m_state == Waiting); 206 ASSERT(m_state == Readable || m_state == Waiting);
161 if (m_state == Waiting) 207 if (m_state == Waiting)
162 m_ready->resolve(ToV8UndefinedGenerator()); 208 m_ready->resolve(ToV8UndefinedGenerator());
163 clearQueue(); 209 clearQueue();
164 m_closed->resolve(ToV8UndefinedGenerator()); 210 m_closed->resolve(ToV8UndefinedGenerator());
165 m_state = Closed; 211 m_state = Closed;
166 return m_source->cancelSource(scriptState, reason).then(ConstUndefined::crea te(scriptState)); 212 return m_source->cancelSource(scriptState, reason).then(ConstUndefined::crea te(scriptState));
167 } 213 }
168 214
169 ScriptPromise ReadableStream::closed(ScriptState* scriptState) 215 ScriptPromise ReadableStream::closed(ScriptState* scriptState)
170 { 216 {
171 return m_closed->promise(scriptState->world()); 217 return m_closed->promise(scriptState->world());
172 } 218 }
173 219
174 void ReadableStream::error(PassRefPtrWillBeRawPtr<DOMException> exception) 220 void ReadableStream::error(PassRefPtrWillBeRawPtr<DOMException> exception)
175 { 221 {
176 switch (m_state) { 222 switch (m_state) {
177 case Waiting: 223 case Waiting:
178 m_exception = exception; 224 m_exception = exception;
179 m_ready->reject(m_exception); 225 m_ready->reject(m_exception);
180 m_closed->reject(m_exception); 226 m_closed->reject(m_exception);
181 m_state = Errored; 227 m_state = Errored;
228 if (m_reader)
229 m_reader->releaseLock();
182 break; 230 break;
183 case Readable: 231 case Readable:
184 clearQueue(); 232 clearQueue();
185 m_exception = exception; 233 m_exception = exception;
186 m_ready->reset(); 234 m_ready->reset();
187 m_ready->reject(m_exception); 235 m_ready->reject(m_exception);
188 m_closed->reject(m_exception); 236 m_closed->reject(m_exception);
189 m_state = Errored; 237 m_state = Errored;
238 if (m_reader)
239 m_reader->releaseLock();
190 break; 240 break;
191 default: 241 default:
192 break; 242 break;
193 } 243 }
194 } 244 }
195 245
196 void ReadableStream::didSourceStart() 246 void ReadableStream::didSourceStart()
197 { 247 {
198 m_isStarted = true; 248 m_isStarted = true;
199 callPullIfNeeded(); 249 callPullIfNeeded();
200 } 250 }
201 251
252 ExclusiveStreamReader* ReadableStream::getReader(ExceptionState& exceptionState)
253 {
254 if (m_reader) {
255 exceptionState.throwTypeError("already locked to an ExclusiveStreamReade r");
256 return nullptr;
257 }
tyoshino (SeeGerritForStatus) 2015/02/02 08:38:24 Throw for closed and errored stream as specified i
yhirano 2015/02/02 10:21:20 Done.
258 return new ExclusiveStreamReader(this);
259 }
260
261 void ReadableStream::setReader(ExclusiveStreamReader* reader)
262 {
263 ASSERT((reader && !m_reader) || (!reader && m_reader));
264 m_reader = reader;
265 }
266
202 void ReadableStream::callPullIfNeeded() 267 void ReadableStream::callPullIfNeeded()
203 { 268 {
204 if (m_isPulling || m_isDraining || !m_isStarted || m_state == Closed || m_st ate == Errored) 269 if (m_isPulling || m_isDraining || !m_isStarted || m_state == Closed || m_st ate == Errored)
205 return; 270 return;
206 271
207 bool shouldApplyBackpressure = this->shouldApplyBackpressure(); 272 bool shouldApplyBackpressure = this->shouldApplyBackpressure();
208 // this->shouldApplyBackpressure may call this->error(). 273 // this->shouldApplyBackpressure may call this->error().
209 if (shouldApplyBackpressure || m_state == Errored) 274 if (shouldApplyBackpressure || m_state == Errored)
210 return; 275 return;
211 m_isPulling = true; 276 m_isPulling = true;
212 m_source->pullSource(); 277 m_source->pullSource();
213 } 278 }
214 279
215 bool ReadableStream::hasPendingActivity() const 280 bool ReadableStream::hasPendingActivity() const
216 { 281 {
217 return m_state == Waiting || m_state == Readable; 282 return m_state == Waiting || m_state == Readable;
218 } 283 }
219 284
220 void ReadableStream::trace(Visitor* visitor) 285 void ReadableStream::trace(Visitor* visitor)
221 { 286 {
222 visitor->trace(m_source); 287 visitor->trace(m_source);
223 visitor->trace(m_ready); 288 visitor->trace(m_ready);
224 visitor->trace(m_closed); 289 visitor->trace(m_closed);
225 visitor->trace(m_exception); 290 visitor->trace(m_exception);
291 visitor->trace(m_reader);
226 ActiveDOMObject::trace(visitor); 292 ActiveDOMObject::trace(visitor);
227 } 293 }
228 294
295 String ReadableStream::stateToString(State state)
296 {
297 switch (state) {
298 case Readable:
299 return "readable";
300 case Waiting:
301 return "waiting";
302 case Closed:
303 return "closed";
304 case Errored:
305 return "errored";
306 }
307 ASSERT(false);
308 return String();
309 }
310
229 } // namespace blink 311 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698