Skip to content

Commit d5bd459

Browse files
authored
chore(rpc): remove some paths from the channel (#2934)
1 parent cc8fe5a commit d5bd459

File tree

10 files changed

+137
-14
lines changed

10 files changed

+137
-14
lines changed

src/rpc/channels.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ export type Binary = string;
2222
export interface Channel extends EventEmitter {
2323
}
2424

25-
2625
export interface PlaywrightChannel extends Channel {
2726
}
2827
export type PlaywrightInitializer = {
@@ -181,8 +180,8 @@ export interface FrameChannel extends Channel {
181180

182181
evalOnSelector(params: { selector: string; expression: string, isFunction: boolean, arg: any} & PageAttribution): Promise<any>;
183182
evalOnSelectorAll(params: { selector: string; expression: string, isFunction: boolean, arg: any} & PageAttribution): Promise<any>;
184-
addScriptTag(params: { url?: string | undefined, path?: string | undefined, content?: string | undefined, type?: string | undefined} & PageAttribution): Promise<ElementHandleChannel>;
185-
addStyleTag(params: { url?: string | undefined, path?: string | undefined, content?: string | undefined} & PageAttribution): Promise<ElementHandleChannel>;
183+
addScriptTag(params: { url?: string, content?: string, type?: string } & PageAttribution): Promise<ElementHandleChannel>;
184+
addStyleTag(params: { url?: string, content?: string } & PageAttribution): Promise<ElementHandleChannel>;
186185
check(params: { selector: string, force?: boolean, noWaitAfter?: boolean } & types.TimeoutOptions & PageAttribution): Promise<void>;
187186
click(params: { selector: string, force?: boolean, noWaitAfter?: boolean } & types.PointerActionOptions & types.MouseClickOptions & types.TimeoutOptions & PageAttribution): Promise<void>;
188187
content(): Promise<string>;
@@ -352,6 +351,7 @@ export type DialogInitializer = {
352351
export interface DownloadChannel extends Channel {
353352
path(): Promise<string | null>;
354353
failure(): Promise<string | null>;
354+
stream(): Promise<StreamChannel | null>;
355355
delete(): Promise<void>;
356356
}
357357
export type DownloadInitializer = {
@@ -360,6 +360,13 @@ export type DownloadInitializer = {
360360
};
361361

362362

363+
export interface StreamChannel extends Channel {
364+
read(params: { size?: number }): Promise<Binary>;
365+
}
366+
export type StreamInitializer = {
367+
}
368+
369+
363370
// Chromium-specific.
364371
export interface CDPSessionChannel extends Channel {
365372
on(event: 'event', callback: (params: { method: string, params?: Object }) => void): this;
@@ -370,7 +377,6 @@ export interface CDPSessionChannel extends Channel {
370377
}
371378
export type CDPSessionInitializer = {};
372379

373-
374380
export type PDFOptions = {
375381
scale?: number,
376382
displayHeaderFooter?: boolean,
@@ -384,7 +390,6 @@ export type PDFOptions = {
384390
height?: string,
385391
preferCSSPageSize?: boolean,
386392
margin?: {top?: string, bottom?: string, left?: string, right?: string},
387-
path?: string,
388393
};
389394

390395

src/rpc/client/connection.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import { Channel } from '../channels';
3737
import { ChromiumBrowser } from './chromiumBrowser';
3838
import { ChromiumBrowserContext } from './chromiumBrowserContext';
3939
import { Selectors } from './selectors';
40+
import { Stream } from './stream';
4041

4142
class Root extends ChannelOwner<Channel, {}> {
4243
constructor(connection: Connection) {
@@ -201,6 +202,9 @@ export class Connection {
201202
case 'request':
202203
result = new Request(parent, type, guid, initializer);
203204
break;
205+
case 'stream':
206+
result = new Stream(parent, type, guid, initializer);
207+
break;
204208
case 'response':
205209
result = new Response(parent, type, guid, initializer);
206210
break;

src/rpc/client/download.ts

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

17-
import * as fs from 'fs';
1817
import { DownloadChannel, DownloadInitializer } from '../channels';
1918
import { ChannelOwner } from './channelOwner';
2019
import { Readable } from 'stream';
20+
import { Stream } from './stream';
2121

2222
export class Download extends ChannelOwner<DownloadChannel, DownloadInitializer> {
2323
static from(download: DownloadChannel): Download {
@@ -45,8 +45,11 @@ export class Download extends ChannelOwner<DownloadChannel, DownloadInitializer>
4545
}
4646

4747
async createReadStream(): Promise<Readable | null> {
48-
const fileName = await this.path();
49-
return fileName ? fs.createReadStream(fileName) : null;
48+
const s = await this._channel.stream();
49+
if (!s)
50+
return null;
51+
const stream = Stream.from(s);
52+
return stream.stream();
5053
}
5154

5255
async delete(): Promise<void> {

src/rpc/client/frame.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,17 @@ import { BrowserContext } from './browserContext';
2222
import { ChannelOwner } from './channelOwner';
2323
import { ElementHandle, convertSelectOptionValues, convertInputFiles } from './elementHandle';
2424
import { JSHandle, Func1, FuncOn, SmartHandle, serializeArgument, parseResult } from './jsHandle';
25+
import * as fs from 'fs';
2526
import * as network from './network';
27+
import * as util from 'util';
2628
import { Page } from './page';
2729
import { EventEmitter } from 'events';
2830
import { Waiter } from './waiter';
2931
import { Events } from '../../events';
3032
import { TimeoutError } from '../../errors';
3133

34+
const fsReadFileAsync = util.promisify(fs.readFile.bind(fs));
35+
3236
export type GotoOptions = types.NavigateOptions & {
3337
referer?: string,
3438
};
@@ -174,10 +178,18 @@ export class Frame extends ChannelOwner<FrameChannel, FrameInitializer> {
174178
}
175179

176180
async addScriptTag(options: { url?: string, path?: string, content?: string, type?: string }): Promise<ElementHandle> {
177-
return ElementHandle.from(await this._channel.addScriptTag({ ...options, isPage: this._page!._isPageCall }));
181+
const copy = { ...options };
182+
if (copy.path) {
183+
copy.content = (await fsReadFileAsync(copy.path)).toString();
184+
copy.content += '//# sourceURL=' + copy.path.replace(/\n/g, '');
185+
}
186+
return ElementHandle.from(await this._channel.addScriptTag({ ...copy, isPage: this._page!._isPageCall }));
178187
}
179188

180189
async addStyleTag(options: { url?: string; path?: string; content?: string; }): Promise<ElementHandle> {
190+
const copy = { ...options };
191+
if (copy.path)
192+
copy.content = (await fsReadFileAsync(copy.path)).toString();
181193
return ElementHandle.from(await this._channel.addStyleTag({ ...options, isPage: this._page!._isPageCall }));
182194
}
183195

src/rpc/client/page.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ import { Buffer } from 'buffer';
3939
import { Coverage } from './coverage';
4040
import { Waiter } from './waiter';
4141

42+
import * as fs from 'fs';
43+
import * as util from 'util';
44+
45+
const fsWriteFileAsync = util.promisify(fs.writeFile.bind(fs));
46+
4247
export class Page extends ChannelOwner<PageChannel, PageInitializer> {
4348
private _browserContext: BrowserContext;
4449
_ownedContext: BrowserContext | undefined;
@@ -494,7 +499,10 @@ export class Page extends ChannelOwner<PageChannel, PageInitializer> {
494499
}
495500

496501
async _pdf(options: types.PDFOptions = {}): Promise<Buffer> {
502+
const path = options.path;
497503
const transportOptions: PDFOptions = { ...options } as PDFOptions;
504+
if (path)
505+
delete (transportOptions as any).path;
498506
if (transportOptions.margin)
499507
transportOptions.margin = { ...transportOptions.margin };
500508
if (typeof options.width === 'number')
@@ -507,7 +515,10 @@ export class Page extends ChannelOwner<PageChannel, PageInitializer> {
507515
transportOptions.margin![index] = transportOptions.margin![index] + 'px';
508516
}
509517
const binary = await this._channel.pdf(transportOptions);
510-
return Buffer.from(binary, 'base64');
518+
const buffer = Buffer.from(binary, 'base64');
519+
if (path)
520+
await fsWriteFileAsync(path, buffer);
521+
return buffer;
511522
}
512523
}
513524

src/rpc/client/stream.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/**
2+
* Copyright (c) Microsoft Corporation.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import { Readable } from 'stream';
18+
import { StreamChannel, StreamInitializer } from '../channels';
19+
import { ChannelOwner } from './channelOwner';
20+
21+
export class Stream extends ChannelOwner<StreamChannel, StreamInitializer> {
22+
static from(Stream: StreamChannel): Stream {
23+
return (Stream as any)._object;
24+
}
25+
26+
constructor(parent: ChannelOwner, type: string, guid: string, initializer: StreamInitializer) {
27+
super(parent, type, guid, initializer);
28+
}
29+
30+
stream(): Readable {
31+
return new StreamImpl(this._channel);
32+
}
33+
}
34+
35+
class StreamImpl extends Readable {
36+
private _channel: StreamChannel;
37+
38+
constructor(channel: StreamChannel) {
39+
super();
40+
this._channel = channel;
41+
}
42+
43+
async _read(size: number) {
44+
const data = await this._channel.read({ size });
45+
if (data)
46+
this.push(Buffer.from(data, 'base64'));
47+
else
48+
this.push(null);
49+
}
50+
}

src/rpc/server/downloadDispatcher.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@
1515
*/
1616

1717
import { Download } from '../../download';
18-
import { DownloadChannel, DownloadInitializer } from '../channels';
18+
import { DownloadChannel, DownloadInitializer, StreamChannel } from '../channels';
1919
import { Dispatcher, DispatcherScope } from './dispatcher';
20+
import { StreamDispatcher } from './streamDispatcher';
2021

2122
export class DownloadDispatcher extends Dispatcher<Download, DownloadInitializer> implements DownloadChannel {
2223
constructor(scope: DispatcherScope, download: Download) {
@@ -30,6 +31,14 @@ export class DownloadDispatcher extends Dispatcher<Download, DownloadInitializer
3031
return this._object.path();
3132
}
3233

34+
async stream(): Promise<StreamChannel | null> {
35+
const stream = await this._object.createReadStream();
36+
if (!stream)
37+
return null;
38+
await new Promise(f => stream.on('readable', f));
39+
return new StreamDispatcher(this._scope, stream);
40+
}
41+
3342
async failure(): Promise<string | null> {
3443
return this._object.failure();
3544
}

src/rpc/server/frameDispatcher.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,12 +110,12 @@ export class FrameDispatcher extends Dispatcher<Frame, FrameInitializer> impleme
110110
await target.setContent(params.html, params);
111111
}
112112

113-
async addScriptTag(params: { url?: string | undefined, path?: string | undefined, content?: string | undefined, type?: string | undefined } & PageAttribution): Promise<ElementHandleChannel> {
113+
async addScriptTag(params: { url?: string, content?: string, type?: string } & PageAttribution): Promise<ElementHandleChannel> {
114114
const target = params.isPage ? this._frame._page : this._frame;
115115
return new ElementHandleDispatcher(this._scope, await target.addScriptTag(params));
116116
}
117117

118-
async addStyleTag(params: { url?: string | undefined, path?: string | undefined, content?: string | undefined } & PageAttribution): Promise<ElementHandleChannel> {
118+
async addStyleTag(params: { url?: string, content?: string } & PageAttribution): Promise<ElementHandleChannel> {
119119
const target = params.isPage ? this._frame._page : this._frame;
120120
return new ElementHandleDispatcher(this._scope, await target.addStyleTag(params));
121121
}

src/rpc/server/streamDispatcher.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/**
2+
* Copyright (c) Microsoft Corporation.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the 'License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import { StreamChannel, StreamInitializer } from '../channels';
18+
import { Dispatcher, DispatcherScope } from './dispatcher';
19+
import * as stream from 'stream';
20+
21+
export class StreamDispatcher extends Dispatcher<stream.Readable, StreamInitializer> implements StreamChannel {
22+
constructor(scope: DispatcherScope, stream: stream.Readable) {
23+
super(scope, stream, 'stream', {});
24+
}
25+
26+
async read(params: { size?: number }): Promise<string> {
27+
const buffer = this._object.read(Math.min(this._object.readableLength, params.size || this._object.readableLength));
28+
return buffer ? buffer.toString('base64') : '';
29+
}
30+
}

test/download.spec.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,6 @@ describe('Download', function() {
162162
stream.on('data', data => content += data.toString());
163163
await new Promise(f => stream.on('end', f));
164164
expect(content).toBe('Hello world');
165-
stream.close();
166165
await page.close();
167166
});
168167
it('should delete downloads on context destruction', async({browser, server}) => {

0 commit comments

Comments
 (0)