chore: make client compile for web (#34792)
This commit is contained in:
parent
4a9b336168
commit
7f742a04b0
|
@ -14,9 +14,6 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { pipeline } from 'stream';
|
|
||||||
import { promisify } from 'util';
|
|
||||||
|
|
||||||
import { Frame } from './frame';
|
import { Frame } from './frame';
|
||||||
import { JSHandle, parseResult, serializeArgument } from './jsHandle';
|
import { JSHandle, parseResult, serializeArgument } from './jsHandle';
|
||||||
import { assert } from '../utils/isomorphic/debug';
|
import { assert } from '../utils/isomorphic/debug';
|
||||||
|
@ -34,8 +31,6 @@ import type * as api from '../../types/types';
|
||||||
import type { Platform } from '../common/platform';
|
import type { Platform } from '../common/platform';
|
||||||
import type * as channels from '@protocol/channels';
|
import type * as channels from '@protocol/channels';
|
||||||
|
|
||||||
const pipelineAsync = promisify(pipeline);
|
|
||||||
|
|
||||||
export class ElementHandle<T extends Node = Node> extends JSHandle<T> implements api.ElementHandle {
|
export class ElementHandle<T extends Node = Node> extends JSHandle<T> implements api.ElementHandle {
|
||||||
readonly _elementChannel: channels.ElementHandleChannel;
|
readonly _elementChannel: channels.ElementHandleChannel;
|
||||||
|
|
||||||
|
@ -306,7 +301,7 @@ export async function convertInputFiles(platform: Platform, files: string | File
|
||||||
}), true);
|
}), true);
|
||||||
for (let i = 0; i < files.length; i++) {
|
for (let i = 0; i < files.length; i++) {
|
||||||
const writable = WritableStream.from(writableStreams[i]);
|
const writable = WritableStream.from(writableStreams[i]);
|
||||||
await pipelineAsync(platform.fs().createReadStream(files[i]), writable.stream());
|
await platform.streamFile(files[i], writable.stream());
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
directoryStream: rootDir,
|
directoryStream: rootDir,
|
||||||
|
|
|
@ -30,29 +30,6 @@ export class Stream extends ChannelOwner<channels.StreamChannel> {
|
||||||
}
|
}
|
||||||
|
|
||||||
stream(): Readable {
|
stream(): Readable {
|
||||||
return new StreamImpl(this._channel);
|
return this._platform.streamReadable(this._channel);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class StreamImpl extends Readable {
|
|
||||||
private _channel: channels.StreamChannel;
|
|
||||||
|
|
||||||
constructor(channel: channels.StreamChannel) {
|
|
||||||
super();
|
|
||||||
this._channel = channel;
|
|
||||||
}
|
|
||||||
|
|
||||||
override async _read() {
|
|
||||||
const result = await this._channel.read({ size: 1024 * 1024 });
|
|
||||||
if (result.binary.byteLength)
|
|
||||||
this.push(result.binary);
|
|
||||||
else
|
|
||||||
this.push(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
override _destroy(error: Error | null, callback: (error: Error | null | undefined) => void): void {
|
|
||||||
// Stream might be destroyed after the connection was closed.
|
|
||||||
this._channel.close().catch(e => null);
|
|
||||||
super._destroy(error, callback);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,11 +14,10 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Writable } from 'stream';
|
|
||||||
|
|
||||||
import { ChannelOwner } from './channelOwner';
|
import { ChannelOwner } from './channelOwner';
|
||||||
|
|
||||||
import type * as channels from '@protocol/channels';
|
import type * as channels from '@protocol/channels';
|
||||||
|
import type { Writable } from 'stream';
|
||||||
|
|
||||||
export class WritableStream extends ChannelOwner<channels.WritableStreamChannel> {
|
export class WritableStream extends ChannelOwner<channels.WritableStreamChannel> {
|
||||||
static from(Stream: channels.WritableStreamChannel): WritableStream {
|
static from(Stream: channels.WritableStreamChannel): WritableStream {
|
||||||
|
@ -30,26 +29,6 @@ export class WritableStream extends ChannelOwner<channels.WritableStreamChannel>
|
||||||
}
|
}
|
||||||
|
|
||||||
stream(): Writable {
|
stream(): Writable {
|
||||||
return new WritableStreamImpl(this._channel);
|
return this._platform.streamWritable(this._channel);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class WritableStreamImpl extends Writable {
|
|
||||||
private _channel: channels.WritableStreamChannel;
|
|
||||||
|
|
||||||
constructor(channel: channels.WritableStreamChannel) {
|
|
||||||
super();
|
|
||||||
this._channel = channel;
|
|
||||||
}
|
|
||||||
|
|
||||||
override async _write(chunk: Buffer | string, encoding: BufferEncoding, callback: (error?: Error | null) => void) {
|
|
||||||
const error = await this._channel.write({ binary: typeof chunk === 'string' ? Buffer.from(chunk) : chunk }).catch(e => e);
|
|
||||||
callback(error || null);
|
|
||||||
}
|
|
||||||
|
|
||||||
override async _final(callback: (error?: Error | null) => void) {
|
|
||||||
// Stream might be destroyed after the connection was closed.
|
|
||||||
const error = await this._channel.close().catch(e => e);
|
|
||||||
callback(error || null);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@ import { webColors, noColors } from '../utils/isomorphic/colors';
|
||||||
import type * as fs from 'fs';
|
import type * as fs from 'fs';
|
||||||
import type * as path from 'path';
|
import type * as path from 'path';
|
||||||
import type { Colors } from '../utils/isomorphic/colors';
|
import type { Colors } from '../utils/isomorphic/colors';
|
||||||
|
import type { Readable, Writable } from 'stream';
|
||||||
|
import type * as channels from '@protocol/channels';
|
||||||
|
|
||||||
export type Zone = {
|
export type Zone = {
|
||||||
push(data: unknown): Zone;
|
push(data: unknown): Zone;
|
||||||
|
@ -47,47 +49,12 @@ export type Platform = {
|
||||||
log(name: 'api' | 'channel', message: string | Error | object): void;
|
log(name: 'api' | 'channel', message: string | Error | object): void;
|
||||||
path: () => typeof path;
|
path: () => typeof path;
|
||||||
pathSeparator: string;
|
pathSeparator: string;
|
||||||
|
streamFile(path: string, writable: Writable): Promise<void>,
|
||||||
|
streamReadable: (channel: channels.StreamChannel) => Readable,
|
||||||
|
streamWritable: (channel: channels.WritableStreamChannel) => Writable,
|
||||||
zones: { empty: Zone, current: () => Zone; };
|
zones: { empty: Zone, current: () => Zone; };
|
||||||
};
|
};
|
||||||
|
|
||||||
export const webPlatform: Platform = {
|
|
||||||
name: 'web',
|
|
||||||
|
|
||||||
calculateSha1: async (text: string) => {
|
|
||||||
const bytes = new TextEncoder().encode(text);
|
|
||||||
const hashBuffer = await window.crypto.subtle.digest('SHA-1', bytes);
|
|
||||||
return Array.from(new Uint8Array(hashBuffer), b => b.toString(16).padStart(2, '0')).join('');
|
|
||||||
},
|
|
||||||
|
|
||||||
colors: webColors,
|
|
||||||
|
|
||||||
createGuid: () => {
|
|
||||||
return Array.from(window.crypto.getRandomValues(new Uint8Array(16)), b => b.toString(16).padStart(2, '0')).join('');
|
|
||||||
},
|
|
||||||
|
|
||||||
fs: () => {
|
|
||||||
throw new Error('File system is not available');
|
|
||||||
},
|
|
||||||
|
|
||||||
inspectCustom: undefined,
|
|
||||||
|
|
||||||
isDebuggerAttached: () => false,
|
|
||||||
|
|
||||||
isLogEnabled(name: 'api' | 'channel') {
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
log(name: 'api' | 'channel', message: string | Error | object) {},
|
|
||||||
|
|
||||||
path: () => {
|
|
||||||
throw new Error('Path module is not available');
|
|
||||||
},
|
|
||||||
|
|
||||||
pathSeparator: '/',
|
|
||||||
|
|
||||||
zones: { empty: noopZone, current: () => noopZone },
|
|
||||||
};
|
|
||||||
|
|
||||||
export const emptyPlatform: Platform = {
|
export const emptyPlatform: Platform = {
|
||||||
name: 'empty',
|
name: 'empty',
|
||||||
|
|
||||||
|
@ -121,5 +88,35 @@ export const emptyPlatform: Platform = {
|
||||||
|
|
||||||
pathSeparator: '/',
|
pathSeparator: '/',
|
||||||
|
|
||||||
|
streamFile(path: string, writable: Writable): Promise<void> {
|
||||||
|
throw new Error('Streams are not available');
|
||||||
|
},
|
||||||
|
|
||||||
|
streamReadable: (channel: channels.StreamChannel) => {
|
||||||
|
throw new Error('Streams are not available');
|
||||||
|
},
|
||||||
|
|
||||||
|
streamWritable: (channel: channels.WritableStreamChannel) => {
|
||||||
|
throw new Error('Streams are not available');
|
||||||
|
},
|
||||||
|
|
||||||
zones: { empty: noopZone, current: () => noopZone },
|
zones: { empty: noopZone, current: () => noopZone },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const webPlatform: Platform = {
|
||||||
|
...emptyPlatform,
|
||||||
|
|
||||||
|
name: 'web',
|
||||||
|
|
||||||
|
calculateSha1: async (text: string) => {
|
||||||
|
const bytes = new TextEncoder().encode(text);
|
||||||
|
const hashBuffer = await window.crypto.subtle.digest('SHA-1', bytes);
|
||||||
|
return Array.from(new Uint8Array(hashBuffer), b => b.toString(16).padStart(2, '0')).join('');
|
||||||
|
},
|
||||||
|
|
||||||
|
colors: webColors,
|
||||||
|
|
||||||
|
createGuid: () => {
|
||||||
|
return Array.from(window.crypto.getRandomValues(new Uint8Array(16)), b => b.toString(16).padStart(2, '0')).join('');
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
|
@ -18,6 +18,7 @@ import * as crypto from 'crypto';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as util from 'util';
|
import * as util from 'util';
|
||||||
|
import { Readable, Writable, pipeline } from 'stream';
|
||||||
|
|
||||||
import { colors } from '../../utilsBundle';
|
import { colors } from '../../utilsBundle';
|
||||||
import { debugLogger } from './debugLogger';
|
import { debugLogger } from './debugLogger';
|
||||||
|
@ -25,6 +26,9 @@ import { currentZone, emptyZone } from './zones';
|
||||||
|
|
||||||
import type { Platform, Zone } from '../../common/platform';
|
import type { Platform, Zone } from '../../common/platform';
|
||||||
import type { Zone as ZoneImpl } from './zones';
|
import type { Zone as ZoneImpl } from './zones';
|
||||||
|
import type * as channels from '@protocol/channels';
|
||||||
|
|
||||||
|
const pipelineAsync = util.promisify(pipeline);
|
||||||
|
|
||||||
class NodeZone implements Zone {
|
class NodeZone implements Zone {
|
||||||
private _zone: ZoneImpl;
|
private _zone: ZoneImpl;
|
||||||
|
@ -81,8 +85,63 @@ export const nodePlatform: Platform = {
|
||||||
|
|
||||||
pathSeparator: path.sep,
|
pathSeparator: path.sep,
|
||||||
|
|
||||||
|
async streamFile(path: string, stream: Writable): Promise<void> {
|
||||||
|
await pipelineAsync(fs.createReadStream(path), stream);
|
||||||
|
},
|
||||||
|
|
||||||
|
streamReadable: (channel: channels.StreamChannel) => {
|
||||||
|
return new ReadableStreamImpl(channel);
|
||||||
|
},
|
||||||
|
|
||||||
|
streamWritable: (channel: channels.WritableStreamChannel) => {
|
||||||
|
return new WritableStreamImpl(channel);
|
||||||
|
},
|
||||||
|
|
||||||
zones: {
|
zones: {
|
||||||
current: () => new NodeZone(currentZone()),
|
current: () => new NodeZone(currentZone()),
|
||||||
empty: new NodeZone(emptyZone),
|
empty: new NodeZone(emptyZone),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ReadableStreamImpl extends Readable {
|
||||||
|
private _channel: channels.StreamChannel;
|
||||||
|
|
||||||
|
constructor(channel: channels.StreamChannel) {
|
||||||
|
super();
|
||||||
|
this._channel = channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
override async _read() {
|
||||||
|
const result = await this._channel.read({ size: 1024 * 1024 });
|
||||||
|
if (result.binary.byteLength)
|
||||||
|
this.push(result.binary);
|
||||||
|
else
|
||||||
|
this.push(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
override _destroy(error: Error | null, callback: (error: Error | null | undefined) => void): void {
|
||||||
|
// Stream might be destroyed after the connection was closed.
|
||||||
|
this._channel.close().catch(e => null);
|
||||||
|
super._destroy(error, callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class WritableStreamImpl extends Writable {
|
||||||
|
private _channel: channels.WritableStreamChannel;
|
||||||
|
|
||||||
|
constructor(channel: channels.WritableStreamChannel) {
|
||||||
|
super();
|
||||||
|
this._channel = channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
override async _write(chunk: Buffer | string, encoding: BufferEncoding, callback: (error?: Error | null) => void) {
|
||||||
|
const error = await this._channel.write({ binary: typeof chunk === 'string' ? Buffer.from(chunk) : chunk }).catch(e => e);
|
||||||
|
callback(error || null);
|
||||||
|
}
|
||||||
|
|
||||||
|
override async _final(callback: (error?: Error | null) => void) {
|
||||||
|
// Stream might be destroyed after the connection was closed.
|
||||||
|
const error = await this._channel.close().catch(e => e);
|
||||||
|
callback(error || null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue