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

Side by Side Diff: third_party/WebKit/Source/modules/fetch/ReadableStreamBytesConsumer.cpp

Issue 2365853002: Implement ReadableStreamBytesConsumer (Closed)
Patch Set: fix Created 4 years, 2 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
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "modules/fetch/ReadableStreamBytesConsumer.h"
6
7 #include "bindings/core/v8/ScopedPersistent.h"
8 #include "bindings/core/v8/ScriptFunction.h"
9 #include "bindings/core/v8/ScriptState.h"
10 #include "bindings/core/v8/ScriptValue.h"
11 #include "bindings/core/v8/V8BindingMacros.h"
12 #include "bindings/core/v8/V8IteratorResultValue.h"
13 #include "bindings/core/v8/V8Uint8Array.h"
14 #include "core/streams/ReadableStreamOperations.h"
15 #include "wtf/Assertions.h"
16 #include "wtf/text/WTFString.h"
17 #include <algorithm>
18 #include <string.h>
19 #include <v8.h>
20
21 namespace blink {
22
23 class ReadableStreamBytesConsumer::OnFulfilled final : public ScriptFunction {
24 public:
25 static v8::Local<v8::Function> createFunction(ScriptState* scriptState, Read ableStreamBytesConsumer* consumer)
26 {
27 return (new OnFulfilled(scriptState, consumer))->bindToV8Function();
28 }
29
30 ScriptValue call(ScriptValue v) override
31 {
32 bool done;
33 v8::Local<v8::Value> item = v.v8Value();
34 DCHECK(item->IsObject());
35 v8::Local<v8::Value> value = v8UnpackIteratorResult(v.getScriptState(), item.As<v8::Object>(), &done).ToLocalChecked();
36 if (done) {
37 m_consumer->onReadDone();
38 return v;
39 }
40 if (!value->IsUint8Array()) {
41 m_consumer->onRejected();
42 return ScriptValue();
43 }
44 m_consumer->onRead(V8Uint8Array::toImpl(value.As<v8::Object>()));
45 return v;
46 }
47
48 DEFINE_INLINE_TRACE()
49 {
50 visitor->trace(m_consumer);
51 ScriptFunction::trace(visitor);
52 }
53
54 private:
55 OnFulfilled(ScriptState* scriptState, ReadableStreamBytesConsumer* consumer)
56 : ScriptFunction(scriptState), m_consumer(consumer) {}
57
58 Member<ReadableStreamBytesConsumer> m_consumer;
59 };
60
61 class ReadableStreamBytesConsumer::OnRejected final : public ScriptFunction {
62 public:
63 static v8::Local<v8::Function> createFunction(ScriptState* scriptState, Read ableStreamBytesConsumer* consumer)
64 {
65 return (new OnRejected(scriptState, consumer))->bindToV8Function();
66 }
67
68 ScriptValue call(ScriptValue v) override
69 {
70 m_consumer->onRejected();
71 return v;
72 }
73
74 DEFINE_INLINE_TRACE()
75 {
76 visitor->trace(m_consumer);
77 ScriptFunction::trace(visitor);
78 }
79
80 private:
81 OnRejected(ScriptState* scriptState, ReadableStreamBytesConsumer* consumer)
82 : ScriptFunction(scriptState), m_consumer(consumer) {}
83
84 Member<ReadableStreamBytesConsumer> m_consumer;
85 };
86
87 ReadableStreamBytesConsumer::ReadableStreamBytesConsumer(ScriptState* scriptStat e, ScriptValue streamReader)
88 : m_reader(scriptState->isolate(), streamReader.v8Value())
89 , m_scriptState(scriptState)
90 {
91 m_reader.setPhantom();
92 }
93
94 ReadableStreamBytesConsumer::~ReadableStreamBytesConsumer()
95 {
96 }
97
98 BytesConsumer::Result ReadableStreamBytesConsumer::beginRead(const char** buffer , size_t* available)
99 {
100 *buffer = nullptr;
101 *available = 0;
102 if (m_state == PublicState::Errored)
103 return Result::Error;
104 if (m_state == PublicState::Closed)
105 return Result::Done;
106
107 if (m_pendingBuffer) {
108 DCHECK_LE(m_pendingOffset, m_pendingBuffer->length());
hiroshige 2016/09/30 06:35:14 This CL seems to allow 0-byte |m_pendingBuffer| wh
yhirano 2016/09/30 09:01:02 Because I think it's simpler.
hiroshige 2016/09/30 11:46:24 Acknowledged.
109 *buffer = reinterpret_cast<const char*>(m_pendingBuffer->data()) + m_pen dingOffset;
110 *available = m_pendingBuffer->length() - m_pendingOffset;
111 return Result::Ok;
112 }
113 if (!m_isReading) {
114 m_isReading = true;
115 ScriptState::Scope scope(m_scriptState.get());
116 ScriptValue reader(m_scriptState.get(), m_reader.newLocal(m_scriptState- >isolate()));
117 // The owner must retain the reader.
118 DCHECK(!reader.isEmpty());
119 ReadableStreamOperations::defaultReaderRead(
120 m_scriptState.get(), reader).then(
121 OnFulfilled::createFunction(m_scriptState.get(), this),
122 OnRejected::createFunction(m_scriptState.get(), this));
123 }
124 return Result::ShouldWait;
125 }
126
127 BytesConsumer::Result ReadableStreamBytesConsumer::endRead(size_t readSize)
128 {
129 DCHECK(m_pendingBuffer);
130 DCHECK_LE(m_pendingOffset + readSize, m_pendingBuffer->length());
131 m_pendingOffset += readSize;
132 if (m_pendingOffset == m_pendingBuffer->length()) {
hiroshige 2016/09/30 06:35:14 Using '>=' instead of '==' is more robust for buff
yhirano 2016/09/30 09:01:02 Done.
133 m_pendingBuffer = nullptr;
134 m_pendingOffset = 0;
135 }
136 return Result::Ok;
137 }
138
139 void ReadableStreamBytesConsumer::setClient(Client* client)
140 {
141 DCHECK(!m_client);
142 DCHECK(client);
143 m_client = client;
144 }
145
146 void ReadableStreamBytesConsumer::clearClient()
147 {
148 m_client = nullptr;
149 }
150
151 void ReadableStreamBytesConsumer::cancel()
152 {
153 if (m_state == PublicState::Closed || m_state == PublicState::Errored)
154 return;
155 m_state = PublicState::Closed;
156 clearClient();
157 m_reader.clear();
158 }
159
160 BytesConsumer::PublicState ReadableStreamBytesConsumer::getPublicState() const
161 {
162 return m_state;
163 }
164
165 BytesConsumer::Error ReadableStreamBytesConsumer::getError() const
166 {
167 return Error("Failed to read from a ReadableStream.");
168 }
169
170 DEFINE_TRACE(ReadableStreamBytesConsumer)
171 {
172 visitor->trace(m_client);
173 visitor->trace(m_pendingBuffer);
174 BytesConsumer::trace(visitor);
175 }
176
177 void ReadableStreamBytesConsumer::dispose()
178 {
179 m_reader.clear();
180 }
181
182 void ReadableStreamBytesConsumer::onRead(DOMUint8Array* buffer)
183 {
184 DCHECK(m_isReading);
185 DCHECK(buffer);
186 DCHECK(!m_pendingBuffer);
187 DCHECK(!m_pendingOffset);
188 m_isReading = false;
189 if (m_state == PublicState::Closed)
190 return;
191 DCHECK_EQ(m_state, PublicState::ReadableOrWaiting);
192 m_pendingBuffer = buffer;
193 if (m_client)
194 m_client->onStateChange();
195 }
196
197 void ReadableStreamBytesConsumer::onReadDone()
198 {
199 DCHECK(m_isReading);
200 DCHECK(!m_pendingBuffer);
201 m_isReading = false;
202 if (m_state == PublicState::Closed)
203 return;
204 DCHECK_EQ(m_state, PublicState::ReadableOrWaiting);
205 m_state = PublicState::Closed;
206 m_reader.clear();
207 Client* client = m_client;
208 clearClient();
209 if (client)
210 client->onStateChange();
211 }
212
213 void ReadableStreamBytesConsumer::onRejected()
214 {
215 DCHECK(m_isReading);
216 DCHECK(!m_pendingBuffer);
217 m_isReading = false;
218 if (m_state == PublicState::Closed)
219 return;
220 DCHECK_EQ(m_state, PublicState::ReadableOrWaiting);
221 m_state = PublicState::Errored;
222 m_reader.clear();
223 Client* client = m_client;
224 clearClient();
225 if (client)
226 client->onStateChange();
227 }
228
229 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698