Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Start adding log module #73

Merged
merged 15 commits into from
Feb 12, 2021
302 changes: 288 additions & 14 deletions index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ spec: WEBDRIVER; urlPrefix: https://w3c.github.io/webdriver/
text: WebDriver new session algorithm; url: dfn-webdriver-new-session-algorithm
text: web element reference; url: dfn-web-element-reference
text: window handle; url: dfn-window-handle
spec: CONSOLE; urlPrefix: https://console.spec.whatwg.org
jgraham marked this conversation as resolved.
Show resolved Hide resolved
type: dfn
text: printer; url: printer
spec: ECMASCRIPT; urlPrefix: https://tc39.es/ecma262/
type: dfn
text: Array; url: sec-array-objects
Expand All @@ -71,7 +74,6 @@ spec: ECMASCRIPT; urlPrefix: https://tc39.es/ecma262/
text: EnumerableOwnPropertyNames; url: sec-enumerableownpropertynames
text: Get; url: sec-get
text: HasProperty; url: sec-hasproperty
text: internal slot; url: sec-object-internal-methods-and-internal-slots
text: IsArray; url: sec-isarray
text: IsCallable; url: sec-iscallable
text: IsPromise; url: sec-ispromise
Expand All @@ -83,12 +85,20 @@ spec: ECMASCRIPT; urlPrefix: https://tc39.es/ecma262/
text: ToDateString; url: sec-todatestring
text: ToString; url: sec-tostring
text: Type; url: sec-ecmascript-data-types-and-values
text: current realm record; url: current-realm
text: internal slot; url: sec-object-internal-methods-and-internal-slots
text: primitive value; url: sec-primitive-value
text: realm; url: sec-code-realms
text: running execution context; url: running-execution-context
text: time value; url: sec-time-values-and-time-range
spec: HTML; urlPrefix: https://html.spec.whatwg.org/
type: dfn
text: WindowProxy; url: windowproxy
text: a browsing context is discarded; url: a-browsing-context-is-discarded
text: create a new browsing context; url: creating-a-new-browsing-context
text: environment settings object's Realm; url: environment-settings-object's-realm
text: handled; url: concept-error-handled
text: report an error; url: report-the-error
text: remove a browsing context; url: bcg-remove
text: session history; url: session-history
text: set up a window environment settings object; url: set-up-a-window-environment-settings-object
Expand Down Expand Up @@ -591,6 +601,25 @@ To <dfn>handle an incoming message</dfn> given a [=WebSocket connection=]

</div>

<div algorithm>

To <dfn>get related contexts</dfn> given an [=script/settings object=]
|settings|:

1. Let |related contexts| be an empty set

1. If the [=responsible document=] of |settings| is a [=Document=], append the
[=responsible document=]'s [=Document/browsing context=] to |related contexts|.

Otherwise if the [=Realm/global object=] specified by |settings| is a
{{WorkerGlobalScope}}, for each |owner| in the [=Realm/global object=]'s
[=owner set=], if |owner| is a [=Document=], append |owner|'s
[=Document/browsing context=] to |related contexts|.

1. Return |related contexts|

</div>

<div algorithm>
To <dfn export>emit an event</dfn> given |body| and |related contexts|:

Expand Down Expand Up @@ -637,8 +666,9 @@ To <dfn>respond with an error</dfn> given a [=WebSocket connection=]


<div algorithm>
To <dfn>handle a connection closing</dfn> given a
[=WebSocket connection=] |connection|:

To <dfn>handle a connection closing</dfn> given a [=WebSocket connection=]
|connection|:

1. If there is a WebDriver [=/session=] with |connection| as its [=connection=],
set the [=connection=] on that [=/session=] to null.
Expand Down Expand Up @@ -1131,8 +1161,10 @@ To <dfn>serialize as a remote value</dfn> given an |value|, a |max depth|,
Otherwise, let |children| be an empty list and, for each node
|child| in the [=children=] of |value|:

