Bug 614586 - Implement string substitution in all console API methods; r=ddahl,Olli.Pettay
authorPanos Astithas <past@mozilla.com>
Thu, 15 Sep 2011 11:20:22 -0700
changeset 78551 8e3e1c5f348da4bb38895b513f42c40d7f5eb087
parent 78550 31153dfd43070444318a813a6979ee01328dc445
child 78552 d1a258f48898ff424099b391904be9d0bd183ae9
push id78
push userclegnitto@mozilla.com
push dateFri, 16 Dec 2011 17:32:24 +0000
treeherdermozilla-release@79d24e644fdd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersddahl, Olli
bugs614586
milestone9.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 614586 - Implement string substitution in all console API methods; r=ddahl,Olli.Pettay
dom/base/ConsoleAPI.js
dom/tests/browser/browser_ConsoleAPITests.js
--- a/dom/base/ConsoleAPI.js
+++ b/dom/base/ConsoleAPI.js
@@ -1,8 +1,10 @@
+/* -*- Mode: js2; js2-basic-offset: 2; indent-tabs-mode: nil; -*- */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
  * The contents of this file are subject to the Mozilla Public License Version
  * 1.1 (the "License"); you may not use this file except in compliance with
  * the License. You may obtain a copy of the License at
  * http://www.mozilla.org/MPL/
  *
@@ -66,29 +68,29 @@ ConsoleAPI.prototype = {
     catch (ex) {
       Cu.reportError(ex);
     }
 
     let self = this;
     let chromeObject = {
       // window.console API
       log: function CA_log() {
-        self.notifyObservers(outerID, innerID, "log", arguments);
+        self.notifyObservers(outerID, innerID, "log", self.processArguments(arguments));
       },
       info: function CA_info() {
-        self.notifyObservers(outerID, innerID, "info", arguments);
+        self.notifyObservers(outerID, innerID, "info", self.processArguments(arguments));
       },
       warn: function CA_warn() {
-        self.notifyObservers(outerID, innerID, "warn", arguments);
+        self.notifyObservers(outerID, innerID, "warn", self.processArguments(arguments));
       },
       error: function CA_error() {
-        self.notifyObservers(outerID, innerID, "error", arguments);
+        self.notifyObservers(outerID, innerID, "error", self.processArguments(arguments));
       },
       debug: function CA_debug() {
-        self.notifyObservers(outerID, innerID, "log", arguments);
+        self.notifyObservers(outerID, innerID, "log", self.processArguments(arguments));
       },
       trace: function CA_trace() {
         self.notifyObservers(outerID, innerID, "trace", self.getStackTrace());
       },
       // Displays an interactive listing of all the properties of an object.
       dir: function CA_dir() {
         self.notifyObservers(outerID, innerID, "dir", arguments);
       },
@@ -164,16 +166,52 @@ ConsoleAPI.prototype = {
 
     ConsoleAPIStorage.recordEvent(aInnerWindowID, consoleEvent);
 
     Services.obs.notifyObservers(consoleEvent,
                                  "console-api-log-event", aOuterWindowID);
   },
 
   /**
+   * Process the console API call arguments in order to perform printf-like
+   * string substitution.
+   * TODO: object substitution should display an interactive property list (bug
+   * 685815) and width and precision qualifiers should be taken into account
+   * (bug 685813).
+   *
+   * @param mixed aArguments
+   *        The arguments given to the console API call.
+   **/
+  processArguments: function CA_processArguments(aArguments) {
+    if (aArguments.length < 2) {
+      return aArguments;
+    }
+    let args = Array.prototype.slice.call(aArguments);
+    let format = args.shift();
+    // Format specification regular expression.
+    let pattern = /%(\d*).?(\d*)[a-zA-Z]/g;
+    let processed = format.replace(pattern, function CA_PA_substitute(spec) {
+      switch (spec[spec.length-1]) {
+        case "o":
+        case "s":
+          return args.shift().toString();
+        case "d":
+        case "i":
+          return parseInt(args.shift());
+        case "f":
+          return parseFloat(args.shift());
+        default:
+          return spec;
+      };
+    });
+    args.unshift(processed);
+    return args;
+  },
+
+  /**
    * Build the stacktrace array for the console.trace() call.
    *
    * @return array
    *         Each element is a stack frame that holds the following properties:
    *         filename, lineNumber, functionName and language.
    **/
   getStackTrace: function CA_getStackTrace() {
     let stack = [];
--- a/dom/tests/browser/browser_ConsoleAPITests.js
+++ b/dom/tests/browser/browser_ConsoleAPITests.js
@@ -156,18 +156,31 @@ function expect(level) {
 function observeConsoleTest() {
   let win = XPCNativeWrapper.unwrap(gWindow);
   expect("log", "arg");
   win.console.log("arg");
 
   expect("info", "arg", "extra arg");
   win.console.info("arg", "extra arg");
 
-  expect("warn", "arg", "extra arg", 1);
-  win.console.warn("arg", "extra arg", 1);
+  // We don't currently support width and precision qualifiers, but we don't
+  // choke on them either.
+  expect("warn", "Lesson 1: PI is approximately equal to 3.14159");
+  win.console.warn("Lesson %d: %s is approximately equal to %1.2f",
+                   1,
+                   "PI",
+                   3.14159);
+  expect("log", "%d, %s, %l");
+  win.console.log("%d, %s, %l");
+  expect("log", "%a %b %c");
+  win.console.log("%a %b %c");
+  expect("log", "%a %b %c", "a", "b");
+  win.console.log("%a %b %c", "a", "b");
+  expect("log", "2, a, %l", 3);
+  win.console.log("%d, %s, %l", 2, "a", 3);
 
   expect("dir", win.toString());
   win.console.dir(win);
 
   expect("error", "arg");
   win.console.error("arg");
 }