1c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)// found in the LICENSE file.
4c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
5c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "config.h"
6c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "core/streams/ReadableStream.h"
7c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
8c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "bindings/core/v8/ExceptionState.h"
9c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "bindings/core/v8/ScriptFunction.h"
10c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "bindings/core/v8/ScriptPromiseResolver.h"
11c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "bindings/core/v8/V8Binding.h"
12c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "core/dom/DOMException.h"
13c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "core/dom/ExceptionCode.h"
14c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "core/dom/ExecutionContext.h"
15c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "core/streams/UnderlyingSource.h"
16c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
17c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
18c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
199e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)ReadableStream::ReadableStream(ExecutionContext* executionContext, UnderlyingSource* source)
209e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    : m_source(source)
21c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    , m_isStarted(false)
22c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    , m_isDraining(false)
23c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    , m_isPulling(false)
24c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    , m_isSchedulingPull(false)
25c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    , m_state(Waiting)
269e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    , m_wait(new WaitPromise(executionContext, this, WaitPromise::Ready))
279e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    , m_closed(new ClosedPromise(executionContext, this, ClosedPromise::Closed))
28c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){
29c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}
30c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
31c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)ReadableStream::~ReadableStream()
32c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){
33c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}
34c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
359e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)String ReadableStream::stateString() const
369e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles){
379e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    switch (m_state) {
389e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    case Readable:
399e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)        return "readable";
409e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    case Waiting:
419e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)        return "waiting";
429e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    case Closed:
439e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)        return "closed";
449e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    case Errored:
459e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)        return "errored";
469e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    }
479e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    ASSERT(false);
489e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    return String();
499e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)}
509e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)
51e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)bool ReadableStream::enqueuePreliminaryCheck(size_t chunkSize)
52c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){
53c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (m_state == Errored || m_state == Closed || m_isDraining)
54c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        return false;
55c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
56c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    // FIXME: Query strategy.
57e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    return true;
58e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)}
59c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
60e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)bool ReadableStream::enqueuePostAction(size_t totalQueueSize)
61e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles){
62c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    m_isPulling = false;
63c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
64c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    // FIXME: Set needsMore correctly.
65c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    bool needsMore = true;
66c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
67c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (m_state == Waiting) {
68c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        m_state = Readable;
69e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        m_wait->resolve(V8UndefinedType());
70c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    }
71c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
72c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    return needsMore;
73c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}
74c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
75c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void ReadableStream::close()
76c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){
77c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (m_state == Waiting) {
78e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        m_wait->resolve(V8UndefinedType());
79c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        m_closed->resolve(V8UndefinedType());
80c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        m_state = Closed;
81c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    } else if (m_state == Readable) {
82c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        m_isDraining = true;
83c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    }
84c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}
85c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
869e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)void ReadableStream::readPreliminaryCheck(ExceptionState& exceptionState)
87c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){
88c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (m_state == Waiting) {
899e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)        exceptionState.throwTypeError("read is called while state is waiting");
90e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        return;
91c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    }
92c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (m_state == Closed) {
939e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)        exceptionState.throwTypeError("read is called while state is closed");
94e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        return;
95c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    }
96c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (m_state == Errored) {
979e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)        exceptionState.throwDOMException(m_exception->code(), m_exception->message());
98e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        return;
99c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    }
100e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)}
101c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
102e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)void ReadableStream::readPostAction()
103e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles){
104c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    ASSERT(m_state == Readable);
105e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    if (isQueueEmpty()) {
106c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        if (m_isDraining) {
107c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            m_state = Closed;
108e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)            m_wait->reset();
109e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)            m_wait->resolve(V8UndefinedType());
110c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            m_closed->resolve(V8UndefinedType());
111c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        } else {
112c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            m_state = Waiting;
113e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)            m_wait->reset();
114c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            callOrSchedulePull();
115c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        }
116c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    }
117c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}
118c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
119c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)ScriptPromise ReadableStream::wait(ScriptState* scriptState)
120c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){
121c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (m_state == Waiting)
122c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        callOrSchedulePull();
123c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    return m_wait->promise(scriptState->world());
124c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}
125c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
126c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)ScriptPromise ReadableStream::cancel(ScriptState* scriptState, ScriptValue reason)
127c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){
128c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (m_state == Errored) {
129c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState);
130c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        ScriptPromise promise = resolver->promise();
131c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        resolver->reject(m_exception);
132c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        return promise;
133c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    }
134c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (m_state == Closed)
135c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        return ScriptPromise::cast(scriptState, v8::Undefined(scriptState->isolate()));
136c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
137c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (m_state == Waiting) {
138e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        m_wait->resolve(V8UndefinedType());
139c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    } else {
140c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        ASSERT(m_state == Readable);
141e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        m_wait->reset();
142e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        m_wait->resolve(V8UndefinedType());
143c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    }
144c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
145e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    clearQueue();
146c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    m_state = Closed;
147c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    m_closed->resolve(V8UndefinedType());
148c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    return m_source->cancelSource(scriptState, reason);
149c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}
150c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
151c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)ScriptPromise ReadableStream::closed(ScriptState* scriptState)
152c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){
153c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    return m_closed->promise(scriptState->world());
154c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}
155c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
156c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void ReadableStream::error(PassRefPtrWillBeRawPtr<DOMException> exception)
157c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){
158c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (m_state == Readable) {
159e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        clearQueue();
160e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        m_wait->reset();
161c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    }
162c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
163c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (m_state == Waiting || m_state == Readable) {
164c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        m_state = Errored;
165c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        m_exception = exception;
166c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        if (m_wait->state() == m_wait->Pending)
167c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            m_wait->reject(m_exception);
168c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        m_closed->reject(m_exception);
169c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    }
170c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}
171c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
1729e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)void ReadableStream::didSourceStart()
173c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){
174c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    m_isStarted = true;
175c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (m_isSchedulingPull)
176c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        m_source->pullSource();
177c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}
178c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
179c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void ReadableStream::callOrSchedulePull()
180c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){
181c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (m_isPulling)
182c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        return;
183c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    m_isPulling = true;
184c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (m_isStarted)
185c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        m_source->pullSource();
186c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    else
187c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        m_isSchedulingPull = true;
188c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}
189c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
190c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void ReadableStream::trace(Visitor* visitor)
191c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){
192c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    visitor->trace(m_source);
193c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    visitor->trace(m_wait);
194c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    visitor->trace(m_closed);
195c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    visitor->trace(m_exception);
196c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}
197c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
198c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink
199c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
200