Status
This specification is an early work in progress that welcomes feedback to refine toward more precise and compatible definitions. It is also the editors' first specification, so please be kind and constructive.
Please join us in the issue tracker for more discussion.
1. Supporting abstract operations
1.1. Logger(logLevel, args)
The logger operation accepts a log level and a
- If args is empty, abort these steps.
- Let first be the first element of args.
- Let rest be all elements following first in args.
- If rest is empty, perform
Printer (logLevel, «first»). Abort these steps. - If first does not contain any format specifiers, perform
Printer (logLevel, args). - Otherwise, perform
Printer (logLevel,Formatter (args)). - Return
undefined .
console.log("hello!"), this should first print "hello!", then the undefined return value from the console.log call.

1.2. Formatter(args)
The formatter operation tries to format the first argument provided, using the other arguments. It will try to format the input until no formatting specifiers are left in the first argument, or no more arguments are left. It returns a
- Let target be the first element of args.
- Let current be the second element of args.
- Find the first possible format specifier specifier, from the left to the right in target.
- If specifier is
%s, let converted be the result ofToString (current). - If specifier is
%dor%i, let converted be the result of%parseInt% (current, 10). - If specifier is
%f, let converted be the result of%parseFloat% (current, 10). - If specifier is
%o, optionally let converted be current with optimally useful formatting applied. - If specifier is
%O, optionally let converted be current with generic JavaScript object formatting applied. TODO: process %c
- If any of the previous steps set converted, replace specifier in target with converted.
- Let result be a
List containing target together with the elements of args starting from the third onward.
- If specifier is
- If target does not have any format specifiers left, return result.
- If result contains just one element, return result.
- Return
Formatter (result).
1.2.1. Summary of formatting specifiers
The following is an informative summary of the format specifiers processed by the above algorithm.
| Specifier | Purpose | Type Conversion |
|---|---|---|
%s
| Element which substitutes is converted to a string | |
%d or %i
| Element which substitutes is converted to an integer | |
%f
| Element which substitutes is converted to a float | |
%o
| Element is displayed with optimally useful formatting | n/a |
%O
| Element is displayed with generic JavaScript object formatting | n/a |
%c
| Applies provided CSS | n/a |
1.3. Printer(logLevel, args)
The printer operation is implementation-defined. It accepts a log level indicating severity, and a
By the time the printer operation is called, all format specifiers will have been taken into account, and any arguments that are meant to be consumed by format specifiers will not be present in args. The implementation’s job is simply to print the
If the console is not open when the printer operation is called, implementations should buffer messages to show them in the future up to an implementation-chosen limit (typically on the order of at least 100).
1.3.1. Common Object Formats
Typically objects will be printed in a format that is suitable for their context. This section describes common ways in which objects are formatted to be most useful in their context. It should be noted that the formatting described in this section is applied to implementation-specific object representations that will eventually be passed into
An object with generic JavaScript object formatting is a potentially expandable representation of a generic JavaScript object. An object with optimally useful formatting is an implementation-specific, potentially-interactive representation of an object judged to be maximally useful and informative.
1.3.2. Example printer in Node.js
stdout or stderr.
Example implementation in Node.js using [ECMASCRIPT]:
const util = require('util');
function print(logLevel, ...args) {
const message = util.format(...args);
if (logLevel === 'error') {
process.stderr.write(message + '\n');
} else if (logLevel === 'log' || logLevel === 'info' || logLevel === 'warn') {
process.stdout.write(message + '\n');
}
}
Here a lot of the work is done by the util.format function. It stringifies nested objects, and converts non-string arguments into a readable string version, e.g. undefined becomes the string "undefined" and false becomes "false":
print('log', 'duck', [{foo: 'bar'}]); // prints: `duck [ { foo: 'bar' } ]\n` on stdout
print('log', 'duck', false); // prints: `duck false\n` on stdout
print('log', 'duck', undefined); // prints: `duck undefined\n` on stdout
2. Namespace console
[Exposed=(Window,Worker,Worklet)] namespace console { // but see namespace object requirements below // Logging void assert(optional boolean condition = false, any... data); void clear(); void count(optional DOMString label = "default"); void debug(any... data); void error(any... data); void info(any... data); void log(any... data); void table(any tabularData, optional sequence<DOMString> properties); void trace(any... data); void warn(any... data); void dir(any item); void dirxml(any... data); // Grouping void group(any... data); void groupCollapsed(any... data); void groupEnd(); // Timing void time(optional DOMString label = "default"); void timeEnd(optional DOMString label = "default"); };
For historical reasons, console is lowercased.
It is important that console is always visible
and usable to scripts, even if the developer console has not been opened or
does not exist.
For historical web-compatibility reasons, the namespace object for console must have as
its [[Prototype]] an empty object, created as if by
2.1. Logging methods
2.1.1. assert(condition, ...data)
- If condition is true, abort these steps.
- Let message be a string without any formatting specifiers indicating generically an assertion failure (such as "Assertion failed").
- If data is empty, append message to data.
- Otherwise, implementations should perform these substeps:
- Let first be the first element of data.
- If
Type (first) is not String, prepend message to data. Abort these substeps. - Let concat be the concatenation of message, U+003A COLON (:), U+0020 SPACE, and first.
- Set data[0] to concat.
- Perform
Logger ("error", data).
2.1.2. clear()
Empty the appropriate group stack, and if possible for the environment, clear the console. Otherwise, do nothing.
2.1.3. count(label)
2.1.4. debug(...data)
Perform
2.1.5. error(...data)
Perform
2.1.6. info(...data)
Perform
2.1.7. log(...data)
Perform
2.1.8. table(tabularData, properties)
Try to construct a table with the columns of the properties of tabularData (or use properties) and rows of tabularData and log it with a logLevel of log. Fall back to just logging the argument if it can’t be parsed as tabular.
TODO: This will need a good algorithm.
2.1.9. trace(...data)
The identifier of a function printed in a stack trace is implementation-dependant. It is also not guaranteed to be the same identifier that would be seen in new Error().stack
2.1.10. warn(...data)
Perform
2.1.11. dir(item)
- Let object be item with generic JavaScript object formatting applied.
- Perform
Printer ("log", «object»).
2.1.12. dirxml(...data)
- Let finalList be a new list, initially empty.
- For each item of data:
- Let converted be a DOM tree representation of item if possible, otherwise let converted be item with optimally useful formatting applied.
- Append converted to finalList.
- Perform
Logger ("log", finalList).
2.2. Grouping methods
A group is an implementation-specific, potentially-interactive view for output produced by calls to console namespace object has an associated group stack, which is a stack, initially empty. Only
the last group in a group stack will host output produced by calls to
2.2.1. group(...data)
- Let group be a new group.
- If data is not empty, let groupLabel be the result of
Formatter (data). Otherwise, let groupLabel be an implementation-chosen label representing a group. - Incorporate groupLabel as a label for group.
- Optionally, if the environment supports interactive groups, group should be expanded by default.
- Perform
Printer ("log", «group»). - Push group onto the appropriate group stack.
2.2.2. groupCollapsed(...data)
- Let group be a new group.
- If data is not empty, let groupLabel be the result of
Formatter (data). Otherwise, let groupLabel be an implementation-chosen label representing a group. - Incorporate groupLabel as a label for group.
- Optionally, if the environment supports interactive groups, group should be collapsed by default.
- Perform
Printer ("log", «group»). - Push group onto the appropriate group stack.
2.2.3. groupEnd()
Pop the last group from the group stack.
2.3. Timing methods
2.3.1. time(label)
Start an internal timer stored in the timer table with key label.
2.3.2. timeEnd(label)
Let duration be the current value of the internal timer with key label in the timer table.
Remove the timer from the timer table.
Then, perform
3. JavaScript object inspection
TODO: Define an interface that allows JavaScript objects to format themselves for inspection.
Acknowledgments
The editors would like to thank Boris Zbarsky, Brent S.A. Cowgill, Brian Grinstead, Corey Farwell, Ian Kilpatrick, Jeff Carpenter, Joseph Pecoraro, Justin Woo, Noah Bass, Paul Irish, Raphaël, and Victor Costan for their contributions to this specification. You are awesome!
This standard is written by Terin Stock (terin@terinstock.com), Robert Kowalski (rok@kowalski.gd), and Dominic Farolino (domfarolino@gmail.com) with major help from Domenic Denicola (Google, d@domenic.me).
Per CC0, to the extent possible under law, the editors have waived all copyright and related or neighboring rights to this work.