[go: nahoru, domu]

Console

Commit Snapshot — Last Updated

Editors:
Terin Stock
Robert Kowalski
Participate:
GitHub whatwg/console (new issue, open issues)
IRC: #whatwg on Freenode
Commits:
GitHub whatwg/console/commits
Go to the living standard
@consolelog
This Is a Commit Snapshot of the Standard

This document contains the contents of the standard as of the 7e472abeb6874a41a1159e86cbe14ae7d6c4993b commit, and should only be used as a historical reference. This commit may not even have been merged into master.

Do not attempt to implement this version of the specification. Do not reference this version as authoritative in any way. Instead, see https://console.spec.whatwg.org/ for the living standard.

Abstract

This specification defines APIs for console debugging facilities.

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 List of other arguments. Its main output is the implementation-defined side effect of printing the result to the console. This specification describes how it processes format specifiers while doing so.

  1. If args is empty, abort these steps.
  2. Let first be the first element of args.
  3. Let rest be all elements following first in args.
  4. If rest is empty, perform Printer(logLevel, «first»). Abort these steps.
  5. If first does not contain any format specifiers, perform Printer(logLevel, args).
  6. Otherwise, perform Printer(logLevel, Formatter(args)).
  7. Return undefined.
It’s important that the printing occurs before returning from the algorithm. Many developer consoles print the result of the last operation entered into them. In such consoles, when a developer enters 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 List of objects suitable for printing.

  1. Let target be the first element of args.
  2. Let current be the second element of args.
  3. Find the first possible format specifier specifier, from the left to the right in target.
    1. If specifier is %s, let converted be the result of ToString(current).
    2. If specifier is %d or %i, let converted be the result of %parseInt%(current, 10).
    3. If specifier is %f, let converted be the result of %parseFloat%(current, 10).
    4. If specifier is %o, optionally let converted be an implementation-specific representation of current that is judged to be maximally useful and informative.
    5. If specifier is %O, optionally let converted be be an implementation-specific representation of current as an expanded or expandable object, treating current as a generic JavaScript object.
    6. TODO: process %c

    7. If any of the previous steps set converted, replace specifier in target with converted.
    8. Let result be a List containing target together with the elements of args starting from the third onward.
  4. If target does not have any format specifiers left, return result.
  5. If result contains just one element, return result.
  6. 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 ToString(element)
%d or %i Element which substitutes is converted to an integer %parseInt%(element, 10)
%f Element which substitutes is converted to a float %parseFloat%(element, 10)
%o Element is displayed in an implementation-specific way judged as most useful; potentially interactive n/a
%O Element is displayed as an expanded JavaScript object; potentially interactive 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 List of arguments to print (which are either JavaScript objects, of any type, or are implementation-specific representations of printable things such as a stack trace, or output produced by the %o and %O specifiers). How the implementation prints args is up to the implementation, but implementations should separate the objects by a space or something similar, as that has become a developer expectation.

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 List. When a group gets printed, output produced by future calls to Printer should be directed only to the newly printed group.

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. Example printer in Node.js

The simplest way to implement the printer operation on the Node.js platform is to join the previously formatted arguments separated by a space and write the output to 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);

  // 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 ObjectCreate(%ObjectPrototype%), instead of %ObjectPrototype%.

2.1. Logging methods

2.1.1. assert(condition, ...data)

  1. If condition is true, abort these steps.
  2. Let message be a string without any formatting specifiers indicating generically an assertion failure (such as "Assertion failed").
  3. If data is empty, append message to data.
  4. Otherwise, implementations should perform these substeps:
    1. Let first be the first element of data.
    2. If Type(first) is not String, prepend message to data. Abort these substeps.
    3. Let concat be the concatenation of message, U+003A COLON (:), U+0020 SPACE, and first.
    4. Set data[0] to concat.
  5. Perform Logger("error", data).

2.1.2. clear()

End all open groups, and if possible for the environment, clear the console. Otherwise, do nothing.

2.1.3. count(label)

  1. Let called be the number of times count has been invoked (including this invocation) with the provided label.
  2. Let concat be the concatenation of label, U+003A COLON (:), U+0020 SPACE, and ToString(called).
  3. Perform Logger("log", concat).

2.1.4. debug(...data)

Perform Logger("log", data).

2.1.5. error(...data)

Perform Logger("error", data).

2.1.6. info(...data)

Perform Logger("info", data).

2.1.7. log(...data)

Perform Logger("log", data).

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)

  1. Let trace be some implementation-specific, potentially-interactive representation of the callstack from where this method was called.
  2. Optionally let formattedData be the result of Formatter(data), and incorporate formattedData as a label for trace.
  3. Perform Printer("log", «trace»).

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 Logger("warn", data).

2.2. Grouping methods

A group is an implementation-specific, potentially-interactive view for output produced by calls to Printer, with one further level of indentation than its parent. A group may host output produced by calls to Printer until it is ended with groupEnd(), and only one group will host output produced by calls to Printer at a time.

2.2.1. group(...data)

  1. Let group be a new group.
  2. Let groupLabel be the result of Formatter(data), and incorporate groupLabel as a label for group.
  3. Optionally if the environment supports interactive groups, group should be expanded by default.
  4. Perform Printer("log", «group»).

2.2.2. groupCollapsed(...data)

  1. Let group be a new group.
  2. Let groupLabel be the result of Formatter(data), and incorporate groupLabel as a label for group.
  3. Optionally if the environment supports interactive groups, group should be collapsed by default.
  4. Perform Printer("log", «group»).

2.2.3. groupEnd()

When a group is ended, the output of any subsequent calls to Printer should be guided to the group’s most immediate parent, which may also be a group. An ended group will never host the output of future calls to Printer again.

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 Logger("info", «label, duration»).

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.

Index

Terms defined by this specification

Terms defined by reference

References

Normative References

[ECMASCRIPT]
ECMAScript Language Specification. URL: https://tc39.github.io/ecma262/
[WebIDL]
Cameron McCormack; Boris Zbarsky; Tobie Langel. Web IDL. URL: https://www.w3.org/TR/WebIDL-1/

IDL Index

[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);

  // Grouping
  void group(any... data);
  void groupCollapsed(any... data);
  void groupEnd();

  // Timing
  void time(optional DOMString label = "default");
  void timeEnd(optional DOMString label = "default");
};