1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef ScriptPromiseResolver_h
6 #define ScriptPromiseResolver_h
8 #include "bindings/core/v8/ScopedPersistent.h"
9 #include "bindings/core/v8/ScriptPromise.h"
10 #include "bindings/core/v8/ScriptState.h"
11 #include "bindings/core/v8/V8Binding.h"
12 #include "core/dom/ActiveDOMObject.h"
13 #include "core/dom/ExecutionContext.h"
14 #include "platform/Timer.h"
15 #include "wtf/RefCounted.h"
20 // This class wraps v8::Promise::Resolver and provides the following
22 // - A ScriptPromiseResolver retains a ScriptState. A caller
23 // can call resolve or reject from outside of a V8 context.
24 // - This class is an ActiveDOMObject and keeps track of the associated
25 // ExecutionContext state. When the ExecutionContext is suspended,
26 // resolve or reject will be delayed. When it is stopped, resolve or reject
28 class ScriptPromiseResolver : public ActiveDOMObject, public RefCounted<ScriptPromiseResolver> {
29 WTF_MAKE_NONCOPYABLE(ScriptPromiseResolver);
32 static PassRefPtr<ScriptPromiseResolver> create(ScriptState* scriptState)
34 RefPtr<ScriptPromiseResolver> resolver = adoptRef(new ScriptPromiseResolver(scriptState));
35 resolver->suspendIfNeeded();
36 return resolver.release();
39 virtual ~ScriptPromiseResolver()
41 // This assertion fails if:
42 // - promise() is called at least once and
43 // - this resolver is destructed before it is resolved, rejected or
44 // the associated ExecutionContext is stopped.
45 ASSERT(m_state == ResolvedOrRejected || !m_isPromiseCalled);
48 // Anything that can be passed to toV8Value can be passed to this function.
52 resolveOrReject(value, Resolving);
55 // Anything that can be passed to toV8Value can be passed to this function.
59 resolveOrReject(value, Rejecting);
62 void resolve() { resolve(V8UndefinedType()); }
63 void reject() { reject(V8UndefinedType()); }
65 ScriptState* scriptState() { return m_scriptState.get(); }
67 // Note that an empty ScriptPromise will be returned after resolve or
69 ScriptPromise promise()
72 m_isPromiseCalled = true;
74 return m_resolver.promise();
77 ScriptState* scriptState() const { return m_scriptState.get(); }
79 // ActiveDOMObject implementation.
80 virtual void suspend() override;
81 virtual void resume() override;
82 virtual void stop() override;
84 // Once this function is called this resolver stays alive while the
85 // promise is pending and the associated ExecutionContext isn't stopped.
86 void keepAliveWhilePending();
89 // You need to call suspendIfNeeded after the construction because
90 // this is an ActiveDOMObject.
91 explicit ScriptPromiseResolver(ScriptState*);
94 typedef ScriptPromise::InternalResolver Resolver;
95 enum ResolutionState {
103 KeepAliveWhilePending,
107 v8::Handle<v8::Value> toV8Value(const T& value)
109 return V8ValueTraits<T>::toV8Value(value, m_scriptState->context()->Global(), m_scriptState->isolate());
112 template <typename T>
113 void resolveOrReject(T value, ResolutionState newState)
115 if (m_state != Pending || !executionContext() || executionContext()->activeDOMObjectsAreStopped())
117 ASSERT(newState == Resolving || newState == Rejecting);
119 // Retain this object until it is actually resolved or rejected.
120 // |deref| will be called in |clear|.
123 ScriptState::Scope scope(m_scriptState.get());
124 m_value.set(m_scriptState->isolate(), toV8Value(value));
125 if (!executionContext()->activeDOMObjectsAreSuspended())
126 resolveOrRejectImmediately();
129 void resolveOrRejectImmediately();
130 void onTimerFired(Timer<ScriptPromiseResolver>*);
133 ResolutionState m_state;
134 const RefPtr<ScriptState> m_scriptState;
136 Timer<ScriptPromiseResolver> m_timer;
138 ScopedPersistent<v8::Value> m_value;
140 // True if promise() is called.
141 bool m_isPromiseCalled;
147 #endif // #ifndef ScriptPromiseResolver_h