Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / bindings / v8 / custom / V8PromiseCustom.cpp
1 /*
2  * Copyright (C) 2013 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "config.h"
32 #include "bindings/v8/custom/V8PromiseCustom.h"
33
34 #include "V8Promise.h"
35 #include "bindings/v8/ScopedPersistent.h"
36 #include "bindings/v8/ScriptFunctionCall.h"
37 #include "bindings/v8/ScriptState.h"
38 #include "bindings/v8/V8Binding.h"
39 #include "bindings/v8/V8HiddenValue.h"
40 #include "bindings/v8/V8PerIsolateData.h"
41 #include "bindings/v8/V8ScriptRunner.h"
42 #include "bindings/v8/WrapperTypeInfo.h"
43 #include "core/dom/Document.h"
44 #include "core/dom/ExecutionContextTask.h"
45 #include "core/frame/DOMWindow.h"
46 #include "core/frame/UseCounter.h"
47 #include "core/inspector/InspectorPromiseInstrumentation.h"
48 #include "core/workers/WorkerGlobalScope.h"
49 #include "platform/Task.h"
50 #include "wtf/Deque.h"
51 #include "wtf/Functional.h"
52 #include "wtf/Noncopyable.h"
53 #include "wtf/PassOwnPtr.h"
54 #include <v8.h>
55
56 #define TONATIVE_VOID_EMPTY(type, var, value)    \
57     type var;                                      \
58     {                                              \
59         v8::TryCatch block;                        \
60         var = (value);                             \
61         if (UNLIKELY(block.HasCaught())) {         \
62             return;                                \
63         }                                          \
64     }
65
66 namespace WebCore {
67
68 namespace {
69
70 v8::Local<v8::ObjectTemplate> cachedObjectTemplate(void* domTemplateKey, int internalFieldCount, v8::Isolate* isolate)
71 {
72     V8PerIsolateData* data = V8PerIsolateData::from(isolate);
73     v8::Handle<v8::FunctionTemplate> functionDescriptor = data->existingDOMTemplate(domTemplateKey);
74     if (!functionDescriptor.IsEmpty())
75         return functionDescriptor->InstanceTemplate();
76
77     functionDescriptor = v8::FunctionTemplate::New(isolate);
78     v8::Local<v8::ObjectTemplate> instanceTemplate = functionDescriptor->InstanceTemplate();
79     instanceTemplate->SetInternalFieldCount(internalFieldCount);
80     data->setDOMTemplate(domTemplateKey, functionDescriptor);
81     return instanceTemplate;
82 }
83
84 v8::Local<v8::ObjectTemplate> promiseAllEnvironmentObjectTemplate(v8::Isolate* isolate)
85 {
86     static int domTemplateKey; // This address is used for a key to look up the dom template.
87     return cachedObjectTemplate(&domTemplateKey, V8PromiseCustom::PromiseAllEnvironmentFieldCount, isolate);
88 }
89
90 v8::Local<v8::ObjectTemplate> primitiveWrapperObjectTemplate(v8::Isolate* isolate)
91 {
92     static int domTemplateKey; // This address is used for a key to look up the dom template.
93     return cachedObjectTemplate(&domTemplateKey, V8PromiseCustom::PrimitiveWrapperFieldCount, isolate);
94 }
95
96 v8::Local<v8::ObjectTemplate> internalObjectTemplate(v8::Isolate* isolate)
97 {
98     static int domTemplateKey; // This address is used for a key to look up the dom template.
99     return cachedObjectTemplate(&domTemplateKey, V8PromiseCustom::InternalFieldCount, isolate);
100 }
101
102 void promiseResolveCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
103 {
104     ASSERT(!info.Data().IsEmpty());
105     v8::Local<v8::Object> promise = info.Data().As<v8::Object>();
106     v8::Local<v8::Value> result = v8::Undefined(info.GetIsolate());
107     if (info.Length() > 0)
108         result = info[0];
109
110     V8PromiseCustom::resolve(promise, result, info.GetIsolate());
111 }
112
113 void promiseRejectCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
114 {
115     ASSERT(!info.Data().IsEmpty());
116     v8::Local<v8::Object> promise = info.Data().As<v8::Object>();
117     v8::Local<v8::Value> result = v8::Undefined(info.GetIsolate());
118     if (info.Length() > 0)
119         result = info[0];
120
121     V8PromiseCustom::reject(promise, result, info.GetIsolate());
122 }
123
124 void promiseAllFulfillCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
125 {
126     v8::Isolate* isolate = info.GetIsolate();
127     ASSERT(!info.Data().IsEmpty());
128     v8::Local<v8::Object> environment = info.Data().As<v8::Object>();
129     v8::Local<v8::Value> result = v8::Undefined(isolate);
130     if (info.Length() > 0)
131         result = info[0];
132
133     v8::Local<v8::Object> promise = environment->GetInternalField(V8PromiseCustom::PromiseAllEnvironmentPromiseIndex).As<v8::Object>();
134     v8::Local<v8::Object> countdownWrapper = environment->GetInternalField(V8PromiseCustom::PromiseAllEnvironmentCountdownIndex).As<v8::Object>();
135     v8::Local<v8::Integer> index = environment->GetInternalField(V8PromiseCustom::PromiseAllEnvironmentIndexIndex).As<v8::Integer>();
136     v8::Local<v8::Array> results = environment->GetInternalField(V8PromiseCustom::PromiseAllEnvironmentResultsIndex).As<v8::Array>();
137
138     results->Set(index->Value(), result);
139
140     v8::Local<v8::Integer> countdown = countdownWrapper->GetInternalField(V8PromiseCustom::PrimitiveWrapperPrimitiveIndex).As<v8::Integer>();
141     ASSERT(countdown->Value() >= 1);
142     if (countdown->Value() == 1) {
143         V8PromiseCustom::resolve(promise, results, isolate);
144         return;
145     }
146     countdownWrapper->SetInternalField(V8PromiseCustom::PrimitiveWrapperPrimitiveIndex, v8::Integer::New(isolate, countdown->Value() - 1));
147 }
148
149 v8::Local<v8::Object> promiseAllEnvironment(v8::Handle<v8::Object> promise, v8::Handle<v8::Object> countdownWrapper, int index, v8::Handle<v8::Array> results, v8::Isolate* isolate)
150 {
151     v8::Local<v8::ObjectTemplate> objectTemplate = promiseAllEnvironmentObjectTemplate(isolate);
152     v8::Local<v8::Object> environment = objectTemplate->NewInstance();
153     if (environment.IsEmpty())
154         return v8::Local<v8::Object>();
155
156     environment->SetInternalField(V8PromiseCustom::PromiseAllEnvironmentPromiseIndex, promise);
157     environment->SetInternalField(V8PromiseCustom::PromiseAllEnvironmentCountdownIndex, countdownWrapper);
158     environment->SetInternalField(V8PromiseCustom::PromiseAllEnvironmentIndexIndex, v8::Integer::New(isolate, index));
159     environment->SetInternalField(V8PromiseCustom::PromiseAllEnvironmentResultsIndex, results);
160     return environment;
161 }
162
163 // Clear |internal|'s derived array.
164 void clearDerived(v8::Handle<v8::Object> internal, v8::Isolate* isolate)
165 {
166     internal->SetInternalField(V8PromiseCustom::InternalFulfillCallbackIndex, v8::Array::New(isolate));
167     internal->SetInternalField(V8PromiseCustom::InternalRejectCallbackIndex, v8::Array::New(isolate));
168     internal->SetInternalField(V8PromiseCustom::InternalDerivedPromiseIndex, v8::Array::New(isolate));
169 }
170
171 // Add a tuple (|derivedPromise|, |onFulfilled|, |onRejected|) to
172 // |internal|'s derived array.
173 // |internal| must be a Promise internal object.
174 // |derivedPromise| must be a Promise instance.
175 // |onFulfilled| and |onRejected| can be an empty value respectively.
176 void addToDerived(v8::Handle<v8::Object> internal, v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Function> onRejected, v8::Isolate* isolate)
177 {
178     v8::Local<v8::Array> fulfillCallbacks = internal->GetInternalField(V8PromiseCustom::InternalFulfillCallbackIndex).As<v8::Array>();
179     v8::Local<v8::Array> rejectCallbacks = internal->GetInternalField(V8PromiseCustom::InternalRejectCallbackIndex).As<v8::Array>();
180     v8::Local<v8::Array> derivedPromises = internal->GetInternalField(V8PromiseCustom::InternalDerivedPromiseIndex).As<v8::Array>();
181
182     if (onFulfilled.IsEmpty()) {
183         fulfillCallbacks->Set(fulfillCallbacks->Length(), v8::Undefined(isolate));
184     } else {
185         fulfillCallbacks->Set(fulfillCallbacks->Length(), onFulfilled);
186     }
187
188     if (onRejected.IsEmpty()) {
189         rejectCallbacks->Set(rejectCallbacks->Length(), v8::Undefined(isolate));
190     } else {
191         rejectCallbacks->Set(rejectCallbacks->Length(), onRejected);
192     }
193
194     ASSERT(!derivedPromise.IsEmpty());
195     derivedPromises->Set(derivedPromises->Length(), derivedPromise);
196
197     // Since they are treated as a tuple,
198     // we need to guaranteed that the length of these arrays are same.
199     ASSERT(fulfillCallbacks->Length() == rejectCallbacks->Length() && rejectCallbacks->Length() == derivedPromises->Length());
200 }
201
202 // Set a |promise|'s state and result that correspond to the state.
203 // |promise| must be a Promise instance.
204 void setStateForPromise(v8::Handle<v8::Object> promise, V8PromiseCustom::PromiseState state, v8::Handle<v8::Value> value, v8::Isolate* isolate)
205 {
206     ASSERT(!value.IsEmpty());
207     ASSERT(state == V8PromiseCustom::Pending || state == V8PromiseCustom::Fulfilled || state == V8PromiseCustom::Rejected || state == V8PromiseCustom::Following);
208     v8::Local<v8::Object> internal = V8PromiseCustom::getInternal(promise);
209     internal->SetInternalField(V8PromiseCustom::InternalStateIndex, v8::Integer::New(isolate, state));
210     internal->SetInternalField(V8PromiseCustom::InternalResultIndex, value);
211     ExecutionContext* context = currentExecutionContext(isolate);
212     if (InspectorInstrumentation::isPromiseTrackerEnabled(context))
213         InspectorInstrumentation::didUpdatePromiseState(context, ScriptObject(ScriptState::current(isolate), promise), state, ScriptValue(ScriptState::current(isolate), value));
214 }
215
216 class TaskPerformScopeForInstrumentation {
217 public:
218     TaskPerformScopeForInstrumentation(ExecutionContext* context, ExecutionContextTask* task)
219         : m_cookie(InspectorInstrumentation::willPerformPromiseTask(context, task))
220     {
221     }
222
223     ~TaskPerformScopeForInstrumentation()
224     {
225         InspectorInstrumentation::didPerformPromiseTask(m_cookie);
226     }
227
228 private:
229     InspectorInstrumentationCookie m_cookie;
230 };
231
232 class CallHandlerTask FINAL : public ExecutionContextTask {
233 public:
234     CallHandlerTask(v8::Handle<v8::Object> promise, v8::Handle<v8::Function> handler, v8::Handle<v8::Value> argument, V8PromiseCustom::PromiseState originatorState, v8::Isolate* isolate, ExecutionContext* context)
235         : m_promise(isolate, promise)
236         , m_handler(isolate, handler)
237         , m_argument(isolate, argument)
238         , m_scriptState(ScriptState::current(isolate))
239     {
240         ASSERT(!m_promise.isEmpty());
241         ASSERT(!m_handler.isEmpty());
242         ASSERT(!m_argument.isEmpty());
243         InspectorInstrumentation::didPostPromiseTask(context, this, originatorState == V8PromiseCustom::Fulfilled);
244     }
245     virtual ~CallHandlerTask() { }
246
247     virtual void performTask(ExecutionContext*) OVERRIDE;
248
249 private:
250     ScopedPersistent<v8::Object> m_promise;
251     ScopedPersistent<v8::Function> m_handler;
252     ScopedPersistent<v8::Value> m_argument;
253     RefPtr<ScriptState> m_scriptState;
254 };
255
256 void CallHandlerTask::performTask(ExecutionContext* context)
257 {
258     TaskPerformScopeForInstrumentation performTaskScope(context, this);
259
260     ASSERT(context);
261     if (context->activeDOMObjectsAreStopped())
262         return;
263
264     ScriptState::Scope scope(m_scriptState.get());
265     v8::Isolate* isolate = m_scriptState->isolate();
266     v8::Handle<v8::Value> info[] = { m_argument.newLocal(isolate) };
267     v8::TryCatch trycatch;
268     v8::Local<v8::Value> value = V8ScriptRunner::callFunction(m_handler.newLocal(isolate), context, v8::Undefined(isolate), WTF_ARRAY_LENGTH(info), info, isolate);
269     if (value.IsEmpty()) {
270         V8PromiseCustom::reject(m_promise.newLocal(isolate), trycatch.Exception(), isolate);
271     } else {
272         V8PromiseCustom::resolve(m_promise.newLocal(isolate), value, isolate);
273     }
274 }
275
276 class UpdateDerivedTask FINAL : public ExecutionContextTask {
277 public:
278     UpdateDerivedTask(v8::Handle<v8::Object> promise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Function> onRejected, v8::Handle<v8::Object> originatorValueObject, v8::Isolate* isolate, ExecutionContext* context)
279         : m_promise(isolate, promise)
280         , m_onFulfilled(isolate, onFulfilled)
281         , m_onRejected(isolate, onRejected)
282         , m_originatorValueObject(isolate, originatorValueObject)
283         , m_scriptState(ScriptState::current(isolate))
284     {
285         ASSERT(!m_promise.isEmpty());
286         ASSERT(!m_originatorValueObject.isEmpty());
287         InspectorInstrumentation::didPostPromiseTask(context, this, true);
288     }
289     virtual ~UpdateDerivedTask() { }
290
291     virtual void performTask(ExecutionContext*) OVERRIDE;
292
293 private:
294     ScopedPersistent<v8::Object> m_promise;
295     ScopedPersistent<v8::Function> m_onFulfilled;
296     ScopedPersistent<v8::Function> m_onRejected;
297     ScopedPersistent<v8::Object> m_originatorValueObject;
298     RefPtr<ScriptState> m_scriptState;
299 };
300
301 void UpdateDerivedTask::performTask(ExecutionContext* context)
302 {
303     TaskPerformScopeForInstrumentation performTaskScope(context, this);
304
305     ASSERT(context);
306     if (context->activeDOMObjectsAreStopped())
307         return;
308
309     ScriptState::Scope scope(m_scriptState.get());
310     v8::Isolate* isolate = m_scriptState->isolate();
311     v8::Local<v8::Object> originatorValueObject = m_originatorValueObject.newLocal(isolate);
312     v8::Local<v8::Value> coercedAlready = V8HiddenValue::getHiddenValue(isolate, originatorValueObject, V8HiddenValue::thenableHiddenPromise(isolate));
313     if (!coercedAlready.IsEmpty() && coercedAlready->IsObject()) {
314         ASSERT(V8PromiseCustom::isPromise(coercedAlready.As<v8::Object>(), isolate));
315         V8PromiseCustom::updateDerivedFromPromise(m_promise.newLocal(isolate), m_onFulfilled.newLocal(isolate), m_onRejected.newLocal(isolate), coercedAlready.As<v8::Object>(), isolate);
316         return;
317     }
318
319     v8::Local<v8::Value> then;
320     v8::TryCatch trycatch;
321     then = originatorValueObject->Get(v8AtomicString(isolate, "then"));
322     if (then.IsEmpty()) {
323         // If calling the [[Get]] internal method threw an exception, catch it and run updateDerivedFromReason.
324         V8PromiseCustom::updateDerivedFromReason(m_promise.newLocal(isolate), m_onRejected.newLocal(isolate), trycatch.Exception(), isolate);
325         return;
326     }
327
328     if (then->IsFunction()) {
329         ASSERT(then->IsObject());
330         v8::Local<v8::Object> coerced = V8PromiseCustom::coerceThenable(originatorValueObject, then.As<v8::Function>(), isolate);
331         // If the stack is exhausted coerced can be empty, but it is impossible
332         // because this function is executed on a fresh stack.
333         ASSERT(!coerced.IsEmpty());
334         V8PromiseCustom::updateDerivedFromPromise(m_promise.newLocal(isolate), m_onFulfilled.newLocal(isolate), m_onRejected.newLocal(isolate), coerced, isolate);
335         return;
336     }
337
338     V8PromiseCustom::updateDerivedFromValue(m_promise.newLocal(isolate), m_onFulfilled.newLocal(isolate), originatorValueObject, isolate);
339 }
340
341 // Since Promises state propagation routines are executed recursively, they cause
342 // stack overflow.
343 // (e.g. UpdateDerived -> UpdateDerivedFromValue -> SetValue ->
344 //  PropagateToDerived -> UpdateDerived)
345 //
346 // To fix that, we introduce PromisePropagator. It holds the stack. When
347 // propagating the result to the derived tuples, we append the derived tuples
348 // to the stack. After that, we drain the stack to propagate the result to
349 // the stored tuples.
350 //
351 // PromisePropagator should be held on the stack and should not be held
352 // as other object's member. PromisePropagator holds Derived tuples. Since
353 // Derived tuples hold persistent handles to JS objects, retaining
354 // PromisePropagator in the heap causes memory leaks.
355 //
356 class PromisePropagator {
357     WTF_MAKE_NONCOPYABLE(PromisePropagator);
358 public:
359     PromisePropagator() { }
360
361     void performPropagation(v8::Isolate*);
362
363     void setValue(v8::Handle<v8::Object> promise, v8::Handle<v8::Value>, v8::Isolate*);
364     void setReason(v8::Handle<v8::Object> promise, v8::Handle<v8::Value>, v8::Isolate*);
365     void propagateToDerived(v8::Handle<v8::Object> promise, v8::Isolate*);
366     void updateDerived(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Function> onRejected, v8::Handle<v8::Object> originator, v8::Isolate*);
367     void updateDerivedFromValue(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Value>, v8::Isolate*);
368     void updateDerivedFromReason(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onRejected, v8::Handle<v8::Value>, v8::Isolate*);
369     void updateDerivedFromPromise(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Function> onRejected, v8::Handle<v8::Object> promise, v8::Isolate*);
370
371 private:
372     class Derived {
373         WTF_MAKE_NONCOPYABLE(Derived);
374     public:
375         Derived(v8::Handle<v8::Object> promise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Function> onRejected, v8::Handle<v8::Object> originator, v8::Isolate* isolate)
376             : m_promise(isolate, promise)
377             , m_onFulfilled(isolate, onFulfilled)
378             , m_onRejected(isolate, onRejected)
379             , m_originator(isolate, originator)
380         {
381             ASSERT(!m_promise.isEmpty());
382             ASSERT(!m_originator.isEmpty());
383         }
384
385         static PassOwnPtr<Derived> create(v8::Handle<v8::Object> promise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Function> onRejected, v8::Handle<v8::Object> originator, v8::Isolate* isolate)
386         {
387             return adoptPtr(new Derived(promise, onFulfilled, onRejected, originator, isolate));
388         }
389
390         v8::Local<v8::Object> promise(v8::Isolate* isolate) const { return m_promise.newLocal(isolate); }
391         v8::Local<v8::Function> onFulfilled(v8::Isolate* isolate) const { return m_onFulfilled.newLocal(isolate); }
392         v8::Local<v8::Function> onRejected(v8::Isolate* isolate) const { return m_onRejected.newLocal(isolate); }
393         v8::Local<v8::Object> originator(v8::Isolate* isolate) const { return m_originator.newLocal(isolate); }
394
395     private:
396         ScopedPersistent<v8::Object> m_promise;
397         ScopedPersistent<v8::Function> m_onFulfilled;
398         ScopedPersistent<v8::Function> m_onRejected;
399         ScopedPersistent<v8::Object> m_originator;
400     };
401
402     Deque<OwnPtr<Derived> > m_derivedStack;
403 };
404
405 void PromisePropagator::performPropagation(v8::Isolate* isolate)
406 {
407     while (!m_derivedStack.isEmpty()) {
408         v8::HandleScope handleScope(isolate);
409         OwnPtr<Derived> derived = m_derivedStack.takeLast();
410         updateDerived(derived->promise(isolate), derived->onFulfilled(isolate), derived->onRejected(isolate), derived->originator(isolate), isolate);
411     }
412 }
413
414 void PromisePropagator::setValue(v8::Handle<v8::Object> promise, v8::Handle<v8::Value> value, v8::Isolate* isolate)
415 {
416     ASSERT(V8PromiseCustom::getState(V8PromiseCustom::getInternal(promise)) != V8PromiseCustom::Fulfilled && V8PromiseCustom::getState(V8PromiseCustom::getInternal(promise)) != V8PromiseCustom::Rejected);
417     setStateForPromise(promise, V8PromiseCustom::Fulfilled, value, isolate);
418     propagateToDerived(promise, isolate);
419 }
420
421 void PromisePropagator::setReason(v8::Handle<v8::Object> promise, v8::Handle<v8::Value> reason, v8::Isolate* isolate)
422 {
423     ASSERT(V8PromiseCustom::getState(V8PromiseCustom::getInternal(promise)) != V8PromiseCustom::Fulfilled && V8PromiseCustom::getState(V8PromiseCustom::getInternal(promise)) != V8PromiseCustom::Rejected);
424     setStateForPromise(promise, V8PromiseCustom::Rejected, reason, isolate);
425     propagateToDerived(promise, isolate);
426 }
427
428 void PromisePropagator::propagateToDerived(v8::Handle<v8::Object> promise, v8::Isolate* isolate)
429 {
430     v8::Local<v8::Object> internal = V8PromiseCustom::getInternal(promise);
431     ASSERT(V8PromiseCustom::getState(internal) == V8PromiseCustom::Fulfilled || V8PromiseCustom::getState(internal) == V8PromiseCustom::Rejected);
432     v8::Local<v8::Array> fulfillCallbacks = internal->GetInternalField(V8PromiseCustom::InternalFulfillCallbackIndex).As<v8::Array>();
433     v8::Local<v8::Array> rejectCallbacks = internal->GetInternalField(V8PromiseCustom::InternalRejectCallbackIndex).As<v8::Array>();
434     v8::Local<v8::Array> derivedPromises = internal->GetInternalField(V8PromiseCustom::InternalDerivedPromiseIndex).As<v8::Array>();
435     // Since they are treated as a tuple,
436     // we need to guaranteed that the length of these arrays are same.
437     ASSERT(fulfillCallbacks->Length() == rejectCallbacks->Length() && rejectCallbacks->Length() == derivedPromises->Length());
438
439     // Append Derived tuple to the stack in reverse order.
440     for (uint32_t count = 0, length = derivedPromises->Length(); count < length; ++count) {
441         uint32_t i = length - count - 1;
442         v8::Local<v8::Object> derivedPromise = derivedPromises->Get(i).As<v8::Object>();
443
444         v8::Local<v8::Function> onFulfilled, onRejected;
445         v8::Local<v8::Value> onFulfilledValue = fulfillCallbacks->Get(i);
446         if (onFulfilledValue->IsFunction()) {
447             onFulfilled = onFulfilledValue.As<v8::Function>();
448         }
449         v8::Local<v8::Value> onRejectedValue = rejectCallbacks->Get(i);
450         if (onRejectedValue->IsFunction()) {
451             onRejected = onRejectedValue.As<v8::Function>();
452         }
453
454         m_derivedStack.append(Derived::create(derivedPromise, onFulfilled, onRejected, promise, isolate));
455     }
456     clearDerived(internal, isolate);
457 }
458
459 void PromisePropagator::updateDerivedFromValue(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Value> value, v8::Isolate* isolate)
460 {
461     if (!onFulfilled.IsEmpty()) {
462         V8PromiseCustom::callHandler(derivedPromise, onFulfilled, value, V8PromiseCustom::Fulfilled, isolate);
463     } else {
464         setValue(derivedPromise, value, isolate);
465     }
466 }
467
468 void PromisePropagator::updateDerivedFromReason(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onRejected, v8::Handle<v8::Value> reason, v8::Isolate* isolate)
469 {
470     if (!onRejected.IsEmpty()) {
471         V8PromiseCustom::callHandler(derivedPromise, onRejected, reason, V8PromiseCustom::Rejected, isolate);
472     } else {
473         setReason(derivedPromise, reason, isolate);
474     }
475 }
476
477 void PromisePropagator::updateDerived(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Function> onRejected, v8::Handle<v8::Object> originator, v8::Isolate* isolate)
478 {
479     v8::Local<v8::Object> originatorInternal = V8PromiseCustom::getInternal(originator);
480     V8PromiseCustom::PromiseState originatorState = V8PromiseCustom::getState(originatorInternal);
481     ASSERT(originatorState == V8PromiseCustom::Fulfilled || originatorState == V8PromiseCustom::Rejected);
482     v8::Local<v8::Value> originatorValue = originatorInternal->GetInternalField(V8PromiseCustom::InternalResultIndex);
483     if (originatorState == V8PromiseCustom::Fulfilled) {
484         if (originatorValue->IsObject()) {
485             ExecutionContext* executionContext = currentExecutionContext(isolate);
486             ASSERT(executionContext && executionContext->isContextThread());
487             executionContext->postTask(adoptPtr(new UpdateDerivedTask(derivedPromise, onFulfilled, onRejected, originatorValue.As<v8::Object>(), isolate, executionContext)));
488         } else {
489             updateDerivedFromValue(derivedPromise, onFulfilled, originatorValue, isolate);
490         }
491     } else {
492         updateDerivedFromReason(derivedPromise, onRejected, originatorValue, isolate);
493     }
494 }
495
496 void PromisePropagator::updateDerivedFromPromise(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Function> onRejected, v8::Handle<v8::Object> promise, v8::Isolate* isolate)
497 {
498     v8::Local<v8::Object> internal = V8PromiseCustom::getInternal(promise);
499     V8PromiseCustom::PromiseState state = V8PromiseCustom::getState(internal);
500     if (state == V8PromiseCustom::Fulfilled || state == V8PromiseCustom::Rejected) {
501         updateDerived(derivedPromise, onFulfilled, onRejected, promise, isolate);
502     } else {
503         addToDerived(internal, derivedPromise, onFulfilled, onRejected, isolate);
504     }
505     ExecutionContext* context = currentExecutionContext(isolate);
506     if (InspectorInstrumentation::isPromiseTrackerEnabled(context)) {
507         ScriptState* scriptState = ScriptState::current(isolate);
508         InspectorInstrumentation::didUpdatePromiseParent(context, ScriptObject(scriptState, derivedPromise), ScriptObject(scriptState, promise));
509     }
510 }
511
512 } // namespace
513
514 void V8Promise::constructorCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
515 {
516     v8SetReturnValue(info, v8::Local<v8::Value>());
517     v8::Isolate* isolate = info.GetIsolate();
518     ExecutionContext* executionContext = callingExecutionContext(isolate);
519     UseCounter::count(executionContext, UseCounter::PromiseConstructor);
520     if (!info.Length() || !info[0]->IsFunction()) {
521         throwTypeError("Promise constructor takes a function argument", isolate);
522         return;
523     }
524     v8::Local<v8::Function> init = info[0].As<v8::Function>();
525     TONATIVE_VOID_EMPTY(v8::Local<v8::Object>, promise, V8PromiseCustom::createPromise(info.Holder(), isolate));
526     TONATIVE_VOID_EMPTY(v8::Handle<v8::Value>, resolve, createClosure(promiseResolveCallback, promise, isolate));
527     TONATIVE_VOID_EMPTY(v8::Handle<v8::Value>, reject, createClosure(promiseRejectCallback, promise, isolate));
528     v8::Handle<v8::Value> argv[] = { resolve, reject };
529     v8::TryCatch trycatch;
530     if (V8ScriptRunner::callFunction(init, currentExecutionContext(isolate), v8::Undefined(isolate), WTF_ARRAY_LENGTH(argv), argv, isolate).IsEmpty()) {
531         // An exception is thrown. Reject the promise if its resolved flag is unset.
532         V8PromiseCustom::reject(promise, trycatch.Exception(), isolate);
533     }
534     v8SetReturnValue(info, promise);
535     return;
536 }
537
538 void V8Promise::thenMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
539 {
540     v8::Isolate* isolate = info.GetIsolate();
541     v8::Local<v8::Function> onFulfilled, onRejected;
542     if (info.Length() > 0 && info[0]->IsFunction())
543         onFulfilled = info[0].As<v8::Function>();
544     if (info.Length() > 1 && info[1]->IsFunction())
545         onRejected = info[1].As<v8::Function>();
546     TONATIVE_VOID_EMPTY(v8::Local<v8::Value>, newPromise, V8PromiseCustom::then(info.Holder(), onFulfilled, onRejected, isolate));
547     v8SetReturnValue(info, newPromise);
548 }
549
550 void V8Promise::castMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
551 {
552     v8::Isolate* isolate = info.GetIsolate();
553     ExecutionContext* executionContext = callingExecutionContext(isolate);
554     UseCounter::count(executionContext, UseCounter::PromiseCast);
555     v8::Local<v8::Value> result = v8::Undefined(isolate);
556     if (info.Length() > 0)
557         result = info[0];
558
559     TONATIVE_VOID_EMPTY(v8::Local<v8::Value>, cast, V8PromiseCustom::toPromise(result, isolate));
560     v8SetReturnValue(info, cast);
561 }
562
563 void V8Promise::catchMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
564 {
565     v8::Isolate* isolate = info.GetIsolate();
566     v8::Local<v8::Function> onFulfilled, onRejected;
567
568     if (info.Length() > 0 && !info[0]->IsUndefined()) {
569         if (!info[0]->IsFunction()) {
570             v8SetReturnValue(info, throwTypeError("onRejected must be a function or undefined", isolate));
571             return;
572         }
573         onRejected = info[0].As<v8::Function>();
574     }
575     TONATIVE_VOID_EMPTY(v8::Local<v8::Value>, newPromise, V8PromiseCustom::then(info.Holder(), onFulfilled, onRejected, isolate));
576     v8SetReturnValue(info, newPromise);
577 }
578
579 void V8Promise::resolveMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
580 {
581     v8::Isolate* isolate = info.GetIsolate();
582     ExecutionContext* executionContext = callingExecutionContext(isolate);
583     UseCounter::count(executionContext, UseCounter::PromiseResolve);
584     v8::Local<v8::Value> result = v8::Undefined(isolate);
585     if (info.Length() > 0)
586         result = info[0];
587
588     TONATIVE_VOID_EMPTY(v8::Local<v8::Object>, promise, V8PromiseCustom::createPromise(info.Holder(), isolate));
589     V8PromiseCustom::resolve(promise, result, isolate);
590     v8SetReturnValue(info, promise);
591 }
592
593 void V8Promise::rejectMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
594 {
595     v8::Isolate* isolate = info.GetIsolate();
596     ExecutionContext* executionContext = callingExecutionContext(isolate);
597     UseCounter::count(executionContext, UseCounter::PromiseReject);
598     v8::Local<v8::Value> result = v8::Undefined(isolate);
599     if (info.Length() > 0)
600         result = info[0];
601
602     TONATIVE_VOID_EMPTY(v8::Local<v8::Object>, promise, V8PromiseCustom::createPromise(info.Holder(), isolate));
603     V8PromiseCustom::reject(promise, result, isolate);
604     v8SetReturnValue(info, promise);
605 }
606
607 void V8Promise::raceMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
608 {
609     v8::Isolate* isolate = info.GetIsolate();
610     TONATIVE_VOID_EMPTY(v8::Local<v8::Object>, promise, V8PromiseCustom::createPromise(info.Holder(), isolate));
611
612     if (!info.Length() || !info[0]->IsArray()) {
613         v8SetReturnValue(info, promise);
614         return;
615     }
616
617     // FIXME: Now we limit the iterable type to the Array type.
618     v8::Local<v8::Array> iterable = info[0].As<v8::Array>();
619     TONATIVE_VOID_EMPTY(v8::Local<v8::Function>, onFulfilled, createClosure(promiseResolveCallback, promise, isolate));
620     TONATIVE_VOID_EMPTY(v8::Local<v8::Function>, onRejected, createClosure(promiseRejectCallback, promise, isolate));
621
622     for (unsigned i = 0, length = iterable->Length(); i < length; ++i) {
623         // Array-holes should not be skipped by for-of iteration semantics.
624         TONATIVE_VOID_EMPTY(v8::Local<v8::Value>, nextValue, iterable->Get(i));
625         TONATIVE_VOID_EMPTY(v8::Local<v8::Object>, nextPromise, V8PromiseCustom::toPromise(nextValue, isolate));
626         TONATIVE_VOID_EMPTY(v8::Local<v8::Value>, unused, V8PromiseCustom::then(nextPromise, onFulfilled, onRejected, isolate));
627     }
628     v8SetReturnValue(info, promise);
629 }
630
631 void V8Promise::allMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
632 {
633     v8::Isolate* isolate = info.GetIsolate();
634     TONATIVE_VOID_EMPTY(v8::Local<v8::Object>, promise, V8PromiseCustom::createPromise(info.Holder(), isolate));
635     v8::Local<v8::Array> results = v8::Array::New(info.GetIsolate());
636
637     if (!info.Length() || !info[0]->IsArray()) {
638         V8PromiseCustom::resolve(promise, results, isolate);
639         v8SetReturnValue(info, promise);
640         return;
641     }
642
643     // FIXME: Now we limit the iterable type to the Array type.
644     v8::Local<v8::Array> iterable = info[0].As<v8::Array>();
645
646     if (!iterable->Length()) {
647         V8PromiseCustom::resolve(promise, results, isolate);
648         v8SetReturnValue(info, promise);
649         return;
650     }
651
652     v8::Local<v8::ObjectTemplate> objectTemplate = primitiveWrapperObjectTemplate(isolate);
653     TONATIVE_VOID_EMPTY(v8::Local<v8::Object>, countdownWrapper, objectTemplate->NewInstance());
654     countdownWrapper->SetInternalField(V8PromiseCustom::PrimitiveWrapperPrimitiveIndex, v8::Integer::New(isolate, iterable->Length()));
655
656     TONATIVE_VOID_EMPTY(v8::Local<v8::Function>, onRejected, createClosure(promiseRejectCallback, promise, isolate));
657     for (unsigned i = 0, length = iterable->Length(); i < length; ++i) {
658         // Array-holes should not be skipped by for-of iteration semantics.
659         TONATIVE_VOID_EMPTY(v8::Local<v8::Object>, environment, promiseAllEnvironment(promise, countdownWrapper, i, results, isolate));
660         TONATIVE_VOID_EMPTY(v8::Local<v8::Function>, onFulfilled, createClosure(promiseAllFulfillCallback, environment, isolate));
661         TONATIVE_VOID_EMPTY(v8::Local<v8::Value>, nextValue, iterable->Get(i));
662         TONATIVE_VOID_EMPTY(v8::Local<v8::Object>, nextPromise, V8PromiseCustom::toPromise(nextValue, isolate));
663         TONATIVE_VOID_EMPTY(v8::Local<v8::Value>, unused, V8PromiseCustom::then(nextPromise, onFulfilled, onRejected, isolate));
664     }
665     v8SetReturnValue(info, promise);
666 }
667
668 //
669 // -- V8PromiseCustom --
670 v8::Local<v8::Object> V8PromiseCustom::createPromise(v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
671 {
672     v8::Local<v8::ObjectTemplate> internalTemplate = internalObjectTemplate(isolate);
673     v8::Local<v8::Object> internal = internalTemplate->NewInstance();
674     if (internal.IsEmpty())
675         return v8::Local<v8::Object>();
676     v8::Local<v8::Object> promise = V8DOMWrapper::createWrapper(creationContext, &V8Promise::wrapperTypeInfo, 0, isolate);
677
678     clearDerived(internal, isolate);
679     promise->SetInternalField(v8DOMWrapperObjectIndex, internal);
680
681     ExecutionContext* context = currentExecutionContext(isolate);
682     if (InspectorInstrumentation::isPromiseTrackerEnabled(context))
683         InspectorInstrumentation::didCreatePromise(context, ScriptObject(ScriptState::current(isolate), promise));
684
685     setStateForPromise(promise, Pending, v8::Undefined(isolate), isolate);
686     return promise;
687 }
688
689 v8::Local<v8::Object> V8PromiseCustom::getInternal(v8::Handle<v8::Object> promise)
690 {
691     v8::Local<v8::Value> value = promise->GetInternalField(v8DOMWrapperObjectIndex);
692     return value.As<v8::Object>();
693 }
694
695 V8PromiseCustom::PromiseState V8PromiseCustom::getState(v8::Handle<v8::Object> internal)
696 {
697     v8::Handle<v8::Value> value = internal->GetInternalField(V8PromiseCustom::InternalStateIndex);
698     uint32_t number = toInt32(value);
699     ASSERT(number == Pending || number == Fulfilled || number == Rejected || number == Following);
700     return static_cast<PromiseState>(number);
701 }
702
703 bool V8PromiseCustom::isPromise(v8::Handle<v8::Value> maybePromise, v8::Isolate* isolate)
704 {
705     return V8Promise::domTemplate(isolate)->HasInstance(maybePromise);
706 }
707
708 v8::Local<v8::Object> V8PromiseCustom::toPromise(v8::Handle<v8::Value> maybePromise, v8::Isolate* isolate)
709 {
710     // FIXME: Currently we don't check [[PromiseConstructor]] since we limit
711     // the creation of the promise objects only from the Blink Promise
712     // constructor.
713     if (isPromise(maybePromise, isolate))
714         return maybePromise.As<v8::Object>();
715
716     v8::Local<v8::Object> promise = createPromise(v8::Handle<v8::Object>(), isolate);
717     if (promise.IsEmpty())
718         return v8::Local<v8::Object>();
719     resolve(promise, maybePromise, isolate);
720     return promise;
721 }
722
723 void V8PromiseCustom::resolve(v8::Handle<v8::Object> promise, v8::Handle<v8::Value> result, v8::Isolate* isolate)
724 {
725     ASSERT(!result.IsEmpty());
726     v8::Local<v8::Object> internal = getInternal(promise);
727     PromiseState state = getState(internal);
728     if (state != Pending)
729         return;
730
731     if (isPromise(result, isolate)) {
732         v8::Local<v8::Object> valuePromise = result.As<v8::Object>();
733         v8::Local<v8::Object> valueInternal = getInternal(valuePromise);
734         PromiseState valueState = getState(valueInternal);
735         if (promise->SameValue(valuePromise)) {
736             v8::Local<v8::Value> reason = V8ThrowException::createTypeError("Resolve a promise with itself", isolate);
737             setReason(promise, reason, isolate);
738         } else if (valueState == Following) {
739             v8::Local<v8::Object> valuePromiseFollowing = valueInternal->GetInternalField(InternalResultIndex).As<v8::Object>();
740             setStateForPromise(promise, Following, valuePromiseFollowing, isolate);
741             addToDerived(getInternal(valuePromiseFollowing), promise, v8::Handle<v8::Function>(), v8::Handle<v8::Function>(), isolate);
742         } else if (valueState == Fulfilled) {
743             setValue(promise, valueInternal->GetInternalField(InternalResultIndex), isolate);
744         } else if (valueState == Rejected) {
745             setReason(promise, valueInternal->GetInternalField(InternalResultIndex), isolate);
746         } else {
747             ASSERT(valueState == Pending);
748             setStateForPromise(promise, Following, valuePromise, isolate);
749             addToDerived(valueInternal, promise, v8::Handle<v8::Function>(), v8::Handle<v8::Function>(), isolate);
750         }
751     } else {
752         setValue(promise, result, isolate);
753     }
754 }
755
756 void V8PromiseCustom::reject(v8::Handle<v8::Object> promise, v8::Handle<v8::Value> reason, v8::Isolate* isolate)
757 {
758     v8::Local<v8::Object> internal = getInternal(promise);
759     PromiseState state = getState(internal);
760     if (state != Pending)
761         return;
762     setReason(promise, reason, isolate);
763 }
764
765 v8::Local<v8::Object> V8PromiseCustom::then(v8::Handle<v8::Object> promise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Function> onRejected, v8::Isolate* isolate)
766 {
767     v8::Handle<v8::Object> internal = getInternal(promise);
768     while (getState(internal) == Following) {
769         promise = internal->GetInternalField(InternalResultIndex).As<v8::Object>();
770         internal = getInternal(promise);
771     }
772     // FIXME: Currently we don't lookup "constructor" property since we limit
773     // the creation of the promise objects only from the Blink Promise
774     // constructor.
775     v8::Local<v8::Object> derivedPromise = createPromise(v8::Handle<v8::Object>(), isolate);
776     if (derivedPromise.IsEmpty())
777         return v8::Local<v8::Object>();
778     updateDerivedFromPromise(derivedPromise, onFulfilled, onRejected, promise, isolate);
779     return derivedPromise;
780 }
781
782 void V8PromiseCustom::setValue(v8::Handle<v8::Object> promise, v8::Handle<v8::Value> value, v8::Isolate* isolate)
783 {
784     PromisePropagator propagator;
785     propagator.setValue(promise, value, isolate);
786     propagator.performPropagation(isolate);
787 }
788
789 void V8PromiseCustom::setReason(v8::Handle<v8::Object> promise, v8::Handle<v8::Value> reason, v8::Isolate* isolate)
790 {
791     PromisePropagator propagator;
792     propagator.setReason(promise, reason, isolate);
793     propagator.performPropagation(isolate);
794 }
795
796 void V8PromiseCustom::propagateToDerived(v8::Handle<v8::Object> promise, v8::Isolate* isolate)
797 {
798     PromisePropagator propagator;
799     propagator.propagateToDerived(promise, isolate);
800     propagator.performPropagation(isolate);
801 }
802
803 void V8PromiseCustom::updateDerived(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Function> onRejected, v8::Handle<v8::Object> originator, v8::Isolate* isolate)
804 {
805     PromisePropagator propagator;
806     propagator.updateDerived(derivedPromise, onFulfilled, onRejected, originator, isolate);
807     propagator.performPropagation(isolate);
808 }
809
810 void V8PromiseCustom::updateDerivedFromValue(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Value> value, v8::Isolate* isolate)
811 {
812     PromisePropagator propagator;
813     propagator.updateDerivedFromValue(derivedPromise, onFulfilled, value, isolate);
814     propagator.performPropagation(isolate);
815 }
816
817 void V8PromiseCustom::updateDerivedFromReason(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onRejected, v8::Handle<v8::Value> reason, v8::Isolate* isolate)
818 {
819     PromisePropagator propagator;
820     propagator.updateDerivedFromReason(derivedPromise, onRejected, reason, isolate);
821     propagator.performPropagation(isolate);
822 }
823
824 void V8PromiseCustom::updateDerivedFromPromise(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Function> onRejected, v8::Handle<v8::Object> promise, v8::Isolate* isolate)
825 {
826     PromisePropagator propagator;
827     propagator.updateDerivedFromPromise(derivedPromise, onFulfilled, onRejected, promise, isolate);
828     propagator.performPropagation(isolate);
829 }
830
831 v8::Local<v8::Object> V8PromiseCustom::coerceThenable(v8::Handle<v8::Object> thenable, v8::Handle<v8::Function> then, v8::Isolate* isolate)
832 {
833     ASSERT(!thenable.IsEmpty());
834     ASSERT(!then.IsEmpty());
835     v8::Local<v8::Object> promise = createPromise(v8::Handle<v8::Object>(), isolate);
836     if (promise.IsEmpty())
837         return v8::Local<v8::Object>();
838     v8::Handle<v8::Value> onFulfilled = createClosure(promiseResolveCallback, promise, isolate);
839     if (onFulfilled.IsEmpty())
840         return v8::Local<v8::Object>();
841     v8::Handle<v8::Value> onRejected = createClosure(promiseRejectCallback, promise, isolate);
842     if (onRejected.IsEmpty())
843         return v8::Local<v8::Object>();
844     v8::Handle<v8::Value> argv[] = { onFulfilled, onRejected };
845
846     v8::TryCatch trycatch;
847     if (V8ScriptRunner::callFunction(then, currentExecutionContext(isolate), thenable, WTF_ARRAY_LENGTH(argv), argv, isolate).IsEmpty()) {
848         reject(promise, trycatch.Exception(), isolate);
849     }
850     V8HiddenValue::setHiddenValue(isolate, thenable, V8HiddenValue::thenableHiddenPromise(isolate), promise);
851     return promise;
852 }
853
854 void V8PromiseCustom::callHandler(v8::Handle<v8::Object> promise, v8::Handle<v8::Function> handler, v8::Handle<v8::Value> argument, PromiseState originatorState, v8::Isolate* isolate)
855 {
856     ASSERT(originatorState == Fulfilled || originatorState == Rejected);
857     ExecutionContext* executionContext = currentExecutionContext(isolate);
858     ASSERT(executionContext && executionContext->isContextThread());
859     executionContext->postTask(adoptPtr(new CallHandlerTask(promise, handler, argument, originatorState, isolate, executionContext)));
860 }
861
862 } // namespace WebCore