Chromium Code Reviews| 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 |