Skip to content

Commit 5d500dd

Browse files
authored
chore: introduce platform for client (1) (#34683)
1 parent 0672f1c commit 5d500dd

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+499
-381
lines changed

packages/playwright-core/src/DEPS.list

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@
77
[inProcessFactory.ts]
88
**
99

10+
[inprocess.ts]
11+
common/
12+
1013
[outofprocess.ts]
1114
client/
1215
protocol/
1316
utils/
17+
common/

packages/playwright-core/src/cli/DEPS.list

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
../common
55
../debug/injected
66
../generated/
7+
../server/
78
../server/injected/
89
../server/trace
910
../utils

packages/playwright-core/src/cli/driver.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import * as playwright from '../..';
2222
import { PipeTransport } from '../protocol/transport';
2323
import { PlaywrightServer } from '../remote/playwrightServer';
2424
import { DispatcherConnection, PlaywrightDispatcher, RootDispatcher, createPlaywright } from '../server';
25-
import { gracefullyProcessExitDoNotHang } from '../utils/processLauncher';
25+
import { gracefullyProcessExitDoNotHang } from '../server/processLauncher';
2626

2727
import type { BrowserType } from '../client/browserType';
2828
import type { LaunchServerOptions } from '../client/types';

packages/playwright-core/src/cli/program.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ import * as os from 'os';
2121
import * as path from 'path';
2222

2323
import * as playwright from '../..';
24-
import { registry, writeDockerVersion } from '../server';
2524
import { launchBrowserServer, printApiJson, runDriver, runServer } from './driver';
2625
import { isTargetClosedError } from '../client/errors';
26+
import { gracefullyProcessExitDoNotHang, registry, writeDockerVersion } from '../server';
2727
import { runTraceInBrowser, runTraceViewerApp } from '../server/trace/viewer/traceViewer';
28-
import { assert, getPackageManagerExecCommand, gracefullyProcessExitDoNotHang, isLikelyNpxGlobal, wrapInASCIIBox } from '../utils';
28+
import { assert, getPackageManagerExecCommand, isLikelyNpxGlobal, wrapInASCIIBox } from '../utils';
2929
import { dotenv, program } from '../utilsBundle';
3030

3131
import type { Browser } from '../client/browser';

packages/playwright-core/src/cli/programWithTestStub.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616

1717
/* eslint-disable no-console */
1818

19-
import { getPackageManager, gracefullyProcessExitDoNotHang } from '../utils';
19+
import { gracefullyProcessExitDoNotHang } from '../server';
20+
import { getPackageManager } from '../utils';
2021
import { program } from './program';
2122
export { program } from './program';
2223

packages/playwright-core/src/client/android.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,23 @@
1515
*/
1616

1717
import { EventEmitter } from 'events';
18-
import * as fs from 'fs';
1918

20-
import { isRegExp, isString, monotonicTime } from '../utils';
2119
import { BrowserContext, prepareBrowserContextParams } from './browserContext';
2220
import { ChannelOwner } from './channelOwner';
2321
import { Connection } from './connection';
2422
import { TargetClosedError, isTargetClosedError } from './errors';
2523
import { Events } from './events';
2624
import { Waiter } from './waiter';
2725
import { TimeoutSettings } from '../common/timeoutSettings';
26+
import { isRegExp, isString } from '../utils/rtti';
27+
import { monotonicTime } from '../utils/time';
2828
import { raceAgainstDeadline } from '../utils/timeoutRunner';
2929

3030
import type { Page } from './page';
3131
import type * as types from './types';
3232
import type * as api from '../../types/types';
3333
import type { AndroidServerLauncherImpl } from '../androidServerImpl';
34+
import type { Platform } from '../common/platform';
3435
import type * as channels from '@protocol/channels';
3536

3637
type Direction = 'down' | 'up' | 'left' | 'right';
@@ -73,7 +74,7 @@ export class Android extends ChannelOwner<channels.AndroidChannel> implements ap
7374
const connectParams: channels.LocalUtilsConnectParams = { wsEndpoint, headers, slowMo: options.slowMo, timeout: options.timeout };
7475
const { pipe } = await localUtils._channel.connect(connectParams);
7576
const closePipe = () => pipe.close().catch(() => {});
76-
const connection = new Connection(localUtils, this._instrumentation);
77+
const connection = new Connection(localUtils, this._platform, this._instrumentation);
7778
connection.markAsRemote();
7879
connection.on('close', closePipe);
7980

@@ -232,7 +233,7 @@ export class AndroidDevice extends ChannelOwner<channels.AndroidDeviceChannel> i
232233
async screenshot(options: { path?: string } = {}): Promise<Buffer> {
233234
const { binary } = await this._channel.screenshot();
234235
if (options.path)
235-
await fs.promises.writeFile(options.path, binary);
236+
await this._platform.fs().promises.writeFile(options.path, binary);
236237
return binary;
237238
}
238239

@@ -267,15 +268,15 @@ export class AndroidDevice extends ChannelOwner<channels.AndroidDeviceChannel> i
267268
}
268269

