Bug 1269646 - Console API should be NOP after window-inner-destroyed, r=smaug
authorAndrea Marchesini <amarchesini@mozilla.com>
Tue, 03 May 2016 10:19:39 +0200
changeset 295794 cc1443870a878e094751dbd0eee36c4cee8a23a4
parent 295793 c637d7478937ae9a68fc03a52b444427a6f616b0
child 295795 d7c74013b32fb3d1052dcde8604f1f8870eac08f
push id76091
push useramarchesini@mozilla.com
push dateTue, 03 May 2016 08:20:29 +0000
treeherdermozilla-inbound@cc1443870a87 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1269646
milestone49.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 1269646 - Console API should be NOP after window-inner-destroyed, r=smaug
dom/base/Console.cpp
dom/base/Console.h
--- a/dom/base/Console.cpp
+++ b/dom/base/Console.cpp
@@ -1044,17 +1044,16 @@ METHOD(Exception, "exception")
 METHOD(Debug, "debug")
 METHOD(Table, "table")
 METHOD(Clear, "clear")
 
 void
 Console::Trace(JSContext* aCx)
 {
   AssertIsOnOwningThread();
-  MOZ_ASSERT(mStatus == eInitialized);
 
   const Sequence<JS::Value> data;
   Method(aCx, MethodTrace, NS_LITERAL_STRING("trace"), data);
 }
 
 // Displays an interactive listing of all the properties of an object.
 METHOD(Dir, "dir");
 METHOD(Dirxml, "dirxml");
