Backed out 3 changesets (bug 1456466) for mochitest failures in /builds/worker/workspace/build/src/obj-firefox/dist/include/mozilla/MozPromise.h on a CLOSED TREE
authorNoemi Erli <nerli@mozilla.com>
Tue, 24 Apr 2018 17:23:09 +0300
changeset 468905 b2a75639bd93809b0fb7d1be9393d18e7c85fd92
parent 468904 88b650567a7f57d782abea7cc2936550ea362e89
child 468906 6bf0f720c39d997ffcb8f3c31367f6707a4df823
push id9165
push userasasaki@mozilla.com
push dateThu, 26 Apr 2018 21:04:54 +0000
treeherdermozilla-beta@064c3804de2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1456466
milestone61.0a1
backs outfd0feb0058fc93361dc94df776a9fea43c0aab82
e3a50afee79e2212c1590430a080d7552d3cd491
89ce7df053441fe04350dbdb0100d011fa8ef5e7
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 3 changesets (bug 1456466) for mochitest failures in /builds/worker/workspace/build/src/obj-firefox/dist/include/mozilla/MozPromise.h on a CLOSED TREE Backed out changeset fd0feb0058fc (bug 1456466) Backed out changeset e3a50afee79e (bug 1456466) Backed out changeset 89ce7df05344 (bug 1456466)
dom/serviceworkers/ServiceWorkerDescriptor.cpp
dom/serviceworkers/ServiceWorkerDescriptor.h
dom/serviceworkers/ServiceWorkerRegistration.cpp
dom/serviceworkers/ServiceWorkerRegistration.h
dom/serviceworkers/ServiceWorkerRegistrationDescriptor.cpp
dom/serviceworkers/ServiceWorkerRegistrationDescriptor.h
dom/serviceworkers/ServiceWorkerRegistrationImpl.cpp
dom/serviceworkers/ServiceWorkerRegistrationImpl.h
dom/serviceworkers/test/worker_update.js
testing/web-platform/meta/MANIFEST.json
testing/web-platform/tests/service-workers/service-worker/update-result.https.html
--- a/dom/serviceworkers/ServiceWorkerDescriptor.cpp
+++ b/dom/serviceworkers/ServiceWorkerDescriptor.cpp
@@ -7,19 +7,16 @@
 #include "ServiceWorkerDescriptor.h"
 #include "mozilla/dom/IPCServiceWorkerDescriptor.h"
 #include "mozilla/dom/ServiceWorkerBinding.h"
 #include "mozilla/ipc/PBackgroundSharedTypes.h"
 
 namespace mozilla {
 namespace dom {
 
-using mozilla::ipc::PrincipalInfo;
-using mozilla::ipc::PrincipalInfoToPrincipal;
-
 ServiceWorkerDescriptor::ServiceWorkerDescriptor(uint64_t aId,
                                                  nsIPrincipal* aPrincipal,
                                                  const nsACString& aScope,
                                                  const nsACString& aScriptURL,
                                                  ServiceWorkerState aState)
   : mData(MakeUnique<IPCServiceWorkerDescriptor>())
 {
   MOZ_ALWAYS_SUCCEEDS(
@@ -93,24 +90,16 @@ ServiceWorkerDescriptor::Id() const
 }
 
 const mozilla::ipc::PrincipalInfo&
 ServiceWorkerDescriptor::PrincipalInfo() const
 {
   return mData->principalInfo();
 }
 
-nsCOMPtr<nsIPrincipal>
-ServiceWorkerDescriptor::GetPrincipal() const
-{
-  AssertIsOnMainThread();
-  nsCOMPtr<nsIPrincipal> ref =  PrincipalInfoToPrincipal(mData->principalInfo());
-  return Move(ref);
-}
-
 const nsCString&
 ServiceWorkerDescriptor::Scope() const
 {
   return mData->scope();
 }
 
 const nsCString&
 ServiceWorkerDescriptor::ScriptURL() const
--- a/dom/serviceworkers/ServiceWorkerDescriptor.h
+++ b/dom/serviceworkers/ServiceWorkerDescriptor.h
@@ -2,17 +2,16 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #ifndef _mozilla_dom_ServiceWorkerDescriptor_h
 #define _mozilla_dom_ServiceWorkerDescriptor_h
 
 #include "mozilla/UniquePtr.h"
-#include "nsCOMPtr.h"
 #include "nsString.h"
 
 class nsIPrincipal;
 
 namespace mozilla {
 
 namespace ipc {
 class PrincipalInfo;
@@ -65,19 +64,16 @@ public:
   operator==(const ServiceWorkerDescriptor& aRight) const;
 
   uint64_t
   Id() const;
 
   const mozilla::ipc::PrincipalInfo&
   PrincipalInfo() const;
 
-  nsCOMPtr<nsIPrincipal>
-  GetPrincipal() const;
-
   const nsCString&
   Scope() const;
 
   const nsCString&
   ScriptURL() const;
 
   ServiceWorkerState
   State() const;
--- a/dom/serviceworkers/ServiceWorkerRegistration.cpp
+++ b/dom/serviceworkers/ServiceWorkerRegistration.cpp
@@ -193,50 +193,17 @@ ServiceWorkerRegistration::GetUpdateViaC
 
 already_AddRefed<Promise>
 ServiceWorkerRegistration::Update(ErrorResult& aRv)
 {
   if (!mInner) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return nullptr;
   }
-
-  nsIGlobalObject* global = GetParentObject();
-  if (!global) {
-    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
-    return nullptr;
-  }
-
-  RefPtr<Promise> outer = Promise::Create(global, aRv);
-  if (NS_WARN_IF(aRv.Failed())) {
-    return nullptr;
-  }
-
-  RefPtr<ServiceWorkerRegistration> self = this;
-
-  mInner->Update(aRv)->Then(
-    global->EventTargetFor(TaskCategory::Other), __func__,
-    [outer, self](const ServiceWorkerRegistrationDescriptor& aDesc) {
-      nsIGlobalObject* global = self->GetParentObject();
-      if (!global) {
-        outer->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
-        return;
-      }
-      RefPtr<ServiceWorkerRegistration> ref =
-        global->GetOrCreateServiceWorkerRegistration(aDesc);
-      if (!ref) {
-        outer->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
-        return;
-      }
-      outer->MaybeResolve(ref);
-    }, [outer] (ErrorResult&& aRv) {
-      outer->MaybeReject(aRv);
-    });
-
-  return outer.forget();
+  return mInner->Update(aRv);
 }
 
 already_AddRefed<Promise>
 ServiceWorkerRegistration::Unregister(ErrorResult& aRv)
 {
   if (!mInner) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return nullptr;
--- a/dom/serviceworkers/ServiceWorkerRegistration.h
+++ b/dom/serviceworkers/ServiceWorkerRegistration.h
@@ -7,17 +7,16 @@
 #ifndef mozilla_dom_ServiceWorkerRegistration_h
 #define mozilla_dom_ServiceWorkerRegistration_h
 
 #include "mozilla/DOMEventTargetHelper.h"
 #include "mozilla/dom/DOMPrefs.h"
 #include "mozilla/dom/ServiceWorkerBinding.h"
 #include "mozilla/dom/ServiceWorkerRegistrationBinding.h"
 #include "mozilla/dom/ServiceWorkerRegistrationDescriptor.h"
-#include "mozilla/dom/ServiceWorkerUtils.h"
 
 // Support for Notification API extension.
 #include "mozilla/dom/NotificationBinding.h"
 
 class nsIGlobalObject;
 
 namespace mozilla {
 namespace dom {
@@ -39,17 +38,17 @@ public:
     NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
 
     virtual void
     SetServiceWorkerRegistration(ServiceWorkerRegistration* aReg) = 0;
 
     virtual void
     ClearServiceWorkerRegistration(ServiceWorkerRegistration* aReg) = 0;
 
-    virtual RefPtr<ServiceWorkerRegistrationPromise>
+    virtual already_AddRefed<Promise>
     Update(ErrorResult& aRv) = 0;
 
     virtual already_AddRefed<Promise>
     Unregister(ErrorResult& aRv) = 0;
 
     virtual already_AddRefed<Promise>
     ShowNotification(JSContext* aCx,
                      const nsAString& aTitle,
--- a/dom/serviceworkers/ServiceWorkerRegistrationDescriptor.cpp
+++ b/dom/serviceworkers/ServiceWorkerRegistrationDescriptor.cpp
@@ -8,19 +8,16 @@
 
 #include "mozilla/dom/IPCServiceWorkerRegistrationDescriptor.h"
 #include "mozilla/ipc/PBackgroundSharedTypes.h"
 #include "ServiceWorkerInfo.h"
 
 namespace mozilla {
 namespace dom {
 
-using mozilla::ipc::PrincipalInfo;
-using mozilla::ipc::PrincipalInfoToPrincipal;
-
 Maybe<IPCServiceWorkerDescriptor>
 ServiceWorkerRegistrationDescriptor::NewestInternal() const
 {
   Maybe<IPCServiceWorkerDescriptor> result;
   if (mData->installing().type() != OptionalIPCServiceWorkerDescriptor::Tvoid_t) {
     result.emplace(mData->installing().get_IPCServiceWorkerDescriptor());
   } else if (mData->waiting().type() != OptionalIPCServiceWorkerDescriptor::Tvoid_t) {
     result.emplace(mData->waiting().get_IPCServiceWorkerDescriptor());
@@ -128,24 +125,16 @@ ServiceWorkerRegistrationDescriptor::Upd
 }
 
 const mozilla::ipc::PrincipalInfo&
 ServiceWorkerRegistrationDescriptor::PrincipalInfo() const
 {
   return mData->principalInfo();
 }
 
-nsCOMPtr<nsIPrincipal>
-ServiceWorkerRegistrationDescriptor::GetPrincipal() const
-{
-  AssertIsOnMainThread();
-  nsCOMPtr<nsIPrincipal> ref =  PrincipalInfoToPrincipal(mData->principalInfo());
-  return Move(ref);
-}
-
 const nsCString&
 ServiceWorkerRegistrationDescriptor::Scope() const
 {
   return mData->scope();
 }
 
 Maybe<ServiceWorkerDescriptor>
 ServiceWorkerRegistrationDescriptor::GetInstalling() const
--- a/dom/serviceworkers/ServiceWorkerRegistrationDescriptor.h
+++ b/dom/serviceworkers/ServiceWorkerRegistrationDescriptor.h
@@ -68,19 +68,16 @@ public:
   Id() const;
 
   ServiceWorkerUpdateViaCache
   UpdateViaCache() const;
 
   const mozilla::ipc::PrincipalInfo&
   PrincipalInfo() const;
 
-  nsCOMPtr<nsIPrincipal>
-  GetPrincipal() const;
-
   const nsCString&
   Scope() const;
 
   Maybe<ServiceWorkerDescriptor>
   GetInstalling() const;
 
   Maybe<ServiceWorkerDescriptor>
   GetWaiting() const;
--- a/dom/serviceworkers/ServiceWorkerRegistrationImpl.cpp
+++ b/dom/serviceworkers/ServiceWorkerRegistrationImpl.cpp
@@ -38,17 +38,16 @@
 namespace mozilla {
 namespace dom {
 
 ////////////////////////////////////////////////////
 // Main Thread implementation
 
 ServiceWorkerRegistrationMainThread::ServiceWorkerRegistrationMainThread(const ServiceWorkerRegistrationDescriptor& aDescriptor)
   : mOuter(nullptr)
-  , mDescriptor(aDescriptor)
   , mScope(NS_ConvertUTF8toUTF16(aDescriptor.Scope()))
   , mListeningForEvents(false)
 {
   MOZ_ASSERT(NS_IsMainThread());
 }
 
 ServiceWorkerRegistrationMainThread::~ServiceWorkerRegistrationMainThread()
 {
@@ -102,17 +101,16 @@ void
 ServiceWorkerRegistrationMainThread::UpdateFound()
 {
   mOuter->DispatchTrustedEvent(NS_LITERAL_STRING("updatefound"));
 }
 
 void
 ServiceWorkerRegistrationMainThread::UpdateState(const ServiceWorkerRegistrationDescriptor& aDescriptor)
 {
-  mDescriptor = aDescriptor;
   mOuter->UpdateState(aDescriptor);
 }
 
 void
 ServiceWorkerRegistrationMainThread::RegistrationRemoved()
 {
   // Queue a runnable to clean up the registration.  This is necessary
   // because there may be runnables in the event queue already to
@@ -165,71 +163,141 @@ UpdateInternal(nsIPrincipal* aPrincipal,
     return;
   }
 
   swm->Update(aPrincipal, aScope, aCallback);
 }
 
 class MainThreadUpdateCallback final : public ServiceWorkerUpdateFinishCallback
 {
-  RefPtr<ServiceWorkerRegistrationPromise::Private> mPromise;
+  PromiseWindowProxy mPromise;
 
   ~MainThreadUpdateCallback()
   { }
 
 public:
-  MainThreadUpdateCallback()
-    : mPromise(new ServiceWorkerRegistrationPromise::Private(__func__))
-  {
-  }
-
-  void
-  UpdateSucceeded(ServiceWorkerRegistrationInfo* aRegistration) override
-  {
-    mPromise->Resolve(aRegistration->Descriptor(), __func__);
-  }
-
-  void
-  UpdateFailed(ErrorResult& aStatus) override
-  {
-    mPromise->Reject(Move(aStatus), __func__);
-  }
-
-  RefPtr<ServiceWorkerRegistrationPromise>
-  Promise() const
-  {
-    return mPromise;
-  }
-};
-
-class WorkerThreadUpdateCallback final : public ServiceWorkerUpdateFinishCallback
-{
-  RefPtr<ServiceWorkerRegistrationPromise::Private> mPromise;
-
-  ~WorkerThreadUpdateCallback()
-  {
-  }
-
-public:
-  explicit WorkerThreadUpdateCallback(ServiceWorkerRegistrationPromise::Private* aPromise)
-    : mPromise(aPromise)
+  explicit MainThreadUpdateCallback(nsPIDOMWindowInner* aWindow,
+                                    Promise* aPromise)
+    : mPromise(aWindow, aPromise)
   {
     MOZ_ASSERT(NS_IsMainThread());
   }
 
   void
   UpdateSucceeded(ServiceWorkerRegistrationInfo* aRegistration) override
   {
-    mPromise->Resolve(aRegistration->Descriptor(), __func__);
+    RefPtr<Promise> promise = mPromise.Get();
+    nsCOMPtr<nsPIDOMWindowInner> win = mPromise.GetWindow();
+    if (!promise || !win) {
+      return;
+    }
+
+    nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
+      "MainThreadUpdateCallback::UpdateSucceeded",
+      [promise = Move(promise)] () {
+        promise->MaybeResolveWithUndefined();
+      });
+    MOZ_ALWAYS_SUCCEEDS(
+      win->EventTargetFor(TaskCategory::Other)->Dispatch(r.forget()));
   }
 
   void
   UpdateFailed(ErrorResult& aStatus) override
   {
-    mPromise->Reject(Move(aStatus), __func__);
+    if (RefPtr<Promise> promise = mPromise.Get()) {
+      promise->MaybeReject(aStatus);
+    }
+  }
+};
+
+class UpdateResultRunnable final : public WorkerRunnable
+{
+  RefPtr<PromiseWorkerProxy> mPromiseProxy;
+  IPC::Message mSerializedErrorResult;
+
+  ~UpdateResultRunnable()
+  {}
+
+public:
+  UpdateResultRunnable(PromiseWorkerProxy* aPromiseProxy, ErrorResult& aStatus)
+    : WorkerRunnable(aPromiseProxy->GetWorkerPrivate())
+    , mPromiseProxy(aPromiseProxy)
+  {
+    // ErrorResult is not thread safe.  Serialize it for transfer across
+    // threads.
+    IPC::WriteParam(&mSerializedErrorResult, aStatus);
+    aStatus.SuppressException();
+  }
+
+  bool
+  WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
+  {
+    // Deserialize the ErrorResult now that we are back in the worker
+    // thread.
+    ErrorResult status;
+    PickleIterator iter = PickleIterator(mSerializedErrorResult);
+    Unused << IPC::ReadParam(&mSerializedErrorResult, &iter, &status);
+
+    Promise* promise = mPromiseProxy->WorkerPromise();
+    if (status.Failed()) {
+      promise->MaybeReject(status);
+    } else {
+      promise->MaybeResolveWithUndefined();
+    }
+    status.SuppressException();
+    mPromiseProxy->CleanUp();
+    return true;
+  }
+};
+
+class WorkerThreadUpdateCallback final : public ServiceWorkerUpdateFinishCallback
+{
+  RefPtr<PromiseWorkerProxy> mPromiseProxy;
+
+  ~WorkerThreadUpdateCallback()
+  {
+  }
+
+public:
+  explicit WorkerThreadUpdateCallback(PromiseWorkerProxy* aPromiseProxy)
+    : mPromiseProxy(aPromiseProxy)
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+  }
+
+  void
+  UpdateSucceeded(ServiceWorkerRegistrationInfo* aRegistration) override
+  {
+    ErrorResult rv(NS_OK);
+    Finish(rv);
+  }
+
+  void
+  UpdateFailed(ErrorResult& aStatus) override
+  {
+    Finish(aStatus);
+  }
+
+  void
+  Finish(ErrorResult& aStatus)
+  {
+    if (!mPromiseProxy) {
+      return;
+    }
+
+    RefPtr<PromiseWorkerProxy> proxy = mPromiseProxy.forget();
+
+    MutexAutoLock lock(proxy->Lock());
+    if (proxy->CleanedUp()) {
+      return;
+    }
+
+    RefPtr<UpdateResultRunnable> r =
+      new UpdateResultRunnable(proxy, aStatus);
+    r->Dispatch();
   }
 };
 
 class SWRUpdateRunnable final : public Runnable
 {
   class TimerCallback final : public nsITimerCallback
   {
     RefPtr<ServiceWorkerPrivate> mPrivate;
@@ -257,39 +325,52 @@ class SWRUpdateRunnable final : public R
     NS_DECL_THREADSAFE_ISUPPORTS
 
   private:
     ~TimerCallback()
     { }
   };
 
 public:
-  explicit SWRUpdateRunnable(const ServiceWorkerDescriptor& aDescriptor)
+  explicit SWRUpdateRunnable(PromiseWorkerProxy* aPromiseProxy)
     : Runnable("dom::SWRUpdateRunnable")
-    , mPromise(new ServiceWorkerRegistrationPromise::Private(__func__))
-    , mDescriptor(aDescriptor)
+    , mPromiseProxy(aPromiseProxy)
+    , mDescriptor(aPromiseProxy->GetWorkerPrivate()->GetServiceWorkerDescriptor())
     , mDelayed(false)
   {
+    MOZ_ASSERT(mPromiseProxy);
+
+    // This runnable is used for update calls originating from a worker thread,
+    // which may be delayed in some cases.
+    MOZ_ASSERT(mPromiseProxy->GetWorkerPrivate()->IsServiceWorker());
+    MOZ_ASSERT(mPromiseProxy->GetWorkerPrivate());
+    mPromiseProxy->GetWorkerPrivate()->AssertIsOnWorkerThread();
   }
 
   NS_IMETHOD
   Run() override
   {
     MOZ_ASSERT(NS_IsMainThread());
     ErrorResult result;
 
-    nsCOMPtr<nsIPrincipal> principal = mDescriptor.GetPrincipal();
-    if (NS_WARN_IF(!principal)) {
-      mPromise->Reject(NS_ERROR_DOM_INVALID_STATE_ERR, __func__);
-      return NS_OK;
+    nsCOMPtr<nsIPrincipal> principal;
+    // UpdateInternal may try to reject the promise synchronously leading
+    // to a deadlock.
+    {
+      MutexAutoLock lock(mPromiseProxy->Lock());
+      if (mPromiseProxy->CleanedUp()) {
+        return NS_OK;
+      }
+
+      principal = mPromiseProxy->GetWorkerPrivate()->GetPrincipal();
     }
+    MOZ_ASSERT(principal);
 
     RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
     if (NS_WARN_IF(!swm)) {
-      mPromise->Reject(NS_ERROR_DOM_INVALID_STATE_ERR, __func__);
       return NS_OK;
     }
 
     // This will delay update jobs originating from a service worker thread.
     // We don't currently handle ServiceWorkerRegistration.update() from other
     // worker types. Also, we assume this registration matches self.registration
     // on the service worker global. This is ok for now because service worker globals
     // are the only worker contexts where we expose ServiceWorkerRegistration.
@@ -325,32 +406,28 @@ public:
         timer->Cancel();
         return NS_OK;
       }
 
       return NS_OK;
     }
 
     RefPtr<WorkerThreadUpdateCallback> cb =
-      new WorkerThreadUpdateCallback(mPromise);
+      new WorkerThreadUpdateCallback(mPromiseProxy);
     UpdateInternal(principal, mDescriptor.Scope(), cb);
-
     return NS_OK;
   }
 
-  RefPtr<ServiceWorkerRegistrationPromise>
-  Promise() const
+private:
+  ~SWRUpdateRunnable()
   {
-    return mPromise;
+    MOZ_ASSERT(NS_IsMainThread());
   }
 
-private:
-  ~SWRUpdateRunnable() = default;
-
-  RefPtr<ServiceWorkerRegistrationPromise::Private> mPromise;
+  RefPtr<PromiseWorkerProxy> mPromiseProxy;
   const ServiceWorkerDescriptor mDescriptor;
   bool mDelayed;
 };
 
 NS_IMPL_ISUPPORTS(SWRUpdateRunnable::TimerCallback, nsITimerCallback)
 
 class UnregisterCallback final : public nsIServiceWorkerUnregisterCallback
 {
@@ -539,32 +616,41 @@ public:
       cb->UnregisterFailed();
     }
 
     return NS_OK;
   }
 };
 } // namespace
 
-RefPtr<ServiceWorkerRegistrationPromise>
+already_AddRefed<Promise>
 ServiceWorkerRegistrationMainThread::Update(ErrorResult& aRv)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_DIAGNOSTIC_ASSERT(mOuter);
 
-  nsCOMPtr<nsIPrincipal> principal = mDescriptor.GetPrincipal();
-  if (!principal) {
-    return ServiceWorkerRegistrationPromise::CreateAndReject(
-      NS_ERROR_DOM_INVALID_STATE_ERR, __func__);
+  nsCOMPtr<nsIGlobalObject> go = mOuter->GetParentObject();
+  if (!go) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return nullptr;
   }
 
-  RefPtr<MainThreadUpdateCallback> cb = new MainThreadUpdateCallback();
-  UpdateInternal(principal, NS_ConvertUTF16toUTF8(mScope), cb);
+  RefPtr<Promise> promise = Promise::Create(go, aRv);
+  if (NS_WARN_IF(aRv.Failed())) {
+    return nullptr;
+  }
 
-  return cb->Promise();
+  nsCOMPtr<nsIDocument> doc = mOuter->GetOwner()->GetExtantDoc();
+  MOZ_ASSERT(doc);
+
+  RefPtr<MainThreadUpdateCallback> cb =
+    new MainThreadUpdateCallback(mOuter->GetOwner(), promise);
+  UpdateInternal(doc->NodePrincipal(), NS_ConvertUTF16toUTF8(mScope), cb);
+
+  return promise.forget();
 }
 
 already_AddRefed<Promise>
 ServiceWorkerRegistrationMainThread::Unregister(ErrorResult& aRv)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_DIAGNOSTIC_ASSERT(mOuter);
 
@@ -799,17 +885,16 @@ private:
   ~WorkerListener()
   {
     MOZ_ASSERT(!mListeningForEvents);
   }
 };
 
 ServiceWorkerRegistrationWorkerThread::ServiceWorkerRegistrationWorkerThread(const ServiceWorkerRegistrationDescriptor& aDescriptor)
   : mOuter(nullptr)
-  , mDescriptor(aDescriptor)
   , mScope(NS_ConvertUTF8toUTF16(aDescriptor.Scope()))
 {
 }
 
 ServiceWorkerRegistrationWorkerThread::~ServiceWorkerRegistrationWorkerThread()
 {
   MOZ_DIAGNOSTIC_ASSERT(!mListener);
   MOZ_DIAGNOSTIC_ASSERT(!mOuter);
@@ -838,66 +923,46 @@ ServiceWorkerRegistrationWorkerThread::S
 void
 ServiceWorkerRegistrationWorkerThread::ClearServiceWorkerRegistration(ServiceWorkerRegistration* aReg)
 {
   MOZ_ASSERT_IF(mOuter, mOuter == aReg);
   ReleaseListener();
   mOuter = nullptr;
 }
 
-RefPtr<ServiceWorkerRegistrationPromise>
+already_AddRefed<Promise>
 ServiceWorkerRegistrationWorkerThread::Update(ErrorResult& aRv)
 {
-  if (NS_WARN_IF(!mWorkerRef->GetPrivate())) {
-    return ServiceWorkerRegistrationPromise::CreateAndReject(
-      NS_ERROR_DOM_INVALID_STATE_ERR, __func__);
-  }
+  WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
+  MOZ_ASSERT(worker);
+  worker->AssertIsOnWorkerThread();
 
-  RefPtr<StrongWorkerRef> workerRef =
-    StrongWorkerRef::Create(mWorkerRef->GetPrivate(),
-                            "ServiceWorkerRegistration::Update");
-  if (NS_WARN_IF(!workerRef)) {
-    return ServiceWorkerRegistrationPromise::CreateAndReject(
-      NS_ERROR_DOM_INVALID_STATE_ERR, __func__);
+  RefPtr<Promise> promise = Promise::Create(worker->GlobalScope(), aRv);
+  if (aRv.Failed()) {
+    return nullptr;
   }
 
   // Avoid infinite update loops by ignoring update() calls during top
   // level script evaluation.  See:
   // https://github.com/slightlyoff/ServiceWorker/issues/800
-  if (workerRef->Private()->LoadScriptAsPartOfLoadingServiceWorkerScript()) {
-    return ServiceWorkerRegistrationPromise::CreateAndResolve(mDescriptor,
-                                                              __func__);
-  }
-
-  // Eventually we need to support all workers, but for right now this
-  // code assumes we're on a service worker global as self.registration.
-  if (NS_WARN_IF(!workerRef->Private()->IsServiceWorker())) {
-    return ServiceWorkerRegistrationPromise::CreateAndReject(
-      NS_ERROR_DOM_INVALID_STATE_ERR, __func__);
+  if (worker->LoadScriptAsPartOfLoadingServiceWorkerScript()) {
+    promise->MaybeResolveWithUndefined();
+    return promise.forget();
   }
 
-  RefPtr<SWRUpdateRunnable> r =
-    new SWRUpdateRunnable(workerRef->Private()->GetServiceWorkerDescriptor());
-  nsresult rv = workerRef->Private()->DispatchToMainThread(r);
-  if (NS_FAILED(rv)) {
-    return ServiceWorkerRegistrationPromise::CreateAndReject(
-      NS_ERROR_DOM_INVALID_STATE_ERR, __func__);
+  RefPtr<PromiseWorkerProxy> proxy = PromiseWorkerProxy::Create(worker, promise);
+  if (!proxy) {
+    aRv.Throw(NS_ERROR_DOM_ABORT_ERR);
+    return nullptr;
   }
 
-  RefPtr<ServiceWorkerRegistrationPromise::Private> outer =
-    new ServiceWorkerRegistrationPromise::Private(__func__);
+  RefPtr<SWRUpdateRunnable> r = new SWRUpdateRunnable(proxy);
+  MOZ_ALWAYS_SUCCEEDS(worker->DispatchToMainThread(r.forget()));
 
-  r->Promise()->Then(workerRef->Private()->HybridEventTarget(), __func__,
-    [workerRef, outer] (const ServiceWorkerRegistrationDescriptor& aDesc) {
-      outer->Resolve(aDesc, __func__);
-    }, [workerRef, outer] (ErrorResult&& aRv) {
-      outer->Reject(Move(aRv), __func__);
-    });
-
-  return outer.forget();
+  return promise.forget();
 }
 
 already_AddRefed<Promise>
 ServiceWorkerRegistrationWorkerThread::Unregister(ErrorResult& aRv)
 {
   WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
   MOZ_ASSERT(worker);
   worker->AssertIsOnWorkerThread();
--- a/dom/serviceworkers/ServiceWorkerRegistrationImpl.h
+++ b/dom/serviceworkers/ServiceWorkerRegistrationImpl.h
@@ -37,17 +37,17 @@ public:
 
   // ServiceWorkerRegistration::Inner
   void
   SetServiceWorkerRegistration(ServiceWorkerRegistration* aReg) override;
 
   void
   ClearServiceWorkerRegistration(ServiceWorkerRegistration* aReg) override;
 
-  RefPtr<ServiceWorkerRegistrationPromise>
+  already_AddRefed<Promise>
   Update(ErrorResult& aRv) override;
 
   already_AddRefed<Promise>
   Unregister(ErrorResult& aRv) override;
 
   already_AddRefed<Promise>
   ShowNotification(JSContext* aCx,
                    const nsAString& aTitle,
@@ -88,17 +88,16 @@ private:
 
   void
   StopListeningForEvents();
 
   void
   RegistrationRemovedInternal();
 
   ServiceWorkerRegistration* mOuter;
-  ServiceWorkerRegistrationDescriptor mDescriptor;
   const nsString mScope;
   bool mListeningForEvents;
 };
 
 ////////////////////////////////////////////////////
 // Worker Thread implementation
 
 class WorkerListener;
@@ -117,17 +116,17 @@ public:
 
   // ServiceWorkerRegistration::Inner
   void
   SetServiceWorkerRegistration(ServiceWorkerRegistration* aReg) override;
 
   void
   ClearServiceWorkerRegistration(ServiceWorkerRegistration* aReg) override;
 
-  RefPtr<ServiceWorkerRegistrationPromise>
+  already_AddRefed<Promise>
   Update(ErrorResult& aRv) override;
 
   already_AddRefed<Promise>
   Unregister(ErrorResult& aRv) override;
 
   already_AddRefed<Promise>
   ShowNotification(JSContext* aCx,
                    const nsAString& aTitle,
@@ -153,17 +152,16 @@ private:
   void
   ReleaseListener();
 
   // This can be called only by WorkerListener.
   WorkerPrivate*
   GetWorkerPrivate(const MutexAutoLock& aProofOfLock);
 
   ServiceWorkerRegistration* mOuter;
-  const ServiceWorkerRegistrationDescriptor mDescriptor;
   const nsString mScope;
   RefPtr<WorkerListener> mListener;
   RefPtr<WeakWorkerRef> mWorkerRef;
 };
 
 } // dom namespace
 } // mozilla namespace
 
--- a/dom/serviceworkers/test/worker_update.js
+++ b/dom/serviceworkers/test/worker_update.js
@@ -1,14 +1,14 @@
 // For now this test only calls update to verify that our registration
 // job queueing works properly when called from the worker thread. We should
 // test actual update scenarios with a SJS test.
 onmessage = function(e) {
   self.registration.update().then(function(v) {
-    return v instanceof ServiceWorkerRegistration ? 'FINISH' : 'FAIL';
+    return v === undefined ? 'FINISH' : 'FAIL';
   }).catch(function(e) {
     return 'FAIL';
   }).then(function(result) {
     clients.matchAll().then(function(c) {
       if (c.length == 0) {
         dump("!!!!!!!!!!! WORKER HAS NO CLIENTS TO FINISH TEST !!!!!!!!!!!!\n");
         return;
       }
--- a/testing/web-platform/meta/MANIFEST.json
+++ b/testing/web-platform/meta/MANIFEST.json
@@ -364334,22 +364334,16 @@
     ]
    ],
    "service-workers/service-worker/update-recovery.https.html": [
     [
      "/service-workers/service-worker/update-recovery.https.html",
      {}
     ]
    ],
-   "service-workers/service-worker/update-result.https.html": [
-    [
-     "/service-workers/service-worker/update-result.https.html",
-     {}
-    ]
-   ],
    "service-workers/service-worker/update.https.html": [
     [
      "/service-workers/service-worker/update.https.html",
      {}
     ]
    ],
    "service-workers/service-worker/waiting.https.html": [
     [
@@ -599321,20 +599315,16 @@
   "service-workers/service-worker/update-bytecheck.https.html": [
    "a39aa4877c3e47c8379b84f8520b6a726936867e",
    "testharness"
   ],
   "service-workers/service-worker/update-recovery.https.html": [
    "aac5705d6844e4a33200418504adb57053a45be2",
    "testharness"
   ],
-  "service-workers/service-worker/update-result.https.html": [
-   "06741e887be9746d7354394f74c054dd920d1b60",
-   "testharness"
-  ],
   "service-workers/service-worker/update.https.html": [
    "d55da98b05b5885084474ebdbabdf6c0998f8bca",
    "testharness"
   ],
   "service-workers/service-worker/waiting.https.html": [
    "7f891059dd421274db18967fd570abb3b1a90285",
    "testharness"
   ],
deleted file mode 100644
--- a/testing/web-platform/tests/service-workers/service-worker/update-result.https.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE html>
-<title>Service Worker: update() should resolve a ServiceWorkerRegistration</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="resources/test-helpers.sub.js"></script>
-<body>
-<script>
-
-promise_test(async function(t) {
-  const script = './resources/empty.js';
-  const scope = './resources/empty.html?update-result';
-
-  let reg = await navigator.serviceWorker.register(script, { scope });
-  t.add_cleanup(async _ => await reg.unregister());
-  await wait_for_state(t, reg.installing, 'activated');
-
-  let result = await reg.update();
-  assert_true(result instanceof ServiceWorkerRegistration,
-              'update() should resolve a ServiceWorkerRegistration');
-}, 'ServiceWorkerRegistration.update() should resolve a registration object');
-
-</script>
-</body>