v8/test/inspector/runtime/console-context.js
Benedikt Meurer 099cb420b9 [console] Proper type conversions in console builtins.
This updates the following set of console builtins in V8 to match the
Console Standard (https://console.spec.whatwg.org) with respect to
(potentially side effecting) type conversions:

  - console.debug
  - console.error
  - console.info
  - console.log
  - console.trace
  - console.warn
  - console.group
  - console.groupCollapsed
  - console.assert

The V8 implementation only performs the type conversions and updates
the arguments in-place with the results from the %String% constructor,
%parseInt%, or %parseFloat% invocations. The actual formatting is
still left completely to the debugger front-end.

To give a concrete example, the following code

```js
const msgFmt = {
  toString() { return 'Message %i' }
};
console.log('LOG: %s`, msgFmt, 42);
```

sends the following parameters to the debugger front-end

```js
["LOG: %s", "Message %i", 42]
```

and it's then the job of the front-end to perform the actual string
substitutions.

It's also worth calling out that the console builtins are only
concerned with %s, %f, %d, and %i formatting specifiers, since
these are the only ones that trigger type conversions, and %o, %O,
and %c can only be implemented in a meaningful way at a higher
level.

Fixed: chromium:1277944
Bug: chromium:1282076
Doc: https://bit.ly/v8-proper-console-type-conversions
Spec: https://console.spec.whatwg.org
Change-Id: I0996680811aa96236bd0d879e4a11101629ef1a7
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3352118
Reviewed-by: Kim-Anh Tran <kimanh@chromium.org>
Auto-Submit: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Igor Sheludko <ishell@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/main@{#78432}
2021-12-22 18:40:54 +00:00

112 lines
4.8 KiB
JavaScript

// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
let {session, contextGroup, Protocol} = InspectorTest.start('Tests console.context');
InspectorTest.runAsyncTestSuite([
async function testConsoleContextMethod() {
InspectorTest.log('console.context description:');
var {result:{result}} = await Protocol.Runtime.evaluate({
expression: 'console.context'});
InspectorTest.logMessage(result);
// Enumerate the methods alpha-sorted to make the test
// independent of the (unspecified) enumeration order
// of console.context() methods.
InspectorTest.log('console.context() methods:');
var {result: {result: {value}}} = await Protocol.Runtime.evaluate({
expression: 'Object.keys(console.context()).sort()',
returnByValue: true
});
InspectorTest.logMessage(value);
},
async function testDefaultConsoleContext() {
await Protocol.Runtime.enable();
Protocol.Runtime.evaluate({expression: 'console.log(239)'});
var {params:{context}} = await Protocol.Runtime.onceConsoleAPICalled();
InspectorTest.log(context);
Protocol.Runtime.evaluate({expression: 'console.info(239)'});
var {params:{context}} = await Protocol.Runtime.onceConsoleAPICalled();
InspectorTest.log(context);
Protocol.Runtime.evaluate({expression: 'console.debug(239)'});
var {params:{context}} = await Protocol.Runtime.onceConsoleAPICalled();
InspectorTest.log(context);
await Protocol.Runtime.evaluate({expression: 'console.clear()'});
await Protocol.Runtime.disable();
},
async function testAnonymousConsoleContext() {
await Protocol.Runtime.enable();
Protocol.Runtime.evaluate({expression: 'console.context().log(239)'});
var {params:{context}} = await Protocol.Runtime.onceConsoleAPICalled();
InspectorTest.log(context);
Protocol.Runtime.evaluate({expression: 'console.context().info(239)'});
var {params:{context}} = await Protocol.Runtime.onceConsoleAPICalled();
InspectorTest.log(context);
Protocol.Runtime.evaluate({expression: 'console.context().debug(239)'});
var {params:{context}} = await Protocol.Runtime.onceConsoleAPICalled();
InspectorTest.log(context);
await Protocol.Runtime.evaluate({expression: 'console.context().clear()'});
await Protocol.Runtime.disable();
},
async function testNamedConsoleContext() {
await Protocol.Runtime.enable();
Protocol.Runtime.evaluate({expression: `
var context = console.context('named-context');
context.log(239);
context.info(239);
context.debug(239);
`});
var {params:{context}} = await Protocol.Runtime.onceConsoleAPICalled();
InspectorTest.log(context);
var {params:{context}} = await Protocol.Runtime.onceConsoleAPICalled();
InspectorTest.log(context);
var {params:{context}} = await Protocol.Runtime.onceConsoleAPICalled();
InspectorTest.log(context);
await Protocol.Runtime.evaluate({expression: 'console.clear()'});
await Protocol.Runtime.disable();
},
async function testTwoConsoleContextsWithTheSameName() {
await Protocol.Runtime.enable();
Protocol.Runtime.evaluate({expression: 'console.context(\'named-context\').log(239)'});
var {params:{context}} = await Protocol.Runtime.onceConsoleAPICalled();
InspectorTest.log(context);
Protocol.Runtime.evaluate({expression: 'console.context(\'named-context\').log(239)'});
var {params:{context}} = await Protocol.Runtime.onceConsoleAPICalled();
InspectorTest.log(context);
await Protocol.Runtime.evaluate({expression: 'console.clear()'});
await Protocol.Runtime.disable();
},
async function testConsoleCountInDifferentConsoleContexts() {
await Protocol.Runtime.enable();
Protocol.Runtime.evaluate({expression: 'console.context(\'named-context\').count(239)'});
var {params:{args}} = await Protocol.Runtime.onceConsoleAPICalled();
InspectorTest.logMessage(args);
Protocol.Runtime.evaluate({expression: 'console.context(\'named-context\').count(239)'});
var {params:{args}} = await Protocol.Runtime.onceConsoleAPICalled();
InspectorTest.logMessage(args);
await Protocol.Runtime.evaluate({expression: 'console.clear()'});
await Protocol.Runtime.disable();
},
async function testConsoleCountForNamedConsoleContext() {
await Protocol.Runtime.enable();
Protocol.Runtime.evaluate({expression: `
var context = console.context('named-context');
context.count(239);
context.count(239);
`});
var {params:{args}} = await Protocol.Runtime.onceConsoleAPICalled();
InspectorTest.logMessage(args);
var {params:{args}} = await Protocol.Runtime.onceConsoleAPICalled();
InspectorTest.logMessage(args);
await Protocol.Runtime.evaluate({expression: 'console.clear()'});
await Protocol.Runtime.disable();
}
]);