@@ -1062,83 +1061,78 @@ METHOD(Dirxml, "dirxml");
 METHOD(Group, "group")
 METHOD(GroupCollapsed, "groupCollapsed")
 METHOD(GroupEnd, "groupEnd")
 
 void
 Console::Time(JSContext* aCx, const JS::Handle<JS::Value> aTime)
 {
   AssertIsOnOwningThread();
-  MOZ_ASSERT(mStatus == eInitialized);
 
   Sequence<JS::Value> data;
   SequenceRooter<JS::Value> rooter(aCx, &data);
 
   if (!aTime.isUndefined() && !data.AppendElement(aTime, fallible)) {
     return;
   }
 
   Method(aCx, MethodTime, NS_LITERAL_STRING("time"), data);
 }
 
 void
 Console::TimeEnd(JSContext* aCx, const JS::Handle<JS::Value> aTime)
 {
   AssertIsOnOwningThread();
-  MOZ_ASSERT(mStatus == eInitialized);
 
   Sequence<JS::Value> data;
   SequenceRooter<JS::Value> rooter(aCx, &data);
 
   if (!aTime.isUndefined() && !data.AppendElement(aTime, fallible)) {
     return;
   }
 
   Method(aCx, MethodTimeEnd, NS_LITERAL_STRING("timeEnd"), data);
 }
 
 void
 Console::TimeStamp(JSContext* aCx, const JS::Handle<JS::Value> aData)
 {
   AssertIsOnOwningThread();
-  MOZ_ASSERT(mStatus == eInitialized);
 
   Sequence<JS::Value> data;
   SequenceRooter<JS::Value> rooter(aCx, &data);
 
   if (aData.isString() && !data.AppendElement(aData, fallible)) {
     return;
   }
 
   Method(aCx, MethodTimeStamp, NS_LITERAL_STRING("timeStamp"), data);
 }
 
 void
 Console::Profile(JSContext* aCx, const Sequence<JS::Value>& aData)
 {
   AssertIsOnOwningThread();
-  MOZ_ASSERT(mStatus == eInitialized);
-
   ProfileMethod(aCx, NS_LITERAL_STRING("profile"), aData);
 }
 
 void
 Console::ProfileEnd(JSContext* aCx, const Sequence<JS::Value>& aData)
 {
   AssertIsOnOwningThread();
-  MOZ_ASSERT(mStatus == eInitialized);
-
   ProfileMethod(aCx, NS_LITERAL_STRING("profileEnd"), aData);
 }
 
 void
 Console::ProfileMethod(JSContext* aCx, const nsAString& aAction,
                        const Sequence<JS::Value>& aData)
 {
-  MOZ_ASSERT(mStatus == eInitialized);
+  if (IsShuttingDown()) {
+    return;
+  }
 
   if (!NS_IsMainThread()) {
     // Here we are in a worker thread.
     RefPtr<ConsoleProfileRunnable> runnable =
       new ConsoleProfileRunnable(this, aAction, aData);
 
     JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
     runnable->Dispatch(aCx);
@@ -1186,30 +1180,28 @@ Console::ProfileMethod(JSContext* aCx, c
   }
 }
 
 void
 Console::Assert(JSContext* aCx, bool aCondition,
                 const Sequence<JS::Value>& aData)
 {
   AssertIsOnOwningThread();
-  MOZ_ASSERT(mStatus == eInitialized);
 
   if (!aCondition) {
     Method(aCx, MethodAssert, NS_LITERAL_STRING("assert"), aData);
   }
 }
 
 METHOD(Count, "count")
 
 void
 Console::NoopMethod()
 {
   AssertIsOnOwningThread();
-  MOZ_ASSERT(mStatus == eInitialized);
 
   // Nothing to do.
 }
 
 static
 nsresult
 StackFrameToStackEntry(JSContext* aCx, nsIStackFrame* aStackFrame,
                        ConsoleStackEntry& aStackEntry)
@@ -1273,17 +1265,19 @@ ReifyStack(JSContext* aCx, nsIStackFrame
 
 // Queue a call to a console method. See the CALL_DELAY constant.
 void
 Console::Method(JSContext* aCx, MethodName aMethodName,
                 const nsAString& aMethodString,
                 const Sequence<JS::Value>& aData)
 {
   AssertIsOnOwningThread();
-  MOZ_ASSERT(mStatus == eInitialized);
+  if (IsShuttingDown()) {
+    return;
+  }
 
   RefPtr<ConsoleCallData> callData(new ConsoleCallData());
 
   ClearException ce(aCx);
 
   if (NS_WARN_IF(!callData->Initialize(aCx, aMethodName, aMethodString,
                                        aData, this))) {
     return;
@@ -2406,10 +2400,17 @@ Console::SetConsoleEventHandler(AnyCallb
 
 void
 Console::AssertIsOnOwningThread() const
 {
   MOZ_ASSERT(mOwningThread);
   MOZ_ASSERT(PR_GetCurrentThread() == mOwningThread);
 }
 
+bool
+Console::IsShuttingDown() const
+{
+  MOZ_ASSERT(mStatus != eUnknown);
+  return mStatus == eShuttingDown;
+}
+
 } // namespace dom
 } // namespace mozilla
--- a/dom/base/Console.h
+++ b/dom/base/Console.h
@@ -31,18 +31,16 @@ class ConsoleRunnable;
 class ConsoleCallDataRunnable;
 class ConsoleProfileRunnable;
 struct ConsoleStackEntry;
 
 class Console final : public nsIObserver
                     , public nsWrapperCache
                     , public nsSupportsWeakReference
 {
-  ~Console();
-
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(Console, nsIObserver)
   NS_DECL_NSIOBSERVER
 
   static already_AddRefed<Console>
   Create(nsPIDOMWindowInner* aWindow, ErrorResult& aRv);
 
@@ -128,16 +126,17 @@ public:
   RetrieveConsoleEvents(JSContext* aCx, nsTArray<JS::Value>& aEvents,
                         ErrorResult& aRv);
 
   void
   SetConsoleEventHandler(AnyCallback* aHandler);
 
 private:
   explicit Console(nsPIDOMWindowInner* aWindow);
+  ~Console();
 
   void
   Initialize(ErrorResult& aRv);
 
   void
   Shutdown();
 
   enum MethodName
@@ -338,16 +337,19 @@ private:
   ShouldIncludeStackTrace(MethodName aMethodName) const;
 
   JSObject*
   GetOrCreateSandbox(JSContext* aCx, nsIPrincipal* aPrincipal);
 
   void
   AssertIsOnOwningThread() const;
 
+  bool
+  IsShuttingDown() const;
+
   // All these nsCOMPtr are touched on main thread only.
   nsCOMPtr<nsPIDOMWindowInner> mWindow;
   nsCOMPtr<nsIConsoleAPIStorage> mStorage;
   RefPtr<JSObjectHolder> mSandbox;
 
   // Touched on the owner thread.
   nsDataHashtable<nsStringHashKey, DOMHighResTimeStamp> mTimerRegistry;
   nsDataHashtable<nsStringHashKey, uint32_t> mCounterRegistry;