diff --git a/src/chromium/ExecutionContext.ts b/src/chromium/ExecutionContext.ts index 683d0ca56c..fd8833a892 100644 --- a/src/chromium/ExecutionContext.ts +++ b/src/chromium/ExecutionContext.ts @@ -164,13 +164,13 @@ export class ExecutionContextDelegate implements js.ExecutionContextDelegate { return valueFromRemoteObject(remoteObject); } - handleToString(handle: js.JSHandle): string { + handleToString(handle: js.JSHandle, includeType: boolean): string { const object = toRemoteObject(handle); if (object.objectId) { const type = object.subtype || object.type; return 'JSHandle@' + type; } - return 'JSHandle:' + valueFromRemoteObject(object); + return (includeType ? 'JSHandle:' : '') + valueFromRemoteObject(object); } } diff --git a/src/chromium/Page.ts b/src/chromium/Page.ts index dbbbd71177..7b98beaab4 100644 --- a/src/chromium/Page.ts +++ b/src/chromium/Page.ts @@ -32,10 +32,10 @@ import { PDF } from './features/pdf'; import { Workers } from './features/workers'; import { FrameManager, FrameManagerEvents } from './FrameManager'; import { RawMouseImpl, RawKeyboardImpl } from './Input'; -import { toHandle, toRemoteObject } from './ExecutionContext'; +import { toHandle } from './ExecutionContext'; import { NetworkManagerEvents } from './NetworkManager'; import { Protocol } from './protocol'; -import { getExceptionMessage, releaseObject, valueFromRemoteObject } from './protocolHelper'; +import { getExceptionMessage, releaseObject } from './protocolHelper'; import { Target } from './Target'; import * as input from '../input'; import * as types from '../types'; @@ -44,6 +44,7 @@ import * as frames from '../frames'; import * as js from '../javascript'; import * as network from '../network'; import * as dialog from '../dialog'; +import * as console from '../console'; import { DOMWorldDelegate } from './JSHandle'; import { Screenshotter, ScreenshotOptions } from './Screenshotter'; @@ -199,7 +200,7 @@ export class Page extends EventEmitter { if (args) args.map(arg => releaseObject(this._client, arg)); if (source !== 'worker') - this.emit(Events.Page.Console, new ConsoleMessage(level, text, [], {url, lineNumber})); + this.emit(Events.Page.Console, new console.ConsoleMessage(level, text, [], {url, lineNumber})); } mainFrame(): frames.Frame { @@ -357,21 +358,12 @@ export class Page extends EventEmitter { args.forEach(arg => arg.dispose()); return; } - const textTokens = []; - for (const arg of args) { - const remoteObject = toRemoteObject(arg); - if (remoteObject.objectId) - textTokens.push(arg.toString()); - else - textTokens.push(valueFromRemoteObject(remoteObject)); - } const location = stackTrace && stackTrace.callFrames.length ? { url: stackTrace.callFrames[0].url, lineNumber: stackTrace.callFrames[0].lineNumber, columnNumber: stackTrace.callFrames[0].columnNumber, } : {}; - const message = new ConsoleMessage(type, textTokens.join(' '), args, location); - this.emit(Events.Page.Console, message); + this.emit(Events.Page.Console, new console.ConsoleMessage(type, undefined, args, location)); } _onDialog(event : Protocol.Page.javascriptDialogOpeningPayload) { @@ -601,42 +593,6 @@ type MediaFeature = { value: string } -type ConsoleMessageLocation = { - url?: string, - lineNumber?: number, - columnNumber?: number -}; - -export class ConsoleMessage { - private _type: string; - private _text: string; - private _args: js.JSHandle[]; - private _location: any; - - constructor(type: string, text: string, args: js.JSHandle[], location: ConsoleMessageLocation = {}) { - this._type = type; - this._text = text; - this._args = args; - this._location = location; - } - - type(): string { - return this._type; - } - - text(): string { - return this._text; - } - - args(): js.JSHandle[] { - return this._args; - } - - location(): object { - return this._location; - } -} - type FileChooser = { element: dom.ElementHandle, multiple: boolean diff --git a/src/chromium/api.ts b/src/chromium/api.ts index ed5ede0afd..c98d47443d 100644 --- a/src/chromium/api.ts +++ b/src/chromium/api.ts @@ -20,6 +20,7 @@ export { Worker, Workers } from './features/workers'; export { Frame } from '../frames'; export { Keyboard, Mouse } from '../input'; export { Request, Response } from '../network'; -export { ConsoleMessage, Page } from './Page'; +export { Page } from './Page'; export { Playwright } from './Playwright'; export { Target } from './Target'; +export { ConsoleMessage } from '../console'; diff --git a/src/console.ts b/src/console.ts new file mode 100644 index 0000000000..7af0ab93e2 --- /dev/null +++ b/src/console.ts @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +import * as js from './javascript'; + +type ConsoleMessageLocation = { + url?: string, + lineNumber?: number, + columnNumber?: number, +}; + +export class ConsoleMessage { + private _type: string; + private _text?: string; + private _args: js.JSHandle[]; + private _location: ConsoleMessageLocation; + + constructor(type: string, text: string | undefined, args: js.JSHandle[], location?: ConsoleMessageLocation) { + this._type = type; + this._text = text; + this._args = args; + this._location = location || {}; + } + + type(): string { + return this._type; + } + + text(): string { + if (this._text === undefined) + this._text = this._args.map(arg => arg.executionContext()._delegate.handleToString(arg, false /* includeType */)).join(' '); + return this._text; + } + + args(): js.JSHandle[] { + return this._args; + } + + location(): ConsoleMessageLocation { + return this._location; + } +} diff --git a/src/firefox/ExecutionContext.ts b/src/firefox/ExecutionContext.ts index 0dff1c6497..1241790818 100644 --- a/src/firefox/ExecutionContext.ts +++ b/src/firefox/ExecutionContext.ts @@ -145,11 +145,11 @@ export class ExecutionContextDelegate implements js.ExecutionContextDelegate { return deserializeValue(simpleValue.result); } - handleToString(handle: js.JSHandle): string { + handleToString(handle: js.JSHandle, includeType: boolean): string { const payload = toPayload(handle); if (payload.objectId) return 'JSHandle@' + (payload.subtype || payload.type); - return 'JSHandle:' + deserializeValue(payload); + return (includeType ? 'JSHandle:' : '') + deserializeValue(payload); } private _toProtocolValue(payload: any): any { diff --git a/src/firefox/Page.ts b/src/firefox/Page.ts index 55307cefe7..79fbb0eb34 100644 --- a/src/firefox/Page.ts +++ b/src/firefox/Page.ts @@ -36,8 +36,9 @@ import * as dom from '../dom'; import * as js from '../javascript'; import * as network from '../network'; import * as frames from '../frames'; -import { toHandle, toPayload, deserializeValue } from './ExecutionContext'; import * as dialog from '../dialog'; +import { toHandle } from './ExecutionContext'; +import * as console from '../console'; const writeFileAsync = helper.promisify(fs.writeFile); @@ -552,7 +553,7 @@ export class Page extends EventEmitter { _onConsole({type, args, executionContextId, location}) { const context = this._frameManager.executionContextById(executionContextId); - this.emit(Events.Page.Console, new ConsoleMessage(type, args.map(arg => toHandle(context, arg)), location)); + this.emit(Events.Page.Console, new console.ConsoleMessage(type, undefined, args.map(arg => toHandle(context, arg)), location)); } isClosed(): boolean { @@ -587,39 +588,6 @@ export class Page extends EventEmitter { } } -export class ConsoleMessage { - private _type: string; - private _args: js.JSHandle[]; - private _location: any; - - constructor(type: string, args: Array, location) { - this._type = type; - this._args = args; - this._location = location; - } - - location() { - return this._location; - } - - type(): string { - return this._type; - } - - args(): Array { - return this._args; - } - - text(): string { - return this._args.map(arg => { - const payload = toPayload(arg); - if (payload.objectId) - return arg.toString(); - return deserializeValue(payload); - }).join(' '); - } -} - function getScreenshotMimeType(options) { // options.type takes precedence over inferring the type from options.path // because it may be a 0-length file with no extension created beforehand (i.e. as a temp file). diff --git a/src/firefox/api.ts b/src/firefox/api.ts index ca25af68b3..7501196264 100644 --- a/src/firefox/api.ts +++ b/src/firefox/api.ts @@ -13,6 +13,6 @@ export { Permissions } from './features/permissions'; export { Frame } from '../frames'; export { ElementHandle } from '../dom'; export { Request, Response } from '../network'; -export { ConsoleMessage, Page } from './Page'; +export { Page } from './Page'; export { Playwright } from './Playwright'; - +export { ConsoleMessage } from '../console'; diff --git a/src/javascript.ts b/src/javascript.ts index edfe2ef493..7321470def 100644 --- a/src/javascript.ts +++ b/src/javascript.ts @@ -9,7 +9,7 @@ export interface ExecutionContextDelegate { evaluate(context: ExecutionContext, returnByValue: boolean, pageFunction: string | Function, ...args: any[]): Promise; getProperties(handle: JSHandle): Promise>; releaseHandle(handle: JSHandle): Promise; - handleToString(handle: JSHandle): string; + handleToString(handle: JSHandle, includeType: boolean): string; handleJSONValue(handle: JSHandle): Promise; } @@ -86,6 +86,6 @@ export class JSHandle { } toString(): string { - return this._context._delegate.handleToString(this); + return this._context._delegate.handleToString(this, true /* includeType */); } } diff --git a/src/webkit/ExecutionContext.ts b/src/webkit/ExecutionContext.ts index 9ad3c53896..ab3307587e 100644 --- a/src/webkit/ExecutionContext.ts +++ b/src/webkit/ExecutionContext.ts @@ -303,7 +303,7 @@ export class ExecutionContextDelegate implements js.ExecutionContextDelegate { return valueFromRemoteObject(remoteObject); } - handleToString(handle: js.JSHandle): string { + handleToString(handle: js.JSHandle, includeType: boolean): string { const object = toRemoteObject(handle); if (object.objectId) { let type: string = object.subtype || object.type; @@ -312,7 +312,7 @@ export class ExecutionContextDelegate implements js.ExecutionContextDelegate { type = 'promise'; return 'JSHandle@' + type; } - return 'JSHandle:' + valueFromRemoteObject(object); + return (includeType ? 'JSHandle:' : '') + valueFromRemoteObject(object); } private _convertArgument(arg: js.JSHandle | any) : Protocol.Runtime.CallArgument { diff --git a/src/webkit/Page.ts b/src/webkit/Page.ts index d1775a3bed..4447d00d00 100644 --- a/src/webkit/Page.ts +++ b/src/webkit/Page.ts @@ -26,10 +26,9 @@ import { TargetSession, TargetSessionEvents } from './Connection'; import { Events } from './events'; import { FrameManager, FrameManagerEvents } from './FrameManager'; import { RawKeyboardImpl, RawMouseImpl } from './Input'; -import { toHandle, toRemoteObject } from './ExecutionContext'; +import { toHandle } from './ExecutionContext'; import { NetworkManagerEvents } from './NetworkManager'; import { Protocol } from './protocol'; -import { valueFromRemoteObject } from './protocolHelper'; import { Target } from './Target'; import { TaskQueue } from './TaskQueue'; import * as input from '../input'; @@ -39,6 +38,7 @@ import * as frames from '../frames'; import * as js from '../javascript'; import * as network from '../network'; import * as dialog from '../dialog'; +import * as console from '../console'; const writeFileAsync = helper.promisify(fs.writeFile); @@ -179,17 +179,7 @@ export class Page extends EventEmitter { } return toHandle(context, p); }); - const textTokens = []; - for (const handle of handles) { - const remoteObject = toRemoteObject(handle); - if (remoteObject.objectId) - textTokens.push(handle.toString()); - else - textTokens.push(valueFromRemoteObject(remoteObject)); - } - const location = {url, lineNumber, columnNumber}; - const formattedText = textTokens.length ? textTokens.join(' ') : text; - this.emit(Events.Page.Console, new ConsoleMessage(derivedType, formattedText, handles, location)); + this.emit(Events.Page.Console, new console.ConsoleMessage(derivedType, handles.length ? undefined : text, handles, { url, lineNumber, columnNumber })); } mainFrame(): frames.Frame { @@ -549,42 +539,6 @@ type ScreenshotOptions = { encoding?: string, } -type ConsoleMessageLocation = { - url?: string, - lineNumber?: number, - columnNumber?: number -}; - -export class ConsoleMessage { - private _type: string; - private _text: string; - private _args: js.JSHandle[]; - private _location: any; - - constructor(type: string, text: string, args: js.JSHandle[], location: ConsoleMessageLocation = {}) { - this._type = type; - this._text = text; - this._args = args; - this._location = location; - } - - type(): string { - return this._type; - } - - text(): string { - return this._text; - } - - args(): js.JSHandle[] { - return this._args; - } - - location(): object { - return this._location; - } -} - type FileChooser = { element: dom.ElementHandle, multiple: boolean diff --git a/src/webkit/api.ts b/src/webkit/api.ts index b167943692..972e7d388a 100644 --- a/src/webkit/api.ts +++ b/src/webkit/api.ts @@ -9,7 +9,8 @@ export { Frame } from '../frames'; export { Mouse, Keyboard } from '../input'; export { ElementHandle } from '../dom'; export { Request, Response } from '../network'; -export { ConsoleMessage, Page } from './Page'; +export { Page } from './Page'; export { Playwright } from './Playwright'; export { Target } from './Target'; export { Dialog } from '../dialog'; +export { ConsoleMessage } from '../console';