Bug 1453339 - Make it harder to mess up Promise::All. r=peterv, a=RyanVM

MozReview-Commit-ID: UO4wssYHj7
This commit is contained in:
Boris Zbarsky 2018-04-12 23:26:44 -04:00 • committed by Roy Tam
commit 72c04aea04
5 changed files with 29 additions and 35 deletions

2
dom/cache/Cache.cpp vendored
View file

@ -618,7 +618,7 @@ Cache::AddAll(const GlobalObject& aGlobal,
new FetchHandler(mActor->GetWorkerHolder(), this, new FetchHandler(mActor->GetWorkerHolder(), this,
Move(aRequestList), promise); Move(aRequestList), promise);
RefPtr<Promise> fetchPromise = Promise::All(aGlobal, fetchList, aRv); RefPtr<Promise> fetchPromise = Promise::All(aGlobal.Context(), fetchList, aRv);
if (NS_WARN_IF(aRv.Failed())) { if (NS_WARN_IF(aRv.Failed())) {
return nullptr; return nullptr;
} }

View file

@ -561,37 +561,40 @@ Promise::Reject(nsIGlobalObject* aGlobal, JSContext* aCx,
// static // static
already_AddRefed<Promise> already_AddRefed<Promise>
Promise::All(const GlobalObject& aGlobal, Promise::All(JSContext* aCx,
const nsTArray<RefPtr<Promise>>& aPromiseList, ErrorResult& aRv) const nsTArray<RefPtr<Promise>>& aPromiseList, ErrorResult& aRv)
{ {
nsCOMPtr<nsIGlobalObject> global; JS::Rooted<JSObject*> globalObj(aCx, JS::CurrentGlobalOrNull(aCx));
global = do_QueryInterface(aGlobal.GetAsSupports()); if (!globalObj) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
nsCOMPtr<nsIGlobalObject> global = xpc::NativeGlobal(globalObj);
if (!global) { if (!global) {
aRv.Throw(NS_ERROR_UNEXPECTED); aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr; return nullptr;
} }
JSContext* cx = aGlobal.Context(); JS::AutoObjectVector promises(aCx);
JS::AutoObjectVector promises(cx);
if (!promises.reserve(aPromiseList.Length())) { if (!promises.reserve(aPromiseList.Length())) {
aRv.NoteJSContextException(cx); aRv.NoteJSContextException(aCx);
return nullptr; return nullptr;
} }
for (auto& promise : aPromiseList) { for (auto& promise : aPromiseList) {
JS::Rooted<JSObject*> promiseObj(cx, promise->PromiseObj()); JS::Rooted<JSObject*> promiseObj(aCx, promise->PromiseObj());
// Just in case, make sure these are all in the context compartment. // Just in case, make sure these are all in the context compartment.
if (!JS_WrapObject(cx, &promiseObj)) { if (!JS_WrapObject(aCx, &promiseObj)) {
aRv.NoteJSContextException(cx); aRv.NoteJSContextException(aCx);
return nullptr; return nullptr;
} }
promises.infallibleAppend(promiseObj); promises.infallibleAppend(promiseObj);
} }
JS::Rooted<JSObject*> result(cx, JS::GetWaitForAllPromise(cx, promises)); JS::Rooted<JSObject*> result(aCx, JS::GetWaitForAllPromise(aCx, promises));
if (!result) { if (!result) {
aRv.NoteJSContextException(cx); aRv.NoteJSContextException(aCx);
return nullptr; return nullptr;
} }

View file

@ -188,23 +188,26 @@ public:
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto, WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto,
JS::MutableHandle<JSObject*> aWrapper); JS::MutableHandle<JSObject*> aWrapper);
// Do the equivalent of Promise.resolve in the current compartment of aCx. // Do the equivalent of Promise.resolve in the compartment of aGlobal. The
// Errorrs are reported on the ErrorResult; if aRv comes back !Failed(), this // compartment of aCx is ignored. Errors are reported on the ErrorResult; if
// function MUST return a non-null value. // aRv comes back !Failed(), this function MUST return a non-null value.
static already_AddRefed<Promise> static already_AddRefed<Promise>
Resolve(nsIGlobalObject* aGlobal, JSContext* aCx, Resolve(nsIGlobalObject* aGlobal, JSContext* aCx,
JS::Handle<JS::Value> aValue, ErrorResult& aRv); JS::Handle<JS::Value> aValue, ErrorResult& aRv);
// Do the equivalent of Promise.reject in the current compartment of aCx. // Do the equivalent of Promise.reject in the compartment of aGlobal. The
// Errorrs are reported on the ErrorResult; if aRv comes back !Failed(), this // compartment of aCx is ignored. Errors are reported on the ErrorResult; if
// function MUST return a non-null value. // aRv comes back !Failed(), this function MUST return a non-null value.
static already_AddRefed<Promise> static already_AddRefed<Promise>
Reject(nsIGlobalObject* aGlobal, JSContext* aCx, Reject(nsIGlobalObject* aGlobal, JSContext* aCx,
JS::Handle<JS::Value> aValue, ErrorResult& aRv); JS::Handle<JS::Value> aValue, ErrorResult& aRv);
// Do the equivalent of Promise.all in the current compartment of aCx. Errors
// are reported on the ErrorResult; if aRv comes back !Failed(), this function
// MUST return a non-null value.
static already_AddRefed<Promise> static already_AddRefed<Promise>
All(const GlobalObject& aGlobal, All(JSContext* aCx, const nsTArray<RefPtr<Promise>>& aPromiseList,
const nsTArray<RefPtr<Promise>>& aPromiseList, ErrorResult& aRv); ErrorResult& aRv);
void void
Then(JSContext* aCx, Then(JSContext* aCx,

View file

@ -948,10 +948,8 @@ ExtendableEvent::GetPromise()
} }
JSContext* cx = jsapi.cx(); JSContext* cx = jsapi.cx();
GlobalObject global(cx, globalObj->GetGlobalJSObject());
ErrorResult result; ErrorResult result;
RefPtr<Promise> p = Promise::All(global, Move(mPromises), result); RefPtr<Promise> p = Promise::All(cx, Move(mPromises), result);
if (NS_WARN_IF(result.MaybeSetPendingException(cx))) { if (NS_WARN_IF(result.MaybeSetPendingException(cx))) {
return nullptr; return nullptr;
} }

View file

@ -343,17 +343,7 @@ FontFaceSet::Load(JSContext* aCx,
} }
} }
nsIGlobalObject* globalObject = GetParentObject(); return Promise::All(aCx, promises, aRv);
if (!globalObject) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
JS::Rooted<JSObject*> jsGlobal(aCx, globalObject->GetGlobalJSObject());
GlobalObject global(aCx, jsGlobal);
RefPtr<Promise> result = Promise::All(global, promises, aRv);
return result.forget();
} }
bool bool