269270
async installApk(file: string | Buffer, options?: { args: string[] }): Promise<void> {
270-
await this._channel.installApk({ file: await loadFile(file), args: options && options.args });
271+
await this._channel.installApk({ file: await loadFile(this._platform, file), args: options && options.args });
271272
}
272273

273274
async push(file: string | Buffer, path: string, options?: { mode: number }): Promise<void> {
274-
await this._channel.push({ file: await loadFile(file), path, mode: options ? options.mode : undefined });
275+
await this._channel.push({ file: await loadFile(this._platform, file), path, mode: options ? options.mode : undefined });
275276
}
276277

277278
async launchBrowser(options: types.BrowserContextOptions & { pkg?: string } = {}): Promise<BrowserContext> {
278-
const contextOptions = await prepareBrowserContextParams(options);
279+
const contextOptions = await prepareBrowserContextParams(this._platform, options);
279280
const result = await this._channel.launchBrowser(contextOptions);
280281
const context = BrowserContext.from(result.context) as BrowserContext;
281282
context._setOptions(contextOptions, {});
@@ -321,9 +322,9 @@ export class AndroidSocket extends ChannelOwner<channels.AndroidSocketChannel> i
321322
}
322323
}
323324

324-
async function loadFile(file: string | Buffer): Promise<Buffer> {
325+
async function loadFile(platform: Platform, file: string | Buffer): Promise<Buffer> {
325326
if (isString(file))
326-
return await fs.promises.readFile(file);
327+
return await platform.fs().promises.readFile(file);
327328
return file;
328329
}
329330

packages/playwright-core/src/client/artifact.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@
1414
* limitations under the License.
1515
*/
1616

17-
import * as fs from 'fs';
18-
1917
import { ChannelOwner } from './channelOwner';
2018
import { Stream } from './stream';
2119
import { mkdirIfNeeded } from '../utils/fileUtils';
@@ -42,9 +40,9 @@ export class Artifact extends ChannelOwner<channels.ArtifactChannel> {
4240

4341
const result = await this._channel.saveAsStream();
4442
const stream = Stream.from(result.stream);
45-
await mkdirIfNeeded(path);
43+
await mkdirIfNeeded(this._platform, path);
4644
await new Promise((resolve, reject) => {
47-
stream.stream().pipe(fs.createWriteStream(path))
45+
stream.stream().pipe(this._platform.fs().createWriteStream(path))
4846
.on('finish' as any, resolve)
4947
.on('error' as any, reject);
5048
});

packages/playwright-core/src/client/browser.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,13 @@
1414
* limitations under the License.
1515
*/
1616

17-
import * as fs from 'fs';
18-
1917
import { Artifact } from './artifact';
2018
import { BrowserContext, prepareBrowserContextParams } from './browserContext';
2119
import { CDPSession } from './cdpSession';
2220
import { ChannelOwner } from './channelOwner';
2321
import { isTargetClosedError } from './errors';
2422
import { Events } from './events';
25-
import { mkdirIfNeeded } from '../utils';
23+
import { mkdirIfNeeded } from '../utils/fileUtils';
2624

2725
import type { BrowserType } from './browserType';
2826
import type { Page } from './page';
@@ -83,7 +81,7 @@ export class Browser extends ChannelOwner<channels.BrowserChannel> implements ap
8381

8482
async _innerNewContext(options: BrowserContextOptions = {}, forReuse: boolean): Promise<BrowserContext> {
8583
options = { ...this._browserType._playwright._defaultContextOptions, ...options };
86-
const contextOptions = await prepareBrowserContextParams(options);
84+
const contextOptions = await prepareBrowserContextParams(this._platform, options);
8785
const response = forReuse ? await this._channel.newContextForReuse(contextOptions) : await this._channel.newContext(contextOptions);
8886
const context = BrowserContext.from(response.context);
8987
await this._browserType._didCreateContext(context, contextOptions, this._options, options.logger || this._logger);
@@ -126,8 +124,8 @@ export class Browser extends ChannelOwner<channels.BrowserChannel> implements ap
126124
const buffer = await artifact.readIntoBuffer();
127125
await artifact.delete();
128126
if (this._path) {
129-
await mkdirIfNeeded(this._path);
130-
await fs.promises.writeFile(this._path, buffer);
127+
await mkdirIfNeeded(this._platform, this._path);
128+
await this._platform.fs().promises.writeFile(this._path, buffer);
131129
this._path = undefined;
132130
}
133131
return buffer;

packages/playwright-core/src/client/browserContext.ts

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,6 @@
1515
* limitations under the License.
1616
*/
1717

18-
import * as fs from 'fs';
19-
import * as path from 'path';
20-
2118
import { Artifact } from './artifact';
2219
import { Browser } from './browser';
2320
import { CDPSession } from './cdpSession';
@@ -38,14 +35,18 @@ import { Waiter } from './waiter';
3835
import { WebError } from './webError';
3936
import { Worker } from './worker';
4037
import { TimeoutSettings } from '../common/timeoutSettings';
41-
import { headersObjectToArray, isRegExp, isString, mkdirIfNeeded, urlMatchesEqual } from '../utils';
38+
import { mkdirIfNeeded } from '../utils/fileUtils';
39+
import { headersObjectToArray } from '../utils/headers';
40+
import { urlMatchesEqual } from '../utils/isomorphic/urlMatch';
41+
import { isRegExp, isString } from '../utils/rtti';
4242
import { rewriteErrorMessage } from '../utils/stackTrace';
4343

4444
import type { BrowserType } from './browserType';
4545
import type { BrowserContextOptions, Headers, LaunchOptions, StorageState, WaitForEventOptions } from './types';
4646
import type * as structs from '../../types/structs';
4747
import type * as api from '../../types/types';
48-
import type { URLMatch } from '../utils';
48+
import type { Platform } from '../common/platform';
49+
import type { URLMatch } from '../utils/isomorphic/urlMatch';
4950
import type * as channels from '@protocol/channels';
5051

5152
export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel> implements api.BrowserContext {
@@ -107,7 +108,7 @@ export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel>
107108
this.emit(Events.BrowserContext.ServiceWorker, serviceWorker);
108109
});
109110
this._channel.on('console', event => {
110-
const consoleMessage = new ConsoleMessage(event);
111+
const consoleMessage = new ConsoleMessage(this._platform, event);
111112
this.emit(Events.BrowserContext.Console, consoleMessage);
112113
const page = consoleMessage.page();
113114
if (page)
@@ -321,7 +322,7 @@ export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel>
321322
}
322323

323324
async addInitScript(script: Function | string | { path?: string, content?: string }, arg?: any): Promise<void> {
324-
const source = await evaluationScript(script, arg);
325+
const source = await evaluationScript(this._platform, script, arg);
325326
await this._channel.addInitScript({ source });
326327
}
327328

@@ -431,8 +432,8 @@ export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel>
431432
async storageState(options: { path?: string, indexedDB?: boolean } = {}): Promise<StorageState> {
432433
const state = await this._channel.storageState({ indexedDB: options.indexedDB });
433434
if (options.path) {
434-
await mkdirIfNeeded(options.path);
435-
await fs.promises.writeFile(options.path, JSON.stringify(state, undefined, 2), 'utf8');
435+
await mkdirIfNeeded(this._platform, options.path);
436+
await this._platform.fs().promises.writeFile(options.path, JSON.stringify(state, undefined, 2), 'utf8');
436437
}
437438
return state;
438439
}
@@ -500,11 +501,11 @@ export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel>
500501
}
501502
}
502503

503-
async function prepareStorageState(options: BrowserContextOptions): Promise<channels.BrowserNewContextParams['storageState']> {
504+
async function prepareStorageState(platform: Platform, options: BrowserContextOptions): Promise<channels.BrowserNewContextParams['storageState']> {
504505
if (typeof options.storageState !== 'string')
505506
return options.storageState;
506507
try {
507-
return JSON.parse(await fs.promises.readFile(options.storageState, 'utf8'));
508+
return JSON.parse(await platform.fs().promises.readFile(options.storageState, 'utf8'));
508509
} catch (e) {
509510
rewriteErrorMessage(e, `Error reading storage state from ${options.storageState}:\n` + e.message);
510511
throw e;
@@ -524,7 +525,7 @@ function prepareRecordHarOptions(options: BrowserContextOptions['recordHar']): c
524525
};
525526
}
526527

527-
export async function prepareBrowserContextParams(options: BrowserContextOptions): Promise<channels.BrowserNewContextParams> {
528+
export async function prepareBrowserContextParams(platform: Platform, options: BrowserContextOptions): Promise<channels.BrowserNewContextParams> {
528529
if (options.videoSize && !options.videosPath)
529530
throw new Error(`"videoSize" option requires "videosPath" to be specified`);
530531
if (options.extraHTTPHeaders)
@@ -534,15 +535,15 @@ export async function prepareBrowserContextParams(options: BrowserContextOptions
534535
viewport: options.viewport === null ? undefined : options.viewport,
535536
noDefaultViewport: options.viewport === null,
536537
extraHTTPHeaders: options.extraHTTPHeaders ? headersObjectToArray(options.extraHTTPHeaders) : undefined,
537-
storageState: await prepareStorageState(options),
538+
storageState: await prepareStorageState(platform, options),
538539
serviceWorkers: options.serviceWorkers,
539540
recordHar: prepareRecordHarOptions(options.recordHar),
540541
colorScheme: options.colorScheme === null ? 'no-override' : options.colorScheme,
541542
reducedMotion: options.reducedMotion === null ? 'no-override' : options.reducedMotion,
542543
forcedColors: options.forcedColors === null ? 'no-override' : options.forcedColors,
543544
contrast: options.contrast === null ? 'no-override' : options.contrast,
544545
acceptDownloads: toAcceptDownloadsProtocol(options.acceptDownloads),
545-
clientCertificates: await toClientCertificatesProtocol(options.clientCertificates),
546+
clientCertificates: await toClientCertificatesProtocol(platform, options.clientCertificates),
546547
};
547548
if (!contextParams.recordVideo && options.videosPath) {
548549
contextParams.recordVideo = {
@@ -551,7 +552,7 @@ export async function prepareBrowserContextParams(options: BrowserContextOptions
551552
};
552553
}
553554
if (contextParams.recordVideo && contextParams.recordVideo.dir)
554-
contextParams.recordVideo.dir = path.resolve(process.cwd(), contextParams.recordVideo.dir);
555+
contextParams.recordVideo.dir = platform.path().resolve(process.cwd(), contextParams.recordVideo.dir);
555556
return contextParams;
556557
}
557558

@@ -563,15 +564,15 @@ function toAcceptDownloadsProtocol(acceptDownloads?: boolean) {
563564
return 'deny';
564565
}
565566

566-
export async function toClientCertificatesProtocol(certs?: BrowserContextOptions['clientCertificates']): Promise<channels.PlaywrightNewRequestParams['clientCertificates']> {
567+
export async function toClientCertificatesProtocol(platform: Platform, certs?: BrowserContextOptions['clientCertificates']): Promise<channels.PlaywrightNewRequestParams['clientCertificates']> {
567568
if (!certs)
568569
return undefined;
569570

570571
const bufferizeContent = async (value?: Buffer, path?: string): Promise<Buffer | undefined> => {
571572
if (value)
572573
return value;
573574
if (path)
574-
return await fs.promises.readFile(path);
575+
return await platform.fs().promises.readFile(path);
575576
};
576577

577578
return await Promise.all(certs.map(async cert => ({

packages/playwright-core/src/client/browserType.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ import { ChannelOwner } from './channelOwner';
2020
import { envObjectToArray } from './clientHelper';
2121
import { Connection } from './connection';
2222
import { Events } from './events';
23-
import { assert, headersObjectToArray, monotonicTime } from '../utils';
23+
import { assert } from '../utils/debug';
24+
import { headersObjectToArray } from '../utils/headers';
25+
import { monotonicTime } from '../utils/time';
2426
import { raceAgainstDeadline } from '../utils/timeoutRunner';
2527

2628
import type { Playwright } from './playwright';
@@ -90,7 +92,7 @@ export class BrowserType extends ChannelOwner<channels.BrowserTypeChannel> imple
9092
const logger = options.logger || this._playwright._defaultLaunchOptions?.logger;
9193
assert(!(options as any).port, 'Cannot specify a port without launching as a server.');
9294
options = { ...this._playwright._defaultLaunchOptions, ...this._playwright._defaultContextOptions, ...options };
93-
const contextParams = await prepareBrowserContextParams(options);
95+
const contextParams = await prepareBrowserContextParams(this._platform, options);
9496
const persistentParams: channels.BrowserTypeLaunchPersistentContextParams = {
9597
...contextParams,
9698
ignoreDefaultArgs: Array.isArray(options.ignoreDefaultArgs) ? options.ignoreDefaultArgs : undefined,
@@ -133,7 +135,7 @@ export class BrowserType extends ChannelOwner<channels.BrowserTypeChannel> imple
133135
connectParams.socksProxyRedirectPortForTest = (params as any).__testHookRedirectPortForwarding;
134136
const { pipe, headers: connectHeaders } = await localUtils._channel.connect(connectParams);
135137
const closePipe = () => pipe.close().catch(() => {});
136-
const connection = new Connection(localUtils, this._instrumentation);
138+
const connection = new Connection(localUtils, this._platform, this._instrumentation);
137139
connection.markAsRemote();
138140
connection.on('close', closePipe);
139141

0 commit comments

Comments
 (0)