chore: do not use process in client (#34816)
This commit is contained in:
parent
3606a434fe
commit
f70f92d5cd
|
@ -177,7 +177,7 @@ const noBooleanCompareRules = {
|
|||
'@typescript-eslint/no-unnecessary-boolean-literal-compare': 2,
|
||||
};
|
||||
|
||||
const noRestrictedGlobalsRules = {
|
||||
const noWebGlobalsRules = {
|
||||
'no-restricted-globals': [
|
||||
'error',
|
||||
{ 'name': 'window' },
|
||||
|
@ -186,6 +186,13 @@ const noRestrictedGlobalsRules = {
|
|||
],
|
||||
};
|
||||
|
||||
const noNodeGlobalsRules = {
|
||||
'no-restricted-globals': [
|
||||
'error',
|
||||
{ 'name': 'process' },
|
||||
],
|
||||
};
|
||||
|
||||
const importOrderRules = {
|
||||
'import/order': [2, {
|
||||
'groups': ['builtin', 'external', 'internal', ['parent', 'sibling'], 'index', 'type'],
|
||||
|
@ -249,7 +256,19 @@ export default [{
|
|||
files: ['packages/playwright-core/src/server/injected/**/*.ts'],
|
||||
languageOptions: languageOptionsWithTsConfig,
|
||||
rules: {
|
||||
...noRestrictedGlobalsRules,
|
||||
...noWebGlobalsRules,
|
||||
...noFloatingPromisesRules,
|
||||
...noBooleanCompareRules,
|
||||
}
|
||||
}, {
|
||||
files: [
|
||||
'packages/playwright-core/src/client/**/*.ts',
|
||||
'packages/playwright-core/src/protocol/**/*.ts',
|
||||
'packages/playwright-core/src/utils/**/*.ts',
|
||||
],
|
||||
languageOptions: languageOptionsWithTsConfig,
|
||||
rules: {
|
||||
...noNodeGlobalsRules,
|
||||
...noFloatingPromisesRules,
|
||||
...noBooleanCompareRules,
|
||||
}
|
||||
|
|
|
@ -23,9 +23,9 @@ import * as path from 'path';
|
|||
import * as playwright from '../..';
|
||||
import { launchBrowserServer, printApiJson, runDriver, runServer } from './driver';
|
||||
import { registry, writeDockerVersion } from '../server';
|
||||
import { gracefullyProcessExitDoNotHang } from '../utils';
|
||||
import { gracefullyProcessExitDoNotHang, isLikelyNpxGlobal } from '../utils';
|
||||
import { runTraceInBrowser, runTraceViewerApp } from '../server/trace/viewer/traceViewer';
|
||||
import { assert, getPackageManagerExecCommand, isLikelyNpxGlobal } from '../utils';
|
||||
import { assert, getPackageManagerExecCommand } from '../utils';
|
||||
import { wrapInASCIIBox } from '../server/utils/ascii';
|
||||
import { dotenv, program } from '../utilsBundle';
|
||||
|
||||
|
|
|
@ -51,7 +51,9 @@ export class Android extends ChannelOwner<channels.AndroidChannel> implements ap
|
|||
|
||||
setDefaultTimeout(timeout: number) {
|
||||
this._timeoutSettings.setDefaultTimeout(timeout);
|
||||
this._channel.setDefaultTimeoutNoReply({ timeout });
|
||||
this._wrapApiCall(async () => {
|
||||
await this._channel.setDefaultTimeoutNoReply({ timeout });
|
||||
}, true).catch(() => {});
|
||||
}
|
||||
|
||||
async devices(options: { port?: number } = {}): Promise<AndroidDevice[]> {
|
||||
|
@ -133,7 +135,9 @@ export class AndroidDevice extends ChannelOwner<channels.AndroidDeviceChannel> i
|
|||
|
||||
setDefaultTimeout(timeout: number) {
|
||||
this._timeoutSettings.setDefaultTimeout(timeout);
|
||||
this._channel.setDefaultTimeoutNoReply({ timeout });
|
||||
this._wrapApiCall(async () => {
|
||||
await this._channel.setDefaultTimeoutNoReply({ timeout });
|
||||
}, true).catch(() => {});
|
||||
}
|
||||
|
||||
serial(): string {
|
||||
|
|
|
@ -246,15 +246,15 @@ export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel>
|
|||
setDefaultNavigationTimeout(timeout: number | undefined) {
|
||||
this._timeoutSettings.setDefaultNavigationTimeout(timeout);
|
||||
this._wrapApiCall(async () => {
|
||||
this._channel.setDefaultNavigationTimeoutNoReply({ timeout }).catch(() => {});
|
||||
}, true);
|
||||
await this._channel.setDefaultNavigationTimeoutNoReply({ timeout });
|
||||
}, true).catch(() => {});
|
||||
}
|
||||
|
||||
setDefaultTimeout(timeout: number | undefined) {
|
||||
this._timeoutSettings.setDefaultTimeout(timeout);
|
||||
this._wrapApiCall(async () => {
|
||||
this._channel.setDefaultTimeoutNoReply({ timeout }).catch(() => {});
|
||||
}, true);
|
||||
await this._channel.setDefaultTimeoutNoReply({ timeout });
|
||||
}, true).catch(() => {});
|
||||
}
|
||||
|
||||
browser(): Browser | null {
|
||||
|
@ -559,7 +559,7 @@ export async function prepareBrowserContextParams(platform: Platform, options: B
|
|||
};
|
||||
}
|
||||
if (contextParams.recordVideo && contextParams.recordVideo.dir)
|
||||
contextParams.recordVideo.dir = platform.path().resolve(process.cwd(), contextParams.recordVideo.dir);
|
||||
contextParams.recordVideo.dir = platform.path().resolve(contextParams.recordVideo.dir);
|
||||
return contextParams;
|
||||
}
|
||||
|
||||
|
|
|
@ -199,7 +199,7 @@ export abstract class ChannelOwner<T extends channels.Channel = channels.Channel
|
|||
}
|
||||
return result;
|
||||
} catch (e) {
|
||||
const innerError = ((process.env.PWDEBUGIMPL || this._platform.isUnderTest()) && e.stack) ? '\n<inner error>\n' + e.stack : '';
|
||||
const innerError = ((this._platform.showInternalStackFrames() || this._platform.isUnderTest()) && e.stack) ? '\n<inner error>\n' + e.stack : '';
|
||||
if (apiZone.apiName && !apiZone.apiName.includes('<anonymous>'))
|
||||
e.message = apiZone.apiName + ': ' + e.message;
|
||||
const stackFrames = '\n' + stringifyStackFrames(stackTrace.frames).join('\n') + innerError;
|
||||
|
|
|
@ -28,7 +28,7 @@ export function captureLibraryStackTrace(platform: Platform): { frames: StackFra
|
|||
isPlaywrightLibrary: boolean;
|
||||
};
|
||||
let parsedFrames = stack.map(line => {
|
||||
const frame = parseStackFrame(line, platform.pathSeparator);
|
||||
const frame = parseStackFrame(line, platform.pathSeparator, platform.showInternalStackFrames());
|
||||
if (!frame || !frame.file)
|
||||
return null;
|
||||
const isPlaywrightLibrary = !!platform.coreDir && frame.file.startsWith(platform.coreDir);
|
||||
|
@ -62,10 +62,8 @@ export function captureLibraryStackTrace(platform: Platform): { frames: StackFra
|
|||
}
|
||||
|
||||
// This is for the inspector so that it did not include the test runner stack frames.
|
||||
const filterPrefixes = platform.coreDir ? [platform.coreDir, ...platform.boxedStackPrefixes()] : platform.boxedStackPrefixes();
|
||||
const filterPrefixes = platform.boxedStackPrefixes();
|
||||
parsedFrames = parsedFrames.filter(f => {
|
||||
if (process.env.PWDEBUGIMPL)
|
||||
return true;
|
||||
if (filterPrefixes.some(prefix => f.frame.file.startsWith(prefix)))
|
||||
return false;
|
||||
return true;
|
||||
|
|
|
@ -54,7 +54,7 @@ export class Electron extends ChannelOwner<channels.ElectronChannel> implements
|
|||
async launch(options: ElectronOptions = {}): Promise<ElectronApplication> {
|
||||
const params: channels.ElectronLaunchParams = {
|
||||
...await prepareBrowserContextParams(this._platform, options),
|
||||
env: envObjectToArray(options.env ? options.env : process.env),
|
||||
env: envObjectToArray(options.env ? options.env : this._platform.env),
|
||||
tracesDir: options.tracesDir,
|
||||
};
|
||||
const app = ElectronApplication.from((await this._channel.launch(params)).electronApplication);
|
||||
|
|
|
@ -277,15 +277,15 @@ export class Page extends ChannelOwner<channels.PageChannel> implements api.Page
|
|||
setDefaultNavigationTimeout(timeout: number) {
|
||||
this._timeoutSettings.setDefaultNavigationTimeout(timeout);
|
||||
this._wrapApiCall(async () => {
|
||||
this._channel.setDefaultNavigationTimeoutNoReply({ timeout }).catch(() => {});
|
||||
}, true);
|
||||
await this._channel.setDefaultNavigationTimeoutNoReply({ timeout });
|
||||
}, true).catch(() => {});
|
||||
}
|
||||
|
||||
setDefaultTimeout(timeout: number) {
|
||||
this._timeoutSettings.setDefaultTimeout(timeout);
|
||||
this._wrapApiCall(async () => {
|
||||
this._channel.setDefaultTimeoutNoReply({ timeout }).catch(() => {});
|
||||
}, true);
|
||||
await this._channel.setDefaultTimeoutNoReply({ timeout });
|
||||
}, true).catch(() => {});
|
||||
}
|
||||
|
||||
private _forceVideo(): Video {
|
||||
|
|
|
@ -45,6 +45,7 @@ export type Platform = {
|
|||
coreDir?: string;
|
||||
createGuid: () => string;
|
||||
defaultMaxListeners: () => number;
|
||||
env: Record<string, string | undefined>;
|
||||
fs: () => typeof fs;
|
||||
inspectCustom: symbol | undefined;
|
||||
isDebugMode: () => boolean;
|
||||
|
@ -54,6 +55,7 @@ export type Platform = {
|
|||
log: (name: 'api' | 'channel', message: string | Error | object) => void;
|
||||
path: () => typeof path;
|
||||
pathSeparator: string;
|
||||
showInternalStackFrames: () => boolean,
|
||||
streamFile: (path: string, writable: Writable) => Promise<void>,
|
||||
streamReadable: (channel: channels.StreamChannel) => Readable,
|
||||
streamWritable: (channel: channels.WritableStreamChannel) => Writable,
|
||||
|
@ -77,6 +79,8 @@ export const emptyPlatform: Platform = {
|
|||
|
||||
defaultMaxListeners: () => 10,
|
||||
|
||||
env: {},
|
||||
|
||||
fs: () => {
|
||||
throw new Error('Not implemented');
|
||||
},
|
||||
|
@ -101,6 +105,8 @@ export const emptyPlatform: Platform = {
|
|||
|
||||
pathSeparator: '/',
|
||||
|
||||
showInternalStackFrames: () => false,
|
||||
|
||||
streamFile(path: string, writable: Writable): Promise<void> {
|
||||
throw new Error('Streams are not available');
|
||||
},
|
||||
|
|
|
@ -96,8 +96,8 @@ export class Waiter {
|
|||
log(s: string) {
|
||||
this._logs.push(s);
|
||||
this._channelOwner._wrapApiCall(async () => {
|
||||
await this._channelOwner._channel.waitForEventInfo({ info: { waitId: this._waitId, phase: 'log', message: s } }).catch(() => {});
|
||||
}, true);
|
||||
await this._channelOwner._channel.waitForEventInfo({ info: { waitId: this._waitId, phase: 'log', message: s } });
|
||||
}, true).catch(() => {});
|
||||
}
|
||||
|
||||
private _rejectOn(promise: Promise<any>, dispose?: () => void) {
|
||||
|
|
|
@ -39,7 +39,7 @@ export async function connectOverWebSocket(parentConnection: Connection, params:
|
|||
connection!.dispatch(message);
|
||||
} catch (e) {
|
||||
closeError = String(e);
|
||||
transport.close();
|
||||
transport.close().catch(() => {});
|
||||
}
|
||||
});
|
||||
return connection;
|
||||
|
@ -70,7 +70,7 @@ class JsonPipeTransport implements Transport {
|
|||
}
|
||||
|
||||
async send(message: object) {
|
||||
this._owner._wrapApiCall(async () => {
|
||||
await this._owner._wrapApiCall(async () => {
|
||||
await this._pipe!.send({ message });
|
||||
}, /* isInternal */ true);
|
||||
}
|
||||
|
|
|
@ -47,3 +47,7 @@ export function getPackageManagerExecCommand() {
|
|||
return 'pnpm exec';
|
||||
return 'npx';
|
||||
}
|
||||
|
||||
export function isLikelyNpxGlobal() {
|
||||
return process.argv.length >= 2 && process.argv[1].includes('_npx');
|
||||
}
|
||||
|
|
|
@ -61,10 +61,16 @@ export function setBoxedStackPrefixes(prefixes: string[]) {
|
|||
boxedStackPrefixes = prefixes;
|
||||
}
|
||||
|
||||
const coreDir = path.dirname(require.resolve('../../../package.json'));
|
||||
|
||||
export const nodePlatform: Platform = {
|
||||
name: 'node',
|
||||
|
||||
boxedStackPrefixes: () => boxedStackPrefixes,
|
||||
boxedStackPrefixes: () => {
|
||||
if (process.env.PWDEBUGIMPL)
|
||||
return [];
|
||||
return [coreDir, ...boxedStackPrefixes];
|
||||
},
|
||||
|
||||
calculateSha1: (text: string) => {
|
||||
const sha1 = crypto.createHash('sha1');
|
||||
|
@ -74,13 +80,15 @@ export const nodePlatform: Platform = {
|
|||
|
||||
colors,
|
||||
|
||||
coreDir: path.dirname(require.resolve('../../../package.json')),
|
||||
coreDir,
|
||||
|
||||
createGuid: () => crypto.randomBytes(16).toString('hex'),
|
||||
|
||||
defaultMaxListeners: () => EventEmitter.defaultMaxListeners,
|
||||
fs: () => fs,
|
||||
|
||||
env: process.env,
|
||||
|
||||
inspectCustom: util.inspect.custom,
|
||||
|
||||
isDebugMode: () => !!debugMode(),
|
||||
|
@ -101,6 +109,8 @@ export const nodePlatform: Platform = {
|
|||
|
||||
pathSeparator: path.sep,
|
||||
|
||||
showInternalStackFrames: () => !!process.env.PWDEBUGIMPL,
|
||||
|
||||
async streamFile(path: string, stream: Writable): Promise<void> {
|
||||
await pipelineAsync(fs.createReadStream(path), stream);
|
||||
},
|
||||
|
|
|
@ -27,5 +27,3 @@ export function isObject(obj: any): obj is NonNullable<object> {
|
|||
export function isError(obj: any): obj is Error {
|
||||
return obj instanceof Error || (obj && Object.getPrototypeOf(obj)?.name === 'Error');
|
||||
}
|
||||
|
||||
export const isLikelyNpxGlobal = () => process.argv.length >= 2 && process.argv[1].includes('_npx');
|
||||
|
|
|
@ -37,7 +37,7 @@ export function captureRawStack(): RawStack {
|
|||
return stack.split('\n');
|
||||
}
|
||||
|
||||
export function parseStackFrame(text: string, pathSeparator: string): StackFrame | null {
|
||||
export function parseStackFrame(text: string, pathSeparator: string, showInternalStackFrames: boolean): StackFrame | null {
|
||||
const match = text && text.match(re);
|
||||
if (!match)
|
||||
return null;
|
||||
|
@ -46,7 +46,7 @@ export function parseStackFrame(text: string, pathSeparator: string): StackFrame
|
|||
let file = match[7];
|
||||
if (!file)
|
||||
return null;
|
||||
if (!process.env.PWDEBUGIMPL && (file.startsWith('internal') || file.startsWith('node:')))
|
||||
if (!showInternalStackFrames && (file.startsWith('internal') || file.startsWith('node:')))
|
||||
return null;
|
||||
|
||||
const line = match[8];
|
||||
|
|
|
@ -522,7 +522,7 @@ export function prepareErrorStack(stack: string): {
|
|||
const stackLines = lines.slice(firstStackLine);
|
||||
let location: Location | undefined;
|
||||
for (const line of stackLines) {
|
||||
const frame = parseStackFrame(line, path.sep);
|
||||
const frame = parseStackFrame(line, path.sep, !!process.env.PWDEBUGIMPL);
|
||||
if (!frame || !frame.file)
|
||||
continue;
|
||||
if (belongsToNodeModules(frame.file))
|
||||
|
|
|
@ -55,7 +55,7 @@ export function filterStackFile(file: string) {
|
|||
export function filteredStackTrace(rawStack: RawStack): StackFrame[] {
|
||||
const frames: StackFrame[] = [];
|
||||
for (const line of rawStack) {
|
||||
const frame = parseStackFrame(line, path.sep);
|
||||
const frame = parseStackFrame(line, path.sep, !!process.env.PWDEBUGIMPL);
|
||||
if (!frame || !frame.file)
|
||||
continue;
|
||||
if (!filterStackFile(frame.file))
|
||||
|
|
Loading…
Reference in New Issue