| 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 an ReadableStreamReader", onR
ejected); | |
| 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 |