1. Let |child depth| be |max depth| - 1 if |max depth| is not null, or null otherwise.

1. Let |serialized| be the result of [=serialize as a remote value=]
with |child|, |max depth| - 1, |node details| and
with |child|, |child depth|, |node details| and
|set of known objects|.

1. Append |serialized| to |children|.
Expand All @@ -1156,9 +1188,14 @@ To <dfn>serialize as a remote value</dfn> given an |value|, a |max depth|,
1. Let |shadow root| be |value|'s [=Element/shadow root=].

1. If |shadow root| is null, let |serialized shadow| be null.
Otherwise let |serialized shadow| be the result of
[=serialize as a remote value=] with |shadow root|, |max depth| - 1,
false and |set of known objects|.
Otherwise run the following substeps:

1. Let |child depth| be |max depth| - 1 if |max depth| is not
null, or null otherwise.

1. Let |serialized shadow| be the result of
[=serialize as a remote value=] with |shadow root|, |child depth|,
false and |set of known objects|.

Note: this means the <code>objectId</code> for the shadow root
will be serialized irrespective of whether the shadow is open or closed,
Expand Down Expand Up @@ -1221,9 +1258,12 @@ To <dfn>serialize as a list</dfn> given |iterable|, |max depth|,

1. For each |child value| in |iterable|:

1. Let |serialized child| be the result of [=serialize as a
remote value=] with arguments |child value|, |max
depth| - 1, |node details| and |set of known objects|.
1. Let |child depth| be |max depth| - 1 if |max depth| is not null, or null
otherwise.

1. Let |serialized child| be the result of [=serialize as a remote value=]
with arguments |child value|, |child depth|, |node details| and |set of
known objects|.

1. Append |serialized child| to |serialized|.

Expand All @@ -1247,14 +1287,17 @@ To <dfn>serialize as a mapping</dfn> given |iterable|, |max depth|,

1. Let |key| be |property|[0] and let |value| be |property|[1]

1. Let |child depth| be |max depth| - 1 if |max depth| is not null, or null
otherwise.

1. If [=Type=](|key|) is String, let |serialized key| be |child key|,
otherwise let |serialized key| be the result of [=serialize as a remote
value=] with arguments |child key|, |max depth| - 1, |node details| and
value=] with arguments |child key|, |child depth|, |node details| and
|set of known objects|.

1. Let |serialized value| be the result of [=serialize as a
remote value=] with arguments |value|, |max
depth| - 1, |node details| and |set of known objects|.
1. Let |serialized value| be the result of [=serialize as a remote value=]
with arguments |value|, |child depth|, |node details| and |set of known
objects|.

1. Let |serialized child| be («|serialized key|, |serialized value|»).

Expand Down Expand Up @@ -1739,6 +1782,7 @@ relating to script realms and execution.
<pre class="cddl remote-cddl">

ScriptCommand = (ScriptGetRealmsCommand)

</pre>

[=local end definition=]
Expand Down Expand Up @@ -2086,6 +2130,210 @@ worker=] algorithm:
1. Let |body| be a map matching the <code>RealmDestroyedEvent</code>
production, with the <code>params</code> field set to |params|.

## Log ## {#module-log}

The <dfn export for=modules>log</dfn> module contains functionality and events
related to logging.

### Definition ### {#module-log-definition}

[=remote end definition=]

<pre class="cddl remote-cddl">

LogEvent = (
LogEntryAddedEvent
)
</pre>

### Types ### {#module-log-types}

#### log.LogEntry #### {#types-log-logentry}

<pre class="cddl local-cddl">

LogLevel = "debug" / "info" / "warning" / "error"
jgraham marked this conversation as resolved.
Show resolved Hide resolved

LogEntry = (
GenericLogEntry //
ConsoleLogEntry //
JavascriptLogEntry
)

