| OLD | NEW |
| (Empty) |
| 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. | |
| 4 | |
| 5 #ifndef SKY_ENGINE_BINDINGS_CORE_V8_SCRIPTPROMISERESOLVER_H_ | |
| 6 #define SKY_ENGINE_BINDINGS_CORE_V8_SCRIPTPROMISERESOLVER_H_ | |
| 7 | |
| 8 #include "sky/engine/bindings/core/v8/ScopedPersistent.h" | |
| 9 #include "sky/engine/bindings/core/v8/ScriptPromise.h" | |
| 10 #include "sky/engine/bindings/core/v8/ScriptState.h" | |
| 11 #include "sky/engine/bindings/core/v8/V8Binding.h" | |
| 12 #include "sky/engine/core/dom/ActiveDOMObject.h" | |
| 13 #include "sky/engine/core/dom/ExecutionContext.h" | |
| 14 #include "sky/engine/platform/Timer.h" | |
| 15 #include "sky/engine/wtf/RefCounted.h" | |
| 16 #include "v8/include/v8.h" | |
| 17 | |
| 18 namespace blink { | |
| 19 | |
| 20 // This class wraps v8::Promise::Resolver and provides the following | |
| 21 // functionalities. | |
| 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 | |
| 27 // will be ignored. | |
| 28 class ScriptPromiseResolver : public ActiveDOMObject, public RefCounted<ScriptPr
omiseResolver> { | |
| 29 WTF_MAKE_NONCOPYABLE(ScriptPromiseResolver); | |
| 30 | |
| 31 public: | |
| 32 static PassRefPtr<ScriptPromiseResolver> create(ScriptState* scriptState) | |
| 33 { | |
| 34 RefPtr<ScriptPromiseResolver> resolver = adoptRef(new ScriptPromiseResol
ver(scriptState)); | |
| 35 resolver->suspendIfNeeded(); | |
| 36 return resolver.release(); | |
| 37 } | |
| 38 | |
| 39 virtual ~ScriptPromiseResolver() | |
| 40 { | |
| 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); | |
| 46 } | |
| 47 | |
| 48 // Anything that can be passed to toV8Value can be passed to this function. | |
| 49 template <typename T> | |
| 50 void resolve(T value) | |
| 51 { | |
| 52 resolveOrReject(value, Resolving); | |
| 53 } | |
| 54 | |
| 55 // Anything that can be passed to toV8Value can be passed to this function. | |
| 56 template <typename T> | |
| 57 void reject(T value) | |
| 58 { | |
| 59 resolveOrReject(value, Rejecting); | |
| 60 } | |
| 61 | |
| 62 void resolve() { resolve(V8UndefinedType()); } | |
| 63 void reject() { reject(V8UndefinedType()); } | |
| 64 | |
| 65 ScriptState* scriptState() { return m_scriptState.get(); } | |
| 66 | |
| 67 // Note that an empty ScriptPromise will be returned after resolve or | |
| 68 // reject is called. | |
| 69 ScriptPromise promise() | |
| 70 { | |
| 71 #if ENABLE(ASSERT) | |
| 72 m_isPromiseCalled = true; | |
| 73 #endif | |
| 74 return m_resolver.promise(); | |
| 75 } | |
| 76 | |
| 77 ScriptState* scriptState() const { return m_scriptState.get(); } | |
| 78 | |
| 79 // ActiveDOMObject implementation. | |
| 80 virtual void suspend() override; | |
| 81 virtual void resume() override; | |
| 82 virtual void stop() override; | |
| 83 | |
| 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(); | |
| 87 | |
| 88 protected: | |
| 89 // You need to call suspendIfNeeded after the construction because | |
| 90 // this is an ActiveDOMObject. | |
| 91 explicit ScriptPromiseResolver(ScriptState*); | |
| 92 | |
| 93 private: | |
| 94 typedef ScriptPromise::InternalResolver Resolver; | |
| 95 enum ResolutionState { | |
| 96 Pending, | |
| 97 Resolving, | |
| 98 Rejecting, | |
| 99 ResolvedOrRejected, | |
| 100 }; | |
| 101 enum LifetimeMode { | |
| 102 Default, | |
| 103 KeepAliveWhilePending, | |
| 104 }; | |
| 105 | |
| 106 template<typename T> | |
| 107 v8::Handle<v8::Value> toV8Value(const T& value) | |
| 108 { | |
| 109 return V8ValueTraits<T>::toV8Value(value, m_scriptState->context()->Glob
al(), m_scriptState->isolate()); | |
| 110 } | |
| 111 | |
| 112 template <typename T> | |
| 113 void resolveOrReject(T value, ResolutionState newState) | |
| 114 { | |
| 115 if (m_state != Pending || !executionContext() || executionContext()->act
iveDOMObjectsAreStopped()) | |
| 116 return; | |
| 117 ASSERT(newState == Resolving || newState == Rejecting); | |
| 118 m_state = newState; | |
| 119 // Retain this object until it is actually resolved or rejected. | |
| 120 // |deref| will be called in |clear|. | |
| 121 ref(); | |
| 122 | |
| 123 ScriptState::Scope scope(m_scriptState.get()); | |
| 124 m_value.set(m_scriptState->isolate(), toV8Value(value)); | |
| 125 if (!executionContext()->activeDOMObjectsAreSuspended()) | |
| 126 resolveOrRejectImmediately(); | |
| 127 } | |
| 128 | |
| 129 void resolveOrRejectImmediately(); | |
| 130 void onTimerFired(Timer<ScriptPromiseResolver>*); | |
| 131 void clear(); | |
| 132 | |
| 133 ResolutionState m_state; | |
| 134 const RefPtr<ScriptState> m_scriptState; | |
| 135 LifetimeMode m_mode; | |
| 136 Timer<ScriptPromiseResolver> m_timer; | |
| 137 Resolver m_resolver; | |
| 138 ScopedPersistent<v8::Value> m_value; | |
| 139 #if ENABLE(ASSERT) | |
| 140 // True if promise() is called. | |
| 141 bool m_isPromiseCalled; | |
| 142 #endif | |
| 143 }; | |
| 144 | |
| 145 } // namespace blink | |
| 146 | |
| 147 #endif // SKY_ENGINE_BINDINGS_CORE_V8_SCRIPTPROMISERESOLVER_H_ | |
| OLD | NEW |