From 96f3d439f5748ff707d64fb41af50786c0d33ad7 Mon Sep 17 00:00:00 2001 From: Yang Guo Date: Fri, 25 Sep 2020 15:27:13 +0200 Subject: [PATCH] feat(console): expose stack trace for console messages (#6445) --- docs/api.md | 7 ++++++ .../puppeteer.consolemessage._constructor_.md | 4 ++-- new-docs/puppeteer.consolemessage.md | 3 ++- .../puppeteer.consolemessage.stacktrace.md | 17 ++++++++++++++ src/common/ConsoleMessage.ts | 15 ++++++++---- src/common/Page.ts | 22 ++++++++++-------- test/assets/consolelog.html | 8 ++++++- test/page.spec.ts | 23 ++++++++++++++++--- 8 files changed, 78 insertions(+), 21 deletions(-) create mode 100644 new-docs/puppeteer.consolemessage.stacktrace.md diff --git a/docs/api.md b/docs/api.md index e8b1151393e..9bf339e21dc 100644 --- a/docs/api.md +++ b/docs/api.md @@ -214,6 +214,7 @@ - [class: ConsoleMessage](#class-consolemessage) * [consoleMessage.args()](#consolemessageargs) * [consoleMessage.location()](#consolemessagelocation) + * [consoleMessage.stackTrace()](#consolemessagestacktrace) * [consoleMessage.text()](#consolemessagetext) * [consoleMessage.type()](#consolemessagetype) - [class: Frame](#class-frame) @@ -2752,6 +2753,12 @@ const puppeteer = require('puppeteer'); - `lineNumber` <[number]> 0-based line number in the resource if known or `undefined` otherwise. - `columnNumber` <[number]> 0-based column number in the resource if known or `undefined` otherwise. +#### consoleMessage.stackTrace() +- returns: <[Array]<[Object]>> + - `url` <[string]> URL of the resource if known or `undefined` otherwise. + - `lineNumber` <[number]> 0-based line number in the resource if known or `undefined` otherwise. + - `columnNumber` <[number]> 0-based column number in the resource if known or `undefined` otherwise. + #### consoleMessage.text() - returns: <[string]> diff --git a/new-docs/puppeteer.consolemessage._constructor_.md b/new-docs/puppeteer.consolemessage._constructor_.md index 79ca5dfa3eb..f362981a9bf 100644 --- a/new-docs/puppeteer.consolemessage._constructor_.md +++ b/new-docs/puppeteer.consolemessage._constructor_.md @@ -9,7 +9,7 @@ Constructs a new instance of the `ConsoleMessage` class Signature: ```typescript -constructor(type: ConsoleMessageType, text: string, args: JSHandle[], location?: ConsoleMessageLocation); +constructor(type: ConsoleMessageType, text: string, args: JSHandle[], stackTraceLocations: ConsoleMessageLocation[]); ``` ## Parameters @@ -19,5 +19,5 @@ constructor(type: ConsoleMessageType, text: string, args: JSHandle[], location?: | type | [ConsoleMessageType](./puppeteer.consolemessagetype.md) | | | text | string | | | args | [JSHandle](./puppeteer.jshandle.md)\[\] | | -| location | [ConsoleMessageLocation](./puppeteer.consolemessagelocation.md) | | +| stackTraceLocations | [ConsoleMessageLocation](./puppeteer.consolemessagelocation.md)\[\] | | diff --git a/new-docs/puppeteer.consolemessage.md b/new-docs/puppeteer.consolemessage.md index 0b3f84a047a..446d75b5a94 100644 --- a/new-docs/puppeteer.consolemessage.md +++ b/new-docs/puppeteer.consolemessage.md @@ -16,7 +16,7 @@ export declare class ConsoleMessage | Constructor | Modifiers | Description | | --- | --- | --- | -| [(constructor)(type, text, args, location)](./puppeteer.consolemessage._constructor_.md) | | Constructs a new instance of the ConsoleMessage class | +| [(constructor)(type, text, args, stackTraceLocations)](./puppeteer.consolemessage._constructor_.md) | | Constructs a new instance of the ConsoleMessage class | ## Methods @@ -24,6 +24,7 @@ export declare class ConsoleMessage | --- | --- | --- | | [args()](./puppeteer.consolemessage.args.md) | | | | [location()](./puppeteer.consolemessage.location.md) | | | +| [stackTrace()](./puppeteer.consolemessage.stacktrace.md) | | | | [text()](./puppeteer.consolemessage.text.md) | | | | [type()](./puppeteer.consolemessage.type.md) | | | diff --git a/new-docs/puppeteer.consolemessage.stacktrace.md b/new-docs/puppeteer.consolemessage.stacktrace.md new file mode 100644 index 00000000000..7c080c79447 --- /dev/null +++ b/new-docs/puppeteer.consolemessage.stacktrace.md @@ -0,0 +1,17 @@ + + +[Home](./index.md) > [puppeteer](./puppeteer.md) > [ConsoleMessage](./puppeteer.consolemessage.md) > [stackTrace](./puppeteer.consolemessage.stacktrace.md) + +## ConsoleMessage.stackTrace() method + +Signature: + +```typescript +stackTrace(): ConsoleMessageLocation[]; +``` +Returns: + +[ConsoleMessageLocation](./puppeteer.consolemessagelocation.md)\[\] + +The array of locations on the stack of the console message. + diff --git a/src/common/ConsoleMessage.ts b/src/common/ConsoleMessage.ts index 7b772dc4616..3387dc59d0b 100644 --- a/src/common/ConsoleMessage.ts +++ b/src/common/ConsoleMessage.ts @@ -68,7 +68,7 @@ export class ConsoleMessage { private _type: ConsoleMessageType; private _text: string; private _args: JSHandle[]; - private _location: ConsoleMessageLocation; + private _stackTraceLocations: ConsoleMessageLocation[]; /** * @public @@ -77,12 +77,12 @@ export class ConsoleMessage { type: ConsoleMessageType, text: string, args: JSHandle[], - location: ConsoleMessageLocation = {} + stackTraceLocations: ConsoleMessageLocation[] ) { this._type = type; this._text = text; this._args = args; - this._location = location; + this._stackTraceLocations = stackTraceLocations; } /** @@ -110,6 +110,13 @@ export class ConsoleMessage { * @returns The location of the console message. */ location(): ConsoleMessageLocation { - return this._location; + return this._stackTraceLocations.length ? this._stackTraceLocations[0] : {}; + } + + /** + * @returns The array of locations on the stack of the console message. + */ + stackTrace(): ConsoleMessageLocation[] { + return this._stackTraceLocations; } } diff --git a/src/common/Page.ts b/src/common/Page.ts index 448279722c0..4000415c2f9 100644 --- a/src/common/Page.ts +++ b/src/common/Page.ts @@ -605,7 +605,7 @@ export class Page extends EventEmitter { if (source !== 'worker') this.emit( PageEmittedEvents.Console, - new ConsoleMessage(level, text, [], { url, lineNumber }) + new ConsoleMessage(level, text, [], [{ url, lineNumber }]) ); } @@ -1230,19 +1230,21 @@ export class Page extends EventEmitter { if (remoteObject.objectId) textTokens.push(arg.toString()); else textTokens.push(helper.valueFromRemoteObject(remoteObject)); } - const location = - stackTrace && stackTrace.callFrames.length - ? { - url: stackTrace.callFrames[0].url, - lineNumber: stackTrace.callFrames[0].lineNumber, - columnNumber: stackTrace.callFrames[0].columnNumber, - } - : {}; + const stackTraceLocations = []; + if (stackTrace) { + for (const callFrame of stackTrace.callFrames) { + stackTraceLocations.push({ + url: callFrame.url, + lineNumber: callFrame.lineNumber, + columnNumber: callFrame.columnNumber, + }); + } + } const message = new ConsoleMessage( type, textTokens.join(' '), args, - location + stackTraceLocations ); this.emit(PageEmittedEvents.Console, message); } diff --git a/test/assets/consolelog.html b/test/assets/consolelog.html index 7fa1b211a4d..4a27803aa9a 100644 --- a/test/assets/consolelog.html +++ b/test/assets/consolelog.html @@ -5,7 +5,13 @@ diff --git a/test/page.spec.ts b/test/page.spec.ts index 9d7c5138868..d0ad766c4f2 100644 --- a/test/page.spec.ts +++ b/test/page.spec.ts @@ -548,7 +548,7 @@ describe('Page', function () { lineNumber: undefined, }); }); - it('should have location for console API calls', async () => { + it('should have location and stack trace for console API calls', async () => { const { page, server, isChrome } = getTestState(); await page.goto(server.EMPTY_PAGE); @@ -560,9 +560,26 @@ describe('Page', function () { expect(message.type()).toBe('log'); expect(message.location()).toEqual({ url: server.PREFIX + '/consolelog.html', - lineNumber: 7, - columnNumber: isChrome ? 14 : 6, // console.|log vs |console.log + lineNumber: 8, + columnNumber: isChrome ? 16 : 8, // console.|log vs |console.log }); + expect(message.stackTrace()).toEqual([ + { + url: server.PREFIX + '/consolelog.html', + lineNumber: 8, + columnNumber: isChrome ? 16 : 8, // console.|log vs |console.log + }, + { + url: server.PREFIX + '/consolelog.html', + lineNumber: 11, + columnNumber: 8, + }, + { + url: server.PREFIX + '/consolelog.html', + lineNumber: 13, + columnNumber: 6, + }, + ]); }); // @see https://github.com/puppeteer/puppeteer/issues/3865 it('should not throw when there are console messages in detached iframes', async () => {