16f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch// Copyright 2014 The Chromium Authors. All rights reserved.
26f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
36f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch// found in the LICENSE file.
46f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch
56f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch#include "config.h"
66f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch#include "bindings/v8/ScriptPromiseResolverWithContext.h"
76f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch
8f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)#include "bindings/v8/V8RecursionScope.h"
9f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
106f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdochnamespace WebCore {
116f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch
12f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo LiuScriptPromiseResolverWithContext::ScriptPromiseResolverWithContext(ScriptState* scriptState)
136f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    : ActiveDOMObject(scriptState->executionContext())
146f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    , m_state(Pending)
156f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    , m_scriptState(scriptState)
165d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    , m_mode(Default)
17f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    , m_timer(this, &ScriptPromiseResolverWithContext::onTimerFired)
18323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    , m_resolver(ScriptPromiseResolver::create(m_scriptState.get()))
1976c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)#if ASSERTION_ENABLED
2076c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)    , m_isPromiseCalled(false)
2176c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)#endif
22323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles){
235d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    if (executionContext()->activeDOMObjectsAreStopped())
245d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        m_state = ResolvedOrRejected;
255d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)}
265d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
276f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdochvoid ScriptPromiseResolverWithContext::suspend()
286f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch{
296f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    m_timer.stop();
306f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch}
316f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch
326f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdochvoid ScriptPromiseResolverWithContext::resume()
336f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch{
346f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    if (m_state == Resolving || m_state == Rejecting)
356f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        m_timer.startOneShot(0, FROM_HERE);
366f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch}
376f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch
386f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdochvoid ScriptPromiseResolverWithContext::stop()
396f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch{
406f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    m_timer.stop();
416f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    clear();
426f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch}
436f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch
445d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)void ScriptPromiseResolverWithContext::keepAliveWhilePending()
455d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles){
465d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    if (m_state == ResolvedOrRejected || m_mode == KeepAliveWhilePending)
475d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        return;
485d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
495d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // Keep |this| while the promise is Pending.
505d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // deref() will be called in clear().
515d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    m_mode = KeepAliveWhilePending;
525d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    ref();
535d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)}
545d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)
55f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liuvoid ScriptPromiseResolverWithContext::onTimerFired(Timer<ScriptPromiseResolverWithContext>*)
56f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu{
57f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    ScriptState::Scope scope(m_scriptState.get());
58f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    resolveOrRejectImmediately();
59f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu}
60f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu
61f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liuvoid ScriptPromiseResolverWithContext::resolveOrRejectImmediately()
626f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch{
636f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    ASSERT(!executionContext()->activeDOMObjectsAreStopped());
646f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    ASSERT(!executionContext()->activeDOMObjectsAreSuspended());
65f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    {
66f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        // FIXME: The V8RecursionScope is only necessary to force microtask delivery for promises
67f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        // resolved or rejected in workers. It can be removed once worker threads run microtasks
68f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        // at the end of every task (rather than just the main thread).
69f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        V8RecursionScope scope(m_scriptState->isolate(), m_scriptState->executionContext());
70f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        if (m_state == Resolving) {
71f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            m_resolver->resolve(m_value.newLocal(m_scriptState->isolate()));
72f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        } else {
73f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            ASSERT(m_state == Rejecting);
74f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            m_resolver->reject(m_value.newLocal(m_scriptState->isolate()));
75f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)        }
766f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    }
776f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    clear();
786f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch}
796f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch
806f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdochvoid ScriptPromiseResolverWithContext::clear()
816f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch{
825d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    if (m_state == ResolvedOrRejected)
835d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        return;
84f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    ResolutionState state = m_state;
85f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    m_state = ResolvedOrRejected;
866f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    m_resolver.clear();
876f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    m_value.clear();
885d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    if (m_mode == KeepAliveWhilePending) {
8976c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)        // |ref| was called in |keepAliveWhilePending|.
905d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        deref();
915d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    }
925d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // |this| may be deleted here, but it is safe to check |state| because
935d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // it doesn't depend on |this|. When |this| is deleted, |state| can't be
945d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    // |Resolving| nor |Rejecting| and hence |this->deref()| can't be executed.
95f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    if (state == Resolving || state == Rejecting) {
96f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        // |ref| was called in |resolveOrReject|.
97f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        deref();
98f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    }
996f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch}
1006f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch
1016f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch} // namespace WebCore
102