--- a/mobile/android/modules/geckoview/GeckoViewUtils.jsm
+++ b/mobile/android/modules/geckoview/GeckoViewUtils.jsm
@@ -9,67 +9,59 @@ XPCOMUtils.defineLazyModuleGetters(this,
AndroidLog: "resource://gre/modules/AndroidLog.jsm",
EventDispatcher: "resource://gre/modules/Messaging.jsm",
Log: "resource://gre/modules/Log.jsm",
Services: "resource://gre/modules/Services.jsm",
});
var EXPORTED_SYMBOLS = ["GeckoViewUtils"];
-var {Appender, BasicFormatter} = Log;
-
/**
* A formatter that does not prepend time/name/level information to messages,
* because those fields are logged separately when using the Android logger.
*/
-function AndroidFormatter() {
- BasicFormatter.call(this);
-}
-AndroidFormatter.prototype = Object.freeze({
- __proto__: BasicFormatter.prototype,
-
+class AndroidFormatter extends Log.BasicFormatter {
format(message) {
return this.formatText(message);
- },
-});
+ }
+}
/*
* AndroidAppender
* Logs to Android logcat using AndroidLog.jsm
*/
-function AndroidAppender(aFormatter) {
- Appender.call(this, aFormatter || new AndroidFormatter());
- this._name = "AndroidAppender";
-}
-AndroidAppender.prototype = {
- __proto__: Appender.prototype,
+class AndroidAppender extends Log.Appender {
+ constructor(aFormatter) {
+ super(aFormatter || new AndroidFormatter());
+ this._name = "AndroidAppender";
- // Map log level to AndroidLog.foo method.
- _mapping: {
- [Log.Level.Fatal]: "e",
- [Log.Level.Error]: "e",
- [Log.Level.Warn]: "w",
- [Log.Level.Info]: "i",
- [Log.Level.Config]: "d",
- [Log.Level.Debug]: "d",
- [Log.Level.Trace]: "v",
- },
+ // Map log level to AndroidLog.foo method.
+ this._mapping = {
+ [Log.Level.Fatal]: "e",
+ [Log.Level.Error]: "e",
+ [Log.Level.Warn]: "w",
+ [Log.Level.Info]: "i",
+ [Log.Level.Config]: "d",
+ [Log.Level.Debug]: "d",
+ [Log.Level.Trace]: "v",
+ };
+ }
append(aMessage) {
if (!aMessage) {
return;
}
// AndroidLog.jsm always prepends "Gecko" to the tag, so we strip any
// leading "Gecko" here. Also strip dots to save space.
const tag = aMessage.loggerName.replace(/^Gecko|\./g, "");
const msg = this._formatter.format(aMessage);
AndroidLog[this._mapping[aMessage.level]](tag, msg);
- },
-};
+ }
+}
var GeckoViewUtils = {
/**
* Define a lazy getter that loads an object from external code, and
* optionally handles observer and/or message manager notifications for the
* object, so the object only loads when a notification is received.
*
* @param scope Scope for holding the loaded object.
--- a/services/common/logmanager.js
+++ b/services/common/logmanager.js
@@ -37,45 +37,41 @@ const DEFAULT_MAX_ERROR_AGE = 20 * 24 *
// Singletons used by each instance.
var formatter;
var dumpAppender;
var consoleAppender;
// A set of all preference roots used by all instances.
var allBranches = new Set();
-let {Appender} = Log;
-
const ONE_BYTE = 1;
const ONE_KILOBYTE = 1024 * ONE_BYTE;
const ONE_MEGABYTE = 1024 * ONE_KILOBYTE;
const STREAM_SEGMENT_SIZE = 4096;
const PR_UINT32_MAX = 0xffffffff;
/**
* Append to an nsIStorageStream
*
* This writes logging output to an in-memory stream which can later be read
* back as an nsIInputStream. It can be used to avoid expensive I/O operations
* during logging. Instead, one can periodically consume the input stream and
* e.g. write it to disk asynchronously.
*/
-function StorageStreamAppender(formatter) {
- Appender.call(this, formatter);
- this._name = "StorageStreamAppender";
-}
+class StorageStreamAppender extends Log.Appender {
+ constructor(formatter) {
+ super(formatter);
+ this._name = "StorageStreamAppender";
-StorageStreamAppender.prototype = {
- __proto__: Appender.prototype,
+ this._converterStream = null; // holds the nsIConverterOutputStream
+ this._outputStream = null; // holds the underlying nsIOutputStream
- _converterStream: null, // holds the nsIConverterOutputStream
- _outputStream: null, // holds the underlying nsIOutputStream
-
- _ss: null,
+ this._ss = null;
+ }
get outputStream() {
if (!this._outputStream) {
// First create a raw stream. We can bail out early if that fails.
this._outputStream = this.newOutputStream();
if (!this._outputStream) {
return null;
}
@@ -84,40 +80,40 @@ StorageStreamAppender.prototype = {
// the instance if we already have one.
if (!this._converterStream) {
this._converterStream = Cc["@mozilla.org/intl/converter-output-stream;1"]
.createInstance(Ci.nsIConverterOutputStream);
}
this._converterStream.init(this._outputStream, "UTF-8");
}
return this._converterStream;
- },
+ }
- newOutputStream: function newOutputStream() {
+ newOutputStream() {
let ss = this._ss = Cc["@mozilla.org/storagestream;1"]
.createInstance(Ci.nsIStorageStream);
ss.init(STREAM_SEGMENT_SIZE, PR_UINT32_MAX, null);
return ss.getOutputStream(0);
- },
+ }
- getInputStream: function getInputStream() {
+ getInputStream() {
if (!this._ss) {
return null;
}
return this._ss.newInputStream(0);
- },
+ }
- reset: function reset() {
+ reset() {
if (!this._outputStream) {
return;
}
this.outputStream.close();
this._outputStream = null;
this._ss = null;
- },
+ }
doAppend(formatted) {
if (!formatted) {
return;
}
try {
this.outputStream.writeString(formatted + "\n");
} catch (ex) {
@@ -127,41 +123,39 @@ StorageStreamAppender.prototype = {
this._outputStream = null;
} try {
this.outputStream.writeString(formatted + "\n");
} catch (ex) {
// Ah well, we tried, but something seems to be hosed permanently.
}
}
}
-};
+}
// A storage appender that is flushable to a file on disk. Policies for
// when to flush, to what file, log rotation etc are up to the consumer
// (although it does maintain a .sawError property to help the consumer decide
// based on its policies)
-function FlushableStorageAppender(formatter) {
- StorageStreamAppender.call(this, formatter);
- this.sawError = false;
-}
-
-FlushableStorageAppender.prototype = {
- __proto__: StorageStreamAppender.prototype,
+class FlushableStorageAppender extends StorageStreamAppender {
+ constructor(formatter) {
+ super(formatter);
+ this.sawError = false;
+ }
append(message) {
if (message.level >= Log.Level.Error) {
this.sawError = true;
}
StorageStreamAppender.prototype.append.call(this, message);
- },
+ }
reset() {
- Log.StorageStreamAppender.prototype.reset.call(this);
+ super.reset();
this.sawError = false;
- },
+ }
// Flush the current stream to a file. Somewhat counter-intuitively, you
// must pass a log which will be written to with details of the operation.
async flushToFile(subdirArray, filename, log) {
let inStream = this.getInputStream();
this.reset();
if (!inStream) {
log.debug("Failed to flush log to a file - no input stream");
@@ -170,17 +164,17 @@ FlushableStorageAppender.prototype = {
log.debug("Flushing file log");
log.trace("Beginning stream copy to " + filename + ": " + Date.now());
try {
await this._copyStreamToFile(inStream, subdirArray, filename, log);
log.trace("onCopyComplete", Date.now());
} catch (ex) {
log.error("Failed to copy log stream to file", ex);
}
- },
+ }
/**
* Copy an input stream to the named file, doing everything off the main
* thread.
* subDirArray is an array of path components, relative to the profile
* directory, where the file will be created.
* outputFileName is the filename to create.
* Returns a promise that is resolved on completion or rejected with an error.
@@ -211,18 +205,18 @@ FlushableStorageAppender.prototype = {
try {
binaryStream.close(); // inputStream is closed by the binaryStream
await output.close();
} catch (ex) {
log.error("Failed to close the input stream", ex);
}
}
log.trace("finished copy to", fullOutputFileName);
- },
-};
+ }
+}
// The public LogManager object.
function LogManager(prefRoot, logNames, logFilePrefix) {
this._prefObservers = [];
this.init(prefRoot, logNames, logFilePrefix);
}
LogManager.StorageStreamAppender = StorageStreamAppender;
--- a/toolkit/modules/Log.jsm
+++ b/toolkit/modules/Log.jsm
@@ -59,60 +59,48 @@ var Log = {
Log.repository = new LoggerRepository();
return Log.repository;
},
set repository(value) {
delete Log.repository;
Log.repository = value;
},
- LogMessage,
- Logger,
- LoggerRepository,
-
- BasicFormatter,
-
- Appender,
- DumpAppender,
- ConsoleAppender,
-
- ParameterFormatter,
-
- _formatError: function _formatError(e) {
- let result = e.toString();
+ _formatError(e) {
+ let result = String(e);
if (e.fileName) {
- result += " (" + e.fileName;
+ let loc = [e.fileName];
if (e.lineNumber) {
- result += ":" + e.lineNumber;
+ loc.push(e.lineNumber);
}
if (e.columnNumber) {
- result += ":" + e.columnNumber;
+ loc.push(e.columnNumber);
}
- result += ")";
+ result += `(${loc.join(":")})`;
}
- return result + " " + Log.stackTrace(e);
+ return `${result} ${Log.stackTrace(e)}`;
},
// This is for back compatibility with services/common/utils.js; we duplicate
// some of the logic in ParameterFormatter
- exceptionStr: function exceptionStr(e) {
+ exceptionStr(e) {
if (!e) {
- return "" + e;
+ return String(e);
}
if (e instanceof Ci.nsIException) {
- return e.toString() + " " + Log.stackTrace(e);
+ return `${e} ${Log.stackTrace(e)}`;
} else if (isError(e)) {
return Log._formatError(e);
}
// else
let message = e.message || e;
- return message + " " + Log.stackTrace(e);
+ return `${message} ${Log.stackTrace(e)}`;
},
- stackTrace: function stackTrace(e) {
+ stackTrace(e) {
// Wrapped nsIException
if (e.location) {
let frame = e.location;
let output = [];
while (frame) {
// Works on frames or exceptions, munges file:// URIs to shorten the paths
// FIXME: filename munging is sort of hackish, might be confusing if
// there are multiple extensions with similar filenames
@@ -131,17 +119,17 @@ var Log = {
str = frame.name + "()@" + str;
}
if (str) {
output.push(str);
}
frame = frame.caller;
}
- return "Stack trace: " + output.join("\n");
+ return `Stack trace: ${output.join("\n")}`;
}
// Standard JS exception
if (e.stack) {
let stack = e.stack;
// Avoid loading Task.jsm if there's no task on the stack.
if (stack.includes("/Task.jsm:"))
stack = Task.Debugging.generateReadableStack(stack);
return "JS Stack trace: " + stack.trim()
@@ -151,80 +139,82 @@ var Log = {
return "No traceback available";
}
};
/*
* LogMessage
* Encapsulates a single log event's data
*/
-function LogMessage(loggerName, level, message, params) {
- this.loggerName = loggerName;
- this.level = level;
- /*
- * Special case to handle "log./level/(object)", for example logging a caught exception
- * without providing text or params like: catch(e) { logger.warn(e) }
- * Treating this as an empty text with the object in the 'params' field causes the
- * object to be formatted properly by BasicFormatter.
- */
- if (!params && message && (typeof(message) == "object") &&
- (typeof(message.valueOf()) != "string")) {
- this.message = null;
- this.params = message;
- } else {
- // If the message text is empty, or a string, or a String object, normal handling
- this.message = message;
- this.params = params;
+class LogMessage {
+ constructor(loggerName, level, message, params) {
+ this.loggerName = loggerName;
+ this.level = level;
+ /*
+ * Special case to handle "log./level/(object)", for example logging a caught exception
+ * without providing text or params like: catch(e) { logger.warn(e) }
+ * Treating this as an empty text with the object in the 'params' field causes the
+ * object to be formatted properly by BasicFormatter.
+ */
+ if (!params && message && (typeof(message) == "object") &&
+ (typeof(message.valueOf()) != "string")) {
+ this.message = null;
+ this.params = message;
+ } else {
+ // If the message text is empty, or a string, or a String object, normal handling
+ this.message = message;
+ this.params = params;
+ }
+
+ // The _structured field will correspond to whether this message is to
+ // be interpreted as a structured message.
+ this._structured = this.params && this.params.action;
+ this.time = Date.now();
}
- // The _structured field will correspond to whether this message is to
- // be interpreted as a structured message.
- this._structured = this.params && this.params.action;
- this.time = Date.now();
-}
-LogMessage.prototype = {
get levelDesc() {
if (this.level in Log.Level.Desc)
return Log.Level.Desc[this.level];
return "UNKNOWN";
- },
+ }
- toString: function LogMsg_toString() {
- let msg = "LogMessage [" + this.time + " " + this.level + " " +
- this.message;
+ toString() {
+ let msg = `${this.time} ${this.level} ${this.message}`;
if (this.params) {
- msg += " " + JSON.stringify(this.params);
+ msg += ` ${JSON.stringify(this.params)}`;
}
- return msg + "]";
+ return `LogMessage [${msg}]`;
}
-};
+}
/*
* Logger
* Hierarchical version. Logs to all appenders, assigned or inherited
*/
-function Logger(name, repository) {
- if (!repository)
- repository = Log.repository;
- this._name = name;
- this.children = [];
- this.ownAppenders = [];
- this.appenders = [];
- this._repository = repository;
-}
-Logger.prototype = {
- _levelPrefName: null,
- _levelPrefValue: null,
+class Logger {
+ constructor(name, repository) {
+ if (!repository)
+ repository = Log.repository;
+ this._name = name;
+ this.children = [];
+ this.ownAppenders = [];
+ this.appenders = [];
+ this._repository = repository;
+
+ this._levelPrefName = null;
+ this._levelPrefValue = null;
+ this._level = null;
+ this._parent = null;
+ }
get name() {
return this._name;
- },
+ }
- _level: null,
get level() {
if (this._levelPrefName) {
// We've been asked to use a preference to configure the logs. If the
// pref has a value we use it, otherwise we continue to use the parent.
const lpv = this._levelPrefValue;
if (lpv) {
const levelValue = Log.Level[lpv];
if (levelValue) {
@@ -240,97 +230,96 @@ Logger.prototype = {
}
}
if (this._level != null)
return this._level;
if (this.parent)
return this.parent.level;
dumpError("Log warning: root logger configuration error: no level defined");
return Log.Level.All;
- },
+ }
set level(level) {
if (this._levelPrefName) {
// I guess we could honor this by nuking this._levelPrefValue, but it
// almost certainly implies confusion, so we'll warn and ignore.
dumpError(`Log warning: The log '${this.name}' is configured to use ` +
`the preference '${this._levelPrefName}' - you must adjust ` +
`the level by setting this preference, not by using the ` +
`level setter`);
return;
}
this._level = level;
- },
+ }
- _parent: null,
get parent() {
return this._parent;
- },
+ }
set parent(parent) {
if (this._parent == parent) {
return;
}
// Remove ourselves from parent's children
if (this._parent) {
let index = this._parent.children.indexOf(this);
if (index != -1) {
this._parent.children.splice(index, 1);
}
}
this._parent = parent;
parent.children.push(this);
this.updateAppenders();
- },
+ }
manageLevelFromPref(prefName) {
if (prefName == this._levelPrefName) {
// We've already configured this log with an observer for that pref.
return;
}
if (this._levelPrefName) {
dumpError(`The log '${this.name}' is already configured with the ` +
`preference '${this._levelPrefName}' - ignoring request to ` +
`also use the preference '${prefName}'`);
return;
}
this._levelPrefName = prefName;
XPCOMUtils.defineLazyPreferenceGetter(this, "_levelPrefValue", prefName);
- },
+ }
- updateAppenders: function updateAppenders() {
+ updateAppenders() {
if (this._parent) {
let notOwnAppenders = this._parent.appenders.filter(function(appender) {
return !this.ownAppenders.includes(appender);
}, this);
this.appenders = notOwnAppenders.concat(this.ownAppenders);
} else {
this.appenders = this.ownAppenders.slice();
}
// Update children's appenders.
for (let i = 0; i < this.children.length; i++) {
this.children[i].updateAppenders();
}
- },
+ }
- addAppender: function Logger_addAppender(appender) {
+ addAppender(appender) {
if (this.ownAppenders.includes(appender)) {
return;
}
this.ownAppenders.push(appender);
this.updateAppenders();
- },
+ }
- removeAppender: function Logger_removeAppender(appender) {
+ removeAppender(appender) {
let index = this.ownAppenders.indexOf(appender);
if (index == -1) {
return;
}
this.ownAppenders.splice(index, 1);
this.updateAppenders();
- },
+ }
_unpackTemplateLiteral(string, params) {
if (!Array.isArray(params)) {
// Regular log() call.
return [string, params];
}
if (!Array.isArray(string)) {
@@ -350,17 +339,17 @@ Logger.prototype = {
return [string[0], undefined];
}
let concat = string[0];
for (let i = 0; i < params.length; i++) {
concat += `\${${i}}${string[i + 1]}`;
}
return [concat, params];
- },
+ }
log(level, string, params) {
if (this.level > level)
return;
// Hold off on creating the message object until we actually have
// an appender that's responsible.
let message;
@@ -370,63 +359,64 @@ Logger.prototype = {
continue;
}
if (!message) {
[string, params] = this._unpackTemplateLiteral(string, params);
message = new LogMessage(this._name, level, string, params);
}
appender.append(message);
}
- },
+ }
fatal(string, ...params) {
this.log(Log.Level.Fatal, string, params);
- },
+ }
error(string, ...params) {
this.log(Log.Level.Error, string, params);
- },
+ }
warn(string, ...params) {
this.log(Log.Level.Warn, string, params);
- },
+ }
info(string, ...params) {
this.log(Log.Level.Info, string, params);
- },
+ }
config(string, ...params) {
this.log(Log.Level.Config, string, params);
- },
+ }
debug(string, ...params) {
this.log(Log.Level.Debug, string, params);
- },
+ }
trace(string, ...params) {
this.log(Log.Level.Trace, string, params);
}
-};
+}
/*
* LoggerRepository
* Implements a hierarchy of Loggers
*/
-function LoggerRepository() {}
-LoggerRepository.prototype = {
- _loggers: {},
+class LoggerRepository {
+ constructor() {
+ this._loggers = {};
+ this._rootLogger = null;
+ }
- _rootLogger: null,
get rootLogger() {
if (!this._rootLogger) {
this._rootLogger = new Logger("root", this);
this._rootLogger.level = Log.Level.All;
}
return this._rootLogger;
- },
+ }
set rootLogger(logger) {
throw "Cannot change the root logger";
- },
+ }
- _updateParents: function LogRep__updateParents(name) {
+ _updateParents(name) {
let pieces = name.split(".");
let cur, parent;
// find the closest parent
// don't test for the logger name itself, as there's a chance it's already
// there in this._loggers
for (let i = 0; i < pieces.length - 1; i++) {
if (cur)
@@ -443,34 +433,34 @@ LoggerRepository.prototype = {
else
this._loggers[name].parent = this._loggers[parent];
// trigger updates for any possible descendants of this logger
for (let logger in this._loggers) {
if (logger != name && logger.indexOf(name) == 0)
this._updateParents(logger);
}
- },
+ }
/**
* Obtain a named Logger.
*
* The returned Logger instance for a particular name is shared among
* all callers. In other words, if two consumers call getLogger("foo"),
* they will both have a reference to the same object.
*
* @return Logger
*/
getLogger(name) {
if (name in this._loggers)
return this._loggers[name];
this._loggers[name] = new Logger(name, this);
this._updateParents(name);
return this._loggers[name];
- },
+ }
/**
* Obtain a Logger that logs all string messages with a prefix.
*
* A common pattern is to have separate Logger instances for each instance
* of an object. But, you still want to distinguish between each instance.
* Since Log.repository.getLogger() returns shared Logger objects,
* monkeypatching one Logger modifies them all.
@@ -494,32 +484,33 @@ LoggerRepository.prototype = {
// We cannot change the original array, so create a new one.
string = [prefix + string[0]].concat(string.slice(1));
} else {
string = prefix + string; // Regular string.
}
return log.log(level, string, params);
};
return proxy;
- },
-};
+ }
+}
/*
* Formatters
* These massage a LogMessage into whatever output is desired.
*/
// Basic formatter that doesn't do anything fancy.
-function BasicFormatter(dateFormat) {
- if (dateFormat) {
- this.dateFormat = dateFormat;
+class BasicFormatter {
+ constructor(dateFormat) {
+ if (dateFormat) {
+ this.dateFormat = dateFormat;
+ }
+ this.parameterFormatter = new ParameterFormatter();
}
- this.parameterFormatter = new ParameterFormatter();
-}
-BasicFormatter.prototype = {
+
/**
* Format the text of a message with optional parameters.
* If the text contains ${identifier}, replace that with
* the value of params[identifier]; if ${}, replace that with
* the entire params object. If no params have been substituted
* into the text, format the entire object and append that
* to the message.
*/
@@ -559,146 +550,159 @@ BasicFormatter.prototype = {
let rest = this.parameterFormatter.format(message.params);
if (rest !== null && rest != "{}") {
textParts.push(rest);
}
}
return textParts.join(": ");
}
return undefined;
- },
+ }
- format: function BF_format(message) {
+ format(message) {
return message.time + "\t" +
message.loggerName + "\t" +
message.levelDesc + "\t" +
this.formatText(message);
}
-};
+}
/**
* Test an object to see if it is a Mozilla JS Error.
*/
function isError(aObj) {
return (aObj && typeof(aObj) == "object" && "name" in aObj && "message" in aObj &&
"fileName" in aObj && "lineNumber" in aObj && "stack" in aObj);
}
/*
* Parameter Formatters
* These massage an object used as a parameter for a LogMessage into
* a string representation of the object.
*/
-function ParameterFormatter() {
- this._name = "ParameterFormatter";
-}
-ParameterFormatter.prototype = {
+class ParameterFormatter {
+ constructor() {
+ this._name = "ParameterFormatter";
+ }
+
format(ob) {
try {
if (ob === undefined) {
return "undefined";
}
if (ob === null) {
return "null";
}
// Pass through primitive types and objects that unbox to primitive types.
if ((typeof(ob) != "object" || typeof(ob.valueOf()) != "object") &&
typeof(ob) != "function") {
return ob;
}
if (ob instanceof Ci.nsIException) {
- return ob.toString() + " " + Log.stackTrace(ob);
+ return `${ob} ${Log.stackTrace(ob)}`;
} else if (isError(ob)) {
return Log._formatError(ob);
}
// Just JSONify it. Filter out our internal fields and those the caller has
// already handled.
return JSON.stringify(ob, (key, val) => {
if (INTERNAL_FIELDS.has(key)) {
return undefined;
}
return val;
});
} catch (e) {
- dumpError("Exception trying to format object for log message: " + Log.exceptionStr(e));
+ dumpError(`Exception trying to format object for log message: ${Log.exceptionStr(e)}`);
}
// Fancy formatting failed. Just toSource() it - but even this may fail!
try {
return ob.toSource();
} catch (_) { }
try {
- return "" + ob;
+ return String(ob);
} catch (_) {
return "[object]";
}
}
-};
+}
/*
* Appenders
* These can be attached to Loggers to log to different places
* Simply subclass and override doAppend to implement a new one
*/
-function Appender(formatter) {
- this._name = "Appender";
- this._formatter = formatter || new BasicFormatter();
-}
-Appender.prototype = {
- level: Log.Level.All,
+class Appender {
+ constructor(formatter) {
+ this.level = Log.Level.All;
+ this._name = "Appender";
+ this._formatter = formatter || new BasicFormatter();
+ }
- append: function App_append(message) {
+ append(message) {
if (message) {
this.doAppend(this._formatter.format(message));
}
- },
- toString: function App_toString() {
- return this._name + " [level=" + this.level +
- ", formatter=" + this._formatter + "]";
- },
-};
+ }
+
+ toString() {
+ return `${this._name} [level=${this.level}, formatter=${this._formatter}]`;
+ }
+}
/*
* DumpAppender
* Logs to standard out
*/
-function DumpAppender(formatter) {
- Appender.call(this, formatter);
- this._name = "DumpAppender";
-}
-DumpAppender.prototype = {
- __proto__: Appender.prototype,
+class DumpAppender extends Appender {
+ constructor(formatter) {
+ super(formatter);
+ this._name = "DumpAppender";
+ }
- doAppend: function DApp_doAppend(formatted) {
+ doAppend(formatted) {
dump(formatted + "\n");
}
-};
+}
/*
* ConsoleAppender
* Logs to the javascript console
*/
-function ConsoleAppender(formatter) {
- Appender.call(this, formatter);
- this._name = "ConsoleAppender";
-}
-ConsoleAppender.prototype = {
- __proto__: Appender.prototype,
+class ConsoleAppender extends Appender {
+ constructor(formatter) {
+ super(formatter);
+ this._name = "ConsoleAppender";
+ }
// XXX this should be replaced with calls to the Browser Console
- append: function App_append(message) {
+ append(message) {
if (message) {
let m = this._formatter.format(message);
if (message.level > Log.Level.Warn) {
Cu.reportError(m);
return;
}
this.doAppend(m);
}
- },
+ }
- doAppend: function CApp_doAppend(formatted) {
+ doAppend(formatted) {
Services.console.logStringMessage(formatted);
}
-};
+}
+
+Object.assign(Log, {
+ LogMessage,
+ Logger,
+ LoggerRepository,
+
+ BasicFormatter,
+
+ Appender,
+ DumpAppender,
+ ConsoleAppender,
+
+ ParameterFormatter,
+});