BaseLogEntry = {
level: LogLevel,
text: text / null,
jgraham marked this conversation as resolved.
Show resolved Hide resolved
jgraham marked this conversation as resolved.
Show resolved Hide resolved
timestamp: int,
?stackTrace: [*StackFrame],
}

GenericLogEntry = {
BaseLogEntry,
type: text,
jgraham marked this conversation as resolved.
Show resolved Hide resolved
}

ConsoleLogEntry = {
BaseLogEntry,
type: "console",
method: text,
realm: Realm,
args: [*RemoteValue],
}

JavascriptLogEntry = {
BaseLogEntry,
type: "javascript",
}

</pre>

Each log event is represented by a <code>LogEntry</code> object. This has a
<code>type</code> property which represents the type of log entry added, a
<code>level</code> property representing severity, a <code>text</code> property
with the log message string itself, and a <code>timestamp</code> property
corresponding to the time the log entry was generated. Specific variants of the
<code>LogEntry</code> are used to represent logs from different sources, and
provide additional fields specific to the entry type.

#### log.StackFrame #### {#types-log-stackframe}

<pre class="cddl local-cddl">

StackFrame = {
url: text,
functionName: text,
lineNumber: int,
columnNumber: int,
}

</pre>

A frame in a stacktrace is represented by a <code>StackFrame</code> object. This
has a <code>url</code> property, which represents the URL of the script, a
<code>functionName</code> property which represents the name of the executing
function, and <code>lineNumber</code> and <code>columnNumber</code> properties,
which represent the line and column number of the executed code.

The <dfn>current stack trace</dfn> is a representation of the stack of the
[=running execution context=]. The details of this are unspecified, and so the
behaviour here is implementation defined, but the general process is as follows:

1. Let |stack trace| be a new list.

1. For each stack frame |frame| in the stack of the running execution context,
starting from the most recently executed frame, run the following steps:

1. Let |url| be the result of running the [=URL serializer=], given
the <a spec=url for=/>URL</a> of |frame|'s associated script resource.

1. Let |functionName| be the name of |frame|'s associated function.

1. Let |lineNumber| and |columnNumber| be the one-based line and zero-based
column numbers, respectively, of the location in |frame|'s associated
script resource corresponding to |frame|.

1. Let |frame info| be a new map matching the <code>StackFrame</code>
production, with the <code>url</code> field set to |url|, the
<code>functionName</code> field set to |functionName|, the
<code>lineNumber</code> field set to |lineNumber| and the
<code>columnNumber</code> field set to |columnNumber|.

1. Append |frame info| to |stack trace|.

1. Return |stack trace|

### Events ### {#module-log-events}

#### entryAdded #### {#event-log-entryAdded}

<dl>
<dt>Event Type</dt>
<dd>
<pre class="cddl local-cddl">
LogEntryAddedEvent = {
method: "log.entryAdded",
params: LogEntry,
}
</pre>
</dd>
</dl>

The [=remote end event trigger=] is:

<div algorithm="remote end event trigger for log.entryAdded">

Define the following [=console steps=] with |method|, |args|, and <var
ignore>options</var>:

1. If |method| is "<code>error</code>" or "<code>assert</code>", let |level| be
"<code>error</code>". If |method| is "<code>debug</code>" or
"<code>trace</code>" let |level| be "<code>debug</code>". If |method| is
"<code>warn</code>" or <code>warning</code>, let |level| be
"<code>warning</code>". Otherwise let
|level| be "<code>info</code>".

1. Let |timestamp| be a [=time value=] representing the current date and time in UTC.

1. Let |text| be an empty string.

1. For each |arg| in |args|:

1. If |arg| is not the first entry in |args|, append a U+0020 SPACE to |text|.

1. If |arg| is a [=primitive value=], append [=ToString=](|arg|) to
|text|. Otherwise append an implementation-defined string to |text|.
jgraham marked this conversation as resolved.
Show resolved Hide resolved
jgraham marked this conversation as resolved.
Show resolved Hide resolved

