From 5d270148ad92b1837a6d1ff1d7a4fd68af33e6d0 Mon Sep 17 00:00:00 2001 From: Alex Rudenko Date: Fri, 4 Feb 2022 20:42:15 +0100 Subject: [PATCH 1/5] chore: remove commit lint from pull requests (#7957) --- .github/workflows/main.yml | 5 +++++ package.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 94aee81c68343..ec09a4a8c83fb 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -50,6 +50,11 @@ jobs: npm run ensure-correct-devtools-protocol-revision npm run test-types-file + - name: Run commit lint + run: | + npm run commitlint + if: github.event_name != 'pull_request' + - name: Run unit tests uses: nick-invision/retry@v2 env: diff --git a/package.json b/package.json index 08e44d153de38..09531729a0b44 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "commitlint": "commitlint --from=HEAD~1", "markdownlint": "prettier --check **/README.md docs/troubleshooting.md", "markdownlint-fix": "prettier --write **/README.md docs/troubleshooting.md", - "lint": "npm run eslint && npm run build && npm run doc && npm run commitlint && npm run markdownlint", + "lint": "npm run eslint && npm run build && npm run doc && npm run markdownlint", "doc": "node utils/doclint/cli.js", "clean-lib": "rimraf lib", "build": "npm run tsc && npm run generate-d-ts", From c3a0895a7a626c7936c81039bd25eca31cc70752 Mon Sep 17 00:00:00 2001 From: Alex Rudenko Date: Mon, 7 Feb 2022 12:59:44 +0100 Subject: [PATCH 2/5] fix: make projectRoot optional in Puppeteer and launchers (#7967) --- src/initialize-node.ts | 4 ---- src/node/Launcher.ts | 20 +++++++++++++++----- src/node/Puppeteer.ts | 9 +++++++-- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/initialize-node.ts b/src/initialize-node.ts index de1c7fc43a162..e5336654034d4 100644 --- a/src/initialize-node.ts +++ b/src/initialize-node.ts @@ -34,10 +34,6 @@ export const initializePuppeteerNode = (packageName: string): PuppeteerNode => { if (!isPuppeteerCore && productName === 'firefox') preferredRevision = PUPPETEER_REVISIONS.firefox; - if (!puppeteerRootDirectory) { - throw new Error('puppeteerRootDirectory is not found.'); - } - return new PuppeteerNode({ projectRoot: puppeteerRootDirectory, preferredRevision, diff --git a/src/node/Launcher.ts b/src/node/Launcher.ts index 2f76dbf6bb1de..4c87f0dbd43e9 100644 --- a/src/node/Launcher.ts +++ b/src/node/Launcher.ts @@ -52,12 +52,12 @@ export interface ProductLauncher { * @internal */ class ChromeLauncher implements ProductLauncher { - _projectRoot: string; + _projectRoot: string | undefined; _preferredRevision: string; _isPuppeteerCore: boolean; constructor( - projectRoot: string, + projectRoot: string | undefined, preferredRevision: string, isPuppeteerCore: boolean ) { @@ -276,12 +276,12 @@ class ChromeLauncher implements ProductLauncher { * @internal */ class FirefoxLauncher implements ProductLauncher { - _projectRoot: string; + _projectRoot: string | undefined; _preferredRevision: string; _isPuppeteerCore: boolean; constructor( - projectRoot: string, + projectRoot: string | undefined, preferredRevision: string, isPuppeteerCore: boolean ) { @@ -428,6 +428,11 @@ class FirefoxLauncher implements ProductLauncher { async _updateRevision(): Promise { // replace 'latest' placeholder with actual downloaded revision if (this._preferredRevision === 'latest') { + if (!this._projectRoot) { + throw new Error( + '_projectRoot is undefined. Unable to create a BrowserFetcher.' + ); + } const browserFetcher = new BrowserFetcher(this._projectRoot, { product: this.product, }); @@ -813,6 +818,11 @@ function resolveExecutablePath(launcher: ChromeLauncher | FirefoxLauncher): { process.env.npm_config_puppeteer_download_path || process.env.npm_package_config_puppeteer_download_path; } + if (!launcher._projectRoot) { + throw new Error( + '_projectRoot is undefined. Unable to create a BrowserFetcher.' + ); + } const browserFetcher = new BrowserFetcher(launcher._projectRoot, { product: launcher.product, path: downloadPath, @@ -845,7 +855,7 @@ function resolveExecutablePath(launcher: ChromeLauncher | FirefoxLauncher): { * @internal */ export default function Launcher( - projectRoot: string, + projectRoot: string | undefined, preferredRevision: string, isPuppeteerCore: boolean, product?: string diff --git a/src/node/Puppeteer.ts b/src/node/Puppeteer.ts index 38799f20967b2..13aa85ee8bc8d 100644 --- a/src/node/Puppeteer.ts +++ b/src/node/Puppeteer.ts @@ -67,7 +67,7 @@ import { Product } from '../common/Product.js'; */ export class PuppeteerNode extends Puppeteer { private _lazyLauncher?: ProductLauncher; - private _projectRoot: string; + private _projectRoot?: string; private __productName?: Product; /** * @internal @@ -79,7 +79,7 @@ export class PuppeteerNode extends Puppeteer { */ constructor( settings: { - projectRoot: string; + projectRoot?: string; preferredRevision: string; productName?: Product; } & CommonPuppeteerSettings @@ -224,6 +224,11 @@ export class PuppeteerNode extends Puppeteer { * @returns A new BrowserFetcher instance. */ createBrowserFetcher(options: BrowserFetcherOptions): BrowserFetcher { + if (!this._projectRoot) { + throw new Error( + '_projectRoot is undefined. Unable to create a BrowserFetcher.' + ); + } return new BrowserFetcher(this._projectRoot, options); } } From bca8388ff27148eda83ca478f2459d8ecba7b84f Mon Sep 17 00:00:00 2001 From: Alex Rudenko Date: Mon, 7 Feb 2022 14:03:54 +0100 Subject: [PATCH 3/5] fix: typos in documentation (#7968) --- docs/api.md | 10 +++++----- examples/oopif.js | 2 +- experimental/puppeteer-firefox/lib/BrowserFetcher.js | 2 +- src/common/Puppeteer.ts | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/api.md b/docs/api.md index f0261ff92b2f1..991b5a99b297e 100644 --- a/docs/api.md +++ b/docs/api.md @@ -4644,9 +4644,9 @@ This method returns boxes of the element, or `null` if the element is not visibl - `button` <"left"|"right"|"middle"> Defaults to `left`. - `clickCount` <[number]> defaults to 1. See [UIEvent.detail]. - `delay` <[number]> Time to wait between `mousedown` and `mouseup` in milliseconds. Defaults to 0. - - `offset` <[Object]> Offset in pixels relative to the top-left corder of the border box of the element. - - `x` x-offset in pixels relative to the top-left corder of the border box of the element. - - `y` y-offset in pixels relative to the top-left corder of the border box of the element. + - `offset` <[Object]> Offset in pixels relative to the top-left corner of the border box of the element. + - `x` x-offset in pixels relative to the top-left corner of the border box of the element. + - `y` y-offset in pixels relative to the top-left corner of the border box of the element. - returns: <[Promise]> Promise which resolves when the element is successfully clicked. Promise gets rejected if the element is detached from DOM. This method scrolls element into view if needed, and then uses [page.mouse](#pagemouse) to click in the center of the element. @@ -4655,8 +4655,8 @@ If the element is detached from DOM, the method throws an error. #### elementHandle.clickablePoint([offset]) - `offset` <[Object]> - - `x` x-offset in pixels relative to the top-left corder of the border box of the element. - - `y` y-offset in pixels relative to the top-left corder of the border box of the element. + - `x` x-offset in pixels relative to the top-left corner of the border box of the element. + - `y` y-offset in pixels relative to the top-left corner of the border box of the element. - returns: <[Promise<[Point]>]> Resolves to the x, y point that describes the element's position. #### elementHandle.contentFrame() diff --git a/examples/oopif.js b/examples/oopif.js index 52e2047b31d37..7a8f8e061fb0a 100644 --- a/examples/oopif.js +++ b/examples/oopif.js @@ -39,7 +39,7 @@ async function attachFrame(frameId, url) { await page.evaluateHandle(attachFrame, 'frame1', 'https://example.com/'); // At this point there should be a message in the output: - // puppeteer:frame The frame '...' moved to another session. Out-of-proccess + // puppeteer:frame The frame '...' moved to another session. Out-of-process // iframes (OOPIF) are not supported by Puppeteer yet. // https://github.com/puppeteer/puppeteer/issues/2548 diff --git a/experimental/puppeteer-firefox/lib/BrowserFetcher.js b/experimental/puppeteer-firefox/lib/BrowserFetcher.js index 3371f7ef5dd0d..cbd4aa42fc9cf 100644 --- a/experimental/puppeteer-firefox/lib/BrowserFetcher.js +++ b/experimental/puppeteer-firefox/lib/BrowserFetcher.js @@ -102,7 +102,7 @@ class BrowserFetcher { */ constructor(projectRoot, options = {}) { this._product = (options.product || 'chromium').toLowerCase(); - assert(this._product === 'chromium' || this._product === 'firefox', `Unkown product: "${options.product}"`); + assert(this._product === 'chromium' || this._product === 'firefox', `Unknown product: "${options.product}"`); this._downloadsFolder = options.path || path.join(projectRoot, '.local-browser'); this._downloadHost = options.host || downloadURLs[this._product].host; this._platform = options.platform || ''; diff --git a/src/common/Puppeteer.ts b/src/common/Puppeteer.ts index 17f9793e038ec..6522dcc46825e 100644 --- a/src/common/Puppeteer.ts +++ b/src/common/Puppeteer.ts @@ -32,7 +32,7 @@ import { } from './NetworkConditions.js'; /** - * Settings that are common to the Puppeteer class, regardless of enviroment. + * Settings that are common to the Puppeteer class, regardless of environment. * @internal */ export interface CommonPuppeteerSettings { From 6dc0e736548092eeae0b5bf135b2358c49c20b92 Mon Sep 17 00:00:00 2001 From: Alex Rudenko Date: Mon, 7 Feb 2022 15:35:33 +0100 Subject: [PATCH 4/5] chore(release): mark v13.2.0 (#7970) --- CHANGELOG.md | 15 +++++++++++++++ README.md | 22 +++++++++++----------- docs/api.md | 3 ++- package.json | 2 +- versions.js | 2 +- 5 files changed, 30 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d402fd595d06f..052986418bae1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,21 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [13.2.0](https://github.com/puppeteer/puppeteer/compare/v13.1.3...v13.2.0) (2022-02-07) + + +### Features + +* add more models to DeviceDescriptors ([#7904](https://github.com/puppeteer/puppeteer/issues/7904)) ([6a655cb](https://github.com/puppeteer/puppeteer/commit/6a655cb647e12eaf1055be0b298908d83bebac25)) +* **chromium:** roll to Chromium 99.0.4844.16 (r961656) ([#7960](https://github.com/puppeteer/puppeteer/issues/7960)) ([96c3f94](https://github.com/puppeteer/puppeteer/commit/96c3f943b2f6e26bd871ecfcce71b6a33e214ebf)) + + +### Bug Fixes + +* make projectRoot optional in Puppeteer and launchers ([#7967](https://github.com/puppeteer/puppeteer/issues/7967)) ([9afdc63](https://github.com/puppeteer/puppeteer/commit/9afdc6300b80f01091dc4cb42d4ebe952c7d60f0)) +* migrate more files to strict-mode TypeScript ([#7950](https://github.com/puppeteer/puppeteer/issues/7950)) ([aaac8d9](https://github.com/puppeteer/puppeteer/commit/aaac8d9c44327a2c503ffd6c97b7f21e8010c3e4)) +* typos in documentation ([#7968](https://github.com/puppeteer/puppeteer/issues/7968)) ([41ab4e9](https://github.com/puppeteer/puppeteer/commit/41ab4e9127df64baa6c43ecde2f7ddd702ba7b0c)) + ### [13.1.3](https://github.com/puppeteer/puppeteer/compare/v13.1.2...v13.1.3) (2022-01-31) diff --git a/README.md b/README.md index a442d17f7ea77..e0f7ef577fbdf 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ -###### [API](https://github.com/puppeteer/puppeteer/blob/v13.1.3/docs/api.md) | [FAQ](#faq) | [Contributing](https://github.com/puppeteer/puppeteer/blob/main/CONTRIBUTING.md) | [Troubleshooting](https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md) +###### [API](https://github.com/puppeteer/puppeteer/blob/v13.2.0/docs/api.md) | [FAQ](#faq) | [Contributing](https://github.com/puppeteer/puppeteer/blob/main/CONTRIBUTING.md) | [Troubleshooting](https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md) > Puppeteer is a Node library which provides a high-level API to control Chrome or Chromium over the [DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/). Puppeteer runs [headless](https://developers.google.com/web/updates/2017/04/headless-chrome) by default, but can be configured to run full (non-headless) Chrome or Chromium. @@ -39,7 +39,7 @@ npm i puppeteer # or "yarn add puppeteer" ``` -Note: When you install Puppeteer, it downloads a recent version of Chromium (~170MB Mac, ~282MB Linux, ~280MB Win) that is guaranteed to work with the API. To skip the download, download into another path, or download a different browser, see [Environment variables](https://github.com/puppeteer/puppeteer/blob/v13.1.3/docs/api.md#environment-variables). +Note: When you install Puppeteer, it downloads a recent version of Chromium (~170MB Mac, ~282MB Linux, ~280MB Win) that is guaranteed to work with the API. To skip the download, download into another path, or download a different browser, see [Environment variables](https://github.com/puppeteer/puppeteer/blob/v13.2.0/docs/api.md#environment-variables). ### puppeteer-core @@ -64,7 +64,7 @@ Note: Prior to v1.18.1, Puppeteer required at least Node v6.4.0. Versions from v Node 8.9.0+. Starting from v3.0.0 Puppeteer starts to rely on Node 10.18.1+. All examples below use async/await which is only supported in Node v7.6.0 or greater. Puppeteer will be familiar to people using other browser testing frameworks. You create an instance -of `Browser`, open pages, and then manipulate them with [Puppeteer's API](https://github.com/puppeteer/puppeteer/blob/v13.1.3/docs/api.md#). +of `Browser`, open pages, and then manipulate them with [Puppeteer's API](https://github.com/puppeteer/puppeteer/blob/v13.2.0/docs/api.md#). **Example** - navigating to https://example.com and saving a screenshot as _example.png_: @@ -89,7 +89,7 @@ Execute script on the command line node example.js ``` -Puppeteer sets an initial page size to 800×600px, which defines the screenshot size. The page size can be customized with [`Page.setViewport()`](https://github.com/puppeteer/puppeteer/blob/v13.1.3/docs/api.md#pagesetviewportviewport). +Puppeteer sets an initial page size to 800×600px, which defines the screenshot size. The page size can be customized with [`Page.setViewport()`](https://github.com/puppeteer/puppeteer/blob/v13.2.0/docs/api.md#pagesetviewportviewport). **Example** - create a PDF. @@ -116,7 +116,7 @@ Execute script on the command line node hn.js ``` -See [`Page.pdf()`](https://github.com/puppeteer/puppeteer/blob/v13.1.3/docs/api.md#pagepdfoptions) for more information about creating pdfs. +See [`Page.pdf()`](https://github.com/puppeteer/puppeteer/blob/v13.2.0/docs/api.md#pagepdfoptions) for more information about creating pdfs. **Example** - evaluate script in the context of the page @@ -151,7 +151,7 @@ Execute script on the command line node get-dimensions.js ``` -See [`Page.evaluate()`](https://github.com/puppeteer/puppeteer/blob/v13.1.3/docs/api.md#pageevaluatepagefunction-args) for more information on `evaluate` and related methods like `evaluateOnNewDocument` and `exposeFunction`. +See [`Page.evaluate()`](https://github.com/puppeteer/puppeteer/blob/v13.2.0/docs/api.md#pageevaluatepagefunction-args) for more information on `evaluate` and related methods like `evaluateOnNewDocument` and `exposeFunction`. @@ -161,7 +161,7 @@ See [`Page.evaluate()`](https://github.com/puppeteer/puppeteer/blob/v13.1.3/docs **1. Uses Headless mode** -Puppeteer launches Chromium in [headless mode](https://developers.google.com/web/updates/2017/04/headless-chrome). To launch a full version of Chromium, set the [`headless` option](https://github.com/puppeteer/puppeteer/blob/v13.1.3/docs/api.md#puppeteerlaunchoptions) when launching a browser: +Puppeteer launches Chromium in [headless mode](https://developers.google.com/web/updates/2017/04/headless-chrome). To launch a full version of Chromium, set the [`headless` option](https://github.com/puppeteer/puppeteer/blob/v13.2.0/docs/api.md#puppeteerlaunchoptions) when launching a browser: ```js const browser = await puppeteer.launch({ headless: false }); // default is true @@ -177,7 +177,7 @@ pass in the executable's path when creating a `Browser` instance: const browser = await puppeteer.launch({ executablePath: '/path/to/Chrome' }); ``` -You can also use Puppeteer with Firefox Nightly (experimental support). See [`Puppeteer.launch()`](https://github.com/puppeteer/puppeteer/blob/v13.1.3/docs/api.md#puppeteerlaunchoptions) for more information. +You can also use Puppeteer with Firefox Nightly (experimental support). See [`Puppeteer.launch()`](https://github.com/puppeteer/puppeteer/blob/v13.2.0/docs/api.md#puppeteerlaunchoptions) for more information. See [`this article`](https://www.howtogeek.com/202825/what%E2%80%99s-the-difference-between-chromium-and-chrome/) for a description of the differences between Chromium and Chrome. [`This article`](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/chromium_browser_vs_google_chrome.md) describes some differences for Linux users. @@ -189,7 +189,7 @@ Puppeteer creates its own browser user profile which it **cleans up on every run ## Resources -- [API Documentation](https://github.com/puppeteer/puppeteer/blob/v13.1.3/docs/api.md) +- [API Documentation](https://github.com/puppeteer/puppeteer/blob/v13.2.0/docs/api.md) - [Examples](https://github.com/puppeteer/puppeteer/tree/main/examples/) - [Community list of Puppeteer resources](https://github.com/transitive-bullshit/awesome-puppeteer) @@ -331,7 +331,7 @@ See [Contributing](https://github.com/puppeteer/puppeteer/blob/main/CONTRIBUTING Official Firefox support is currently experimental. The ongoing collaboration with Mozilla aims to support common end-to-end testing use cases, for which developers expect cross-browser coverage. The Puppeteer team needs input from users to stabilize Firefox support and to bring missing APIs to our attention. -From Puppeteer v2.1.0 onwards you can specify [`puppeteer.launch({product: 'firefox'})`](https://github.com/puppeteer/puppeteer/blob/v13.1.3/docs/api.md#puppeteerlaunchoptions) to run your Puppeteer scripts in Firefox Nightly, without any additional custom patches. While [an older experiment](https://www.npmjs.com/package/puppeteer-firefox) required a patched version of Firefox, [the current approach](https://wiki.mozilla.org/Remote) works with “stock” Firefox. +From Puppeteer v2.1.0 onwards you can specify [`puppeteer.launch({product: 'firefox'})`](https://github.com/puppeteer/puppeteer/blob/v13.2.0/docs/api.md#puppeteerlaunchoptions) to run your Puppeteer scripts in Firefox Nightly, without any additional custom patches. While [an older experiment](https://www.npmjs.com/package/puppeteer-firefox) required a patched version of Firefox, [the current approach](https://wiki.mozilla.org/Remote) works with “stock” Firefox. We will continue to collaborate with other browser vendors to bring Puppeteer support to browsers such as Safari. This effort includes exploration of a standard for executing cross-browser commands (instead of relying on the non-standard DevTools Protocol used by Chrome). @@ -431,7 +431,7 @@ await page.evaluate(() => { You may find that Puppeteer does not behave as expected when controlling pages that incorporate audio and video. (For example, [video playback/screenshots is likely to fail](https://github.com/puppeteer/puppeteer/issues/291).) There are two reasons for this: -- Puppeteer is bundled with Chromium — not Chrome — and so by default, it inherits all of [Chromium's media-related limitations](https://www.chromium.org/audio-video). This means that Puppeteer does not support licensed formats such as AAC or H.264. (However, it is possible to force Puppeteer to use a separately-installed version Chrome instead of Chromium via the [`executablePath` option to `puppeteer.launch`](https://github.com/puppeteer/puppeteer/blob/v13.1.3/docs/api.md#puppeteerlaunchoptions). You should only use this configuration if you need an official release of Chrome that supports these media formats.) +- Puppeteer is bundled with Chromium — not Chrome — and so by default, it inherits all of [Chromium's media-related limitations](https://www.chromium.org/audio-video). This means that Puppeteer does not support licensed formats such as AAC or H.264. (However, it is possible to force Puppeteer to use a separately-installed version Chrome instead of Chromium via the [`executablePath` option to `puppeteer.launch`](https://github.com/puppeteer/puppeteer/blob/v13.2.0/docs/api.md#puppeteerlaunchoptions). You should only use this configuration if you need an official release of Chrome that supports these media formats.) - Since Puppeteer (in all configurations) controls a desktop version of Chromium/Chrome, features that are only supported by the mobile version of Chrome are not supported. This means that Puppeteer [does not support HTTP Live Streaming (HLS)](https://caniuse.com/#feat=http-live-streaming). #### Q: I am having trouble installing / running Puppeteer in my test environment. Where should I look for help? diff --git a/docs/api.md b/docs/api.md index 991b5a99b297e..499aa74570f38 100644 --- a/docs/api.md +++ b/docs/api.md @@ -1,4 +1,4 @@ -# Puppeteer API Tip-Of-Tree +# Puppeteer API v13.2.0 @@ -10,6 +10,7 @@ - Releases per Chromium version: + * Chromium 99.0.4844.16 - [Puppeteer v13.2.0](https://github.com/puppeteer/puppeteer/blob/v13.2.0/docs/api.md) * Chromium 98.0.4758.0 - [Puppeteer v13.1.0](https://github.com/puppeteer/puppeteer/blob/v13.1.0/docs/api.md) * Chromium 97.0.4692.0 - [Puppeteer v12.0.0](https://github.com/puppeteer/puppeteer/blob/v12.0.0/docs/api.md) * Chromium 93.0.4577.0 - [Puppeteer v10.2.0](https://github.com/puppeteer/puppeteer/blob/v10.2.0/docs/api.md) diff --git a/package.json b/package.json index 09531729a0b44..18a1c99337f8f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "puppeteer", - "version": "13.1.3-post", + "version": "13.2.0", "description": "A high-level API to control headless Chrome over the DevTools Protocol", "main": "./cjs-entry.js", "types": "lib/types.d.ts", diff --git a/versions.js b/versions.js index f44f1cc2dea78..e506fa8b38200 100644 --- a/versions.js +++ b/versions.js @@ -17,7 +17,7 @@ const versionsPerRelease = new Map([ // This is a mapping from Chromium version => Puppeteer version. // In Chromium roll patches, use 'NEXT' for the Puppeteer version. - ['99.0.4844.16', 'NEXT'], + ['99.0.4844.16', 'v13.2.0'], ['98.0.4758.0', 'v13.1.0'], ['97.0.4692.0', 'v12.0.0'], ['93.0.4577.0', 'v10.2.0'], From 55459aee56b6f2af6ea1758f8b30980f5f4a2f17 Mon Sep 17 00:00:00 2001 From: Randolf Jung Date: Fri, 4 Feb 2022 13:52:16 +0100 Subject: [PATCH 5/5] feat(puppeteer): export esm modules in package.json Signed-off-by: Randolf Jung --- compat/README.md | 16 ++++++++++++++++ compat/cjs/compat.ts | 1 + compat/cjs/tsconfig.json | 11 +++++++++++ compat/esm/compat.ts | 4 ++++ compat/esm/tsconfig.json | 9 +++++++++ package.json | 12 ++++++++++-- src/common/Debug.ts | 4 +++- src/compat.ts | 3 +++ src/initialize-node.ts | 3 ++- tsconfig.json | 2 +- 10 files changed, 60 insertions(+), 5 deletions(-) create mode 100644 compat/README.md create mode 100644 compat/cjs/compat.ts create mode 100644 compat/cjs/tsconfig.json create mode 100644 compat/esm/compat.ts create mode 100644 compat/esm/tsconfig.json create mode 100644 src/compat.ts diff --git a/compat/README.md b/compat/README.md new file mode 100644 index 0000000000000..a72ecab4e8a3c --- /dev/null +++ b/compat/README.md @@ -0,0 +1,16 @@ +# Compatibility layer + +This directory provides an additional compatibility layer between ES modules and CommonJS. + +## Why? + +Both `./cjs/compat.ts` and `./esm/compat.ts` are written as ES modules, but `./cjs/compat.ts` can additionally use NodeJS CommonJS globals such as `__dirname` and `require` while these are disabled in ES module mode. For more information, see [Differences between ES modules and CommonJS](https://nodejs.org/api/esm.html#differences-between-es-modules-and-commonjs). + +## Adding exports + +In order to add exports, two things need to be done: + +- The exports must be declared in `src/compat.ts`. +- The exports must be realized in `./cjs/compat.ts` and `./esm/compat.ts`. + +In the event `compat.ts` becomes too large, you can place declarations in another file. Just make sure `./cjs`, `./esm`, and `src` have the same structure. diff --git a/compat/cjs/compat.ts b/compat/cjs/compat.ts new file mode 100644 index 0000000000000..5b51524dd12ab --- /dev/null +++ b/compat/cjs/compat.ts @@ -0,0 +1 @@ +export const puppeteerDirname = __dirname; diff --git a/compat/cjs/tsconfig.json b/compat/cjs/tsconfig.json new file mode 100644 index 0000000000000..0de31b76c4440 --- /dev/null +++ b/compat/cjs/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "../../lib/cjs/puppeteer", + "module": "CommonJS" + }, + "references": [ + { "path": "../../vendor/tsconfig.cjs.json"} + ] +} diff --git a/compat/esm/compat.ts b/compat/esm/compat.ts new file mode 100644 index 0000000000000..2ddd69ef0e448 --- /dev/null +++ b/compat/esm/compat.ts @@ -0,0 +1,4 @@ +import { dirname } from 'path'; +import { fileURLToPath } from 'url'; + +export const puppeteerDirname = dirname(fileURLToPath(import.meta.url)); diff --git a/compat/esm/tsconfig.json b/compat/esm/tsconfig.json new file mode 100644 index 0000000000000..42b320fcd3f28 --- /dev/null +++ b/compat/esm/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "../../lib/esm/puppeteer", + "module": "esnext" + }, + "references": [{ "path": "../../vendor/tsconfig.esm.json" }] +} diff --git a/package.json b/package.json index 18a1c99337f8f..8c6d41b84d82e 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,12 @@ "name": "puppeteer", "version": "13.2.0", "description": "A high-level API to control headless Chrome over the DevTools Protocol", + "type": "commonjs", "main": "./cjs-entry.js", + "exports": { + "import": "./lib/esm/puppeteer/node.js", + "require": "./cjs-entry.js" + }, "types": "lib/types.d.ts", "repository": "github:puppeteer/puppeteer", "engines": { @@ -29,15 +34,18 @@ "lint": "npm run eslint && npm run build && npm run doc && npm run markdownlint", "doc": "node utils/doclint/cli.js", "clean-lib": "rimraf lib", - "build": "npm run tsc && npm run generate-d-ts", - "tsc": "npm run clean-lib && tsc --version && npm run tsc-cjs && npm run tsc-esm", + "build": "npm run tsc && npm run generate-d-ts && npm run generate-pkg-json", + "tsc": "npm run clean-lib && tsc --version && (npm run tsc-cjs & npm run tsc-esm) && (npm run tsc-compat-cjs & npm run tsc-compat-esm)", "tsc-cjs": "tsc -b src/tsconfig.cjs.json", "tsc-esm": "tsc -b src/tsconfig.esm.json", + "tsc-compat-cjs": "tsc -b compat/cjs/tsconfig.json", + "tsc-compat-esm": "tsc -b compat/esm/tsconfig.json", "apply-next-version": "node utils/apply_next_version.js", "test-install": "scripts/test-install.sh", "clean-docs": "rimraf website/docs && rimraf docs-api-json", "generate-d-ts": "npm run clean-docs && api-extractor run --local --verbose", "generate-docs": "npm run generate-d-ts && api-documenter markdown -i docs-api-json -o website/docs && node utils/remove-tag.js", + "generate-pkg-json": "echo '{\"type\": \"module\"}' > lib/esm/package.json", "ensure-correct-devtools-protocol-revision": "ts-node -s scripts/ensure-correct-devtools-protocol-package", "ensure-pinned-deps": "ts-node -s scripts/ensure-pinned-deps", "test-types-file": "ts-node -s scripts/test-ts-definition-files.ts", diff --git a/src/common/Debug.ts b/src/common/Debug.ts index 8ff124b094b3b..ce01a7d7dd208 100644 --- a/src/common/Debug.ts +++ b/src/common/Debug.ts @@ -55,7 +55,9 @@ import { isNode } from '../environment.js'; export const debug = (prefix: string): ((...args: unknown[]) => void) => { if (isNode) { // eslint-disable-next-line @typescript-eslint/no-var-requires - return require('debug')(prefix); + return async (...logArgs: unknown[]) => { + (await import('debug')).default(prefix)(logArgs); + }; } return (...logArgs: unknown[]): void => { diff --git a/src/compat.ts b/src/compat.ts new file mode 100644 index 0000000000000..873dcea7966e5 --- /dev/null +++ b/src/compat.ts @@ -0,0 +1,3 @@ +declare const puppeteerDirname: string; + +export { puppeteerDirname }; diff --git a/src/initialize-node.ts b/src/initialize-node.ts index e5336654034d4..17f410275131a 100644 --- a/src/initialize-node.ts +++ b/src/initialize-node.ts @@ -18,9 +18,10 @@ import { PuppeteerNode } from './node/Puppeteer.js'; import { PUPPETEER_REVISIONS } from './revisions.js'; import pkgDir from 'pkg-dir'; import { Product } from './common/Product.js'; +import { puppeteerDirname } from './compat.js'; export const initializePuppeteerNode = (packageName: string): PuppeteerNode => { - const puppeteerRootDirectory = pkgDir.sync(__dirname); + const puppeteerRootDirectory = pkgDir.sync(puppeteerDirname); let preferredRevision = PUPPETEER_REVISIONS.chromium; const isPuppeteerCore = packageName === 'puppeteer-core'; diff --git a/tsconfig.json b/tsconfig.json index 0fe7e06ad83c7..0abb2d09decad 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,5 +12,5 @@ */ "module": "esnext" }, - "include": ["src"] + "include": ["src"], }