chore(rpc): remove some paths from the channel (#2934)
This commit is contained in:
parent
cc8fe5a763
commit
d5bd459986
|
|
@ -22,7 +22,6 @@ export type Binary = string;
|
|||
export interface Channel extends EventEmitter {
|
||||
}
|
||||
|
||||
|
||||
export interface PlaywrightChannel extends Channel {
|
||||
}
|
||||
export type PlaywrightInitializer = {
|
||||
|
|
@ -181,8 +180,8 @@ export interface FrameChannel extends Channel {
|
|||
|
||||
evalOnSelector(params: { selector: string; expression: string, isFunction: boolean, arg: any} & PageAttribution): Promise<any>;
|
||||
evalOnSelectorAll(params: { selector: string; expression: string, isFunction: boolean, arg: any} & PageAttribution): Promise<any>;
|
||||
addScriptTag(params: { url?: string | undefined, path?: string | undefined, content?: string | undefined, type?: string | undefined} & PageAttribution): Promise<ElementHandleChannel>;
|
||||
addStyleTag(params: { url?: string | undefined, path?: string | undefined, content?: string | undefined} & PageAttribution): Promise<ElementHandleChannel>;
|
||||
addScriptTag(params: { url?: string, content?: string, type?: string } & PageAttribution): Promise<ElementHandleChannel>;
|
||||
addStyleTag(params: { url?: string, content?: string } & PageAttribution): Promise<ElementHandleChannel>;
|
||||
check(params: { selector: string, force?: boolean, noWaitAfter?: boolean } & types.TimeoutOptions & PageAttribution): Promise<void>;
|
||||
click(params: { selector: string, force?: boolean, noWaitAfter?: boolean } & types.PointerActionOptions & types.MouseClickOptions & types.TimeoutOptions & PageAttribution): Promise<void>;
|
||||
content(): Promise<string>;
|
||||
|
|
@ -352,6 +351,7 @@ export type DialogInitializer = {
|
|||
export interface DownloadChannel extends Channel {
|
||||
path(): Promise<string | null>;
|
||||
failure(): Promise<string | null>;
|
||||
stream(): Promise<StreamChannel | null>;
|
||||
delete(): Promise<void>;
|
||||
}
|
||||
export type DownloadInitializer = {
|
||||
|
|
@ -360,6 +360,13 @@ export type DownloadInitializer = {
|
|||
};
|
||||
|
||||
|
||||
export interface StreamChannel extends Channel {
|
||||
read(params: { size?: number }): Promise<Binary>;
|
||||
}
|
||||
export type StreamInitializer = {
|
||||
}
|
||||
|
||||
|
||||
// Chromium-specific.
|
||||
export interface CDPSessionChannel extends Channel {
|
||||
on(event: 'event', callback: (params: { method: string, params?: Object }) => void): this;
|
||||
|
|
@ -370,7 +377,6 @@ export interface CDPSessionChannel extends Channel {
|
|||
}
|
||||
export type CDPSessionInitializer = {};
|
||||
|
||||
|
||||
export type PDFOptions = {
|
||||
scale?: number,
|
||||
displayHeaderFooter?: boolean,
|
||||
|
|
@ -384,7 +390,6 @@ export type PDFOptions = {
|
|||
height?: string,
|
||||
preferCSSPageSize?: boolean,
|
||||
margin?: {top?: string, bottom?: string, left?: string, right?: string},
|
||||
path?: string,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ import { Channel } from '../channels';
|
|||
import { ChromiumBrowser } from './chromiumBrowser';
|
||||
import { ChromiumBrowserContext } from './chromiumBrowserContext';
|
||||
import { Selectors } from './selectors';
|
||||
import { Stream } from './stream';
|
||||
|
||||
class Root extends ChannelOwner<Channel, {}> {
|
||||
constructor(connection: Connection) {
|
||||
|
|
@ -201,6 +202,9 @@ export class Connection {
|
|||
case 'request':
|
||||
result = new Request(parent, type, guid, initializer);
|
||||
break;
|
||||
case 'stream':
|
||||
result = new Stream(parent, type, guid, initializer);
|
||||
break;
|
||||
case 'response':
|
||||
result = new Response(parent, type, guid, initializer);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -14,10 +14,10 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import * as fs from 'fs';
|
||||
import { DownloadChannel, DownloadInitializer } from '../channels';
|
||||
import { ChannelOwner } from './channelOwner';
|
||||
import { Readable } from 'stream';
|
||||
import { Stream } from './stream';
|
||||
|
||||
export class Download extends ChannelOwner<DownloadChannel, DownloadInitializer> {
|
||||
static from(download: DownloadChannel): Download {
|
||||
|
|
@ -45,8 +45,11 @@ export class Download extends ChannelOwner<DownloadChannel, DownloadInitializer>
|
|||
}
|
||||
|
||||
async createReadStream(): Promise<Readable | null> {
|
||||
const fileName = await this.path();
|
||||
return fileName ? fs.createReadStream(fileName) : null;
|
||||
const s = await this._channel.stream();
|
||||
if (!s)
|
||||
return null;
|
||||
const stream = Stream.from(s);
|
||||
return stream.stream();
|
||||
}
|
||||
|
||||
async delete(): Promise<void> {
|
||||
|
|
|
|||
|
|
@ -22,13 +22,17 @@ import { BrowserContext } from './browserContext';
|
|||
import { ChannelOwner } from './channelOwner';
|
||||
import { ElementHandle, convertSelectOptionValues, convertInputFiles } from './elementHandle';
|
||||
import { JSHandle, Func1, FuncOn, SmartHandle, serializeArgument, parseResult } from './jsHandle';
|
||||
import * as fs from 'fs';
|
||||
import * as network from './network';
|
||||
import * as util from 'util';
|
||||
import { Page } from './page';
|
||||
import { EventEmitter } from 'events';
|
||||
import { Waiter } from './waiter';
|
||||
import { Events } from '../../events';
|
||||
import { TimeoutError } from '../../errors';
|
||||
|
||||
const fsReadFileAsync = util.promisify(fs.readFile.bind(fs));
|
||||
|
||||
export type GotoOptions = types.NavigateOptions & {
|
||||
referer?: string,
|
||||
};
|
||||
|
|
@ -174,10 +178,18 @@ export class Frame extends ChannelOwner<FrameChannel, FrameInitializer> {
|
|||
}
|
||||
|
||||
async addScriptTag(options: { url?: string, path?: string, content?: string, type?: string }): Promise<ElementHandle> {
|
||||
return ElementHandle.from(await this._channel.addScriptTag({ ...options, isPage: this._page!._isPageCall }));
|
||||
const copy = { ...options };
|
||||
if (copy.path) {
|
||||
copy.content = (await fsReadFileAsync(copy.path)).toString();
|
||||
copy.content += '//# sourceURL=' + copy.path.replace(/\n/g, '');
|
||||
}
|
||||
return ElementHandle.from(await this._channel.addScriptTag({ ...copy, isPage: this._page!._isPageCall }));
|
||||
}
|
||||
|
||||
async addStyleTag(options: { url?: string; path?: string; content?: string; }): Promise<ElementHandle> {
|
||||
const copy = { ...options };
|
||||
if (copy.path)
|
||||
copy.content = (await fsReadFileAsync(copy.path)).toString();
|
||||
return ElementHandle.from(await this._channel.addStyleTag({ ...options, isPage: this._page!._isPageCall }));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,6 +39,11 @@ import { Buffer } from 'buffer';
|
|||
import { Coverage } from './coverage';
|
||||
import { Waiter } from './waiter';
|
||||
|
||||
import * as fs from 'fs';
|
||||
import * as util from 'util';
|
||||
|
||||
const fsWriteFileAsync = util.promisify(fs.writeFile.bind(fs));
|
||||
|
||||
export class Page extends ChannelOwner<PageChannel, PageInitializer> {
|
||||
private _browserContext: BrowserContext;
|
||||
_ownedContext: BrowserContext | undefined;
|
||||
|
|
@ -494,7 +499,10 @@ export class Page extends ChannelOwner<PageChannel, PageInitializer> {
|
|||
}
|
||||
|
||||
async _pdf(options: types.PDFOptions = {}): Promise<Buffer> {
|
||||
const path = options.path;
|
||||
const transportOptions: PDFOptions = { ...options } as PDFOptions;
|
||||
if (path)
|
||||
delete (transportOptions as any).path;
|
||||
if (transportOptions.margin)
|
||||
transportOptions.margin = { ...transportOptions.margin };
|
||||
if (typeof options.width === 'number')
|
||||
|
|
@ -507,7 +515,10 @@ export class Page extends ChannelOwner<PageChannel, PageInitializer> {
|
|||
transportOptions.margin![index] = transportOptions.margin![index] + 'px';
|
||||
}
|
||||
const binary = await this._channel.pdf(transportOptions);
|
||||
return Buffer.from(binary, 'base64');
|
||||
const buffer = Buffer.from(binary, 'base64');
|
||||
if (path)
|
||||
await fsWriteFileAsync(path, buffer);
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
50
src/rpc/client/stream.ts
Normal file
50
src/rpc/client/stream.ts
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/**
|
||||
* 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 { Readable } from 'stream';
|
||||
import { StreamChannel, StreamInitializer } from '../channels';
|
||||
import { ChannelOwner } from './channelOwner';
|
||||
|
||||
export class Stream extends ChannelOwner<StreamChannel, StreamInitializer> {
|
||||
static from(Stream: StreamChannel): Stream {
|
||||
return (Stream as any)._object;
|
||||
}
|
||||
|
||||
constructor(parent: ChannelOwner, type: string, guid: string, initializer: StreamInitializer) {
|
||||
super(parent, type, guid, initializer);
|
||||
}
|
||||
|
||||
stream(): Readable {
|
||||
return new StreamImpl(this._channel);
|
||||
}
|
||||
}
|
||||
|
||||
class StreamImpl extends Readable {
|
||||
private _channel: StreamChannel;
|
||||
|
||||
constructor(channel: StreamChannel) {
|
||||
super();
|
||||
this._channel = channel;
|
||||
}
|
||||
|
||||
async _read(size: number) {
|
||||
const data = await this._channel.read({ size });
|
||||
if (data)
|
||||
this.push(Buffer.from(data, 'base64'));
|
||||
else
|
||||
this.push(null);
|
||||
}
|
||||
}
|
||||
|
|
@ -15,8 +15,9 @@
|
|||
*/
|
||||
|
||||
import { Download } from '../../download';
|
||||
import { DownloadChannel, DownloadInitializer } from '../channels';
|
||||
import { DownloadChannel, DownloadInitializer, StreamChannel } from '../channels';
|
||||
import { Dispatcher, DispatcherScope } from './dispatcher';
|
||||
import { StreamDispatcher } from './streamDispatcher';
|
||||
|
||||
export class DownloadDispatcher extends Dispatcher<Download, DownloadInitializer> implements DownloadChannel {
|
||||
constructor(scope: DispatcherScope, download: Download) {
|
||||
|
|
@ -30,6 +31,14 @@ export class DownloadDispatcher extends Dispatcher<Download, DownloadInitializer
|
|||
return this._object.path();
|
||||
}
|
||||
|
||||
async stream(): Promise<StreamChannel | null> {
|
||||
const stream = await this._object.createReadStream();
|
||||
if (!stream)
|
||||
return null;
|
||||
await new Promise(f => stream.on('readable', f));
|
||||
return new StreamDispatcher(this._scope, stream);
|
||||
}
|
||||
|
||||
async failure(): Promise<string | null> {
|
||||
return this._object.failure();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -110,12 +110,12 @@ export class FrameDispatcher extends Dispatcher<Frame, FrameInitializer> impleme
|
|||
await target.setContent(params.html, params);
|
||||
}
|
||||
|
||||
async addScriptTag(params: { url?: string | undefined, path?: string | undefined, content?: string | undefined, type?: string | undefined } & PageAttribution): Promise<ElementHandleChannel> {
|
||||
async addScriptTag(params: { url?: string, content?: string, type?: string } & PageAttribution): Promise<ElementHandleChannel> {
|
||||
const target = params.isPage ? this._frame._page : this._frame;
|
||||
return new ElementHandleDispatcher(this._scope, await target.addScriptTag(params));
|
||||
}
|
||||
|
||||
async addStyleTag(params: { url?: string | undefined, path?: string | undefined, content?: string | undefined } & PageAttribution): Promise<ElementHandleChannel> {
|
||||
async addStyleTag(params: { url?: string, content?: string } & PageAttribution): Promise<ElementHandleChannel> {
|
||||
const target = params.isPage ? this._frame._page : this._frame;
|
||||
return new ElementHandleDispatcher(this._scope, await target.addStyleTag(params));
|
||||
}
|
||||
|
|
|
|||
30
src/rpc/server/streamDispatcher.ts
Normal file
30
src/rpc/server/streamDispatcher.ts
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* 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 { StreamChannel, StreamInitializer } from '../channels';
|
||||
import { Dispatcher, DispatcherScope } from './dispatcher';
|
||||
import * as stream from 'stream';
|
||||
|
||||
export class StreamDispatcher extends Dispatcher<stream.Readable, StreamInitializer> implements StreamChannel {
|
||||
constructor(scope: DispatcherScope, stream: stream.Readable) {
|
||||
super(scope, stream, 'stream', {});
|
||||
}
|
||||
|
||||
async read(params: { size?: number }): Promise<string> {
|
||||
const buffer = this._object.read(Math.min(this._object.readableLength, params.size || this._object.readableLength));
|
||||
return buffer ? buffer.toString('base64') : '';
|
||||
}
|
||||
}
|
||||
|
|
@ -162,7 +162,6 @@ describe('Download', function() {
|
|||
stream.on('data', data => content += data.toString());
|
||||
await new Promise(f => stream.on('end', f));
|
||||
expect(content).toBe('Hello world');
|
||||
stream.close();
|
||||
await page.close();
|
||||
});
|
||||
it('should delete downloads on context destruction', async({browser, server}) => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue