| Index: Source/core/dom/Future.cpp
|
| diff --git a/Source/core/dom/Future.cpp b/Source/core/dom/Future.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..109e84ed48b7cfccea95ea8d0e42beee58d6f442
|
| --- /dev/null
|
| +++ b/Source/core/dom/Future.cpp
|
| @@ -0,0 +1,300 @@
|
| +/*
|
| + * Copyright (C) 2013 Google Inc. All rights reserved.
|
| + *
|
| + * Redistribution and use in source and binary forms, with or without
|
| + * modification, are permitted provided that the following conditions are
|
| + * met:
|
| + *
|
| + * * Redistributions of source code must retain the above copyright
|
| + * notice, this list of conditions and the following disclaimer.
|
| + * * Redistributions in binary form must reproduce the above
|
| + * copyright notice, this list of conditions and the following disclaimer
|
| + * in the documentation and/or other materials provided with the
|
| + * distribution.
|
| + * * Neither the name of Google Inc. nor the names of its
|
| + * contributors may be used to endorse or promote products derived from
|
| + * this software without specific prior written permission.
|
| + *
|
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
| + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| + */
|
| +
|
| +#include "config.h"
|
| +
|
| +#include "core/dom/Future.h"
|
| +
|
| +#include "bindings/v8/V8Utilities.h"
|
| +#include "core/dom/AnyCallback.h"
|
| +#include "core/platform/Logging.h"
|
| +
|
| +namespace WebCore {
|
| +
|
| +namespace {
|
| +
|
| +class ProcessAcceptCallbacksTask : public ScriptExecutionContext::Task {
|
| +public:
|
| + static PassOwnPtr<ProcessAcceptCallbacksTask> create(PassRefPtr<Future> future, const ScriptValue& value)
|
| + {
|
| + return adoptPtr(new ProcessAcceptCallbacksTask(future, value));
|
| + }
|
| +
|
| + virtual void performTask(ScriptExecutionContext*) OVERRIDE
|
| + {
|
| + LOG(Network, "ProcessAcceptCallbacksTask::performTask %d", m_future.get()->refCount());
|
| + m_future->processAcceptCallbacks(m_value);
|
| + }
|
| +
|
| +private:
|
| + ProcessAcceptCallbacksTask(PassRefPtr<Future> future, const ScriptValue& value)
|
| + : m_future(future)
|
| + , m_value(value)
|
| + {
|
| + }
|
| +
|
| + RefPtr<Future> m_future;
|
| + ScriptValue m_value;
|
| +};
|
| +
|
| +class ProcessRejectCallbacksTask : public ScriptExecutionContext::Task {
|
| +public:
|
| + static PassOwnPtr<ProcessRejectCallbacksTask> create(PassRefPtr<Future> future, const ScriptValue& value)
|
| + {
|
| + return adoptPtr(new ProcessRejectCallbacksTask(future, value));
|
| + }
|
| +
|
| + virtual void performTask(ScriptExecutionContext*) OVERRIDE
|
| + {
|
| + LOG(Network, "ProcessRejectCallbacksTask::performTask %d", m_future.get()->refCount());
|
| +
|
| + m_future->processRejectCallbacks(m_value);
|
| + }
|
| +
|
| +private:
|
| + ProcessRejectCallbacksTask(PassRefPtr<Future> future, const ScriptValue& value)
|
| + : m_future(future)
|
| + , m_value(value)
|
| + {
|
| + }
|
| +
|
| + RefPtr<Future> m_future;
|
| + ScriptValue m_value;
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| +PassRefPtr<Future> Future::create()
|
| +{
|
| + LOG(Network, "Future::create start");
|
| +
|
| + ScriptExecutionContext* context = getScriptExecutionContext();
|
| +
|
| + RefPtr<Future> future = adoptRef(new Future(context));
|
| +
|
| + RefPtr<FutureResolver> resolver = FutureResolver::create(future);
|
| + future->setResolver(resolver);
|
| +
|
| + return future;
|
| +}
|
| +
|
| +PassRefPtr<Future> Future::createAndRunInit(PassRefPtr<FutureInit> init)
|
| +{
|
| + RefPtr<Future> future = Future::create();
|
| +
|
| + LOG(Network, "Future::create call init start %d", future->refCount());
|
| +
|
| + RefPtr<FutureResolver> resolver = future->getResolver();
|
| +
|
| + ScriptExecutionContext* context = getScriptExecutionContext();
|
| +
|
| + // Pass future as this as specified in the spec.
|
| + ScriptValue result = init->call(resolver, future, context);
|
| + if (!result.hasNoValue())
|
| + resolver->rejectInternal(result, false);
|
| +
|
| + LOG(Network, "Future::create call init done");
|
| +
|
| + return future;
|
| +}
|
| +
|
| +Future::Future(ScriptExecutionContext* context)
|
| + : ActiveDOMObject(context)
|
| + , m_state(Pending)
|
| +{
|
| + LOG(Network, "Future::Future start %d", refCount());
|
| +
|
| + suspendIfNeeded();
|
| +}
|
| +
|
| +Future::~Future()
|
| +{
|
| + LOG(Network, "Future dtor");
|
| +}
|
| +
|
| +PassRefPtr<Future> Future::accept(const ScriptValue& value)
|
| +{
|
| + RefPtr<Future> future = Future::create();
|
| + future->getResolver()->accept(value);
|
| +
|
| + LOG(Network, "Future::accept end %d", future->refCount());
|
| +
|
| + return future;
|
| +}
|
| +
|
| +PassRefPtr<Future> Future::resolve(const ScriptValue& value)
|
| +{
|
| + return 0;
|
| +}
|
| +
|
| +PassRefPtr<Future> Future::reject(const ScriptValue& value)
|
| +{
|
| + RefPtr<Future> future = Future::create();
|
| + future->getResolver()->reject(value);
|
| +
|
| + return future;
|
| +}
|
| +
|
| +PassRefPtr<Future> Future::anyof(Vector<ScriptValue>& values)
|
| +{
|
| + return 0;
|
| +}
|
| +
|
| +PassRefPtr<Future> Future::every(Vector<ScriptValue>& values)
|
| +{
|
| + return 0;
|
| +}
|
| +
|
| +PassRefPtr<Future> Future::some(Vector<ScriptValue>& values)
|
| +{
|
| + return 0;
|
| +}
|
| +
|
| +void Future::FutureCallback::invoke(const ScriptValue& value)
|
| +{
|
| + LOG(Network, "invoke %d", m_algorithm);
|
| +
|
| + bool exceptionThrown = false;
|
| + switch (m_algorithm) {
|
| + case NoAlgorithm:
|
| + m_callback->call(value, 0, &exceptionThrown);
|
| + break;
|
| + case WrapperAlgorithm:
|
| + ASSERT(m_callback);
|
| + {
|
| + ScriptValue result = m_callback->call(value, m_resolver->getFuture(), &exceptionThrown);
|
| + if (exceptionThrown)
|
| + m_resolver->rejectInternal(result, true);
|
| + // FIXME
|
| + // else
|
| + // m_resolver->resolveInternal(result, true);
|
| + else
|
| + m_resolver->acceptInternal(result, true);
|
| + }
|
| + break;
|
| + case AcceptAlgorithm:
|
| + m_resolver->acceptInternal(value, true);
|
| + break;
|
| + case ResolveAlgorithm:
|
| + // FIXME
|
| + // m_resolver->resolveInternal(value, true);
|
| + break;
|
| + case RejectAlgorithm:
|
| + m_resolver->rejectInternal(value, true);
|
| + break;
|
| + }
|
| +}
|
| +
|
| +void Future::appendCallbacks(PassRefPtr<FutureCallback> acceptCallback, PassRefPtr<FutureCallback> rejectCallback)
|
| +{
|
| + m_acceptCallbacks.append(acceptCallback);
|
| +
|
| + m_rejectCallbacks.append(rejectCallback);
|
| +
|
| + if (m_state == Accepted)
|
| + queueProcessAcceptCallbacksTask(m_result);
|
| +
|
| + if (m_state == Rejected)
|
| + queueProcessRejectCallbacksTask(m_result);
|
| +}
|
| +
|
| +PassRefPtr<Future> Future::then(PassRefPtr<AnyCallback> acceptCallback, PassRefPtr<AnyCallback> rejectCallback)
|
| +{
|
| + RefPtr<Future> newFuture = Future::create();
|
| +
|
| + RefPtr<FutureResolver> newResolver = newFuture->getResolver();
|
| +
|
| + FutureCallback::Algorithm algorithmForAccept = FutureCallback::AcceptAlgorithm;
|
| + if (acceptCallback)
|
| + algorithmForAccept = FutureCallback::WrapperAlgorithm;
|
| + RefPtr<FutureCallback> acceptFutureCallback = FutureCallback::create(algorithmForAccept, newResolver, acceptCallback);
|
| +
|
| + FutureCallback::Algorithm algorithmForReject = FutureCallback::RejectAlgorithm;
|
| + if (rejectCallback)
|
| + algorithmForReject = FutureCallback::WrapperAlgorithm;
|
| + RefPtr<FutureCallback> rejectFutureCallback = FutureCallback::create(algorithmForReject, newResolver, rejectCallback);
|
| +
|
| + appendCallbacks(acceptFutureCallback, rejectFutureCallback);
|
| +
|
| + return newFuture;
|
| +}
|
| +
|
| +void Future::then(PassRefPtr<Future> future)
|
| +{
|
| + ScriptExecutionContext* context = getScriptExecutionContext();
|
| +
|
| + RefPtr<FutureResolver> resolver = future->getResolver();
|
| +
|
| + FutureCallback::Algorithm algorithmForAccept = FutureCallback::AcceptAlgorithm;
|
| + RefPtr<FutureCallback> acceptFutureCallback = FutureCallback::create(algorithmForAccept, resolver, 0);
|
| +
|
| + FutureCallback::Algorithm algorithmForReject = FutureCallback::RejectAlgorithm;
|
| + RefPtr<FutureCallback> rejectFutureCallback = FutureCallback::create(algorithmForReject, resolver, 0);
|
| +
|
| + appendCallbacks(acceptFutureCallback, rejectFutureCallback);
|
| +}
|
| +
|
| +void Future::done(PassRefPtr<AnyCallback> acceptCallback, PassRefPtr<AnyCallback> rejectCallback)
|
| +{
|
| + RefPtr<FutureCallback> acceptFutureCallback = FutureCallback::create(FutureCallback::NoAlgorithm, 0, acceptCallback);
|
| + RefPtr<FutureCallback> rejectFutureCallback = FutureCallback::create(FutureCallback::NoAlgorithm, 0, rejectCallback);
|
| + appendCallbacks(acceptFutureCallback, rejectFutureCallback);
|
| +}
|
| +
|
| +void Future::processAcceptCallbacks(const ScriptValue& value)
|
| +{
|
| + LOG(Network, "processAcceptCallbacks %d", refCount());
|
| +
|
| + for (int i = 0; i < m_acceptCallbacks.size(); ++i)
|
| + m_acceptCallbacks[i]->invoke(value);
|
| +
|
| + m_acceptCallbacks.clear();
|
| +}
|
| +
|
| +void Future::queueProcessAcceptCallbacksTask(const ScriptValue& value)
|
| +{
|
| + getScriptExecutionContext()->postTask(ProcessAcceptCallbacksTask::create(this, value));
|
| +}
|
| +
|
| +void Future::processRejectCallbacks(const ScriptValue& value)
|
| +{
|
| + LOG(Network, "processRejectCallbacks");
|
| +
|
| + for (int i = 0; i < m_rejectCallbacks.size(); ++i)
|
| + m_rejectCallbacks[i]->invoke(value);
|
| + m_rejectCallbacks.clear();
|
| +}
|
| +
|
| +void Future::queueProcessRejectCallbacksTask(const ScriptValue& value)
|
| +{
|
| + getScriptExecutionContext()->postTask(ProcessRejectCallbacksTask::create(this, value));
|
| +}
|
| +
|
| +} // namespace WebCore
|
|
|