099cb420b9
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}
701 lines
15 KiB
Plaintext
701 lines
15 KiB
Plaintext
Test for console formatting
|
|
|
|
Running test: testFloatFormatter
|
|
Testing console.debug('%f', 3.1415)...
|
|
debug[
|
|
[0] : {
|
|
type : string
|
|
value : %f
|
|
}
|
|
[1] : {
|
|
description : 3.1415
|
|
type : number
|
|
value : 3.1415
|
|
}
|
|
]
|
|
Testing console.error('%f', '3e2')...
|
|
error[
|
|
[0] : {
|
|
type : string
|
|
value : %f
|
|
}
|
|
[1] : {
|
|
description : 300
|
|
type : number
|
|
value : 300
|
|
}
|
|
]
|
|
Testing console.info('%f', Symbol('1.1'))...
|
|
info[
|
|
[0] : {
|
|
type : string
|
|
value : %f
|
|
}
|
|
[1] : {
|
|
description : NaN
|
|
type : number
|
|
unserializableValue : NaN
|
|
}
|
|
]
|
|
Testing console.log('%f', {toString() { return '42'; }})...
|
|
log[
|
|
[0] : {
|
|
type : string
|
|
value : %f
|
|
}
|
|
[1] : {
|
|
description : 42
|
|
type : number
|
|
value : 42
|
|
}
|
|
]
|
|
Testing console.trace('%f', {[Symbol.toPrimitive]() { return 2.78; }})...
|
|
trace[
|
|
[0] : {
|
|
type : string
|
|
value : %f
|
|
}
|
|
[1] : {
|
|
description : 2.78
|
|
type : number
|
|
value : 2.78
|
|
}
|
|
]
|
|
Testing console.warn('%f', {toString() { throw new Error(); }})...
|
|
{
|
|
columnNumber : 33
|
|
exception : {
|
|
className : Error
|
|
description : Error at Object.toString (<anonymous>:1:40) at parseFloat (<anonymous>) at console.warn (<anonymous>) at <anonymous>:1:9
|
|
objectId : <objectId>
|
|
subtype : error
|
|
type : object
|
|
}
|
|
exceptionId : <exceptionId>
|
|
lineNumber : 0
|
|
scriptId : <scriptId>
|
|
stackTrace : {
|
|
callFrames : [
|
|
[0] : {
|
|
columnNumber : 39
|
|
functionName : toString
|
|
lineNumber : 0
|
|
scriptId : <scriptId>
|
|
url :
|
|
}
|
|
[1] : {
|
|
columnNumber : 8
|
|
functionName :
|
|
lineNumber : 0
|
|
scriptId : <scriptId>
|
|
url :
|
|
}
|
|
]
|
|
}
|
|
text : Uncaught
|
|
}
|
|
|
|
Running test: testIntegerFormatter
|
|
Testing console.debug('%d', 42)...
|
|
debug[
|
|
[0] : {
|
|
type : string
|
|
value : %d
|
|
}
|
|
[1] : {
|
|
description : 42
|
|
type : number
|
|
value : 42
|
|
}
|
|
]
|
|
Testing console.error('%i', '987654321')...
|
|
error[
|
|
[0] : {
|
|
type : string
|
|
value : %i
|
|
}
|
|
[1] : {
|
|
description : 987654321
|
|
type : number
|
|
value : 987654321
|
|
}
|
|
]
|
|
Testing console.info('%d', Symbol('12345'))...
|
|
info[
|
|
[0] : {
|
|
type : string
|
|
value : %d
|
|
}
|
|
[1] : {
|
|
description : NaN
|
|
type : number
|
|
unserializableValue : NaN
|
|
}
|
|
]
|
|
Testing console.log('%i', {toString() { return '42'; }})...
|
|
log[
|
|
[0] : {
|
|
type : string
|
|
value : %i
|
|
}
|
|
[1] : {
|
|
description : 42
|
|
type : number
|
|
value : 42
|
|
}
|
|
]
|
|
Testing console.trace('%d', {[Symbol.toPrimitive]() { return 256; }})...
|
|
trace[
|
|
[0] : {
|
|
type : string
|
|
value : %d
|
|
}
|
|
[1] : {
|
|
description : 256
|
|
type : number
|
|
value : 256
|
|
}
|
|
]
|
|
Testing console.warn('%i', {toString() { throw new Error(); }})...
|
|
{
|
|
columnNumber : 33
|
|
exception : {
|
|
className : Error
|
|
description : Error at Object.toString (<anonymous>:1:40) at parseInt (<anonymous>) at console.warn (<anonymous>) at <anonymous>:1:9
|
|
objectId : <objectId>
|
|
subtype : error
|
|
type : object
|
|
}
|
|
exceptionId : <exceptionId>
|
|
lineNumber : 0
|
|
scriptId : <scriptId>
|
|
stackTrace : {
|
|
callFrames : [
|
|
[0] : {
|
|
columnNumber : 39
|
|
functionName : toString
|
|
lineNumber : 0
|
|
scriptId : <scriptId>
|
|
url :
|
|
}
|
|
[1] : {
|
|
columnNumber : 8
|
|
functionName :
|
|
lineNumber : 0
|
|
scriptId : <scriptId>
|
|
url :
|
|
}
|
|
]
|
|
}
|
|
text : Uncaught
|
|
}
|
|
|
|
Running test: testStringFormatter
|
|
Testing console.debug('%s', 42)...
|
|
debug[
|
|
[0] : {
|
|
type : string
|
|
value : %s
|
|
}
|
|
[1] : {
|
|
type : string
|
|
value : 42
|
|
}
|
|
]
|
|
Testing console.error('%s', 'Test string')...
|
|
error[
|
|
[0] : {
|
|
type : string
|
|
value : %s
|
|
}
|
|
[1] : {
|
|
type : string
|
|
value : Test string
|
|
}
|
|
]
|
|
Testing console.info('%s', Symbol('Test symbol'))...
|
|
info[
|
|
[0] : {
|
|
type : string
|
|
value : %s
|
|
}
|
|
[1] : {
|
|
type : string
|
|
value : Symbol(Test symbol)
|
|
}
|
|
]
|
|
Testing console.log('%s', {toString() { return 'Test object'; }})...
|
|
log[
|
|
[0] : {
|
|
type : string
|
|
value : %s
|
|
}
|
|
[1] : {
|
|
type : string
|
|
value : Test object
|
|
}
|
|
]
|
|
Testing console.trace('%s', {[Symbol.toPrimitive]() { return true; }})...
|
|
trace[
|
|
[0] : {
|
|
type : string
|
|
value : %s
|
|
}
|
|
[1] : {
|
|
type : string
|
|
value : true
|
|
}
|
|
]
|
|
Testing console.warn('%s', {toString() { throw new Error(); }})...
|
|
{
|
|
columnNumber : 33
|
|
exception : {
|
|
className : Error
|
|
description : Error at Object.toString (<anonymous>:1:40) at String (<anonymous>) at console.warn (<anonymous>) at <anonymous>:1:9
|
|
objectId : <objectId>
|
|
subtype : error
|
|
type : object
|
|
}
|
|
exceptionId : <exceptionId>
|
|
lineNumber : 0
|
|
scriptId : <scriptId>
|
|
stackTrace : {
|
|
callFrames : [
|
|
[0] : {
|
|
columnNumber : 39
|
|
functionName : toString
|
|
lineNumber : 0
|
|
scriptId : <scriptId>
|
|
url :
|
|
}
|
|
[1] : {
|
|
columnNumber : 8
|
|
functionName :
|
|
lineNumber : 0
|
|
scriptId : <scriptId>
|
|
url :
|
|
}
|
|
]
|
|
}
|
|
text : Uncaught
|
|
}
|
|
|
|
Running test: testOtherFormatters
|
|
Testing console.debug('%c', 'color:red')...
|
|
debug[
|
|
[0] : {
|
|
type : string
|
|
value : %c
|
|
}
|
|
[1] : {
|
|
type : string
|
|
value : color:red
|
|
}
|
|
]
|
|
Testing console.error('%o', {toString() { throw new Error(); }})...
|
|
error[
|
|
[0] : {
|
|
type : string
|
|
value : %o
|
|
}
|
|
[1] : {
|
|
className : Object
|
|
description : Object
|
|
objectId : 1.1.7
|
|
preview : {
|
|
description : Object
|
|
overflow : false
|
|
properties : [
|
|
[0] : {
|
|
name : toString
|
|
type : function
|
|
value :
|
|
}
|
|
]
|
|
type : object
|
|
}
|
|
type : object
|
|
}
|
|
]
|
|
Testing console.info('%O', {toString() { throw new Error(); }})...
|
|
info[
|
|
[0] : {
|
|
type : string
|
|
value : %O
|
|
}
|
|
[1] : {
|
|
className : Object
|
|
description : Object
|
|
objectId : 1.1.8
|
|
preview : {
|
|
description : Object
|
|
overflow : false
|
|
properties : [
|
|
[0] : {
|
|
name : toString
|
|
type : function
|
|
value :
|
|
}
|
|
]
|
|
type : object
|
|
}
|
|
type : object
|
|
}
|
|
]
|
|
Testing console.log('We have reached 100% of our users', 'with this!')...
|
|
log[
|
|
[0] : {
|
|
type : string
|
|
value : We have reached 100% of our users
|
|
}
|
|
[1] : {
|
|
type : string
|
|
value : with this!
|
|
}
|
|
]
|
|
|
|
Running test: testMultipleFormatters
|
|
Testing console.debug('%s%some Text%i', '', 'S', 1)...
|
|
debug[
|
|
[0] : {
|
|
type : string
|
|
value : %s%some Text%i
|
|
}
|
|
[1] : {
|
|
type : string
|
|
value :
|
|
}
|
|
[2] : {
|
|
type : string
|
|
value : S
|
|
}
|
|
[3] : {
|
|
description : 1
|
|
type : number
|
|
value : 1
|
|
}
|
|
]
|
|
Testing console.error('%c%i%c%s', 'color:red', 42, 'color:green', 'Message!')...
|
|
error[
|
|
[0] : {
|
|
type : string
|
|
value : %c%i%c%s
|
|
}
|
|
[1] : {
|
|
type : string
|
|
value : color:red
|
|
}
|
|
[2] : {
|
|
description : 42
|
|
type : number
|
|
value : 42
|
|
}
|
|
[3] : {
|
|
type : string
|
|
value : color:green
|
|
}
|
|
[4] : {
|
|
type : string
|
|
value : Message!
|
|
}
|
|
]
|
|
Testing console.info('%s', {toString() { return '%i% %s %s'; }}, {toString() { return '100'; }}, 'more', 'arguments')...
|
|
info[
|
|
[0] : {
|
|
type : string
|
|
value : %s
|
|
}
|
|
[1] : {
|
|
type : string
|
|
value : %i% %s %s
|
|
}
|
|
[2] : {
|
|
description : 100
|
|
type : number
|
|
value : 100
|
|
}
|
|
[3] : {
|
|
type : string
|
|
value : more
|
|
}
|
|
[4] : {
|
|
type : string
|
|
value : arguments
|
|
}
|
|
]
|
|
Testing console.log('%s %s', {toString() { return 'Too %s %s'; }}, 'many', 'specifiers')...
|
|
log[
|
|
[0] : {
|
|
type : string
|
|
value : %s %s
|
|
}
|
|
[1] : {
|
|
type : string
|
|
value : Too %s %s
|
|
}
|
|
[2] : {
|
|
type : string
|
|
value : many
|
|
}
|
|
[3] : {
|
|
type : string
|
|
value : specifiers
|
|
}
|
|
]
|
|
Testing console.trace('%s %f', {toString() { return '%s'; }}, {[Symbol.toPrimitive]() { return 'foo'; }}, 1, 'Test')...
|
|
trace[
|
|
[0] : {
|
|
type : string
|
|
value : %s %f
|
|
}
|
|
[1] : {
|
|
type : string
|
|
value : %s
|
|
}
|
|
[2] : {
|
|
type : string
|
|
value : foo
|
|
}
|
|
[3] : {
|
|
description : 1
|
|
type : number
|
|
value : 1
|
|
}
|
|
[4] : {
|
|
type : string
|
|
value : Test
|
|
}
|
|
]
|
|
|
|
Running test: testAssert
|
|
Testing console.assert(true, '%s', {toString() { throw new Error(); }})...
|
|
Testing console.assert(false, '%s %i', {toString() { return '%s'; }}, {[Symbol.toPrimitive]() { return 1; }}, 1, 'Test')...
|
|
assert[
|
|
[0] : {
|
|
type : string
|
|
value : %s %i
|
|
}
|
|
[1] : {
|
|
type : string
|
|
value : %s
|
|
}
|
|
[2] : {
|
|
type : string
|
|
value : 1
|
|
}
|
|
[3] : {
|
|
description : 1
|
|
type : number
|
|
value : 1
|
|
}
|
|
[4] : {
|
|
type : string
|
|
value : Test
|
|
}
|
|
]
|
|
Testing console.assert(false, '%s', {toString() { throw new Error(); }})...
|
|
{
|
|
columnNumber : 42
|
|
exception : {
|
|
className : Error
|
|
description : Error at Object.toString (<anonymous>:1:49) at String (<anonymous>) at console.assert (<anonymous>) at <anonymous>:1:9
|
|
objectId : <objectId>
|
|
subtype : error
|
|
type : object
|
|
}
|
|
exceptionId : <exceptionId>
|
|
lineNumber : 0
|
|
scriptId : <scriptId>
|
|
stackTrace : {
|
|
callFrames : [
|
|
[0] : {
|
|
columnNumber : 48
|
|
functionName : toString
|
|
lineNumber : 0
|
|
scriptId : <scriptId>
|
|
url :
|
|
}
|
|
[1] : {
|
|
columnNumber : 8
|
|
functionName :
|
|
lineNumber : 0
|
|
scriptId : <scriptId>
|
|
url :
|
|
}
|
|
]
|
|
}
|
|
text : Uncaught
|
|
}
|
|
|
|
Running test: testGroup
|
|
Testing console.group('%s', {toString() { throw new Error(); }})...
|
|
{
|
|
columnNumber : 34
|
|
exception : {
|
|
className : Error
|
|
description : Error at Object.toString (<anonymous>:1:41) at String (<anonymous>) at console.group (<anonymous>) at <anonymous>:1:9
|
|
objectId : <objectId>
|
|
subtype : error
|
|
type : object
|
|
}
|
|
exceptionId : <exceptionId>
|
|
lineNumber : 0
|
|
scriptId : <scriptId>
|
|
stackTrace : {
|
|
callFrames : [
|
|
[0] : {
|
|
columnNumber : 40
|
|
functionName : toString
|
|
lineNumber : 0
|
|
scriptId : <scriptId>
|
|
url :
|
|
}
|
|
[1] : {
|
|
columnNumber : 8
|
|
functionName :
|
|
lineNumber : 0
|
|
scriptId : <scriptId>
|
|
url :
|
|
}
|
|
]
|
|
}
|
|
text : Uncaught
|
|
}
|
|
Testing console.group('%s%i', 'Gruppe', {[Symbol.toPrimitive]() { return 1; }})...
|
|
startGroup[
|
|
[0] : {
|
|
type : string
|
|
value : %s%i
|
|
}
|
|
[1] : {
|
|
type : string
|
|
value : Gruppe
|
|
}
|
|
[2] : {
|
|
description : 1
|
|
type : number
|
|
value : 1
|
|
}
|
|
]
|
|
Testing console.groupEnd()...
|
|
endGroup[
|
|
[0] : {
|
|
type : string
|
|
value : console.groupEnd
|
|
}
|
|
]
|
|
|
|
Running test: testGroupCollapsed
|
|
Testing console.groupCollapsed('%d', {toString() { throw new Error(); }})...
|
|
{
|
|
columnNumber : 43
|
|
exception : {
|
|
className : Error
|
|
description : Error at Object.toString (<anonymous>:1:50) at parseInt (<anonymous>) at console.groupCollapsed (<anonymous>) at <anonymous>:1:9
|
|
objectId : <objectId>
|
|
subtype : error
|
|
type : object
|
|
}
|
|
exceptionId : <exceptionId>
|
|
lineNumber : 0
|
|
scriptId : <scriptId>
|
|
stackTrace : {
|
|
callFrames : [
|
|
[0] : {
|
|
columnNumber : 49
|
|
functionName : toString
|
|
lineNumber : 0
|
|
scriptId : <scriptId>
|
|
url :
|
|
}
|
|
[1] : {
|
|
columnNumber : 8
|
|
functionName :
|
|
lineNumber : 0
|
|
scriptId : <scriptId>
|
|
url :
|
|
}
|
|
]
|
|
}
|
|
text : Uncaught
|
|
}
|
|
Testing console.groupCollapsed('%s%f', {[Symbol.toPrimitive]() { return 'Gruppe'; }}, 3.1415)...
|
|
startGroupCollapsed[
|
|
[0] : {
|
|
type : string
|
|
value : %s%f
|
|
}
|
|
[1] : {
|
|
type : string
|
|
value : Gruppe
|
|
}
|
|
[2] : {
|
|
description : 3.1415
|
|
type : number
|
|
value : 3.1415
|
|
}
|
|
]
|
|
Testing console.groupEnd()...
|
|
endGroup[
|
|
[0] : {
|
|
type : string
|
|
value : console.groupEnd
|
|
}
|
|
]
|
|
|
|
Running test: testNonStandardFormatSpecifiers
|
|
Testing console.log('%_ %s', {toString() { throw new Error(); }}, {toString() { return 'foo'; }})...
|
|
log[
|
|
[0] : {
|
|
type : string
|
|
value : %_ %s
|
|
}
|
|
[1] : {
|
|
className : Object
|
|
description : Object
|
|
objectId : 1.1.15
|
|
preview : {
|
|
description : Object
|
|
overflow : false
|
|
properties : [
|
|
[0] : {
|
|
name : toString
|
|
type : function
|
|
value :
|
|
}
|
|
]
|
|
type : object
|
|
}
|
|
type : object
|
|
}
|
|
[2] : {
|
|
type : string
|
|
value : foo
|
|
}
|
|
]
|
|
Testing console.log('%%s', {toString() { throw new Error(); }})...
|
|
log[
|
|
[0] : {
|
|
type : string
|
|
value : %%s
|
|
}
|
|
[1] : {
|
|
className : Object
|
|
description : Object
|
|
objectId : 1.1.16
|
|
preview : {
|
|
description : Object
|
|
overflow : false
|
|
properties : [
|
|
[0] : {
|
|
name : toString
|
|
type : function
|
|
value :
|
|
}
|
|
]
|
|
type : object
|
|
}
|
|
type : object
|
|
}
|
|
]
|