Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
fix: improve TS types for launching browsers (#6888)
This commit tidies up the quite confusing state of all the various types
required to launch a browser. As we saw when upgrading DevTools
(https://source.chromium.org/chromium/chromium/src/+/master:third_party/devtools-frontend/src/test/conductor/hooks.ts;l=77),
we had to define our launch options variable like so:

```ts
const opts: puppeteer.LaunchOptions & puppeteer.ChromeArgOptions & puppeteer.BrowserOptions = {
  ...
};
```

This commit fixes that by introducing `AllNodeLaunchOptions`, which is
defined as the intersection of all the above types.

Additionally, the types defined as `ChromeArgOptions` are actually used
for launching both Chrome and Firefox, so I have renamed them to
`BrowserArgOptions`, and therefore this change is breaking because
anyone using `ChromeArgOptions` in their types will need to switch.

BREAKING CHANGE: renamed type `ChromeArgOptions` to `BrowserLaunchArgumentOptions`
BREAKING CHANGE: renamed type `BrowserOptions` to `BrowserConnectOptions`
  • Loading branch information
jackfranklin committed Feb 16, 2021
1 parent be7c229 commit 98c8145
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 36 deletions.
11 changes: 7 additions & 4 deletions src/api-docs-entry.ts
Expand Up @@ -14,8 +14,11 @@
* limitations under the License.
*/

import { LaunchOptions, ChromeArgOptions } from './node/LaunchOptions.js';
import { BrowserOptions } from './common/BrowserConnector.js';
import {
LaunchOptions,
BrowserLaunchArgumentOptions,
} from './node/LaunchOptions.js';
import { BrowserConnectOptions } from './common/BrowserConnector.js';
import { Product } from './common/Product.js';
import { Browser } from './common/Browser.js';
import { ConnectOptions } from './common/Puppeteer.js';
Expand Down Expand Up @@ -95,8 +98,8 @@ export * from 'devtools-protocol/types/protocol';
*/
export declare function launch(
options?: LaunchOptions &
ChromeArgOptions &
BrowserOptions & {
BrowserLaunchArgumentOptions &
BrowserConnectOptions & {
product?: Product;
extraPrefsFirefox?: Record<string, unknown>;
}
Expand Down
18 changes: 15 additions & 3 deletions src/common/BrowserConnector.ts
Expand Up @@ -24,12 +24,24 @@ import { Viewport } from './PuppeteerViewport.js';
import { isNode } from '../environment.js';

/**
* Generic browser options that can be passed when launching any browser.
* Generic browser options that can be passed when launching any browser or when
* connecting to an existing browser instance.
* @public
*/
export interface BrowserOptions {
export interface BrowserConnectOptions {
/**
* Whether to ignore HTTPS errors during navigation.
* @defaultValue false
*/
ignoreHTTPSErrors?: boolean;
/**
* Sets the viewport for each page.
*/
defaultViewport?: Viewport;
/**
* Slows down Puppeteer operations by the specified amount of milliseconds to
* aid debugging.
*/
slowMo?: number;
}

Expand All @@ -46,7 +58,7 @@ const getWebSocketTransportClass = async () => {
* @internal
*/
export const connectToBrowser = async (
options: BrowserOptions & {
options: BrowserConnectOptions & {
browserWSEndpoint?: string;
browserURL?: string;
transport?: ConnectionTransport;
Expand Down
4 changes: 2 additions & 2 deletions src/common/Puppeteer.ts
Expand Up @@ -25,7 +25,7 @@ import {
CustomQueryHandler,
} from './QueryHandler.js';
import { Product } from './Product.js';
import { connectToBrowser, BrowserOptions } from './BrowserConnector.js';
import { connectToBrowser, BrowserConnectOptions } from './BrowserConnector.js';
import {
PredefinedNetworkConditions,
networkConditions,
Expand All @@ -39,7 +39,7 @@ export interface CommonPuppeteerSettings {
isPuppeteerCore: boolean;
}

export interface ConnectOptions extends BrowserOptions {
export interface ConnectOptions extends BrowserConnectOptions {
browserWSEndpoint?: string;
browserURL?: string;
transport?: ConnectionTransport;
Expand Down
84 changes: 82 additions & 2 deletions src/node/LaunchOptions.ts
Expand Up @@ -13,30 +13,110 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { BrowserConnectOptions } from '../common/BrowserConnector.js';
import { Product } from '../common/Product.js';

/**
* Launcher options that only apply to Chrome.
*
* @public
*/
export interface ChromeArgOptions {
export interface BrowserLaunchArgumentOptions {
/**
* Whether to run the browser in headless mode.
* @defaultValue true
*/
headless?: boolean;
args?: string[];
/**
* Path to a user data directory.
* {@link https://chromium.googlesource.com/chromium/src/+/master/docs/user_data_dir.md | see the Chromium docs}
* for more info.
*/
userDataDir?: string;
/**
* Whether to auto-open a DevTools panel for each tab. If this is set to
* `true`, then `headless` will be set to `false` automatically.
* @defaultValue `false`
*/
devtools?: boolean;
/**
* Additional command line arguments to pass to the browser instance.
*/
args?: string[];
}

/**
* Generic launch options that can be passed when launching any browser.
* @public
*/
export interface LaunchOptions {
/**
* Path to a browser executable to use instead of the bundled Chromium. Note
* that Puppeteer is only guaranteed to work with the bundled Chromium, so use
* this setting at your own risk.
*/
executablePath?: string;
/**
* If `true`, do not use `puppeteer.defaultArgs()` when creating a browser. If
* an array is provided, these args will be filtered out. Use this with care -
* you probably want the default arguments Puppeteer uses.
* @defaultValue false
*/
ignoreDefaultArgs?: boolean | string[];
/**
* Close the browser process on `Ctrl+C`.
* @defaultValue `true`
*/
handleSIGINT?: boolean;
/**
* Close the browser process on `SIGTERM`.
* @defaultValue `true`
*/
handleSIGTERM?: boolean;
/**
* Close the browser process on `SIGHUP`.
* @defaultValue `true`
*/
handleSIGHUP?: boolean;
/**
* Maximum time in milliseconds to wait for the browser to start.
* Pass `0` to disable the timeout.
* @defaultValue 30000 (30 seconds).
*/
timeout?: number;
/**
* If true, pipes the browser process stdout and stderr to `process.stdout`
* and `process.stderr`.
* @defaultValue false
*/
dumpio?: boolean;
/**
* Specify environment variables that will be visible to the browser.
* @defaultValue The contents of `process.env`.
*/
env?: Record<string, string | undefined>;
/**
* Connect to a browser over a pipe instead of a WebSocket.
* @defaultValue false
*/
pipe?: boolean;
/**
* Which browser to launch.
* @defaultValue `chrome`
*/
product?: Product;
/**
* {@link https://developer.mozilla.org/en-US/docs/Mozilla/Preferences/Preference_reference | Additional preferences } that can be passed when launching with Firefox.
*/
extraPrefsFirefox?: Record<string, unknown>;
}

/**
* Utility type exposed to enable users to define options that can be passed to
* `puppeteer.launch` without having to list the set of all types.
* @public
*/
export type PuppeteerNodeLaunchOptions = BrowserLaunchArgumentOptions &
LaunchOptions &
BrowserConnectOptions;
30 changes: 10 additions & 20 deletions src/node/Launcher.ts
Expand Up @@ -25,18 +25,20 @@ import { promisify } from 'util';
const mkdtempAsync = promisify(fs.mkdtemp);
const writeFileAsync = promisify(fs.writeFile);

import { ChromeArgOptions, LaunchOptions } from './LaunchOptions.js';
import { BrowserOptions } from '../common/BrowserConnector.js';
import {
BrowserLaunchArgumentOptions,
PuppeteerNodeLaunchOptions,
} from './LaunchOptions.js';
import { Product } from '../common/Product.js';

/**
* Describes a launcher - a class that is able to create and launch a browser instance.
* @public
*/
export interface ProductLauncher {
launch(object);
launch(object: PuppeteerNodeLaunchOptions);
executablePath: () => string;
defaultArgs(object);
defaultArgs(object: BrowserLaunchArgumentOptions);
product: Product;
}

Expand All @@ -58,9 +60,7 @@ class ChromeLauncher implements ProductLauncher {
this._isPuppeteerCore = isPuppeteerCore;
}

async launch(
options: LaunchOptions & ChromeArgOptions & BrowserOptions = {}
): Promise<Browser> {
async launch(options: PuppeteerNodeLaunchOptions = {}): Promise<Browser> {
const {
ignoreDefaultArgs = false,
args = [],
Expand Down Expand Up @@ -152,11 +152,7 @@ class ChromeLauncher implements ProductLauncher {
}
}

/**
* @param {!Launcher.ChromeArgOptions=} options
* @returns {!Array<string>}
*/
defaultArgs(options: ChromeArgOptions = {}): string[] {
defaultArgs(options: BrowserLaunchArgumentOptions = {}): string[] {
const chromeArguments = [
'--disable-background-networking',
'--enable-features=NetworkService,NetworkServiceInProcess',
Expand Down Expand Up @@ -230,13 +226,7 @@ class FirefoxLauncher implements ProductLauncher {
this._isPuppeteerCore = isPuppeteerCore;
}

async launch(
options: LaunchOptions &
ChromeArgOptions &
BrowserOptions & {
extraPrefsFirefox?: { [x: string]: unknown };
} = {}
): Promise<Browser> {
async launch(options: PuppeteerNodeLaunchOptions = {}): Promise<Browser> {
const {
ignoreDefaultArgs = false,
args = [],
Expand Down Expand Up @@ -346,7 +336,7 @@ class FirefoxLauncher implements ProductLauncher {
return 'firefox';
}

defaultArgs(options: ChromeArgOptions = {}): string[] {
defaultArgs(options: BrowserLaunchArgumentOptions = {}): string[] {
const firefoxArguments = ['--no-remote', '--foreground'];
if (os.platform().startsWith('win')) {
firefoxArguments.push('--wait-for-browser');
Expand Down
13 changes: 8 additions & 5 deletions src/node/Puppeteer.ts
Expand Up @@ -20,8 +20,11 @@ import {
ConnectOptions,
} from '../common/Puppeteer.js';
import { BrowserFetcher, BrowserFetcherOptions } from './BrowserFetcher.js';
import { LaunchOptions, ChromeArgOptions } from './LaunchOptions.js';
import { BrowserOptions } from '../common/BrowserConnector.js';
import {
LaunchOptions,
BrowserLaunchArgumentOptions,
} from './LaunchOptions.js';
import { BrowserConnectOptions } from '../common/BrowserConnector.js';
import { Browser } from '../common/Browser.js';
import Launcher, { ProductLauncher } from './Launcher.js';
import { PUPPETEER_REVISIONS } from '../revisions.js';
Expand Down Expand Up @@ -146,8 +149,8 @@ export class PuppeteerNode extends Puppeteer {
*/
launch(
options: LaunchOptions &
ChromeArgOptions &
BrowserOptions & {
BrowserLaunchArgumentOptions &
BrowserConnectOptions & {
product?: Product;
extraPrefsFirefox?: Record<string, unknown>;
} = {}
Expand Down Expand Up @@ -215,7 +218,7 @@ export class PuppeteerNode extends Puppeteer {
* @param options - Set of configurable options to set on the browser.
* @returns The default flags that Chromium will be launched with.
*/
defaultArgs(options: ChromeArgOptions = {}): string[] {
defaultArgs(options: BrowserLaunchArgumentOptions = {}): string[] {
return this._launcher.defaultArgs(options);
}

Expand Down

0 comments on commit 98c8145

Please sign in to comment.