1. Let |serialized args| be a new list.

1. For each |arg| of |args|, append the result of [=serialize as a remote
value=] given |arg|, null, true, and an empty [=set=] to |serialized args|.
Comment on lines +2300 to +2301
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Meaning with implicit maxDepth = null. Should serialisationMaxDepth be kind of a global param?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, I think we're going to need to improve the control of serialization for the whole spec at some point. I think I'd prefer to work on that when we specify script execution. So maybe file an issue for now?

Copy link
Contributor

@sadym-chromium sadym-chromium Feb 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree it's not in the scope of this PR.

Filed Allow maxDepth serialisation setting #86


1. Let |realm| be the [=realm id=] of the [=current Realm Record=].

1. Let |stack| be the [=current stack trace=].

1. Let |entry| be a map matching the <code>ConsoleLogEntry</code> production,
with the the <code>level</code> field set to |level|, the <code>text</code>
field set to |text|, the <code>timestamp</code> field set to |timestamp|, the
<code>stackTrace</code> field set to |stack| if |stack| is not null, or
omitted otherwise, the |method| field set to |method|, the <code>realm</code>
field set to |realm| and the <code>args</code> field set to |serialized
args|.

1. Let |body| be a map matching the <code>LogEntryAddedEvent</code> production, with
the <code>params</code> field set to |entry|.

1. Let |settings| be the [=current settings object=]

1. Let |related contexts| be the result of [=get related contexts=] given |settings|.

1. [=Emit an event=] with |body| and |related contexts|.
jgraham marked this conversation as resolved.
Show resolved Hide resolved

Define the following [=error reporting steps=] with arguments |script|, <var
ignore>line number</var>, <var ignore>column number</var>, |message| and
|handled|:

1. If |handled| is true return.

1. Let |settings| be |script|'s [=script/settings object=].

1. Let |stack| be the [=current stack trace=] for the exception.

1. Let |entry| be a map matching the <code>JavascriptLogEntry</code> production,
with <code>level</code> set to "<code>error</code>", <code>text</code> set to
|message|, and the <code>timestamp</code> field set to |timestamp|.

1. Let |related contexts| be the result of [=get related contexts=] given |settings|.

1. [=Emit an event=] with |body| and |related contexts|.

Issue: Lots more things require logging. CDP has LogEntryAdded types xml,
javascript, network, storage, appcache, rendering, security, deprecation,
worker, violation, intervention, recommendation, other. These are in addition to
the js exception and console API types that are represented by different methods.

Issue: Allow implementation-defined log types

</div>

# Patches to Other Specifications # {#patches}
Expand Down Expand Up @@ -2115,3 +2363,29 @@ To discard a browsing context |browsingContext|, run these steps:
Issue: The actual patch might be better to split the algorithm into an outer algorithm that is
called by external callers and an inner algorithm that's used for recursive calls. That's quite hard
to express as a patch to the specification since it requires changing multiple parts.


The [=report an error=] algorithm is modified with an additional step at the
end:

<div algorithm>
11. Call any <dfn>error reporting steps</dfn> decined in external specifications
jgraham marked this conversation as resolved.
Show resolved Hide resolved
with <var ignore>script</var>, <var ignore>line</var>, <var
ignore>col</var>, <var ignore>message</var>, and true if the error is
[=handled=], or false otherwise.

</div>
## Console ## {#patches-console}

Other specifications can define <dfn>console steps</dfn>. When any method of the
{{console}} interface is called, with method name
|method| and argument |args|:

1. If that method does not call the [=Printer=] operation, call any [=console
steps=] defined in external specification with arguments |method|, |args|
and, undefined.

Otherwise, at the point when the [=Printer=] operation is called with
arguments |name|, |printerArgs| and |options| (which is undefined if the
argument is not provided), call any [=console steps=] defined in
external specification with arguments |name|, |printerArgs|, and |options|.