Bug 1359017 - onmessageerror for Workers in case StructuredClone algorithm fails when deserializing, r=masayuki, r=smaug
☠☠ backed out by 37abc7027f1d ☠ ☠
authorAndrea Marchesini <amarchesini@mozilla.com>
Wed, 13 Sep 2017 05:59:06 +0200
changeset 430133 9248962260f96b0f3d413f866aa9297989abf2d1
parent 430132 354139a05e750c3f74e0efbdab34436a73c962a6
child 430134 7b45c1aebf7ffaaedafa8cabd3f6ef2a2a1c3b94
push id7761
push userjlund@mozilla.com
push dateFri, 15 Sep 2017 00:19:52 +0000
treeherdermozilla-beta@c38455951db4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmasayuki, smaug
bugs1359017
milestone57.0a1
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
Bug 1359017 - onmessageerror for Workers in case StructuredClone algorithm fails when deserializing, r=masayuki, r=smaug
dom/webidl/DedicatedWorkerGlobalScope.webidl
dom/webidl/Worker.webidl
dom/workers/WorkerPrivate.cpp
dom/workers/WorkerPrivate.h
dom/workers/WorkerScope.h
--- a/dom/webidl/DedicatedWorkerGlobalScope.webidl
+++ b/dom/webidl/DedicatedWorkerGlobalScope.webidl
@@ -19,9 +19,10 @@ interface DedicatedWorkerGlobalScope : W
   readonly attribute DOMString name;
 
   [Throws]
   void postMessage(any message, optional sequence<object> transfer = []);
 
   void close();
 
   attribute EventHandler onmessage;
+  attribute EventHandler onmessageerror;
 };
--- a/dom/webidl/Worker.webidl
+++ b/dom/webidl/Worker.webidl
@@ -17,16 +17,17 @@
  Exposed=(Window,DedicatedWorker,SharedWorker,System)]
 interface Worker : EventTarget {
   void terminate();
 
   [Throws]
   void postMessage(any message, optional sequence<object> transfer = []);
 
   attribute EventHandler onmessage;
+  attribute EventHandler onmessageerror;
 };
 
 Worker implements AbstractWorker;
 
 dictionary WorkerOptions {
   // WorkerType type = "classic"; TODO: Bug 1247687
   // RequestCredentials credentials = "omit"; // credentials is only used if type is "module" TODO: Bug 1247687
   DOMString name = "";
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -724,17 +724,17 @@ public:
       if (NS_WARN_IF(!parent)) {
         return false;
       }
     }
 
     MOZ_ASSERT(parent);
 
     JS::Rooted<JS::Value> messageData(aCx);
-    ErrorResult rv;
+    IgnoredErrorResult rv;
 
     UniquePtr<AbstractTimelineMarker> start;
     UniquePtr<AbstractTimelineMarker> end;
     RefPtr<TimelineConsumers> timelines = TimelineConsumers::Get();
     bool isTimelineRecording = timelines && !timelines->IsEmpty();
 
     if (isTimelineRecording) {
       start = MakeUnique<WorkerTimelineMarker>(aIsMainThread
@@ -750,22 +750,23 @@ public:
         ? ProfileTimelineWorkerOperationType::DeserializeDataOnMainThread
         : ProfileTimelineWorkerOperationType::DeserializeDataOffMainThread,
         MarkerTracingType::END);
       timelines->AddMarkerForAllObservedDocShells(start);
       timelines->AddMarkerForAllObservedDocShells(end);
     }
 
     if (NS_WARN_IF(rv.Failed())) {
-      xpc::Throw(aCx, rv.StealNSResult());
+      DispatchError(aCx, aTarget);
       return false;
     }
 
     Sequence<OwningNonNull<MessagePort>> ports;
     if (!TakeTransferredPortsAsSequence(ports)) {
+      DispatchError(aCx, aTarget);
       return false;
     }
 
     nsCOMPtr<nsIDOMEvent> domEvent;
     RefPtr<MessageEvent> event = new MessageEvent(aTarget, nullptr, nullptr);
     event->InitMessageEvent(nullptr,
                             NS_LITERAL_STRING("message"),
                             false /* non-bubbling */,
@@ -809,16 +810,31 @@ private:
                               !aWorkerPrivate->GetParent());
     }
 
     MOZ_ASSERT(aWorkerPrivate == GetWorkerPrivateFromContext(aCx));
 
     return DispatchDOMEvent(aCx, aWorkerPrivate, aWorkerPrivate->GlobalScope(),
                             false);
   }
+
+  void
+  DispatchError(JSContext* aCx, DOMEventTargetHelper* aTarget)
+  {
+    RootedDictionary<MessageEventInit> init(aCx);
+    init.mBubbles = false;
+    init.mCancelable = false;
+
+    RefPtr<Event> event =
+      MessageEvent::Constructor(aTarget, NS_LITERAL_STRING("messageerror"), init);
+    event->SetTrusted(true);
+
+    bool dummy;
+    aTarget->DispatchEvent(event, &dummy);
+  }
 };
 
 class DebuggerMessageEventRunnable : public WorkerDebuggerRunnable {
   nsString mMessage;
 
 public:
   DebuggerMessageEventRunnable(WorkerPrivate* aWorkerPrivate,
                                const nsAString& aMessage)
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -877,16 +877,17 @@ public:
   {
     return mLoadInfo.mLoadFailedAsyncRunnable.forget();
   }
 
   void
   FlushReportsToSharedWorkers(nsIConsoleReportCollector* aReporter);
 
   IMPL_EVENT_HANDLER(message)
+  IMPL_EVENT_HANDLER(messageerror)
   IMPL_EVENT_HANDLER(error)
 
   // Check whether this worker is a secure context.  For use from the parent
   // thread only; the canonical "is secure context" boolean is stored on the
   // compartment of the worker global.  The only reason we don't
   // AssertIsOnParentThread() here is so we can assert that this value matches
   // the one on the compartment, which has to be done from the worker thread.
   bool IsSecureContext() const
--- a/dom/workers/WorkerScope.h
+++ b/dom/workers/WorkerScope.h
@@ -246,16 +246,17 @@ public:
   PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
               const Sequence<JSObject*>& aTransferable,
               ErrorResult& aRv);
 
   void
   Close(JSContext* aCx);
 
   IMPL_EVENT_HANDLER(message)
+  IMPL_EVENT_HANDLER(messageerror)
 };
 
 class SharedWorkerGlobalScope final : public WorkerGlobalScope
 {
   const nsString mName;
 
   ~SharedWorkerGlobalScope() { }
 
@@ -391,16 +392,17 @@ public:
 
   void
   LeaveEventLoop();
 
   void
   PostMessage(const nsAString& aMessage);
 
   IMPL_EVENT_HANDLER(message)
+  IMPL_EVENT_HANDLER(messageerror)
 
   void
   SetImmediate(Function& aHandler, ErrorResult& aRv);
 
   void
   ReportError(JSContext* aCx, const nsAString& aMessage);
 
   void