From 0bbce93c83d3f73f91ee6e8cb8906b9884715db1 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Wed, 25 Nov 2015 15:48:09 -0500 Subject: [PATCH] Bug 1170760 part 11. Add subclassing support to Promise::Reject. r=baku,efaust --- browser/base/content/sync/aboutSyncTabs.js | 2 +- dom/promise/Promise.cpp | 48 ++++++++++++++++--- dom/promise/Promise.h | 5 +- dom/promise/tests/test_bug883683.html | 2 +- dom/promise/tests/test_promise_xrays.html | 14 ++++++ dom/webidl/Promise.webidl | 4 +- services/cloudsync/CloudSyncBookmarks.jsm | 12 ++--- .../js/builtins/Promise-subclassing.html | 11 +++++ 8 files changed, 79 insertions(+), 19 deletions(-) diff --git a/browser/base/content/sync/aboutSyncTabs.js b/browser/base/content/sync/aboutSyncTabs.js index 01057047f9b8..afaa5db3bd5b 100644 --- a/browser/base/content/sync/aboutSyncTabs.js +++ b/browser/base/content/sync/aboutSyncTabs.js @@ -273,7 +273,7 @@ var RemoteTabViewer = { }.bind(this); return CloudSync().tabs.getRemoteTabs() - .then(updateTabList, Promise.reject); + .then(updateTabList, Promise.reject.bind(Promise)); }, adjustContextMenu: function (event) { diff --git a/dom/promise/Promise.cpp b/dom/promise/Promise.cpp index c54cfd7520cd..6b199af795e0 100644 --- a/dom/promise/Promise.cpp +++ b/dom/promise/Promise.cpp @@ -1092,22 +1092,56 @@ Promise::Resolve(nsIGlobalObject* aGlobal, JSContext* aCx, return promise.forget(); } -/* static */ already_AddRefed +/* static */ void Promise::Reject(const GlobalObject& aGlobal, JS::Handle aThisv, - JS::Handle aValue, ErrorResult& aRv) + JS::Handle aValue, + JS::MutableHandle aRetval, ErrorResult& aRv) { + // Implementation of + // http://www.ecma-international.org/ecma-262/6.0/#sec-promise.reject + + JSContext* cx = aGlobal.Context(); + nsCOMPtr global = do_QueryInterface(aGlobal.GetAsSupports()); if (!global) { aRv.Throw(NS_ERROR_UNEXPECTED); - return nullptr; + return; } - RefPtr p = Reject(global, aGlobal.Context(), aValue, aRv); - if (p) { - p->mRejectionStack = p->mAllocationStack; + // Steps 1 and 2. + if (!aThisv.isObject()) { + aRv.ThrowTypeError(); + return; } - return p.forget(); + + // Step 3. + PromiseCapability capability(cx); + NewPromiseCapability(cx, global, aThisv, false, capability, aRv); + // Step 4. + if (aRv.Failed()) { + return; + } + + // Step 5. + Promise* p = capability.mNativePromise; + if (p) { + p->MaybeRejectInternal(cx, aValue); + p->mRejectionStack = p->mAllocationStack; + } else { + JS::Rooted value(cx, aValue); + JS::Rooted ignored(cx); + if (!JS::Call(cx, JS::UndefinedHandleValue /* thisVal */, + capability.mReject, JS::HandleValueArray(value), + &ignored)) { + // Step 6. + aRv.NoteJSContextException(); + return; + } + } + + // Step 7. + aRetval.set(capability.PromiseValue()); } /* static */ already_AddRefed diff --git a/dom/promise/Promise.h b/dom/promise/Promise.h index 40a95286865b..5e7a371c0c80 100644 --- a/dom/promise/Promise.h +++ b/dom/promise/Promise.h @@ -172,9 +172,10 @@ public: Resolve(nsIGlobalObject* aGlobal, JSContext* aCx, JS::Handle aValue, ErrorResult& aRv); - static already_AddRefed + static void Reject(const GlobalObject& aGlobal, JS::Handle aThisv, - JS::Handle aValue, ErrorResult& aRv); + JS::Handle aValue, + JS::MutableHandle aRetval, ErrorResult& aRv); static already_AddRefed Reject(nsIGlobalObject* aGlobal, JSContext* aCx, diff --git a/dom/promise/tests/test_bug883683.html b/dom/promise/tests/test_bug883683.html index 866fdd6a5df9..ab23ca10d462 100644 --- a/dom/promise/tests/test_bug883683.html +++ b/dom/promise/tests/test_bug883683.html @@ -17,7 +17,7 @@