| Index: Source/bindings/v8/custom/V8PromiseCustom.cpp
|
| diff --git a/Source/bindings/v8/custom/V8PromiseCustom.cpp b/Source/bindings/v8/custom/V8PromiseCustom.cpp
|
| index 14200e2541949968394eeac583b2fa28360c0c6f..130c1bae26877b607e744a04eaee9bf0b865c380 100644
|
| --- a/Source/bindings/v8/custom/V8PromiseCustom.cpp
|
| +++ b/Source/bindings/v8/custom/V8PromiseCustom.cpp
|
| @@ -31,7 +31,6 @@
|
| #include "config.h"
|
| #include "bindings/v8/custom/V8PromiseCustom.h"
|
|
|
| -#include <v8.h>
|
| #include "V8Promise.h"
|
| #include "bindings/v8/DOMRequestState.h"
|
| #include "bindings/v8/ScopedPersistent.h"
|
| @@ -52,6 +51,7 @@
|
| #include "wtf/Functional.h"
|
| #include "wtf/Noncopyable.h"
|
| #include "wtf/PassOwnPtr.h"
|
| +#include <v8.h>
|
|
|
| namespace WebCore {
|
|
|
| @@ -141,6 +141,8 @@ v8::Local<v8::Object> promiseAllEnvironment(v8::Handle<v8::Object> promise, v8::
|
| {
|
| v8::Local<v8::ObjectTemplate> objectTemplate = promiseAllEnvironmentObjectTemplate(isolate);
|
| v8::Local<v8::Object> environment = objectTemplate->NewInstance();
|
| + if (environment.IsEmpty())
|
| + return v8::Local<v8::Object>();
|
|
|
| environment->SetInternalField(V8PromiseCustom::PromiseAllEnvironmentPromiseIndex, promise);
|
| environment->SetInternalField(V8PromiseCustom::PromiseAllEnvironmentCountdownIndex, countdownWrapper);
|
| @@ -303,6 +305,9 @@ void UpdateDerivedTask::performTask(ExecutionContext* context)
|
| if (then->IsFunction()) {
|
| ASSERT(then->IsObject());
|
| v8::Local<v8::Object> coerced = V8PromiseCustom::coerceThenable(originatorValueObject, then.As<v8::Function>(), isolate);
|
| + // If the stack is exhausted coerced can be empty, but it is impossible
|
| + // because this function is executed on a fresh stack.
|
| + ASSERT(!coerced.IsEmpty());
|
| V8PromiseCustom::updateDerivedFromPromise(m_promise.newLocal(isolate), m_onFulfilled.newLocal(isolate), m_onRejected.newLocal(isolate), coerced, isolate);
|
| return;
|
| }
|
| @@ -491,11 +496,10 @@ void V8Promise::constructorCustom(const v8::FunctionCallbackInfo<v8::Value>& inf
|
| return;
|
| }
|
| v8::Local<v8::Function> init = info[0].As<v8::Function>();
|
| - v8::Local<v8::Object> promise = V8PromiseCustom::createPromise(info.Holder(), isolate);
|
| - v8::Handle<v8::Value> argv[] = {
|
| - createClosure(promiseResolveCallback, promise, isolate),
|
| - createClosure(promiseRejectCallback, promise, isolate)
|
| - };
|
| + V8TRYCATCH_VOID(v8::Local<v8::Object>, promise, V8PromiseCustom::createPromise(info.Holder(), isolate));
|
| + V8TRYCATCH_VOID(v8::Handle<v8::Value>, resolve, createClosure(promiseResolveCallback, promise, isolate));
|
| + V8TRYCATCH_VOID(v8::Handle<v8::Value>, reject, createClosure(promiseRejectCallback, promise, isolate));
|
| + v8::Handle<v8::Value> argv[] = { resolve, reject };
|
| v8::TryCatch trycatch;
|
| if (V8ScriptRunner::callFunction(init, currentExecutionContext(isolate), v8::Undefined(isolate), WTF_ARRAY_LENGTH(argv), argv, isolate).IsEmpty()) {
|
| // An exception is thrown. Reject the promise if its resolved flag is unset.
|
| @@ -513,7 +517,8 @@ void V8Promise::thenMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info
|
| onFulfilled = info[0].As<v8::Function>();
|
| if (info.Length() > 1 && info[1]->IsFunction())
|
| onRejected = info[1].As<v8::Function>();
|
| - v8SetReturnValue(info, V8PromiseCustom::then(info.Holder(), onFulfilled, onRejected, isolate));
|
| + V8TRYCATCH_VOID(v8::Local<v8::Value>, newPromise, V8PromiseCustom::then(info.Holder(), onFulfilled, onRejected, isolate));
|
| + v8SetReturnValue(info, newPromise);
|
| }
|
|
|
| void V8Promise::castMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
|
| @@ -525,7 +530,8 @@ void V8Promise::castMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info
|
| if (info.Length() > 0)
|
| result = info[0];
|
|
|
| - v8SetReturnValue(info, V8PromiseCustom::toPromise(result, isolate));
|
| + V8TRYCATCH_VOID(v8::Local<v8::Value>, cast, V8PromiseCustom::toPromise(result, isolate));
|
| + v8SetReturnValue(info, cast);
|
| }
|
|
|
| void V8Promise::catchMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
|
| @@ -540,7 +546,8 @@ void V8Promise::catchMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& inf
|
| }
|
| onRejected = info[0].As<v8::Function>();
|
| }
|
| - v8SetReturnValue(info, V8PromiseCustom::then(info.Holder(), onFulfilled, onRejected, isolate));
|
| + V8TRYCATCH_VOID(v8::Local<v8::Value>, newPromise, V8PromiseCustom::then(info.Holder(), onFulfilled, onRejected, isolate));
|
| + v8SetReturnValue(info, newPromise);
|
| }
|
|
|
| void V8Promise::resolveMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
|
| @@ -552,7 +559,7 @@ void V8Promise::resolveMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& i
|
| if (info.Length() > 0)
|
| result = info[0];
|
|
|
| - v8::Local<v8::Object> promise = V8PromiseCustom::createPromise(info.Holder(), isolate);
|
| + V8TRYCATCH_VOID(v8::Local<v8::Object>, promise, V8PromiseCustom::createPromise(info.Holder(), isolate));
|
| V8PromiseCustom::resolve(promise, result, isolate);
|
| v8SetReturnValue(info, promise);
|
| }
|
| @@ -566,7 +573,7 @@ void V8Promise::rejectMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& in
|
| if (info.Length() > 0)
|
| result = info[0];
|
|
|
| - v8::Local<v8::Object> promise = V8PromiseCustom::createPromise(info.Holder(), isolate);
|
| + V8TRYCATCH_VOID(v8::Local<v8::Object>, promise, V8PromiseCustom::createPromise(info.Holder(), isolate));
|
| V8PromiseCustom::reject(promise, result, isolate);
|
| v8SetReturnValue(info, promise);
|
| }
|
| @@ -574,7 +581,7 @@ void V8Promise::rejectMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& in
|
| void V8Promise::raceMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
|
| {
|
| v8::Isolate* isolate = info.GetIsolate();
|
| - v8::Local<v8::Object> promise = V8PromiseCustom::createPromise(info.Holder(), isolate);
|
| + V8TRYCATCH_VOID(v8::Local<v8::Object>, promise, V8PromiseCustom::createPromise(info.Holder(), isolate));
|
|
|
| if (!info.Length() || !info[0]->IsArray()) {
|
| v8SetReturnValue(info, promise);
|
| @@ -583,14 +590,14 @@ void V8Promise::raceMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info
|
|
|
| // FIXME: Now we limit the iterable type to the Array type.
|
| v8::Local<v8::Array> iterable = info[0].As<v8::Array>();
|
| - v8::Local<v8::Function> onFulfilled = createClosure(promiseResolveCallback, promise, isolate);
|
| - v8::Local<v8::Function> onRejected = createClosure(promiseRejectCallback, promise, isolate);
|
| + V8TRYCATCH_VOID(v8::Local<v8::Function>, onFulfilled, createClosure(promiseResolveCallback, promise, isolate));
|
| + V8TRYCATCH_VOID(v8::Local<v8::Function>, onRejected, createClosure(promiseRejectCallback, promise, isolate));
|
|
|
| for (unsigned i = 0, length = iterable->Length(); i < length; ++i) {
|
| // Array-holes should not be skipped by for-of iteration semantics.
|
| V8TRYCATCH_VOID(v8::Local<v8::Value>, nextValue, iterable->Get(i));
|
| - v8::Local<v8::Object> nextPromise = V8PromiseCustom::toPromise(nextValue, isolate);
|
| - V8PromiseCustom::then(nextPromise, onFulfilled, onRejected, isolate);
|
| + V8TRYCATCH_VOID(v8::Local<v8::Object>, nextPromise, V8PromiseCustom::toPromise(nextValue, isolate));
|
| + V8TRYCATCH_VOID(v8::Local<v8::Value>, unused, V8PromiseCustom::then(nextPromise, onFulfilled, onRejected, isolate));
|
| }
|
| v8SetReturnValue(info, promise);
|
| }
|
| @@ -598,7 +605,7 @@ void V8Promise::raceMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info
|
| void V8Promise::allMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
|
| {
|
| v8::Isolate* isolate = info.GetIsolate();
|
| - v8::Local<v8::Object> promise = V8PromiseCustom::createPromise(info.Holder(), isolate);
|
| + V8TRYCATCH_VOID(v8::Local<v8::Object>, promise, V8PromiseCustom::createPromise(info.Holder(), isolate));
|
| v8::Local<v8::Array> results = v8::Array::New(info.GetIsolate());
|
|
|
| if (!info.Length() || !info[0]->IsArray()) {
|
| @@ -617,17 +624,17 @@ void V8Promise::allMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
|
| }
|
|
|
| v8::Local<v8::ObjectTemplate> objectTemplate = primitiveWrapperObjectTemplate(isolate);
|
| - v8::Local<v8::Object> countdownWrapper = objectTemplate->NewInstance();
|
| + V8TRYCATCH_VOID(v8::Local<v8::Object>, countdownWrapper, objectTemplate->NewInstance());
|
| countdownWrapper->SetInternalField(V8PromiseCustom::PrimitiveWrapperPrimitiveIndex, v8::Integer::New(isolate, iterable->Length()));
|
|
|
| - v8::Local<v8::Function> onRejected = createClosure(promiseRejectCallback, promise, isolate);
|
| + V8TRYCATCH_VOID(v8::Local<v8::Function>, onRejected, createClosure(promiseRejectCallback, promise, isolate));
|
| for (unsigned i = 0, length = iterable->Length(); i < length; ++i) {
|
| // Array-holes should not be skipped by for-of iteration semantics.
|
| - v8::Local<v8::Object> environment = promiseAllEnvironment(promise, countdownWrapper, i, results, isolate);
|
| - v8::Local<v8::Function> onFulfilled = createClosure(promiseAllFulfillCallback, environment, isolate);
|
| + V8TRYCATCH_VOID(v8::Local<v8::Object>, environment, promiseAllEnvironment(promise, countdownWrapper, i, results, isolate));
|
| + V8TRYCATCH_VOID(v8::Local<v8::Function>, onFulfilled, createClosure(promiseAllFulfillCallback, environment, isolate));
|
| V8TRYCATCH_VOID(v8::Local<v8::Value>, nextValue, iterable->Get(i));
|
| - v8::Local<v8::Object> nextPromise = V8PromiseCustom::toPromise(nextValue, isolate);
|
| - V8PromiseCustom::then(nextPromise, onFulfilled, onRejected, isolate);
|
| + V8TRYCATCH_VOID(v8::Local<v8::Object>, nextPromise, V8PromiseCustom::toPromise(nextValue, isolate));
|
| + V8TRYCATCH_VOID(v8::Local<v8::Value>, unused, V8PromiseCustom::then(nextPromise, onFulfilled, onRejected, isolate));
|
| }
|
| v8SetReturnValue(info, promise);
|
| }
|
| @@ -638,6 +645,8 @@ v8::Local<v8::Object> V8PromiseCustom::createPromise(v8::Handle<v8::Object> crea
|
| {
|
| v8::Local<v8::ObjectTemplate> internalTemplate = internalObjectTemplate(isolate);
|
| v8::Local<v8::Object> internal = internalTemplate->NewInstance();
|
| + if (internal.IsEmpty())
|
| + return v8::Local<v8::Object>();
|
| v8::Local<v8::Object> promise = V8DOMWrapper::createWrapper(creationContext, &V8Promise::wrapperTypeInfo, 0, isolate);
|
|
|
| clearDerived(internal, isolate);
|
| @@ -684,6 +693,8 @@ v8::Local<v8::Object> V8PromiseCustom::toPromise(v8::Handle<v8::Value> maybeProm
|
| return maybePromise.As<v8::Object>();
|
|
|
| v8::Local<v8::Object> promise = createPromise(v8::Handle<v8::Object>(), isolate);
|
| + if (promise.IsEmpty())
|
| + return v8::Local<v8::Object>();
|
| resolve(promise, maybePromise, isolate);
|
| return promise;
|
| }
|
| @@ -741,6 +752,8 @@ v8::Local<v8::Object> V8PromiseCustom::then(v8::Handle<v8::Object> promise, v8::
|
| // the creation of the promise objects only from the Blink Promise
|
| // constructor.
|
| v8::Local<v8::Object> derivedPromise = createPromise(v8::Handle<v8::Object>(), isolate);
|
| + if (derivedPromise.IsEmpty())
|
| + return v8::Local<v8::Object>();
|
| updateDerivedFromPromise(derivedPromise, onFulfilled, onRejected, promise, isolate);
|
| return derivedPromise;
|
| }
|
| @@ -799,10 +812,16 @@ v8::Local<v8::Object> V8PromiseCustom::coerceThenable(v8::Handle<v8::Object> the
|
| ASSERT(!thenable.IsEmpty());
|
| ASSERT(!then.IsEmpty());
|
| v8::Local<v8::Object> promise = createPromise(v8::Handle<v8::Object>(), isolate);
|
| - v8::Handle<v8::Value> argv[] = {
|
| - createClosure(promiseResolveCallback, promise, isolate),
|
| - createClosure(promiseRejectCallback, promise, isolate)
|
| - };
|
| + if (promise.IsEmpty())
|
| + return v8::Local<v8::Object>();
|
| + v8::Handle<v8::Value> onFulfilled = createClosure(promiseResolveCallback, promise, isolate);
|
| + if (onFulfilled.IsEmpty())
|
| + return v8::Local<v8::Object>();
|
| + v8::Handle<v8::Value> onRejected = createClosure(promiseRejectCallback, promise, isolate);
|
| + if (onRejected.IsEmpty())
|
| + return v8::Local<v8::Object>();
|
| + v8::Handle<v8::Value> argv[] = { onFulfilled, onRejected };
|
| +
|
| v8::TryCatch trycatch;
|
| if (V8ScriptRunner::callFunction(then, currentExecutionContext(isolate), thenable, WTF_ARRAY_LENGTH(argv), argv, isolate).IsEmpty()) {
|
| reject(promise, trycatch.Exception(), isolate);
|
|
|