Bug 1453339. Make it harder to mess up Promise::All. r=peterv

MozReview-Commit-ID: UO4wssYHj7
This commit is contained in:
Boris Zbarsky 2018-04-13 19:31:42 -04:00
parent e5e108a524
commit ecac16fefa
5 changed files with 29 additions and 35 deletions

View File

@ -395,8 +395,6 @@ nsFrameLoader::FireWillChangeProcessEvent()
return nullptr; return nullptr;
} }
JSContext* cx = jsapi.cx(); JSContext* cx = jsapi.cx();
GlobalObject global(cx, mOwnerContent->GetOwnerGlobal()->GetGlobalJSObject());
MOZ_ASSERT(!global.Failed());
// Set our mBrowserChangingProcessBlockers property to refer to the blockers // Set our mBrowserChangingProcessBlockers property to refer to the blockers
// list. We will synchronously dispatch a DOM event to collect this list of // list. We will synchronously dispatch a DOM event to collect this list of
@ -418,7 +416,7 @@ nsFrameLoader::FireWillChangeProcessEvent()
mBrowserChangingProcessBlockers = nullptr; mBrowserChangingProcessBlockers = nullptr;
ErrorResult rv; ErrorResult rv;
RefPtr<Promise> allPromise = Promise::All(global, blockers, rv); RefPtr<Promise> allPromise = Promise::All(cx, blockers, rv);
return allPromise.forget(); return allPromise.forget();
} }

2
dom/cache/Cache.cpp vendored
View File

@ -630,7 +630,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

@ -135,37 +135,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

@ -111,23 +111,26 @@ public:
return mGlobal; return mGlobal;
} }
// 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

@ -346,17 +346,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