Bug 851044 - Modified stringifyArgs to use the objects toString method if it is not Object.prototype.toString when logging. r=Yoric
authorJonathan Laver <jonathan.laver@gmail.com>
Fri, 05 Apr 2013 10:29:16 +0100
changeset 127815 8f6b9b15be231ae3c5222ae45d959fd5f54fcbab
parent 127814 32001b4712e80dc7262ac96c6c62e1a279589d6b
child 127816 c291c98a1bfc00edfe2f5e90808fce5af69234fb
push id24512
push userryanvm@gmail.com
push dateFri, 05 Apr 2013 20:13:49 +0000
treeherdermozilla-central@139b6ba547fa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersYoric
bugs851044
milestone23.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 851044 - Modified stringifyArgs to use the objects toString method if it is not Object.prototype.toString when logging. r=Yoric
toolkit/components/osfile/osfile_shared_allthreads.jsm
toolkit/components/osfile/tests/xpcshell/test_logging.js
toolkit/components/osfile/tests/xpcshell/xpcshell.ini
--- a/toolkit/components/osfile/osfile_shared_allthreads.jsm
+++ b/toolkit/components/osfile/osfile_shared_allthreads.jsm
@@ -98,27 +98,41 @@
          for (let i = 0; i < arguments.length; ++i) {
            text += (" " + arguments[i]);
          }
          dump(text + "\n");
        };
      }
 
      /**
-      * Apply JSON.stringify to an argument of type object.
+      * Returns |arg.toString()| if available, otherwise
+      * applies JSON.stringify.
       * Return itself otherwise.
       *
       * @param arg An argument to be stringified if possible.
       */
      let stringifyArg = function stringifyArg(arg) {
        if (typeof arg === "string") {
          return arg;
        }
        if (arg && typeof arg === "object") {
-         return JSON.stringify(arg);
+         let argToString = arg.toString();
+
+         /**
+           * The only way to detect whether this object has a non-default
+           * implementation of |toString| is to check whether it returns
+           * '[object Object]'. Unfortunately, we cannot simply compare |arg.toString|
+           * and |Object.prototype.toString| as |arg| typically comes from another
+           * compartment.
+           */
+         if (argToString === "[object Object]") {
+           return JSON.stringify(arg);
+         } else {
+           return argToString;
+         }
        }
        return arg;
      };
 
      /**
       * A Shared LOG utility function that only logs when DEBUG is set.
       *
       * @params {string|object}
new file mode 100644
--- /dev/null
+++ b/toolkit/components/osfile/tests/xpcshell/test_logging.js
@@ -0,0 +1,64 @@
+"use strict";
+
+Components.utils.import("resource://gre/modules/osfile.jsm");
+Components.utils.import("resource://gre/modules/Services.jsm");
+
+/**
+ * Tests logging by passing OS.Shared.LOG both an object with its own
+ * toString method, and one with the default.
+ */
+function run_test() {
+  do_test_pending();
+  let messageCount = 0;
+
+  // Create a console listener.
+  let consoleListener = {
+    observe: function (aMessage) {
+      ++messageCount;
+      //Ignore unexpected messages.
+      if (!(aMessage instanceof Components.interfaces.nsIConsoleMessage)) {
+        return;
+      }
+      if (aMessage.message.indexOf("TEST OS") < 0) {
+        return;
+      }
+
+      if(messageCount == 1) {
+       do_check_eq(aMessage.message, "TEST OS {\"name\":\"test\"}\n");
+      }
+      if(messageCount == 2) {
+        do_check_eq(aMessage.message, "TEST OS name is test\n");
+        // This is required, as printing to the |Services.console|
+        // while in the observe function causes an exception.
+        do_execute_soon(function() {
+          toggleConsoleListener(false);
+          do_test_finished();
+        });
+      }
+    }
+  };
+
+  // Set/Unset the console listener.
+  function toggleConsoleListener (pref) {
+    OS.Shared.DEBUG = pref;
+    OS.Shared.TEST = pref;
+    Services.console[pref ? "registerListener" : "unregisterListener"](
+      consoleListener);
+  }
+
+  toggleConsoleListener(true);
+
+  let objectDefault = {name: "test"};
+  let CustomToString = function() {
+    this.name = "test";
+  }
+  CustomToString.prototype.toString = function() {
+    return "name is " + this.name;
+  }
+  let objectCustom = new CustomToString();
+  OS.Shared.LOG(objectDefault);
+  OS.Shared.LOG(objectCustom);
+  // Once both messages are observed OS.Shared.DEBUG, and OS.Shared.TEST
+  // are reset to false.
+}
+
--- a/toolkit/components/osfile/tests/xpcshell/xpcshell.ini
+++ b/toolkit/components/osfile/tests/xpcshell/xpcshell.ini
@@ -1,7 +1,8 @@
 [DEFAULT]
 head =
 tail =
 
 [test_path.js]
 [test_osfile_async.js]
 [test_profiledir.js]
+[test_logging.js]