Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 31 additions & 13 deletions packages/playwright-core/src/server/artifact.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import { TargetClosedError } from './errors';
import { SdkObject } from './instrumentation';
import { ManualPromise } from '../utils/isomorphic/manualPromise';

import type { Progress } from '@protocol/progress';

type SaveCallback = (localPath: string, error?: Error) => Promise<void>;
type CancelCallback = () => Promise<void>;

Expand All @@ -32,7 +34,7 @@ export class Artifact extends SdkObject {
private _saveCallbacks: SaveCallback[] = [];
private _finished: boolean = false;
private _deleted = false;
private _failureError: Error | undefined;
private _failureErrorValue: Error | undefined;

constructor(parent: SdkObject, localPath: string, unaccessibleErrorMessage?: string, cancelCallback?: CancelCallback) {
super(parent, 'artifact');
Expand All @@ -41,26 +43,42 @@ export class Artifact extends SdkObject {
this._cancelCallback = cancelCallback;
}

async localPathAfterFinished(progress: Progress): Promise<string> {
return await progress.race(this._localPathAfterFinished());
}

async failureError(progress: Progress): Promise<string | null> {
return await progress.race(this._failureError());
}

async cancel(progress: Progress): Promise<void> {
return await progress.race(this._cancel());
}

async delete(progress: Progress): Promise<void> {
return await progress.race(this._delete());
}

localPath() {
return this._localPath;
}

async localPathAfterFinished(): Promise<string> {
private async _localPathAfterFinished(): Promise<string> {
if (this._unaccessibleErrorMessage)
throw new Error(this._unaccessibleErrorMessage);
await this._finishedPromise;
if (this._failureError)
throw this._failureError;
if (this._failureErrorValue)
throw this._failureErrorValue;
return this._localPath;
}

saveAs(saveCallback: SaveCallback) {
saveAs(progress: Progress, saveCallback: SaveCallback) {
if (this._unaccessibleErrorMessage)
throw new Error(this._unaccessibleErrorMessage);
if (this._deleted)
throw new Error(`File already deleted. Save before deleting.`);
if (this._failureError)
throw this._failureError;
if (this._failureErrorValue)
throw this._failureErrorValue;

if (this._finished) {
saveCallback(this._localPath).catch(() => {});
Expand All @@ -69,22 +87,22 @@ export class Artifact extends SdkObject {
this._saveCallbacks.push(saveCallback);
}

async failureError(): Promise<string | null> {
async _failureError(): Promise<string | null> {
if (this._unaccessibleErrorMessage)
return this._unaccessibleErrorMessage;
await this._finishedPromise;
return this._failureError?.message || null;
return this._failureErrorValue?.message || null;
}

async cancel(): Promise<void> {
async _cancel(): Promise<void> {
assert(this._cancelCallback !== undefined);
return this._cancelCallback();
}

async delete(): Promise<void> {
async _delete(): Promise<void> {
if (this._unaccessibleErrorMessage)
return;
const fileName = await this.localPathAfterFinished();
const fileName = await this._localPathAfterFinished();
if (this._deleted)
return;
this._deleted = true;
Expand All @@ -107,7 +125,7 @@ export class Artifact extends SdkObject {
if (this._finished)
return;
this._finished = true;
this._failureError = error;
this._failureErrorValue = error;

if (error) {
for (const callback of this._saveCallbacks)
Expand Down
15 changes: 10 additions & 5 deletions packages/playwright-core/src/server/chromium/crConnection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import type { ConnectionTransport, ProtocolRequest, ProtocolResponse } from '../
import type { Protocol } from './protocol';
import type { RecentLogsCollector } from '../utils/debugLogger';
import type { ProtocolLogger } from '../types';
import type { Progress } from '@protocol/progress';


export const ConnectionEvents = {
Expand Down Expand Up @@ -213,16 +214,20 @@ export class CDPSession extends SdkObject {
})];
}

async send(method: string, params?: any) {
return await this._session.send(method as any, params);
async send(progress: Progress, method: string, params?: any) {
return await progress.race(this._send(method, params));
}

async detach() {
return await this._session.detach();
async detach(progress: Progress) {
return await progress.race(this._session.detach());
}

private async _send(method: string, params?: any) {
return await this._session.send(method as any, params);
}

async attachToTarget(targetId: string) {
const { sessionId } = await this.send('Target.attachToTarget', { targetId, flatten: true });
const { sessionId } = await this._send('Target.attachToTarget', { targetId, flatten: true });
return new CDPSession(this._session, sessionId);
}

Expand Down
12 changes: 8 additions & 4 deletions packages/playwright-core/src/server/debugController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,19 @@ export class DebugController extends SdkObject {
this._playwright = playwright;
}

initialize(codegenId: string, sdkLanguage: Language) {
initialize(progress: Progress, codegenId: string, sdkLanguage: Language) {
this._sdkLanguage = sdkLanguage;
}

dispose() {
this.setReportStateChanged(false);
this._setReportStateChanged(false);
}

setReportStateChanged(enabled: boolean) {
setReportStateChanged(progress: Progress, enabled: boolean) {
this._setReportStateChanged(enabled);
}

private _setReportStateChanged(enabled: boolean) {
if (enabled && !this._trackHierarchyListener) {
this._trackHierarchyListener = {
onPageOpen: () => this._emitSnapshot(false),
Expand Down Expand Up @@ -139,7 +143,7 @@ export class DebugController extends SdkObject {
recorder.resume();
}

kill() {
kill(progress: Progress) {
gracefullyProcessExitDoNotHang(0);
}

Expand Down
30 changes: 30 additions & 0 deletions packages/playwright-core/src/server/debugger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { BrowserContext } from './browserContext';
import { getMetainfo } from '../utils/isomorphic/protocolMetainfo';

import type { CallMetadata, InstrumentationListener } from './instrumentation';
import type { Progress } from '@protocol/progress';

const symbol = Symbol('Debugger');

Expand Down Expand Up @@ -47,6 +48,35 @@ export class Debugger extends SdkObject implements InstrumentationListener {
});
}

requestPause(progress: Progress) {
if (this.isPaused())
throw new Error('Debugger is already paused');
this.setPauseBeforeWaitingActions();
this.setPauseAt({ next: true });
}

doResume(progress: Progress) {
if (!this.isPaused())
throw new Error('Debugger is not paused');
this.resume();
}

next(progress: Progress) {
if (!this.isPaused())
throw new Error('Debugger is not paused');
this.setPauseBeforeWaitingActions();
this.setPauseAt({ next: true });
this.resume();
}

runTo(progress: Progress, location: { file: string, line?: number, column?: number }) {
if (!this.isPaused())
throw new Error('Debugger is not paused');
this.setPauseBeforeWaitingActions();
this.setPauseAt({ location });
this.resume();
}

async setMuted(muted: boolean) {
this._muted = muted;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,13 @@ export class ArtifactDispatcher extends Dispatcher<Artifact, channels.ArtifactCh
}

async pathAfterFinished(params: channels.ArtifactPathAfterFinishedParams, progress: Progress): Promise<channels.ArtifactPathAfterFinishedResult> {
const path = await progress.race(this._object.localPathAfterFinished());
const path = await this._object.localPathAfterFinished(progress);
return { value: path };
}

async saveAs(params: channels.ArtifactSaveAsParams, progress: Progress): Promise<channels.ArtifactSaveAsResult> {
return await progress.race(new Promise((resolve, reject) => {
this._object.saveAs(async (localPath, error) => {
this._object.saveAs(progress, async (localPath, error) => {
if (error) {
reject(error);
return;
Expand All @@ -70,7 +70,7 @@ export class ArtifactDispatcher extends Dispatcher<Artifact, channels.ArtifactCh

async saveAsStream(params: channels.ArtifactSaveAsStreamParams, progress: Progress): Promise<channels.ArtifactSaveAsStreamResult> {
return await progress.race(new Promise((resolve, reject) => {
this._object.saveAs(async (localPath, error) => {
this._object.saveAs(progress, async (localPath, error) => {
if (error) {
reject(error);
return;
Expand All @@ -94,23 +94,23 @@ export class ArtifactDispatcher extends Dispatcher<Artifact, channels.ArtifactCh
}

async stream(params: channels.ArtifactStreamParams, progress: Progress): Promise<channels.ArtifactStreamResult> {
const fileName = await progress.race(this._object.localPathAfterFinished());
const fileName = await this._object.localPathAfterFinished(progress);
const readable = fs.createReadStream(fileName, { highWaterMark: 1024 * 1024 });
return { stream: new StreamDispatcher(this, readable) };
}

async failure(params: channels.ArtifactFailureParams, progress: Progress): Promise<channels.ArtifactFailureResult> {
const error = await progress.race(this._object.failureError());
const error = await this._object.failureError(progress);
return { error: error || undefined };
}

async cancel(params: channels.ArtifactCancelParams, progress: Progress): Promise<void> {
await progress.race(this._object.cancel());
await this._object.cancel(progress);
}

async delete(params: channels.ArtifactDeleteParams, progress: Progress): Promise<void> {
progress.metadata.potentiallyClosesScope = true;
await progress.race(this._object.delete());
await this._object.delete(progress);
this._dispose();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ export class CDPSessionDispatcher extends Dispatcher<CDPSession, channels.CDPSes
}

async send(params: channels.CDPSessionSendParams, progress: Progress): Promise<channels.CDPSessionSendResult> {
return { result: await progress.race(this._object.send(params.method as any, params.params)) };
return { result: await this._object.send(progress, params.method as any, params.params) };
}

async detach(_: any, progress: Progress): Promise<void> {
progress.metadata.potentiallyClosesScope = true;
await this._object.detach();
await this._object.detach(progress);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,11 @@ export class DebugControllerDispatcher extends Dispatcher<DebugController, chann
}

async initialize(params: channels.DebugControllerInitializeParams, progress: Progress) {
this._object.initialize(params.codegenId, params.sdkLanguage);
this._object.initialize(progress, params.codegenId, params.sdkLanguage);
}

async setReportStateChanged(params: channels.DebugControllerSetReportStateChangedParams, progress: Progress) {
this._object.setReportStateChanged(params.enabled);
this._object.setReportStateChanged(progress, params.enabled);
}

async setRecorderMode(params: channels.DebugControllerSetRecorderModeParams, progress: Progress) {
Expand All @@ -75,7 +75,7 @@ export class DebugControllerDispatcher extends Dispatcher<DebugController, chann
}

async kill(params: channels.DebugControllerKillParams, progress: Progress) {
this._object.kill();
this._object.kill(progress);
}

override _onDispose() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,31 +55,18 @@ export class DebuggerDispatcher extends Dispatcher<Debugger, channels.DebuggerCh
}

async requestPause(params: channels.DebuggerRequestPauseParams, progress: Progress): Promise<void> {
if (this._object.isPaused())
throw new Error('Debugger is already paused');
this._object.setPauseBeforeWaitingActions();
this._object.setPauseAt({ next: true });
this._object.requestPause(progress);
}

async resume(params: channels.DebuggerResumeParams, progress: Progress): Promise<void> {
if (!this._object.isPaused())
throw new Error('Debugger is not paused');
this._object.resume();
this._object.doResume(progress);
}

async next(params: channels.DebuggerNextParams, progress: Progress): Promise<void> {
if (!this._object.isPaused())
throw new Error('Debugger is not paused');
this._object.setPauseBeforeWaitingActions();
this._object.setPauseAt({ next: true });
this._object.resume();
this._object.next(progress);
}

async runTo(params: channels.DebuggerRunToParams, progress: Progress): Promise<void> {
if (!this._object.isPaused())
throw new Error('Debugger is not paused');
this._object.setPauseBeforeWaitingActions();
this._object.setPauseAt({ location: params.location });
this._object.resume();
this._object.runTo(progress, params.location);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export class ElectronApplicationDispatcher extends Dispatcher<ElectronApplicatio
}

async browserWindow(params: channels.ElectronApplicationBrowserWindowParams, progress: Progress): Promise<channels.ElectronApplicationBrowserWindowResult> {
const handle = await progress.race(this._object.browserWindow((params.page as PageDispatcher).page()));
const handle = await this._object.browserWindow(progress, (params.page as PageDispatcher).page());
return { handle: JSHandleDispatcher.fromJSHandle(this, handle) };
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import { ArtifactDispatcher } from './artifactDispatcher';
import { Dispatcher } from './dispatcher';
import { nullProgress } from '../progress';

import type { BrowserContextDispatcher } from './browserContextDispatcher';
import type { APIRequestContextDispatcher } from './networkDispatchers';
Expand All @@ -37,7 +38,7 @@ export class TracingDispatcher extends Dispatcher<Tracing, channels.TracingChann
}

async tracingStart(params: channels.TracingTracingStartParams, progress: Progress): Promise<channels.TracingTracingStartResult> {
this._object.start(params);
this._object.start(progress, params);
this._started = true;
}

Expand All @@ -47,11 +48,11 @@ export class TracingDispatcher extends Dispatcher<Tracing, channels.TracingChann

async tracingGroup(params: channels.TracingTracingGroupParams, progress: Progress): Promise<channels.TracingTracingGroupResult> {
const { name, location } = params;
this._object.group(name, location, progress.metadata);
this._object.group(progress, name, location);
}

async tracingGroupEnd(params: channels.TracingTracingGroupEndParams, progress: Progress): Promise<channels.TracingTracingGroupEndResult> {
this._object.groupEnd();
this._object.groupEnd(progress);
}

async tracingStopChunk(params: channels.TracingTracingStopChunkParams, progress: Progress): Promise<channels.TracingTracingStopChunkResult> {
Expand All @@ -67,7 +68,7 @@ export class TracingDispatcher extends Dispatcher<Tracing, channels.TracingChann
override _onDispose() {
// Avoid protocol calls for the closed context.
if (this._started)
this._object.stopChunk(undefined, { mode: 'discard' }).then(() => this._object.stop(undefined)).catch(() => {});
this._object.stopChunk(nullProgress, { mode: 'discard' }).then(() => this._object.stop(nullProgress)).catch(() => {});
this._started = false;
}
}
2 changes: 1 addition & 1 deletion packages/playwright-core/src/server/electron/electron.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ export class ElectronApplication extends SdkObject {
await this._browserContext.close({ reason: 'Application exited' });
}

async browserWindow(page: Page): Promise<js.JSHandle<BrowserWindow>> {
async browserWindow(progress: Progress, page: Page): Promise<js.JSHandle<BrowserWindow>> {
// Assume CRPage as Electron is always Chromium.
const targetId = (page.delegate as CRPage)._targetId;
const electronHandle = await this._nodeElectronHandlePromise;
Expand Down
Loading
Loading