diff --git a/index.bs b/index.bs
index db579fb..81405ba 100644
--- a/index.bs
+++ b/index.bs
@@ -3,7 +3,7 @@ Group: WHATWG
H1: Console
Shortname: console
Text Macro: TWITTER consolelog
-Text Macro: LATESTRD 2022-12
+Text Macro: LATESTRD 2024-06
Abstract: This specification defines APIs for console debugging facilities.
Translation: ja https://triple-underscore.github.io/console-ja.html
Indent: 2
diff --git a/review-drafts/2024-06.bs b/review-drafts/2024-06.bs
new file mode 100644
index 0000000..74ecf93
--- /dev/null
+++ b/review-drafts/2024-06.bs
@@ -0,0 +1,589 @@
+
+Group: WHATWG
+Status: RD
+Date: 2024-06-17
+H1: Console
+Shortname: console
+Text Macro: TWITTER consolelog
+Text Macro: LATESTRD 2024-06
+Abstract: This specification defines APIs for console debugging facilities.
+Translation: ja https://triple-underscore.github.io/console-ja.html
+Indent: 2
+Markup Shorthands: markdown yes
+
+
+
+urlPrefix: https://tc39.github.io/ecma262/#; spec: ECMASCRIPT
+ type: abstract-op
+ text: ObjectCreate; url: sec-objectcreate
+ text: Type; url: sec-ecmascript-data-types-and-values
+ text: ToString; url: sec-tostring
+ text: Call; url: sec-call
+ type: interface
+ text: %ObjectPrototype%; url: sec-properties-of-the-object-prototype-object
+ type: constructor
+ text: %String%; url: sec-string-constructor
+ type: dfn
+ text: %parseFloat%; url: sec-parsefloat-string
+ text: %parseInt%; url: sec-parseint-string-radix
+
+
+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.
+
+Namespace {{console}}
+
+
+[Exposed=*]
+namespace console { // but see namespace object requirements below
+ // Logging
+ undefined assert(optional boolean condition = false, any... data);
+ undefined clear();
+ undefined debug(any... data);
+ undefined error(any... data);
+ undefined info(any... data);
+ undefined log(any... data);
+ undefined table(optional any tabularData, optional sequence<DOMString> properties);
+ undefined trace(any... data);
+ undefined warn(any... data);
+ undefined dir(optional any item, optional object? options);
+ undefined dirxml(any... data);
+
+ // Counting
+ undefined count(optional DOMString label = "default");
+ undefined countReset(optional DOMString label = "default");
+
+ // Grouping
+ undefined group(any... data);
+ undefined groupCollapsed(any... data);
+ undefined groupEnd();
+
+ // Timing
+ undefined time(optional DOMString label = "default");
+ undefined timeLog(optional DOMString label = "default", any... data);
+ undefined 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%}}.
+
+Logging functions
+
+assert(|condition|, ...|data|)
+
+1. If |condition| is true, return.
+1. Let |message| be a string without any formatting specifiers indicating generically an assertion
+ failure (such as "Assertion failed").
+1. If |data| is [=list/is empty|empty=], [=list/append=] |message| to |data|.
+1. Otherwise:
+ 1. Let |first| be |data|[0].
+ 1. If Type(|first|) is not String, then [=list/prepend=] |message| to |data|.
+ 1. Otherwise:
+ 1. Let |concat| be the concatenation of |message|, U+003A (:), U+0020 SPACE, and |first|.
+ 1. Set |data|[0] to |concat|.
+1. Perform Logger("assert", |data|).
+
+clear()
+
+1. [=stack/Empty=] the appropriate group stack.
+1. If possible for the environment, clear the console. (Otherwise, do nothing.)
+
+debug(...|data|)
+
+1. Perform Logger("debug", |data|).
+
+error(...|data|)
+
+1. Perform Logger("error", |data|).
+
+info(...|data|)
+
+1. Perform Logger("info", |data|).
+
+log(...|data|)
+
+1. Perform Logger("log", |data|).
+
+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.
+
+trace(...|data|)
+
+1. Let |trace| be some implementation-specific, potentially-interactive representation of the
+ callstack from where this function was called.
+1. Optionally, let |formattedData| be the result of Formatter(|data|), and
+ incorporate |formattedData| as a label for |trace|.
+1. Perform Printer("trace", « |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`.
+
+
+warn(...|data|)
+
+1. Perform Logger("warn", |data|).
+
+dir(|item|, |options|)
+
+1. Let |object| be |item| with generic JavaScript object formatting applied.
+1. Perform Printer("dir", « |object| », |options|).
+
+dirxml(...|data|)
+
+1. Let |finalList| be a new [=/list=], initially empty.
+1. [=list/For each=] |item| of |data|:
+ 1. Let |converted| be a DOM tree representation of |item| if possible; otherwise let
+ |converted| be |item| with optimally useful formatting applied.
+ 1. Append |converted| to |finalList|.
+1. Perform Logger("dirxml", |finalList|).
+
+Counting functions
+
+Each {{console}} namespace object has an associated count map, which is a map of
+strings to numbers, initially empty.
+
+count(|label|)
+
+1. Let |map| be the associated count map.
+1. If |map|[|label|] [=map/exists=], [=map/set=] |map|[|label|] to |map|[|label|] + 1.
+1. Otherwise, [=map/set=] |map|[|label|] to 1.
+1. Let |concat| be the concatenation of |label|, U+003A (:), U+0020 SPACE, and
+ ToString(|map|[|label|]).
+1. Perform Logger("count", « |concat| »).
+
+countReset(|label|)
+
+1. Let |map| be the associated count map.
+1. If |map|[|label|] [=map/exists=], [=map/set=] |map|[|label|] to 0.
+1. Otherwise:
+ 1. Let |message| be a string without any formatting specifiers indicating generically that the
+ given label does not have an associated count.
+ 1. Perform Logger("countReset", « |message| »);
+
+Grouping functions
+
+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. Each {{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 Printer.
+
+group(...|data|)
+
+1. Let |group| be a new group.
+1. If |data| is not [=list/is empty|empty=], let |groupLabel| be the result of
+ Formatter(|data|). Otherwise, let |groupLabel| be an implementation-chosen
+ label representing a group.
+1. Incorporate |groupLabel| as a label for |group|.
+1. Optionally, if the environment supports interactive groups, |group| should be expanded by
+ default.
+1. Perform Printer("group", « |group| »).
+1. [=stack/Push=] |group| onto the appropriate group stack.
+
+groupCollapsed(...|data|)
+
+1. Let |group| be a new group.
+1. If |data| is not empty, let |groupLabel| be the result of
+ Formatter(|data|). Otherwise, let |groupLabel| be an implementation-chosen
+ label representing a group.
+1. Incorporate |groupLabel| as a label for |group|.
+1. Optionally, if the environment supports interactive groups, |group| should be collapsed by
+ default.
+1. Perform Printer("groupCollapsed", « |group| »).
+1. [=stack/Push=] |group| onto the appropriate group stack.
+
+groupEnd()
+
+1. Pop the last group from the group stack.
+
+Timing functions
+
+Each {{console}} namespace object has an associated timer table, which is a map of
+strings to times, initially empty.
+
+time(|label|)
+
+1. If the associated timer table [=map/contains=] an entry with key |label|, return,
+ optionally reporting a warning to the console indicating that a timer with label |label| has
+ already been started.
+1. Otherwise, [=map/set=] the value of the entry with key |label| in the associated
+ timer table to the current time.
+
+timeLog(|label|, ...|data|)
+
+1. Let |timerTable| be the associated timer table.
+1. Let |startTime| be |timerTable|[|label|].
+1. Let |duration| be a string representing the difference between the current time and
+ |startTime|, in an implementation-defined format.
+ "4650", "4650.69 ms", "5 seconds", and "00:05"
+ are all reasonable ways of displaying a 4650.69 ms duration.
+1. Let |concat| be the concatenation of |label|, U+003A (:), U+0020 SPACE, and |duration|.
+1. [=list/prepend|Prepend=] |concat| to |data|.
+1. Perform Printer("timeLog", data).
+
+
+ The |data| parameter in calls to {{console/timeLog()}} is included in the call to
+
Logger to make it easier for users to supply intermediate timer logs with
+ some extra data throughout the life of a timer. For example:
+
+
+ console.time("MyTimer");
+ console.timeLog("MyTimer", "Starting application up…");
+ // Perhaps some code runs to bootstrap a complex app
+ // ...
+ console.timeLog("MyTimer", "UI is setup, making API calls now");
+ // Perhaps some fetch()'s here filling the app with data
+ // ...
+ console.timeEnd("MyTimer");
+
+
+
+timeEnd(|label|)
+
+1. Let |timerTable| be the associated timer table.
+1. Let |startTime| be |timerTable|[|label|].
+1. [=map/Remove=] |timerTable|[|label|].
+1. Let |duration| be a string representing the difference between the current time and
+ |startTime|, in an implementation-defined format.
+1. Let |concat| be the concatenation of |label|, U+003A (:), U+0020 SPACE, and |duration|.
+1. Perform Printer("timeEnd", « |concat| »).
+
+See whatwg/console#134
+for plans to make {{console/timeEnd()}} and {{console/timeLog()}} formally report warnings to the
+console when a given |label| does not exist in the associated timer table.
+
+
+Supporting abstract operations
+
+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 [=list/is empty|empty=], return.
+1. Let |first| be |args|[0].
+1. Let |rest| be all elements following |first| in |args|.
+1. If |rest| is [=list/is empty|empty=], perform
+ Printer(|logLevel|, « |first| ») and return.
+1. Otherwise, perform Printer(|logLevel|, Formatter(|args|)).
+1. 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 will first print "hello!", then the
+ undefined return value from the console.log call.
+
+
+
+
+
+
+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. If |args|'s [=list/size=] is 1, return |args|.
+1. Let |target| be the first element of |args|.
+1. Let |current| be the second element of |args|.
+1. Find the first possible format specifier |specifier|, from the left to the right in |target|.
+1. If no format specifier was found, return |args|.
+1. Otherwise:
+ 1. If |specifier| is `%s`, let |converted| be the result of
+ [$Call$](%String%, **undefined**, « |current| »).
+ 1. If |specifier| is `%d` or `%i`:
+ 1. If [$Type$](|current|) is Symbol, let |converted| be `NaN`
+ 1. Otherwise, let |converted| be the result of
+ [$Call$]([=%parseInt%=], **undefined**, « |current|, 10 »).
+ 1. If |specifier| is `%f`:
+ 1. If [$Type$](|current|) is Symbol, let |converted| be `NaN`
+ 1. Otherwise, let |converted| be the result of
+ [$Call$]([=%parseFloat%=], **undefined**, « |current| »).
+ 1. If |specifier| is `%o`, optionally let |converted| be |current| with
+ optimally useful formatting applied.
+ 1. If |specifier| is `%O`, optionally let |converted| be |current| with
+ generic JavaScript object formatting applied.
+ 1. TODO: process %c
+ 1. If any of the previous steps set |converted|, replace |specifier| in |target| with
+ |converted|.
+1. Let |result| be a [=/list=] containing |target| together with the elements of |args| starting
+ from the third onward.
+1. Return Formatter(|result|).
+
+
+
+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 |
+ %String%(|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 with optimally useful formatting |
+ n/a |
+
+
+ `%O` |
+ Element is displayed with generic JavaScript object formatting |
+ n/a |
+
+
+ `%c` |
+ Applies provided CSS |
+ n/a |
+
+
+
+Printer(|logLevel|, |args|[, |options|])
+
+The printer operation is implementation-defined. It accepts a log level indicating severity, a List
+of arguments to print, and an optional object of implementation-specific formatting options.
+Elements appearing in |args| will be one of the following:
+
+- JavaScript objects of any type.
+- Implementation-specific representations of printable things such as a stack trace or group.
+- Objects with either generic JavaScript object formatting or
+ optimally useful formatting applied.
+
+If the |options| object is passed, and is not undefined or null, implementations may use |options|
+to apply implementation-specific formatting to the elements in |args|.
+
+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. The output produced by calls to
+Printer should appear only within the last group on the appropriate group stack if the
+group stack is not empty, or elsewhere in the console otherwise.
+
+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).
+
+Indicating |logLevel| severity
+
+Each {{console}} function uses a unique value for the |logLevel| parameter when calling
+Printer, allowing implementations to customize each printed message depending on the function from
+which it originated. However, it is common practice to group together certain functions and treat
+their output similarly, in four broad categories. This table summarizes these common groupings:
+
+
+
+
+ Grouping |
+ {{console}} functions |
+ Description |
+
+
+
+ log |
+
+ {{console/log()}}, {{console/trace()}}, {{console/dir()}}, {{console/dirxml()}},
+ {{console/group()}}, {{console/groupCollapsed()}}, {{console/debug()}}, {{console/timeLog()}}
+ |
+
+ A generic log
+ |
+
+
+ info |
+ {{console/count()}}, {{console/info()}}, {{console/timeEnd()}} |
+
+ An informative log
+ |
+
+
+ warn |
+
+ {{console/warn()}}, {{console/countReset()}}
+ |
+
+ A log warning the user of something indicated by the message
+ |
+
+
+ error |
+ {{console/error()}}, {{console/assert()}} |
+
+ A log indicating an error to the user
+ |
+
+
+
+These groupings are meant to document common practices, and do not constrain implementations from
+providing special behavior for each function, as in the following examples:
+
+
+
+
+ Calls to {{console/count()}} might not always print new output, but instead could update
+ previously-output counts.
+
+
+
+
+Printer user experience innovation
+
+Since Printer is implementation-defined, it is common to see UX innovations in
+its implementations. The following is a non-exhaustive list of potential UX enhancements:
+
+
+
+
+
+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 Printer, where the actual
+side effect of formatting will be seen.
+
+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.
+
+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
+
+
+
+Reporting warnings to the console
+
+To report a warning to the console given a generic description of a warning
+|description|, implementations must run these steps:
+
+1. Let |warning| be an implementation-defined string derived from |description|.
+1. Perform Printer("reportWarning", « |warning| »).
+
+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,
+Luc Martin,
+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).