OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/ReadableStreamReader.h" | 6 #include "core/streams/ReadableStreamReader.h" |
7 | 7 |
8 #include "bindings/core/v8/ExceptionState.h" | 8 #include "bindings/core/v8/ExceptionState.h" |
9 #include "bindings/core/v8/ScriptState.h" | 9 #include "bindings/core/v8/ScriptState.h" |
10 #include "bindings/core/v8/ToV8.h" | 10 #include "bindings/core/v8/ToV8.h" |
11 #include "bindings/core/v8/V8ThrowException.h" | 11 #include "bindings/core/v8/V8ThrowException.h" |
12 #include "core/dom/DOMException.h" | 12 #include "core/dom/DOMException.h" |
13 #include "core/dom/Document.h" | 13 #include "core/dom/Document.h" |
14 #include "core/dom/ExceptionCode.h" | 14 #include "core/dom/ExceptionCode.h" |
15 #include "core/streams/ReadableStream.h" | 15 #include "core/streams/ReadableStream.h" |
16 #include "core/streams/ReadableStreamImpl.h" | 16 #include "core/streams/ReadableStreamImpl.h" |
17 #include "core/streams/UnderlyingSource.h" | 17 #include "core/streams/UnderlyingSource.h" |
18 #include "core/testing/DummyPageHolder.h" | 18 #include "core/testing/DummyPageHolder.h" |
19 #include <gtest/gtest.h> | 19 #include <gtest/gtest.h> |
20 | 20 |
21 namespace blink { | 21 namespace blink { |
22 | 22 |
23 using StringStream = ReadableStreamImpl<ReadableStreamChunkTypeTraits<String>>; | 23 using StringStream = ReadableStreamImpl<ReadableStreamChunkTypeTraits<String>>; |
24 | 24 |
25 namespace { | 25 namespace { |
26 | 26 |
| 27 struct ReadResult { |
| 28 ReadResult() : isDone(false), isSet(false) { } |
| 29 |
| 30 String valueString; |
| 31 bool isDone; |
| 32 bool isSet; |
| 33 }; |
| 34 |
27 class StringCapturingFunction final : public ScriptFunction { | 35 class StringCapturingFunction final : public ScriptFunction { |
28 public: | 36 public: |
29 static v8::Handle<v8::Function> createFunction(ScriptState* scriptState, Str
ing* value) | 37 static v8::Handle<v8::Function> createFunction(ScriptState* scriptState, Str
ing* value) |
30 { | 38 { |
31 StringCapturingFunction* self = new StringCapturingFunction(scriptState,
value); | 39 StringCapturingFunction* self = new StringCapturingFunction(scriptState,
value); |
32 return self->bindToV8Function(); | 40 return self->bindToV8Function(); |
33 } | 41 } |
34 | 42 |
35 private: | 43 private: |
36 StringCapturingFunction(ScriptState* scriptState, String* value) | 44 StringCapturingFunction(ScriptState* scriptState, String* value) |
37 : ScriptFunction(scriptState) | 45 : ScriptFunction(scriptState) |
38 , m_value(value) | 46 , m_value(value) |
39 { | 47 { |
40 } | 48 } |
41 | 49 |
42 ScriptValue call(ScriptValue value) override | 50 ScriptValue call(ScriptValue value) override |
43 { | 51 { |
44 ASSERT(!value.isEmpty()); | 52 ASSERT(!value.isEmpty()); |
45 *m_value = toCoreString(value.v8Value()->ToString(scriptState()->isolate
())); | 53 *m_value = toCoreString(value.v8Value()->ToString(scriptState()->isolate
())); |
46 return value; | 54 return value; |
47 } | 55 } |
48 | 56 |
49 String* m_value; | 57 String* m_value; |
50 }; | 58 }; |
51 | 59 |
| 60 class ReadResultCapturingFunction final : public ScriptFunction { |
| 61 public: |
| 62 static v8::Handle<v8::Function> createFunction(ScriptState* scriptState, Rea
dResult* value) |
| 63 { |
| 64 ReadResultCapturingFunction* self = new ReadResultCapturingFunction(scri
ptState, value); |
| 65 return self->bindToV8Function(); |
| 66 } |
| 67 |
| 68 private: |
| 69 ReadResultCapturingFunction(ScriptState* scriptState, ReadResult* value) |
| 70 : ScriptFunction(scriptState) |
| 71 , m_result(value) |
| 72 { |
| 73 } |
| 74 |
| 75 ScriptValue call(ScriptValue result) override |
| 76 { |
| 77 ASSERT(!result.isEmpty()); |
| 78 v8::Isolate* isolate = scriptState()->isolate(); |
| 79 if (!result.isObject()) { |
| 80 return result; |
| 81 } |
| 82 v8::Local<v8::Object> object = result.v8Value().As<v8::Object>(); |
| 83 v8::Local<v8::String> doneString = v8String(isolate, "done"); |
| 84 v8::Local<v8::String> valueString = v8String(isolate, "value"); |
| 85 v8::Local<v8::Context> context = scriptState()->context(); |
| 86 v8::Maybe<bool> hasDone = object->Has(context, doneString); |
| 87 v8::Maybe<bool> hasValue = object->Has(context, valueString); |
| 88 |
| 89 if (hasDone.IsNothing() || !hasDone.FromJust() || hasValue.IsNothing() |
| !hasValue.FromJust()) { |
| 90 return result; |
| 91 } |
| 92 |
| 93 v8::Local<v8::Value> done; |
| 94 v8::Local<v8::Value> value; |
| 95 |
| 96 if (!object->Get(context, doneString).ToLocal(&done) || !object->Get(con
text, valueString).ToLocal(&value) || !done->IsBoolean()) { |
| 97 return result; |
| 98 } |
| 99 |
| 100 m_result->isSet = true; |
| 101 m_result->isDone = done.As<v8::Boolean>()->Value(); |
| 102 m_result->valueString = toCoreString(value->ToString(isolate)); |
| 103 |
| 104 return result; |
| 105 } |
| 106 |
| 107 ReadResult* m_result; |
| 108 }; |
| 109 |
52 class NoopUnderlyingSource final : public GarbageCollectedFinalized<NoopUnderlyi
ngSource>, public UnderlyingSource { | 110 class NoopUnderlyingSource final : public GarbageCollectedFinalized<NoopUnderlyi
ngSource>, public UnderlyingSource { |
53 USING_GARBAGE_COLLECTED_MIXIN(NoopUnderlyingSource); | 111 USING_GARBAGE_COLLECTED_MIXIN(NoopUnderlyingSource); |
54 public: | 112 public: |
55 ~NoopUnderlyingSource() override { } | 113 ~NoopUnderlyingSource() override { } |
56 | 114 |
57 void pullSource() override { } | 115 void pullSource() override { } |
58 ScriptPromise cancelSource(ScriptState* scriptState, ScriptValue reason) { r
eturn ScriptPromise::cast(scriptState, reason); } | 116 ScriptPromise cancelSource(ScriptState* scriptState, ScriptValue reason) { r
eturn ScriptPromise::cast(scriptState, reason); } |
59 DEFINE_INLINE_VIRTUAL_TRACE() { UnderlyingSource::trace(visitor); } | 117 DEFINE_INLINE_VIRTUAL_TRACE() { UnderlyingSource::trace(visitor); } |
60 }; | 118 }; |
61 | 119 |
62 class PermissiveStrategy final : public StringStream::Strategy { | 120 class PermissiveStrategy final : public StringStream::Strategy { |
63 public: | 121 public: |
64 bool shouldApplyBackpressure(size_t, ReadableStream*) override { return fals
e; } | 122 bool shouldApplyBackpressure(size_t, ReadableStream*) override { return fals
e; } |
65 }; | 123 }; |
66 | 124 |
67 class ReadableStreamReaderTest : public ::testing::Test { | 125 class ReadableStreamReaderTest : public ::testing::Test { |
68 public: | 126 public: |
69 ReadableStreamReaderTest() | 127 ReadableStreamReaderTest() |
70 : m_page(DummyPageHolder::create(IntSize(1, 1))) | 128 : m_page(DummyPageHolder::create(IntSize(1, 1))) |
71 , m_scope(scriptState()) | 129 , m_scope(scriptState()) |
72 , m_exceptionState(ExceptionState::ConstructionContext, "property", "int
erface", scriptState()->context()->Global(), isolate()) | 130 , m_exceptionState(ExceptionState::ConstructionContext, "property", "int
erface", scriptState()->context()->Global(), isolate()) |
73 , m_stream(new StringStream(scriptState()->executionContext(), new NoopU
nderlyingSource, new PermissiveStrategy)) | 131 , m_stream(new StringStream(scriptState()->executionContext(), new NoopU
nderlyingSource, new PermissiveStrategy)) |
74 { | 132 { |
75 m_stream->didSourceStart(); | 133 m_stream->didSourceStart(); |
76 } | 134 } |
77 | 135 |
78 ~ReadableStreamReaderTest() | 136 ~ReadableStreamReaderTest() override |
79 { | 137 { |
| 138 EXPECT_FALSE(m_exceptionState.hadException()); |
| 139 |
80 // We need to call |error| in order to make | 140 // We need to call |error| in order to make |
81 // ActiveDOMObject::hasPendingActivity return false. | 141 // ActiveDOMObject::hasPendingActivity return false. |
82 m_stream->error(DOMException::create(AbortError, "done")); | 142 m_stream->error(DOMException::create(AbortError, "done")); |
83 } | 143 } |
84 | 144 |
85 ScriptState* scriptState() { return ScriptState::forMainWorld(m_page->docume
nt().frame()); } | 145 ScriptState* scriptState() { return ScriptState::forMainWorld(m_page->docume
nt().frame()); } |
86 v8::Isolate* isolate() { return scriptState()->isolate(); } | 146 v8::Isolate* isolate() { return scriptState()->isolate(); } |
87 | 147 |
88 v8::Handle<v8::Function> createCaptor(String* value) | 148 v8::Handle<v8::Function> createCaptor(String* value) |
89 { | 149 { |
90 return StringCapturingFunction::createFunction(scriptState(), value); | 150 return StringCapturingFunction::createFunction(scriptState(), value); |
91 } | 151 } |
92 | 152 |
| 153 v8::Handle<v8::Function> createResultCaptor(ReadResult* value) |
| 154 { |
| 155 return ReadResultCapturingFunction::createFunction(scriptState(), value)
; |
| 156 } |
| 157 |
93 OwnPtr<DummyPageHolder> m_page; | 158 OwnPtr<DummyPageHolder> m_page; |
94 ScriptState::Scope m_scope; | 159 ScriptState::Scope m_scope; |
95 ExceptionState m_exceptionState; | 160 ExceptionState m_exceptionState; |
96 Persistent<StringStream> m_stream; | 161 Persistent<StringStream> m_stream; |
97 }; | 162 }; |
98 | 163 |
99 TEST_F(ReadableStreamReaderTest, Construct) | 164 TEST_F(ReadableStreamReaderTest, Construct) |
100 { | 165 { |
101 ReadableStreamReader* reader = new ReadableStreamReader(m_stream); | 166 ReadableStreamReader* reader = new ReadableStreamReader(m_stream); |
102 EXPECT_TRUE(reader->isActive()); | 167 EXPECT_TRUE(reader->isActive()); |
103 } | 168 } |
104 | 169 |
105 TEST_F(ReadableStreamReaderTest, Release) | 170 TEST_F(ReadableStreamReaderTest, Release) |
106 { | 171 { |
| 172 String onFulfilled, onRejected; |
107 ReadableStreamReader* reader = new ReadableStreamReader(m_stream); | 173 ReadableStreamReader* reader = new ReadableStreamReader(m_stream); |
108 EXPECT_TRUE(reader->isActive()); | 174 EXPECT_TRUE(reader->isActive()); |
109 reader->releaseLock(); | 175 |
| 176 reader->closed(scriptState()).then(createCaptor(&onFulfilled), createCaptor(
&onRejected)); |
| 177 reader->releaseLock(m_exceptionState); |
110 EXPECT_FALSE(reader->isActive()); | 178 EXPECT_FALSE(reader->isActive()); |
| 179 EXPECT_FALSE(m_exceptionState.hadException()); |
| 180 |
| 181 EXPECT_TRUE(onFulfilled.isNull()); |
| 182 EXPECT_TRUE(onRejected.isNull()); |
| 183 |
| 184 isolate()->RunMicrotasks(); |
| 185 EXPECT_EQ("undefined", onFulfilled); |
| 186 EXPECT_TRUE(onRejected.isNull()); |
111 | 187 |
112 ReadableStreamReader* another = new ReadableStreamReader(m_stream); | 188 ReadableStreamReader* another = new ReadableStreamReader(m_stream); |
113 EXPECT_TRUE(another->isActive()); | 189 EXPECT_TRUE(another->isActive()); |
114 EXPECT_FALSE(reader->isActive()); | 190 EXPECT_FALSE(reader->isActive()); |
115 reader->releaseLock(); | 191 reader->releaseLock(m_exceptionState); |
116 EXPECT_TRUE(another->isActive()); | 192 EXPECT_TRUE(another->isActive()); |
117 EXPECT_FALSE(reader->isActive()); | 193 EXPECT_FALSE(reader->isActive()); |
| 194 EXPECT_FALSE(m_exceptionState.hadException()); |
118 } | 195 } |
119 | 196 |
120 TEST_F(ReadableStreamReaderTest, MaskState) | 197 TEST_F(ReadableStreamReaderTest, ReadAfterRelease) |
| 198 { |
| 199 ReadableStreamReader* reader = new ReadableStreamReader(m_stream); |
| 200 EXPECT_TRUE(reader->isActive()); |
| 201 reader->releaseLock(m_exceptionState); |
| 202 EXPECT_FALSE(m_exceptionState.hadException()); |
| 203 EXPECT_FALSE(reader->isActive()); |
| 204 |
| 205 ReadResult result; |
| 206 String onRejected; |
| 207 reader->read(scriptState()).then(createResultCaptor(&result), createCaptor(&
onRejected)); |
| 208 |
| 209 EXPECT_FALSE(result.isSet); |
| 210 EXPECT_TRUE(onRejected.isNull()); |
| 211 isolate()->RunMicrotasks(); |
| 212 |
| 213 EXPECT_TRUE(result.isSet); |
| 214 EXPECT_TRUE(result.isDone); |
| 215 EXPECT_EQ("undefined", result.valueString); |
| 216 EXPECT_TRUE(onRejected.isNull()); |
| 217 } |
| 218 |
| 219 TEST_F(ReadableStreamReaderTest, ReleaseShouldFailWhenCalledWhileReading) |
| 220 { |
| 221 ReadableStreamReader* reader = new ReadableStreamReader(m_stream); |
| 222 EXPECT_TRUE(reader->isActive()); |
| 223 reader->read(scriptState()); |
| 224 |
| 225 reader->releaseLock(m_exceptionState); |
| 226 EXPECT_TRUE(reader->isActive()); |
| 227 EXPECT_TRUE(m_exceptionState.hadException()); |
| 228 m_exceptionState.clearException(); |
| 229 |
| 230 m_stream->enqueue("hello"); |
| 231 reader->releaseLock(m_exceptionState); |
| 232 EXPECT_FALSE(reader->isActive()); |
| 233 EXPECT_FALSE(m_exceptionState.hadException()); |
| 234 } |
| 235 |
| 236 TEST_F(ReadableStreamReaderTest, EnqueueThenRead) |
121 { | 237 { |
122 m_stream->enqueue("hello"); | 238 m_stream->enqueue("hello"); |
123 EXPECT_EQ("readable", m_stream->stateString()); | 239 m_stream->enqueue("world"); |
| 240 ReadableStreamReader* reader = new ReadableStreamReader(m_stream); |
| 241 EXPECT_EQ(ReadableStream::Readable, m_stream->stateInternal()); |
124 | 242 |
125 ReadableStreamReader* reader = new ReadableStreamReader(m_stream); | 243 ReadResult result; |
126 EXPECT_EQ("waiting", m_stream->stateString()); | 244 String onRejected; |
127 EXPECT_EQ("readable", reader->state()); | 245 reader->read(scriptState()).then(createResultCaptor(&result), createCaptor(&
onRejected)); |
128 | 246 |
129 reader->releaseLock(); | 247 EXPECT_FALSE(result.isSet); |
130 EXPECT_EQ("readable", m_stream->stateString()); | 248 EXPECT_TRUE(onRejected.isNull()); |
131 EXPECT_EQ("closed", reader->state()); | |
132 | 249 |
133 ReadableStreamReader* another = new ReadableStreamReader(m_stream); | 250 isolate()->RunMicrotasks(); |
134 EXPECT_EQ("waiting", m_stream->stateString()); | 251 |
135 EXPECT_EQ("closed", reader->state()); | 252 EXPECT_TRUE(result.isSet); |
136 EXPECT_EQ("readable", another->state()); | 253 EXPECT_FALSE(result.isDone); |
| 254 EXPECT_EQ("hello", result.valueString); |
| 255 EXPECT_TRUE(onRejected.isNull()); |
| 256 |
| 257 ReadResult result2; |
| 258 String onRejected2; |
| 259 reader->read(scriptState()).then(createResultCaptor(&result2), createCaptor(
&onRejected2)); |
| 260 |
| 261 EXPECT_FALSE(result2.isSet); |
| 262 EXPECT_TRUE(onRejected2.isNull()); |
| 263 |
| 264 isolate()->RunMicrotasks(); |
| 265 |
| 266 EXPECT_TRUE(result2.isSet); |
| 267 EXPECT_FALSE(result2.isDone); |
| 268 EXPECT_EQ("world", result2.valueString); |
| 269 EXPECT_TRUE(onRejected2.isNull()); |
137 } | 270 } |
138 | 271 |
139 TEST_F(ReadableStreamReaderTest, MaskReady) | 272 TEST_F(ReadableStreamReaderTest, ReadThenEnqueue) |
140 { | 273 { |
| 274 ReadableStreamReader* reader = new ReadableStreamReader(m_stream); |
| 275 EXPECT_EQ(ReadableStream::Readable, m_stream->stateInternal()); |
| 276 |
| 277 ReadResult result, result2; |
| 278 String onRejected, onRejected2; |
| 279 reader->read(scriptState()).then(createResultCaptor(&result), createCaptor(&
onRejected)); |
| 280 reader->read(scriptState()).then(createResultCaptor(&result2), createCaptor(
&onRejected2)); |
| 281 |
| 282 EXPECT_FALSE(result.isSet); |
| 283 EXPECT_TRUE(onRejected.isNull()); |
| 284 EXPECT_FALSE(result2.isSet); |
| 285 EXPECT_TRUE(onRejected2.isNull()); |
| 286 |
| 287 isolate()->RunMicrotasks(); |
| 288 |
| 289 EXPECT_FALSE(result.isSet); |
| 290 EXPECT_TRUE(onRejected.isNull()); |
| 291 EXPECT_FALSE(result2.isSet); |
| 292 EXPECT_TRUE(onRejected2.isNull()); |
| 293 |
141 m_stream->enqueue("hello"); | 294 m_stream->enqueue("hello"); |
142 isolate()->RunMicrotasks(); | 295 isolate()->RunMicrotasks(); |
143 | 296 |
144 ReadableStreamReader* reader = new ReadableStreamReader(m_stream); | 297 EXPECT_TRUE(result.isSet); |
145 { | 298 EXPECT_FALSE(result.isDone); |
146 String s1, s2; | 299 EXPECT_EQ("hello", result.valueString); |
147 reader->ready(scriptState()).then(createCaptor(&s1)); | 300 EXPECT_TRUE(onRejected.isNull()); |
148 m_stream->ready(scriptState()).then(createCaptor(&s2)); | 301 EXPECT_FALSE(result2.isSet); |
149 isolate()->RunMicrotasks(); | 302 EXPECT_TRUE(onRejected2.isNull()); |
150 EXPECT_EQ("undefined", s1); | |
151 EXPECT_TRUE(s2.isNull()); | |
152 | 303 |
153 reader->releaseLock(); | 304 m_stream->enqueue("world"); |
154 isolate()->RunMicrotasks(); | 305 isolate()->RunMicrotasks(); |
155 EXPECT_EQ("undefined", s2); | |
156 } | |
157 | 306 |
158 { | 307 EXPECT_TRUE(result2.isSet); |
159 String s1, s2; | 308 EXPECT_FALSE(result2.isDone); |
160 reader->ready(scriptState()).then(createCaptor(&s1)); | 309 EXPECT_EQ("world", result2.valueString); |
161 m_stream->ready(scriptState()).then(createCaptor(&s2)); | 310 EXPECT_TRUE(onRejected2.isNull()); |
162 isolate()->RunMicrotasks(); | |
163 EXPECT_EQ("undefined", s1); | |
164 EXPECT_EQ("undefined", s2); | |
165 } | |
166 | |
167 ReadableStreamReader* another = new ReadableStreamReader(m_stream); | |
168 { | |
169 String s1, s2, s3; | |
170 reader->ready(scriptState()).then(createCaptor(&s1)); | |
171 m_stream->ready(scriptState()).then(createCaptor(&s2)); | |
172 another->ready(scriptState()).then(createCaptor(&s3)); | |
173 isolate()->RunMicrotasks(); | |
174 EXPECT_EQ("undefined", s1); | |
175 EXPECT_TRUE(s2.isNull()); | |
176 EXPECT_EQ("undefined", s3); | |
177 | |
178 // We need to call here to ensure all promises having captors are | |
179 // resolved or rejected. | |
180 m_stream->error(DOMException::create(AbortError, "done")); | |
181 isolate()->RunMicrotasks(); | |
182 } | |
183 } | |
184 | |
185 TEST_F(ReadableStreamReaderTest, ReaderRead) | |
186 { | |
187 m_stream->enqueue("hello"); | |
188 ReadableStreamReader* reader = new ReadableStreamReader(m_stream); | |
189 | |
190 EXPECT_EQ(ReadableStream::Readable, m_stream->stateInternal()); | |
191 ScriptValue value = reader->read(scriptState(), m_exceptionState); | |
192 | |
193 EXPECT_FALSE(m_exceptionState.hadException()); | |
194 String stringValue; | |
195 EXPECT_TRUE(value.toString(stringValue)); | |
196 EXPECT_EQ("hello", stringValue); | |
197 } | |
198 | |
199 TEST_F(ReadableStreamReaderTest, StreamReadShouldFailWhenLocked) | |
200 { | |
201 m_stream->enqueue("hello"); | |
202 ReadableStreamReader* reader = new ReadableStreamReader(m_stream); | |
203 EXPECT_TRUE(reader->isActive()); | |
204 | |
205 EXPECT_EQ(ReadableStream::Readable, m_stream->stateInternal()); | |
206 m_stream->read(scriptState(), m_exceptionState); | |
207 | |
208 EXPECT_TRUE(m_exceptionState.hadException()); | |
209 EXPECT_EQ(ReadableStream::Readable, m_stream->stateInternal()); | |
210 } | |
211 | |
212 TEST_F(ReadableStreamReaderTest, ReaderReadShouldFailWhenNotLocked) | |
213 { | |
214 m_stream->enqueue("hello"); | |
215 ReadableStreamReader* reader = new ReadableStreamReader(m_stream); | |
216 reader->releaseLock(); | |
217 EXPECT_FALSE(reader->isActive()); | |
218 | |
219 EXPECT_EQ(ReadableStream::Readable, m_stream->stateInternal()); | |
220 reader->read(scriptState(), m_exceptionState); | |
221 | |
222 EXPECT_TRUE(m_exceptionState.hadException()); | |
223 EXPECT_EQ(ReadableStream::Readable, m_stream->stateInternal()); | |
224 } | 311 } |
225 | 312 |
226 TEST_F(ReadableStreamReaderTest, ClosedReader) | 313 TEST_F(ReadableStreamReaderTest, ClosedReader) |
227 { | 314 { |
228 ReadableStreamReader* reader = new ReadableStreamReader(m_stream); | 315 ReadableStreamReader* reader = new ReadableStreamReader(m_stream); |
229 | 316 |
230 m_stream->close(); | 317 m_stream->close(); |
231 | 318 |
232 EXPECT_EQ("closed", m_stream->stateString()); | |
233 EXPECT_EQ("closed", reader->state()); | |
234 EXPECT_FALSE(reader->isActive()); | 319 EXPECT_FALSE(reader->isActive()); |
235 | 320 |
236 String onClosedFulfilled, onClosedRejected; | 321 String onClosedFulfilled, onClosedRejected; |
237 String onReadyFulfilled, onReadyRejected; | 322 ReadResult result; |
| 323 String onReadRejected; |
238 isolate()->RunMicrotasks(); | 324 isolate()->RunMicrotasks(); |
239 reader->closed(scriptState()).then(createCaptor(&onClosedFulfilled), createC
aptor(&onClosedRejected)); | 325 reader->closed(scriptState()).then(createCaptor(&onClosedFulfilled), createC
aptor(&onClosedRejected)); |
240 reader->ready(scriptState()).then(createCaptor(&onReadyFulfilled), createCap
tor(&onReadyRejected)); | 326 reader->read(scriptState()).then(createResultCaptor(&result), createCaptor(&
onReadRejected)); |
241 EXPECT_TRUE(onClosedFulfilled.isNull()); | 327 EXPECT_TRUE(onClosedFulfilled.isNull()); |
242 EXPECT_TRUE(onClosedRejected.isNull()); | 328 EXPECT_TRUE(onClosedRejected.isNull()); |
243 EXPECT_TRUE(onReadyFulfilled.isNull()); | 329 EXPECT_FALSE(result.isSet); |
244 EXPECT_TRUE(onReadyRejected.isNull()); | 330 EXPECT_TRUE(onReadRejected.isNull()); |
245 | 331 |
246 isolate()->RunMicrotasks(); | 332 isolate()->RunMicrotasks(); |
247 EXPECT_EQ("undefined", onClosedFulfilled); | 333 EXPECT_EQ("undefined", onClosedFulfilled); |
248 EXPECT_TRUE(onClosedRejected.isNull()); | 334 EXPECT_TRUE(onClosedRejected.isNull()); |
249 EXPECT_EQ("undefined", onReadyFulfilled); | 335 EXPECT_TRUE(result.isSet); |
250 EXPECT_TRUE(onReadyRejected.isNull()); | 336 EXPECT_TRUE(result.isDone); |
| 337 EXPECT_EQ("undefined", result.valueString); |
| 338 EXPECT_TRUE(onReadRejected.isNull()); |
251 } | 339 } |
252 | 340 |
253 TEST_F(ReadableStreamReaderTest, ErroredReader) | 341 TEST_F(ReadableStreamReaderTest, ErroredReader) |
254 { | 342 { |
255 ReadableStreamReader* reader = new ReadableStreamReader(m_stream); | 343 ReadableStreamReader* reader = new ReadableStreamReader(m_stream); |
256 | 344 |
257 m_stream->error(DOMException::create(SyntaxError, "some error")); | 345 m_stream->error(DOMException::create(SyntaxError, "some error")); |
258 | 346 |
259 EXPECT_EQ("errored", m_stream->stateString()); | 347 EXPECT_EQ(ReadableStream::Errored, m_stream->stateInternal()); |
260 EXPECT_EQ("errored", reader->state()); | |
261 EXPECT_FALSE(reader->isActive()); | 348 EXPECT_FALSE(reader->isActive()); |
262 | 349 |
263 String onClosedFulfilled, onClosedRejected; | 350 String onClosedFulfilled, onClosedRejected; |
264 String onReadyFulfilled, onReadyRejected; | 351 String onReadFulfilled, onReadRejected; |
| 352 isolate()->RunMicrotasks(); |
265 reader->closed(scriptState()).then(createCaptor(&onClosedFulfilled), createC
aptor(&onClosedRejected)); | 353 reader->closed(scriptState()).then(createCaptor(&onClosedFulfilled), createC
aptor(&onClosedRejected)); |
266 reader->ready(scriptState()).then(createCaptor(&onReadyFulfilled), createCap
tor(&onReadyRejected)); | 354 reader->read(scriptState()).then(createCaptor(&onReadFulfilled), createCapto
r(&onReadRejected)); |
267 EXPECT_TRUE(onClosedFulfilled.isNull()); | 355 EXPECT_TRUE(onClosedFulfilled.isNull()); |
268 EXPECT_TRUE(onClosedRejected.isNull()); | 356 EXPECT_TRUE(onClosedRejected.isNull()); |
269 EXPECT_TRUE(onReadyFulfilled.isNull()); | 357 EXPECT_TRUE(onReadFulfilled.isNull()); |
270 EXPECT_TRUE(onReadyRejected.isNull()); | 358 EXPECT_TRUE(onReadRejected.isNull()); |
271 | 359 |
272 isolate()->RunMicrotasks(); | 360 isolate()->RunMicrotasks(); |
273 EXPECT_TRUE(onClosedFulfilled.isNull()); | 361 EXPECT_TRUE(onClosedFulfilled.isNull()); |
274 EXPECT_EQ("SyntaxError: some error", onClosedRejected); | 362 EXPECT_EQ("SyntaxError: some error", onClosedRejected); |
275 EXPECT_EQ("undefined", onReadyFulfilled); | 363 EXPECT_TRUE(onReadFulfilled.isNull()); |
276 EXPECT_TRUE(onReadyRejected.isNull()); | 364 EXPECT_EQ("SyntaxError: some error", onReadRejected); |
277 } | 365 } |
278 | 366 |
279 TEST_F(ReadableStreamReaderTest, ReadyPromiseShouldNotBeResolvedWhenLocked) | 367 TEST_F(ReadableStreamReaderTest, PendingReadsShouldBeResolvedWhenClosed) |
280 { | 368 { |
281 String s; | 369 ReadableStreamReader* reader = new ReadableStreamReader(m_stream); |
282 ScriptPromise ready = m_stream->ready(scriptState()); | 370 EXPECT_EQ(ReadableStream::Readable, m_stream->stateInternal()); |
283 ready.then(createCaptor(&s)); | 371 |
284 isolate()->RunMicrotasks(); | 372 ReadResult result, result2; |
285 EXPECT_TRUE(s.isNull()); | 373 String onRejected, onRejected2; |
286 | 374 reader->read(scriptState()).then(createResultCaptor(&result), createCaptor(&
onRejected)); |
287 ReadableStreamReader* reader = new ReadableStreamReader(m_stream); | 375 reader->read(scriptState()).then(createResultCaptor(&result2), createCaptor(
&onRejected2)); |
288 EXPECT_TRUE(reader->isActive()); | 376 |
289 EXPECT_NE(ready, m_stream->ready(scriptState())); | 377 isolate()->RunMicrotasks(); |
290 | 378 EXPECT_FALSE(result.isSet); |
291 isolate()->RunMicrotasks(); | 379 EXPECT_TRUE(onRejected.isNull()); |
292 EXPECT_TRUE(s.isNull()); | 380 EXPECT_FALSE(result2.isSet); |
293 | 381 EXPECT_TRUE(onRejected2.isNull()); |
294 // We need to call here to ensure all promises having captors are resolved | 382 |
295 // or rejected. | |
296 m_stream->error(DOMException::create(AbortError, "done")); | |
297 isolate()->RunMicrotasks(); | |
298 } | |
299 | |
300 TEST_F(ReadableStreamReaderTest, ReaderShouldBeReleasedWhenClosed) | |
301 { | |
302 ReadableStreamReader* reader = new ReadableStreamReader(m_stream); | |
303 EXPECT_TRUE(reader->isActive()); | |
304 m_stream->close(); | 383 m_stream->close(); |
305 EXPECT_FALSE(reader->isActive()); | 384 EXPECT_FALSE(result.isSet); |
306 } | 385 EXPECT_TRUE(onRejected.isNull()); |
307 | 386 EXPECT_FALSE(result2.isSet); |
308 TEST_F(ReadableStreamReaderTest, ReaderShouldBeReleasedWhenCanceled) | 387 EXPECT_TRUE(onRejected2.isNull()); |
309 { | 388 |
310 ReadableStreamReader* reader = new ReadableStreamReader(m_stream); | 389 isolate()->RunMicrotasks(); |
311 EXPECT_TRUE(reader->isActive()); | 390 |
| 391 EXPECT_TRUE(result.isSet); |
| 392 EXPECT_TRUE(result.isDone); |
| 393 EXPECT_EQ("undefined", result.valueString); |
| 394 EXPECT_TRUE(onRejected.isNull()); |
| 395 |
| 396 EXPECT_TRUE(result2.isSet); |
| 397 EXPECT_TRUE(result2.isDone); |
| 398 EXPECT_EQ("undefined", result2.valueString); |
| 399 EXPECT_TRUE(onRejected2.isNull()); |
| 400 } |
| 401 |
| 402 TEST_F(ReadableStreamReaderTest, PendingReadsShouldBeRejectedWhenErrored) |
| 403 { |
| 404 ReadableStreamReader* reader = new ReadableStreamReader(m_stream); |
| 405 EXPECT_EQ(ReadableStream::Readable, m_stream->stateInternal()); |
| 406 |
| 407 String onFulfilled, onFulfilled2; |
| 408 String onRejected, onRejected2; |
| 409 reader->read(scriptState()).then(createCaptor(&onFulfilled), createCaptor(&o
nRejected)); |
| 410 reader->read(scriptState()).then(createCaptor(&onFulfilled2), createCaptor(&
onRejected2)); |
| 411 |
| 412 isolate()->RunMicrotasks(); |
| 413 EXPECT_TRUE(onFulfilled.isNull()); |
| 414 EXPECT_TRUE(onRejected.isNull()); |
| 415 EXPECT_TRUE(onFulfilled2.isNull()); |
| 416 EXPECT_TRUE(onRejected2.isNull()); |
| 417 |
| 418 m_stream->error(DOMException::create(SyntaxError, "some error")); |
| 419 EXPECT_TRUE(onFulfilled.isNull()); |
| 420 EXPECT_TRUE(onRejected.isNull()); |
| 421 EXPECT_TRUE(onFulfilled2.isNull()); |
| 422 EXPECT_TRUE(onRejected2.isNull()); |
| 423 |
| 424 isolate()->RunMicrotasks(); |
| 425 |
| 426 EXPECT_TRUE(onFulfilled.isNull()); |
| 427 EXPECT_EQ(onRejected, "SyntaxError: some error"); |
| 428 EXPECT_TRUE(onFulfilled2.isNull()); |
| 429 EXPECT_EQ(onRejected2, "SyntaxError: some error"); |
| 430 } |
| 431 |
| 432 TEST_F(ReadableStreamReaderTest, PendingReadsShouldBeResolvedWhenCanceled) |
| 433 { |
| 434 ReadableStreamReader* reader = new ReadableStreamReader(m_stream); |
| 435 EXPECT_EQ(ReadableStream::Readable, m_stream->stateInternal()); |
| 436 |
| 437 ReadResult result, result2; |
| 438 String onRejected, onRejected2; |
| 439 reader->read(scriptState()).then(createResultCaptor(&result), createCaptor(&
onRejected)); |
| 440 reader->read(scriptState()).then(createResultCaptor(&result2), createCaptor(
&onRejected2)); |
| 441 |
| 442 isolate()->RunMicrotasks(); |
| 443 EXPECT_FALSE(result.isSet); |
| 444 EXPECT_TRUE(onRejected.isNull()); |
| 445 EXPECT_FALSE(result2.isSet); |
| 446 EXPECT_TRUE(onRejected2.isNull()); |
| 447 |
312 reader->cancel(scriptState(), ScriptValue(scriptState(), v8::Undefined(isola
te()))); | 448 reader->cancel(scriptState(), ScriptValue(scriptState(), v8::Undefined(isola
te()))); |
313 EXPECT_FALSE(reader->isActive()); | 449 EXPECT_FALSE(reader->isActive()); |
314 } | 450 EXPECT_FALSE(result.isSet); |
315 | 451 EXPECT_TRUE(onRejected.isNull()); |
316 TEST_F(ReadableStreamReaderTest, ReaderShouldBeReleasedWhenErrored) | 452 EXPECT_FALSE(result2.isSet); |
317 { | 453 EXPECT_TRUE(onRejected2.isNull()); |
318 ReadableStreamReader* reader = new ReadableStreamReader(m_stream); | 454 |
319 EXPECT_TRUE(reader->isActive()); | 455 isolate()->RunMicrotasks(); |
| 456 |
| 457 EXPECT_TRUE(result.isSet); |
| 458 EXPECT_TRUE(result.isDone); |
| 459 EXPECT_EQ("undefined", result.valueString); |
| 460 EXPECT_TRUE(onRejected.isNull()); |
| 461 |
| 462 EXPECT_TRUE(result2.isSet); |
| 463 EXPECT_TRUE(result2.isDone); |
| 464 EXPECT_EQ("undefined", result2.valueString); |
| 465 EXPECT_TRUE(onRejected2.isNull()); |
| 466 } |
| 467 |
| 468 TEST_F(ReadableStreamReaderTest, CancelShouldNotWorkWhenNotActive) |
| 469 { |
| 470 ReadableStreamReader* reader = new ReadableStreamReader(m_stream); |
| 471 reader->releaseLock(m_exceptionState); |
| 472 EXPECT_FALSE(reader->isActive()); |
| 473 |
| 474 String onFulfilled, onRejected; |
| 475 reader->cancel(scriptState(), ScriptValue(scriptState(), v8::Undefined(isola
te()))).then(createCaptor(&onFulfilled), createCaptor(&onRejected)); |
| 476 EXPECT_EQ(ReadableStream::Readable, m_stream->stateInternal()); |
| 477 |
| 478 EXPECT_TRUE(onFulfilled.isNull()); |
| 479 EXPECT_TRUE(onRejected.isNull()); |
| 480 |
| 481 isolate()->RunMicrotasks(); |
| 482 |
| 483 EXPECT_EQ("undefined", onFulfilled); |
| 484 EXPECT_TRUE(onRejected.isNull()); |
| 485 EXPECT_EQ(ReadableStream::Readable, m_stream->stateInternal()); |
| 486 } |
| 487 |
| 488 TEST_F(ReadableStreamReaderTest, Cancel) |
| 489 { |
| 490 ReadableStreamReader* reader = new ReadableStreamReader(m_stream); |
| 491 EXPECT_EQ(ReadableStream::Readable, m_stream->stateInternal()); |
| 492 |
| 493 String onClosedFulfilled, onClosedRejected; |
| 494 String onCancelFulfilled, onCancelRejected; |
| 495 reader->closed(scriptState()).then(createCaptor(&onClosedFulfilled), createC
aptor(&onClosedRejected)); |
| 496 reader->cancel(scriptState(), ScriptValue(scriptState(), v8::Undefined(isola
te()))).then(createCaptor(&onCancelFulfilled), createCaptor(&onCancelRejected)); |
| 497 |
| 498 EXPECT_EQ(ReadableStream::Closed, m_stream->stateInternal()); |
| 499 EXPECT_TRUE(onClosedFulfilled.isNull()); |
| 500 EXPECT_TRUE(onClosedRejected.isNull()); |
| 501 EXPECT_TRUE(onCancelFulfilled.isNull()); |
| 502 EXPECT_TRUE(onCancelRejected.isNull()); |
| 503 |
| 504 isolate()->RunMicrotasks(); |
| 505 EXPECT_EQ("undefined", onClosedFulfilled); |
| 506 EXPECT_TRUE(onClosedRejected.isNull()); |
| 507 EXPECT_EQ("undefined", onCancelFulfilled); |
| 508 EXPECT_TRUE(onCancelRejected.isNull()); |
| 509 } |
| 510 |
| 511 TEST_F(ReadableStreamReaderTest, Close) |
| 512 { |
| 513 ReadableStreamReader* reader = new ReadableStreamReader(m_stream); |
| 514 EXPECT_EQ(ReadableStream::Readable, m_stream->stateInternal()); |
| 515 |
| 516 String onFulfilled, onRejected; |
| 517 reader->closed(scriptState()).then(createCaptor(&onFulfilled), createCaptor(
&onRejected)); |
| 518 |
| 519 m_stream->close(); |
| 520 |
| 521 EXPECT_EQ(ReadableStream::Closed, m_stream->stateInternal()); |
| 522 EXPECT_TRUE(onFulfilled.isNull()); |
| 523 EXPECT_TRUE(onRejected.isNull()); |
| 524 |
| 525 isolate()->RunMicrotasks(); |
| 526 EXPECT_EQ("undefined", onFulfilled); |
| 527 EXPECT_TRUE(onRejected.isNull()); |
| 528 } |
| 529 |
| 530 TEST_F(ReadableStreamReaderTest, Error) |
| 531 { |
| 532 ReadableStreamReader* reader = new ReadableStreamReader(m_stream); |
| 533 EXPECT_EQ(ReadableStream::Readable, m_stream->stateInternal()); |
| 534 |
| 535 String onFulfilled, onRejected; |
| 536 reader->closed(scriptState()).then(createCaptor(&onFulfilled), createCaptor(
&onRejected)); |
| 537 |
320 m_stream->error(DOMException::create(SyntaxError, "some error")); | 538 m_stream->error(DOMException::create(SyntaxError, "some error")); |
321 EXPECT_FALSE(reader->isActive()); | 539 |
322 } | 540 EXPECT_EQ(ReadableStream::Errored, m_stream->stateInternal()); |
323 | 541 EXPECT_TRUE(onFulfilled.isNull()); |
324 TEST_F(ReadableStreamReaderTest, StreamCancelShouldFailWhenLocked) | 542 EXPECT_TRUE(onRejected.isNull()); |
325 { | 543 |
326 ReadableStreamReader* reader = new ReadableStreamReader(m_stream); | 544 isolate()->RunMicrotasks(); |
327 EXPECT_TRUE(reader->isActive()); | 545 EXPECT_TRUE(onFulfilled.isNull()); |
328 ScriptPromise p = m_stream->cancel(scriptState(), ScriptValue(scriptState(),
v8::Undefined(isolate()))); | 546 EXPECT_EQ("SyntaxError: some error", onRejected); |
329 EXPECT_EQ(ReadableStream::Waiting, m_stream->stateInternal()); | |
330 String onFulfilled, onRejected; | |
331 p.then(createCaptor(&onFulfilled), createCaptor(&onRejected)); | |
332 | |
333 EXPECT_TRUE(onFulfilled.isNull()); | |
334 EXPECT_TRUE(onRejected.isNull()); | |
335 isolate()->RunMicrotasks(); | |
336 EXPECT_TRUE(onFulfilled.isNull()); | |
337 EXPECT_EQ("TypeError: this stream is locked to a ReadableStreamReader", onRe
jected); | |
338 } | |
339 | |
340 TEST_F(ReadableStreamReaderTest, ReaderCancelShouldNotWorkWhenNotActive) | |
341 { | |
342 ReadableStreamReader* reader = new ReadableStreamReader(m_stream); | |
343 reader->releaseLock(); | |
344 EXPECT_FALSE(reader->isActive()); | |
345 | |
346 ScriptPromise p = reader->cancel(scriptState(), ScriptValue(scriptState(), v
8::Undefined(isolate()))); | |
347 EXPECT_EQ(ReadableStream::Waiting, m_stream->stateInternal()); | |
348 String onFulfilled, onRejected; | |
349 p.then(createCaptor(&onFulfilled), createCaptor(&onRejected)); | |
350 | |
351 EXPECT_TRUE(onFulfilled.isNull()); | |
352 EXPECT_TRUE(onRejected.isNull()); | |
353 isolate()->RunMicrotasks(); | |
354 EXPECT_EQ("undefined", onFulfilled); | |
355 EXPECT_TRUE(onRejected.isNull()); | |
356 } | |
357 | |
358 TEST_F(ReadableStreamReaderTest, ReadyShouldNotBeResolvedWhileLocked) | |
359 { | |
360 String onFulfilled; | |
361 m_stream->ready(scriptState()).then(createCaptor(&onFulfilled)); | |
362 | |
363 ReadableStreamReader* reader = new ReadableStreamReader(m_stream); | |
364 | |
365 m_stream->enqueue("hello"); | |
366 m_stream->enqueue("world"); | |
367 | |
368 ASSERT_EQ("readable", reader->state()); | |
369 reader->read(scriptState(), m_exceptionState); | |
370 ASSERT_EQ("readable", reader->state()); | |
371 reader->read(scriptState(), m_exceptionState); | |
372 ASSERT_EQ("waiting", reader->state()); | |
373 | |
374 isolate()->RunMicrotasks(); | |
375 EXPECT_TRUE(onFulfilled.isNull()); | |
376 | |
377 // We need to call here to ensure all promises having captors are resolved | |
378 // or rejected. | |
379 m_stream->error(DOMException::create(AbortError, "done")); | |
380 isolate()->RunMicrotasks(); | |
381 } | |
382 | |
383 TEST_F(ReadableStreamReaderTest, ReadyShouldNotBeResolvedWhenReleasedIfNotReady) | |
384 { | |
385 String onFulfilled; | |
386 m_stream->ready(scriptState()).then(createCaptor(&onFulfilled)); | |
387 | |
388 ReadableStreamReader* reader = new ReadableStreamReader(m_stream); | |
389 | |
390 m_stream->enqueue("hello"); | |
391 m_stream->enqueue("world"); | |
392 | |
393 ASSERT_EQ("readable", reader->state()); | |
394 reader->read(scriptState(), m_exceptionState); | |
395 ASSERT_EQ("readable", reader->state()); | |
396 reader->read(scriptState(), m_exceptionState); | |
397 ASSERT_EQ("waiting", reader->state()); | |
398 | |
399 reader->releaseLock(); | |
400 | |
401 isolate()->RunMicrotasks(); | |
402 EXPECT_TRUE(onFulfilled.isNull()); | |
403 | |
404 // We need to call here to ensure all promises having captors are resolved | |
405 // or rejected. | |
406 m_stream->error(DOMException::create(AbortError, "done")); | |
407 isolate()->RunMicrotasks(); | |
408 } | |
409 | |
410 TEST_F(ReadableStreamReaderTest, ReadyShouldBeResolvedWhenReleasedIfReady) | |
411 { | |
412 String onFulfilled; | |
413 m_stream->ready(scriptState()).then(createCaptor(&onFulfilled)); | |
414 | |
415 ReadableStreamReader* reader = new ReadableStreamReader(m_stream); | |
416 | |
417 m_stream->enqueue("hello"); | |
418 m_stream->enqueue("world"); | |
419 | |
420 ASSERT_EQ("readable", reader->state()); | |
421 reader->read(scriptState(), m_exceptionState); | |
422 ASSERT_EQ("readable", reader->state()); | |
423 | |
424 isolate()->RunMicrotasks(); | |
425 reader->releaseLock(); | |
426 EXPECT_TRUE(onFulfilled.isNull()); | |
427 | |
428 isolate()->RunMicrotasks(); | |
429 EXPECT_EQ("undefined", onFulfilled); | |
430 } | 547 } |
431 | 548 |
432 } // namespace | 549 } // namespace |
433 | 550 |
434 } // namespace blink | 551 } // namespace blink |
OLD | NEW |