Index: Source/bindings/v8/ScriptPromiseResolverWithContext.h |
diff --git a/Source/bindings/v8/ScriptPromiseResolverWithContext.h b/Source/bindings/v8/ScriptPromiseResolverWithContext.h |
index 126b45b68d9bcc751b297b3172ce4aa07feb28bb..5dda8931fecb56f24f9bd72d1a514a8147050f92 100644 |
--- a/Source/bindings/v8/ScriptPromiseResolverWithContext.h |
+++ b/Source/bindings/v8/ScriptPromiseResolverWithContext.h |
@@ -27,6 +27,10 @@ namespace WebCore { |
// ExecutionContext state. When the ExecutionContext is suspended, |
// resolve or reject will be delayed. When it is stopped, resolve or reject |
// will be ignored. |
+// |
+// If you use ScriptPromiseResolverWithContext::resolve or reject from a |
+// non script execution environment, you should NOT enter a v8 context |
+// at the call site. |
class ScriptPromiseResolverWithContext FINAL : public ActiveDOMObject, public RefCounted<ScriptPromiseResolverWithContext> { |
WTF_MAKE_NONCOPYABLE(ScriptPromiseResolverWithContext); |
@@ -38,30 +42,20 @@ public: |
return resolver.release(); |
} |
+ virtual ~ScriptPromiseResolverWithContext(); |
+ |
// Anything that can be passed to toV8Value can be passed to this function. |
template <typename T> |
void resolve(T value) |
{ |
- if (m_state != Pending || !executionContext() || executionContext()->activeDOMObjectsAreStopped()) |
- return; |
- m_state = Resolving; |
- NewScriptState::Scope scope(m_scriptState.get()); |
- m_value.set(m_scriptState->isolate(), toV8Value(value)); |
- if (!executionContext()->activeDOMObjectsAreSuspended()) |
- resolveOrRejectImmediately(&m_timer); |
+ resolveOrReject(value, Resolving); |
} |
// Anything that can be passed to toV8Value can be passed to this function. |
template <typename T> |
void reject(T value) |
{ |
- if (m_state != Pending || !executionContext() || executionContext()->activeDOMObjectsAreStopped()) |
- return; |
- m_state = Rejecting; |
- NewScriptState::Scope scope(m_scriptState.get()); |
- m_value.set(m_scriptState->isolate(), toV8Value(value)); |
- if (!executionContext()->activeDOMObjectsAreSuspended()) |
- resolveOrRejectImmediately(&m_timer); |
+ resolveOrReject(value, Rejecting); |
} |
NewScriptState* scriptState() { return m_scriptState.get(); } |
@@ -81,6 +75,7 @@ public: |
virtual void stop() OVERRIDE; |
private: |
+ class RetainThis; |
jochen (gone - plz use gerrit)
2014/04/22 06:49:41
we'd usually just ref() and deref()
yhirano
2014/04/22 07:49:05
Done.
|
enum ResolutionState { |
Pending, |
Resolving, |
@@ -120,7 +115,29 @@ private: |
return v8ArrayNoInline(value, m_scriptState->isolate()); |
} |
- void resolveOrRejectImmediately(Timer<ScriptPromiseResolverWithContext>*); |
+ template <typename T> |
+ void resolveOrReject(T value, ResolutionState newState) |
+ { |
+ if (m_state != Pending || !executionContext() || executionContext()->activeDOMObjectsAreStopped()) |
+ return; |
+ m_state = newState; |
+ retainThis(); |
+ |
+ bool isInContext = m_scriptState->isolate()->InContext(); |
+ NewScriptState::Scope scope(m_scriptState.get()); |
+ m_value.set(m_scriptState->isolate(), toV8Value(value)); |
+ if (!executionContext()->activeDOMObjectsAreSuspended()) { |
+ if (isInContext) { |
+ resolveOrRejectImmediately(); |
+ } else { |
+ m_timer.startOneShot(0, FROM_HERE); |
+ } |
+ } |
+ } |
+ |
+ void resolveOrRejectImmediately(); |
+ void onTimerFired(Timer<ScriptPromiseResolverWithContext>*); |
+ void retainThis(); |
void clear(); |
ResolutionState m_state; |
@@ -128,6 +145,8 @@ private: |
Timer<ScriptPromiseResolverWithContext> m_timer; |
RefPtr<ScriptPromiseResolver> m_resolver; |
ScopedPersistent<v8::Value> m_value; |
+ // Retain this object during waiting for the timer. |
+ RefPtr<RetainThis> m_retainThis; |
}; |
} // namespace WebCore |