chore: split error to client and server sides (#27672)
This commit is contained in:
parent
8eab375c1d
commit
3aa147914c
|
|
@ -34,7 +34,7 @@ import { spawn } from 'child_process';
|
|||
import { wrapInASCIIBox, isLikelyNpxGlobal, assert, gracefullyProcessExitDoNotHang, getPackageManagerExecCommand } from '../utils';
|
||||
import type { Executable } from '../server';
|
||||
import { registry, writeDockerVersion } from '../server';
|
||||
import { isTargetClosedError } from '../common/errors';
|
||||
import { isTargetClosedError } from '../client/errors';
|
||||
|
||||
const packageJSON = require('../../package.json');
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ import { TimeoutSettings } from '../common/timeoutSettings';
|
|||
import { Waiter } from './waiter';
|
||||
import { EventEmitter } from 'events';
|
||||
import { Connection } from './connection';
|
||||
import { isTargetClosedError, TargetClosedError } from '../common/errors';
|
||||
import { isTargetClosedError, TargetClosedError } from './errors';
|
||||
import { raceAgainstDeadline } from '../utils/timeoutRunner';
|
||||
import type { AndroidServerLauncherImpl } from '../androidServerImpl';
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ export { Locator, FrameLocator } from './locator';
|
|||
export { ElementHandle } from './elementHandle';
|
||||
export { FileChooser } from './fileChooser';
|
||||
export type { Logger } from './types';
|
||||
export { TimeoutError } from '../common/errors';
|
||||
export { TimeoutError } from './errors';
|
||||
export { Frame } from './frame';
|
||||
export { Keyboard, Mouse, Touchscreen } from './input';
|
||||
export { JSHandle } from './jsHandle';
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import type { Page } from './page';
|
|||
import { ChannelOwner } from './channelOwner';
|
||||
import { Events } from './events';
|
||||
import type { LaunchOptions, BrowserContextOptions, HeadersArray } from './types';
|
||||
import { isTargetClosedError } from '../common/errors';
|
||||
import { isTargetClosedError } from './errors';
|
||||
import type * as api from '../../types/types';
|
||||
import { CDPSession } from './cdpSession';
|
||||
import type { BrowserType } from './browserType';
|
||||
|
|
|
|||
|
|
@ -43,8 +43,7 @@ import { HarRouter } from './harRouter';
|
|||
import { ConsoleMessage } from './consoleMessage';
|
||||
import { Dialog } from './dialog';
|
||||
import { WebError } from './webError';
|
||||
import { parseError } from '../protocol/serializers';
|
||||
import { TargetClosedError } from '../common/errors';
|
||||
import { TargetClosedError, parseError } from './errors';
|
||||
|
||||
export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel> implements api.BrowserContext {
|
||||
_pages = new Set<Page>();
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ import { Request, Response, Route, WebSocket } from './network';
|
|||
import { Page, BindingCall } from './page';
|
||||
import { Worker } from './worker';
|
||||
import { Dialog } from './dialog';
|
||||
import { parseError } from '../protocol/serializers';
|
||||
import { parseError, TargetClosedError } from './errors';
|
||||
import { CDPSession } from './cdpSession';
|
||||
import { Playwright } from './playwright';
|
||||
import { Electron, ElectronApplication } from './electron';
|
||||
|
|
@ -44,7 +44,6 @@ import { Tracing } from './tracing';
|
|||
import { findValidator, ValidationError, type ValidatorContext } from '../protocol/validator';
|
||||
import { createInstrumentation } from './clientInstrumentation';
|
||||
import type { ClientInstrumentation } from './clientInstrumentation';
|
||||
import { TargetClosedError } from '../common/errors';
|
||||
import { formatCallLog, rewriteErrorMessage } from '../utils';
|
||||
|
||||
class Root extends ChannelOwner<channels.RootChannel> {
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ import { JSHandle, parseResult, serializeArgument } from './jsHandle';
|
|||
import type { Page } from './page';
|
||||
import type { Env, WaitForEventOptions, Headers, BrowserContextOptions } from './types';
|
||||
import { Waiter } from './waiter';
|
||||
import { TargetClosedError } from '../common/errors';
|
||||
import { TargetClosedError } from './errors';
|
||||
|
||||
type ElectronOptions = Omit<channels.ElectronLaunchOptions, 'env'|'extraHTTPHeaders'|'recordHar'|'colorScheme'|'acceptDownloads'> & {
|
||||
env?: Env,
|
||||
|
|
|
|||
59
packages/playwright-core/src/client/errors.ts
Normal file
59
packages/playwright-core/src/client/errors.ts
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { SerializedError } from '@protocol/channels';
|
||||
import { isError } from '../utils';
|
||||
import { parseSerializedValue, serializeValue } from '../protocol/serializers';
|
||||
|
||||
export class TimeoutError extends Error {}
|
||||
|
||||
export class TargetClosedError extends Error {
|
||||
constructor(cause?: string) {
|
||||
super(cause || 'Target page, context or browser has been closed');
|
||||
}
|
||||
}
|
||||
|
||||
export function isTargetClosedError(error: Error) {
|
||||
return error instanceof TargetClosedError;
|
||||
}
|
||||
|
||||
export function serializeError(e: any): SerializedError {
|
||||
if (isError(e))
|
||||
return { error: { message: e.message, stack: e.stack, name: e.name } };
|
||||
return { value: serializeValue(e, value => ({ fallThrough: value })) };
|
||||
}
|
||||
|
||||
export function parseError(error: SerializedError): Error {
|
||||
if (!error.error) {
|
||||
if (error.value === undefined)
|
||||
throw new Error('Serialized error must have either an error or a value');
|
||||
return parseSerializedValue(error.value, undefined);
|
||||
}
|
||||
if (error.error.name === 'TimeoutError') {
|
||||
const e = new TimeoutError(error.error.message);
|
||||
e.stack = error.error.stack || '';
|
||||
return e;
|
||||
}
|
||||
if (error.error.name === 'TargetClosedError') {
|
||||
const e = new TargetClosedError(error.error.message);
|
||||
e.stack = error.error.stack || '';
|
||||
return e;
|
||||
}
|
||||
const e = new Error(error.error.message);
|
||||
e.stack = error.error.stack || '';
|
||||
e.name = error.error.name;
|
||||
return e;
|
||||
}
|
||||
|
|
@ -28,7 +28,7 @@ import { RawHeaders } from './network';
|
|||
import type { FilePayload, Headers, StorageState } from './types';
|
||||
import type { Playwright } from './playwright';
|
||||
import { Tracing } from './tracing';
|
||||
import { isTargetClosedError } from '../common/errors';
|
||||
import { isTargetClosedError } from './errors';
|
||||
|
||||
export type FetchOptions = {
|
||||
params?: { [key: string]: string; },
|
||||
|
|
|
|||
|
|
@ -19,11 +19,10 @@ import fs from 'fs';
|
|||
import path from 'path';
|
||||
import type * as structs from '../../types/structs';
|
||||
import type * as api from '../../types/types';
|
||||
import { isTargetClosedError, TargetClosedError } from '../common/errors';
|
||||
import { serializeError, isTargetClosedError, TargetClosedError } from './errors';
|
||||
import { urlMatches } from '../utils/network';
|
||||
import { TimeoutSettings } from '../common/timeoutSettings';
|
||||
import type * as channels from '@protocol/channels';
|
||||
import { serializeError } from '../protocol/serializers';
|
||||
import { assert, headersObjectToArray, isObject, isRegExp, isString, LongStandingScope, urlMatchesEqual } from '../utils';
|
||||
import { mkdirIfNeeded } from '../utils/fileUtils';
|
||||
import { Accessibility } from './accessibility';
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
*/
|
||||
|
||||
import type * as channels from '@protocol/channels';
|
||||
import { TimeoutError } from '../common/errors';
|
||||
import { TimeoutError } from './errors';
|
||||
import { Android } from './android';
|
||||
import { BrowserType } from './browserType';
|
||||
import { ChannelOwner } from './channelOwner';
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
import type { EventEmitter } from 'events';
|
||||
import { rewriteErrorMessage } from '../utils/stackTrace';
|
||||
import { TimeoutError } from '../common/errors';
|
||||
import { TimeoutError } from './errors';
|
||||
import { createGuid } from '../utils';
|
||||
import type * as channels from '@protocol/channels';
|
||||
import type { ChannelOwner } from './channelOwner';
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import type { BrowserContext } from './browserContext';
|
|||
import type * as api from '../../types/types';
|
||||
import type * as structs from '../../types/structs';
|
||||
import { LongStandingScope } from '../utils';
|
||||
import { TargetClosedError } from '../common/errors';
|
||||
import { TargetClosedError } from './errors';
|
||||
|
||||
export class Worker extends ChannelOwner<channels.WorkerChannel> implements api.Worker {
|
||||
_page: Page | undefined; // Set for web workers.
|
||||
|
|
|
|||
|
|
@ -14,36 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { TargetClosedError, TimeoutError } from '../common/errors';
|
||||
import type { SerializedError, SerializedValue } from '@protocol/channels';
|
||||
|
||||
export function serializeError(e: any): SerializedError {
|
||||
if (isError(e))
|
||||
return { error: { message: e.message, stack: e.stack, name: e.name } };
|
||||
return { value: serializeValue(e, value => ({ fallThrough: value })) };
|
||||
}
|
||||
|
||||
export function parseError(error: SerializedError): Error {
|
||||
if (!error.error) {
|
||||
if (error.value === undefined)
|
||||
throw new Error('Serialized error must have either an error or a value');
|
||||
return parseSerializedValue(error.value, undefined);
|
||||
}
|
||||
if (error.error.name === 'TimeoutError') {
|
||||
const e = new TimeoutError(error.error.message);
|
||||
e.stack = error.error.stack || '';
|
||||
return e;
|
||||
}
|
||||
if (error.error.name === 'TargetClosedError') {
|
||||
const e = new TargetClosedError(error.error.message);
|
||||
e.stack = error.error.stack || '';
|
||||
return e;
|
||||
}
|
||||
const e = new Error(error.error.message);
|
||||
e.stack = error.error.stack || '';
|
||||
e.name = error.error.name;
|
||||
return e;
|
||||
}
|
||||
import type { SerializedValue } from '@protocol/channels';
|
||||
|
||||
export function parseSerializedValue(value: SerializedValue, handles: any[] | undefined): any {
|
||||
return innerParseSerializedValue(value, handles, new Map());
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import fs from 'fs';
|
|||
import { assert } from '../utils';
|
||||
import { ManualPromise } from '../utils/manualPromise';
|
||||
import { SdkObject } from './instrumentation';
|
||||
import { TargetClosedError } from '../common/errors';
|
||||
import { TargetClosedError } from './errors';
|
||||
|
||||
type SaveCallback = (localPath: string, error?: Error) => Promise<void>;
|
||||
type CancelCallback = () => Promise<void>;
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ import { platformToFontFamilies } from './defaultFontFamilies';
|
|||
import type { Protocol } from './protocol';
|
||||
import { VideoRecorder } from './videoRecorder';
|
||||
import { BrowserContext } from '../browserContext';
|
||||
import { TargetClosedError } from '../../common/errors';
|
||||
import { TargetClosedError } from '../errors';
|
||||
|
||||
|
||||
const UTILITY_WORLD_NAME = '__playwright_utility_world__';
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ import { DialogDispatcher } from './dialogDispatcher';
|
|||
import type { Page } from '../page';
|
||||
import type { Dialog } from '../dialog';
|
||||
import type { ConsoleMessage } from '../console';
|
||||
import { serializeError } from '../../protocol/serializers';
|
||||
import { serializeError } from '../errors';
|
||||
import { ElementHandleDispatcher } from './elementHandlerDispatcher';
|
||||
|
||||
export class BrowserContextDispatcher extends Dispatcher<BrowserContext, channels.BrowserContextChannel, DispatcherScope> implements channels.BrowserContextChannel {
|
||||
|
|
|
|||
|
|
@ -16,10 +16,9 @@
|
|||
|
||||
import { EventEmitter } from 'events';
|
||||
import type * as channels from '@protocol/channels';
|
||||
import { serializeError } from '../../protocol/serializers';
|
||||
import { findValidator, ValidationError, createMetadataValidator, type ValidatorContext } from '../../protocol/validator';
|
||||
import { assert, isUnderTest, monotonicTime, rewriteErrorMessage } from '../../utils';
|
||||
import { TargetClosedError, isTargetClosedError } from '../../common/errors';
|
||||
import { TargetClosedError, isTargetClosedError, serializeError } from '../errors';
|
||||
import type { CallMetadata } from '../instrumentation';
|
||||
import { SdkObject } from '../instrumentation';
|
||||
import type { PlaywrightDispatcher } from './playwrightDispatcher';
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
import type * as channels from '@protocol/channels';
|
||||
import { Dispatcher } from './dispatcher';
|
||||
import { createGuid } from '../../utils';
|
||||
import { serializeError } from '../../protocol/serializers';
|
||||
import { serializeError } from '../errors';
|
||||
import type { LocalUtilsDispatcher } from './localUtilsDispatcher';
|
||||
|
||||
export class JsonPipeDispatcher extends Dispatcher<{ guid: string }, channels.JsonPipeChannel, LocalUtilsDispatcher> implements channels.JsonPipeChannel {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import type { Frame } from '../frames';
|
|||
import { Page, Worker } from '../page';
|
||||
import type * as channels from '@protocol/channels';
|
||||
import { Dispatcher, existingDispatcher } from './dispatcher';
|
||||
import { parseError } from '../../protocol/serializers';
|
||||
import { parseError } from '../errors';
|
||||
import { FrameDispatcher } from './frameDispatcher';
|
||||
import { RequestDispatcher } from './networkDispatchers';
|
||||
import { ResponseDispatcher } from './networkDispatchers';
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
/**
|
||||
* Copyright 2018 Google Inc. All rights reserved.
|
||||
* Modifications copyright (c) Microsoft Corporation.
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
|
@ -15,23 +14,43 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { SerializedError } from '@protocol/channels';
|
||||
import { isError } from '../utils';
|
||||
import { parseSerializedValue, serializeValue } from '../protocol/serializers';
|
||||
|
||||
class CustomError extends Error {
|
||||
constructor(message: string) {
|
||||
super(message);
|
||||
this.name = this.constructor.name;
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
}
|
||||
}
|
||||
|
||||
export class TimeoutError extends CustomError {}
|
||||
|
||||
export class TargetClosedError extends Error {
|
||||
export class TargetClosedError extends CustomError {
|
||||
constructor(cause?: string, logs?: string) {
|
||||
super((cause || 'Target page, context or browser has been closed') + (logs || ''));
|
||||
this.name = this.constructor.name;
|
||||
}
|
||||
}
|
||||
|
||||
export function isTargetClosedError(error: Error) {
|
||||
return error instanceof TargetClosedError || error.name === 'TargetClosedError';
|
||||
}
|
||||
|
||||
export function serializeError(e: any): SerializedError {
|
||||
if (isError(e))
|
||||
return { error: { message: e.message, stack: e.stack, name: e.name } };
|
||||
return { value: serializeValue(e, value => ({ fallThrough: value })) };
|
||||
}
|
||||
|
||||
export function parseError(error: SerializedError): Error {
|
||||
if (!error.error) {
|
||||
if (error.value === undefined)
|
||||
throw new Error('Serialized error must have either an error or a value');
|
||||
return parseSerializedValue(error.value, undefined);
|
||||
}
|
||||
const e = new Error(error.error.message);
|
||||
e.stack = error.error.stack || '';
|
||||
e.name = error.error.name;
|
||||
return e;
|
||||
}
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { TargetClosedError } from '../../common/errors';
|
||||
import { TargetClosedError } from '../errors';
|
||||
import { assert } from '../../utils';
|
||||
import type { BrowserOptions } from '../browser';
|
||||
import { Browser } from '../browser';
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ import { splitErrorMessage } from '../../utils/stackTrace';
|
|||
import { debugLogger } from '../../common/debugLogger';
|
||||
import { ManualPromise } from '../../utils/manualPromise';
|
||||
import { BrowserContext } from '../browserContext';
|
||||
import { TargetClosedError } from '../../common/errors';
|
||||
import { TargetClosedError } from '../errors';
|
||||
|
||||
export const UTILITY_WORLD_NAME = '__playwright_utility_world__';
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ import type { ScreenshotOptions } from './screenshotter';
|
|||
import type { InputFilesItems } from './dom';
|
||||
import { asLocator } from '../utils/isomorphic/locatorGenerators';
|
||||
import { FrameSelectors } from './frameSelectors';
|
||||
import { TimeoutError } from '../common/errors';
|
||||
import { TimeoutError } from './errors';
|
||||
|
||||
type ContextData = {
|
||||
contextPromise: ManualPromise<dom.FrameExecutionContext | { destroyedReason: string }>;
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ import type { TimeoutOptions } from '../common/types';
|
|||
import { isInvalidSelectorError } from '../utils/isomorphic/selectorParser';
|
||||
import { parseEvaluationResultValue, source } from './isomorphic/utilityScriptSerializers';
|
||||
import type { SerializedValue } from './isomorphic/utilityScriptSerializers';
|
||||
import { TargetClosedError } from '../common/errors';
|
||||
import { TargetClosedError } from './errors';
|
||||
|
||||
export interface PageDelegate {
|
||||
readonly rawMouse: input.RawMouse;
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { TimeoutError } from '../common/errors';
|
||||
import { TimeoutError } from './errors';
|
||||
import { assert, monotonicTime } from '../utils';
|
||||
import type { LogName } from '../common/debugLogger';
|
||||
import type { CallMetadata, Instrumentation, SdkObject } from './instrumentation';
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ import type { Protocol } from './protocol';
|
|||
import type { PageProxyMessageReceivedPayload } from './wkConnection';
|
||||
import { kPageProxyMessageReceived, WKConnection, WKSession } from './wkConnection';
|
||||
import { WKPage } from './wkPage';
|
||||
import { TargetClosedError } from '../../common/errors';
|
||||
import { TargetClosedError } from '../errors';
|
||||
import type { SdkObject } from '../instrumentation';
|
||||
|
||||
const DEFAULT_USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Safari/605.1.15';
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ import { WKWorkers } from './wkWorkers';
|
|||
import { debugLogger } from '../../common/debugLogger';
|
||||
import { ManualPromise } from '../../utils/manualPromise';
|
||||
import { BrowserContext } from '../browserContext';
|
||||
import { TargetClosedError } from '../../common/errors';
|
||||
import { TargetClosedError } from '../errors';
|
||||
|
||||
const UTILITY_WORLD_NAME = '__playwright_utility_world__';
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue