Skip to content

Commit 7f742a0

Browse files
authored
chore: make client compile for web (#34792)
1 parent 4a9b336 commit 7f742a0

File tree

5 files changed

+96
-89
lines changed

5 files changed

+96
-89
lines changed

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

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,6 @@
1414
* limitations under the License.
1515
*/
1616

17-
import { pipeline } from 'stream';
18-
import { promisify } from 'util';
19-
2017
import { Frame } from './frame';
2118
import { JSHandle, parseResult, serializeArgument } from './jsHandle';
2219
import { assert } from '../utils/isomorphic/debug';
@@ -34,8 +31,6 @@ import type * as api from '../../types/types';
3431
import type { Platform } from '../common/platform';
3532
import type * as channels from '@protocol/channels';
3633

37-
const pipelineAsync = promisify(pipeline);
38-
3934
export class ElementHandle<T extends Node = Node> extends JSHandle<T> implements api.ElementHandle {
4035
readonly _elementChannel: channels.ElementHandleChannel;
4136

@@ -306,7 +301,7 @@ export async function convertInputFiles(platform: Platform, files: string | File
306301
}), true);
307302
for (let i = 0; i < files.length; i++) {
308303
const writable = WritableStream.from(writableStreams[i]);
309-
await pipelineAsync(platform.fs().createReadStream(files[i]), writable.stream());
304+
await platform.streamFile(files[i], writable.stream());
310305
}
311306
return {
312307
directoryStream: rootDir,

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

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -30,29 +30,6 @@ export class Stream extends ChannelOwner<channels.StreamChannel> {
3030
}
3131

3232
stream(): Readable {
33-
return new StreamImpl(this._channel);
34-
}
35-
}
36-
37-
class StreamImpl extends Readable {
38-
private _channel: channels.StreamChannel;
39-
40-
constructor(channel: channels.StreamChannel) {
41-
super();
42-
this._channel = channel;
43-
}
44-
45-
override async _read() {
46-
const result = await this._channel.read({ size: 1024 * 1024 });
47-
if (result.binary.byteLength)
48-
this.push(result.binary);
49-
else
50-
this.push(null);
51-
}
52-
53-
override _destroy(error: Error | null, callback: (error: Error | null | undefined) => void): void {
54-
// Stream might be destroyed after the connection was closed.
55-
this._channel.close().catch(e => null);
56-
super._destroy(error, callback);
33+
return this._platform.streamReadable(this._channel);
5734
}
5835
}

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

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

17-
import { Writable } from 'stream';
18-
1917
import { ChannelOwner } from './channelOwner';
2018

2119
import type * as channels from '@protocol/channels';
20+
import type { Writable } from 'stream';
2221

2322
export class WritableStream extends ChannelOwner<channels.WritableStreamChannel> {
2423
static from(Stream: channels.WritableStreamChannel): WritableStream {
@@ -30,26 +29,6 @@ export class WritableStream extends ChannelOwner<channels.WritableStreamChannel>
3029
}
3130

3231
stream(): Writable {
33-
return new WritableStreamImpl(this._channel);
34-
}
35-
}
36-
37-
class WritableStreamImpl extends Writable {
38-
private _channel: channels.WritableStreamChannel;
39-
40-
constructor(channel: channels.WritableStreamChannel) {
41-
super();
42-
this._channel = channel;
43-
}
44-
45-
override async _write(chunk: Buffer | string, encoding: BufferEncoding, callback: (error?: Error | null) => void) {
46-
const error = await this._channel.write({ binary: typeof chunk === 'string' ? Buffer.from(chunk) : chunk }).catch(e => e);
47-
callback(error || null);
48-
}
49-
50-
override async _final(callback: (error?: Error | null) => void) {
51-
// Stream might be destroyed after the connection was closed.
52-
const error = await this._channel.close().catch(e => e);
53-
callback(error || null);
32+
return this._platform.streamWritable(this._channel);
5433
}
5534
}

packages/playwright-core/src/common/platform.ts

Lines changed: 33 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ import { webColors, noColors } from '../utils/isomorphic/colors';
1919
import type * as fs from 'fs';
2020
import type * as path from 'path';
2121
import type { Colors } from '../utils/isomorphic/colors';
22+
import type { Readable, Writable } from 'stream';
23+
import type * as channels from '@protocol/channels';
2224

