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 #include "config.h" | |
6 #include "bindings/v8/ScriptPromiseResolver.h" | |
7 | |
8 #include "bindings/v8/V8RecursionScope.h" | |
9 | |
10 namespace WebCore { | |
11 | |
12 ScriptPromiseResolver::ScriptPromiseResolver(ScriptState* scriptState) | |
13 : ActiveDOMObject(scriptState->executionContext()) | |
14 , m_state(Pending) | |
15 , m_scriptState(scriptState) | |
16 , m_mode(Default) | |
17 , m_timer(this, &ScriptPromiseResolver::onTimerFired) | |
18 , m_resolver(scriptState) | |
19 #if ASSERTION_ENABLED | |
20 , m_isPromiseCalled(false) | |
21 #endif | |
22 { | |
23 if (executionContext()->activeDOMObjectsAreStopped()) | |
24 m_state = ResolvedOrRejected; | |
25 } | |
26 | |
27 void ScriptPromiseResolver::suspend() | |
28 { | |
29 m_timer.stop(); | |
30 } | |
31 | |
32 void ScriptPromiseResolver::resume() | |
33 { | |
34 if (m_state == Resolving || m_state == Rejecting) | |
35 m_timer.startOneShot(0, FROM_HERE); | |
36 } | |
37 | |
38 void ScriptPromiseResolver::stop() | |
39 { | |
40 m_timer.stop(); | |
41 clear(); | |
42 } | |
43 | |
44 void ScriptPromiseResolver::keepAliveWhilePending() | |
45 { | |
46 if (m_state == ResolvedOrRejected || m_mode == KeepAliveWhilePending) | |
47 return; | |
48 | |
49 // Keep |this| while the promise is Pending. | |
50 // deref() will be called in clear(). | |
51 m_mode = KeepAliveWhilePending; | |
52 ref(); | |
53 } | |
54 | |
55 void ScriptPromiseResolver::onTimerFired(Timer<ScriptPromiseResolver>*) | |
56 { | |
57 ASSERT(m_state == Resolving || m_state == Rejecting); | |
58 ScriptState::Scope scope(m_scriptState.get()); | |
59 resolveOrRejectImmediately(); | |
60 } | |
61 | |
62 void ScriptPromiseResolver::resolveOrRejectImmediately() | |
63 { | |
64 ASSERT(!executionContext()->activeDOMObjectsAreStopped()); | |
65 ASSERT(!executionContext()->activeDOMObjectsAreSuspended()); | |
66 { | |
67 // FIXME: The V8RecursionScope is only necessary to force microtask deli
very for promises | |
68 // resolved or rejected in workers. It can be removed once worker thread
s run microtasks | |
69 // at the end of every task (rather than just the main thread). | |
70 V8RecursionScope scope(m_scriptState->isolate(), m_scriptState->executio
nContext()); | |
71 if (m_state == Resolving) { | |
72 m_resolver.resolve(m_value.newLocal(m_scriptState->isolate())); | |
73 } else { | |
74 ASSERT(m_state == Rejecting); | |
75 m_resolver.reject(m_value.newLocal(m_scriptState->isolate())); | |
76 } | |
77 } | |
78 clear(); | |
79 } | |
80 | |
81 void ScriptPromiseResolver::clear() | |
82 { | |
83 if (m_state == ResolvedOrRejected) | |
84 return; | |
85 ResolutionState state = m_state; | |
86 m_state = ResolvedOrRejected; | |
87 m_resolver.clear(); | |
88 m_value.clear(); | |
89 if (m_mode == KeepAliveWhilePending) { | |
90 // |ref| was called in |keepAliveWhilePending|. | |
91 deref(); | |
92 } | |
93 // |this| may be deleted here, but it is safe to check |state| because | |
94 // it doesn't depend on |this|. When |this| is deleted, |state| can't be | |
95 // |Resolving| nor |Rejecting| and hence |this->deref()| can't be executed. | |
96 if (state == Resolving || state == Rejecting) { | |
97 // |ref| was called in |resolveOrReject|. | |
98 deref(); | |
99 } | |
100 } | |
101 | |
102 } // namespace WebCore | |
OLD | NEW |