2325
export type Zone = {
2426
push(data: unknown): Zone;
@@ -47,26 +49,27 @@ export type Platform = {
4749
log(name: 'api' | 'channel', message: string | Error | object): void;
4850
path: () => typeof path;
4951
pathSeparator: string;
52+
streamFile(path: string, writable: Writable): Promise<void>,
53+
streamReadable: (channel: channels.StreamChannel) => Readable,
54+
streamWritable: (channel: channels.WritableStreamChannel) => Writable,
5055
zones: { empty: Zone, current: () => Zone; };
5156
};
5257

53-
export const webPlatform: Platform = {
54-
name: 'web',
58+
export const emptyPlatform: Platform = {
59+
name: 'empty',
5560

56-
calculateSha1: async (text: string) => {
57-
const bytes = new TextEncoder().encode(text);
58-
const hashBuffer = await window.crypto.subtle.digest('SHA-1', bytes);
59-
return Array.from(new Uint8Array(hashBuffer), b => b.toString(16).padStart(2, '0')).join('');
61+
calculateSha1: async () => {
62+
throw new Error('Not implemented');
6063
},
6164

62-
colors: webColors,
65+
colors: noColors,
6366

6467
createGuid: () => {
65-
return Array.from(window.crypto.getRandomValues(new Uint8Array(16)), b => b.toString(16).padStart(2, '0')).join('');
68+
throw new Error('Not implemented');
6669
},
6770

6871
fs: () => {
69-
throw new Error('File system is not available');
72+
throw new Error('Not implemented');
7073
},
7174

7275
inspectCustom: undefined,
@@ -77,49 +80,43 @@ export const webPlatform: Platform = {
7780
return false;
7881
},
7982

80-
log(name: 'api' | 'channel', message: string | Error | object) {},
83+
log(name: 'api' | 'channel', message: string | Error | object) { },
8184

8285
path: () => {
83-
throw new Error('Path module is not available');
86+
throw new Error('Function not implemented.');
8487
},
8588

8689
pathSeparator: '/',
8790

88-
zones: { empty: noopZone, current: () => noopZone },
89-
};
90-
91-
export const emptyPlatform: Platform = {
92-
name: 'empty',
93-
94-
calculateSha1: async () => {
95-
throw new Error('Not implemented');
91+
streamFile(path: string, writable: Writable): Promise<void> {
92+
throw new Error('Streams are not available');
9693
},
9794

98-
colors: noColors,
99-
100-
createGuid: () => {
101-
throw new Error('Not implemented');
95+
streamReadable: (channel: channels.StreamChannel) => {
96+
throw new Error('Streams are not available');
10297
},
10398

104-
fs: () => {
105-
throw new Error('Not implemented');
99+
streamWritable: (channel: channels.WritableStreamChannel) => {
100+
throw new Error('Streams are not available');
106101
},
107102

108-
inspectCustom: undefined,
109-
110-
isDebuggerAttached: () => false,
103+
zones: { empty: noopZone, current: () => noopZone },
104+
};
111105

112-
isLogEnabled(name: 'api' | 'channel') {
113-
return false;
114-
},
106+
export const webPlatform: Platform = {
107+
...emptyPlatform,
115108

116-
log(name: 'api' | 'channel', message: string | Error | object) { },
109+
name: 'web',
117110

118-
path: () => {
119-
throw new Error('Function not implemented.');
111+
calculateSha1: async (text: string) => {
112+
const bytes = new TextEncoder().encode(text);
113+
const hashBuffer = await window.crypto.subtle.digest('SHA-1', bytes);
114+
return Array.from(new Uint8Array(hashBuffer), b => b.toString(16).padStart(2, '0')).join('');
120115
},
121116

122-
pathSeparator: '/',
117+
colors: webColors,
123118

124-
zones: { empty: noopZone, current: () => noopZone },
119+
createGuid: () => {
120+
return Array.from(window.crypto.getRandomValues(new Uint8Array(16)), b => b.toString(16).padStart(2, '0')).join('');
121+
},
125122
};

packages/playwright-core/src/server/utils/nodePlatform.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,17 @@ import * as crypto from 'crypto';
1818
import * as fs from 'fs';
1919
import * as path from 'path';
2020
import * as util from 'util';
21+
import { Readable, Writable, pipeline } from 'stream';
2122

2223
import { colors } from '../../utilsBundle';
2324
import { debugLogger } from './debugLogger';
2425
import { currentZone, emptyZone } from './zones';
2526

2627
import type { Platform, Zone } from '../../common/platform';
2728
import type { Zone as ZoneImpl } from './zones';
29+
import type * as channels from '@protocol/channels';
30+
31+
const pipelineAsync = util.promisify(pipeline);
2832

2933
class NodeZone implements Zone {
3034
private _zone: ZoneImpl;
@@ -81,8 +85,63 @@ export const nodePlatform: Platform = {
8185

8286
pathSeparator: path.sep,
8387

88+
async streamFile(path: string, stream: Writable): Promise<void> {
89+
await pipelineAsync(fs.createReadStream(path), stream);
90+
},
91+
92+
streamReadable: (channel: channels.StreamChannel) => {
93+
return new ReadableStreamImpl(channel);
94+
},
95+
96+
streamWritable: (channel: channels.WritableStreamChannel) => {
97+
return new WritableStreamImpl(channel);
98+
},
99+
84100
zones: {
85101
current: () => new NodeZone(currentZone()),
86102
empty: new NodeZone(emptyZone),
87103
}
88104
};
105+
106+
class ReadableStreamImpl extends Readable {
107+
private _channel: channels.StreamChannel;
108+
109+
constructor(channel: channels.StreamChannel) {
110+
super();
111+
this._channel = channel;
112+
}
113+
114+
override async _read() {
115+
const result = await this._channel.read({ size: 1024 * 1024 });
116+
if (result.binary.byteLength)
117+
this.push(result.binary);
118+
else
119+
this.push(null);
120+
}
121+
122+
override _destroy(error: Error | null, callback: (error: Error | null | undefined) => void): void {
123+
// Stream might be destroyed after the connection was closed.
124+
this._channel.close().catch(e => null);
125+
super._destroy(error, callback);
126+
}
127+
}
128+
129+
class WritableStreamImpl extends Writable {
130+
private _channel: channels.WritableStreamChannel;
131+
132+
constructor(channel: channels.WritableStreamChannel) {
133+
super();
134+
this._channel = channel;
135+
}
136+
137+
override async _write(chunk: Buffer | string, encoding: BufferEncoding, callback: (error?: Error | null) => void) {
138+
const error = await this._channel.write({ binary: typeof chunk === 'string' ? Buffer.from(chunk) : chunk }).catch(e => e);
139+
callback(error || null);
140+
}
141+
142+
override async _final(callback: (error?: Error | null) => void) {
143+
// Stream might be destroyed after the connection was closed.
144+
const error = await this._channel.close().catch(e => e);
145+
callback(error || null);
146+
}
147+
}

0 commit comments

Comments
 (0)