puppeteer 13.2.0

立て続けにpuppeteer 13.2.0がリリースされました。

さっそくリリースノートを見ていきましょう。

Features
・add more models to DeviceDescriptors
・chromium: roll to Chromium 99.0.4844.16
Bug Fixes
・make projectRoot optional in Puppeteer and launchers
・migrate more files to strict-mode TypeScript
・typos in documentation

https://github.com/puppeteer/puppeteer/releases/tag/v13.2.0

今回の追加機能はどちらも興味深いですね。

add more models to DeviceDescriptors

DeviceDescriptorsにAppleのハードウェアが一気に追加されました。これまではどちからというとAndroid系ばっかりだったので、ここにきて最新のiPhone 12やiPhone 13の定義が追加されるのはありがたいです。

chromium: roll to Chromium 99.0.4844.16

puppeteer 13.1.0でChromium 98に上がったばかりでしたが、さっそくChromium 99に上がりました。先日Chrome 97が正式リリースされた際に「そろそろChromeのバージョンが3ケタ(100)になるので準備してね!」という発表がありましたが、その100まであと1つにまで迫りましたね。

バグやセキュリティ対応は影響が少なめですが、重要な機能ですのでしっかりアップデートしておきましょう。

puppeteer 13.1.2 & 13.1.3

ちょっと間があいてしまいましたが、puppeteer 13.1.213.1.3 がリリースされました。

まずは 13.1.3 の方からです。

Bug Fixes

・issue with reading versions.js in doclint
・make more files work in strict-mode TypeScript
・page.pdf producing an invalid pdf

https://github.com/puppeteer/puppeteer/releases/tag/v13.1.3

PDFを生成する際に発生する可能性があったバグが修正されています。自分はそのバグを踏んだことがないので、ちょっと正確な条件は分かりませんでした。

一方で重要なのは 13.1.2 の方です。

Bug Fixes

package.json: update node-fetch package
・types in Browser.ts to be compatible with strict mode Typescript
・types in Connection.ts to be compatible with strict mode Typescript

https://github.com/puppeteer/puppeteer/releases/tag/v13.1.2

この1つ目 package.json が問題でした。実際に1つ前のバージョンである13.1.1をnpmでインストールしてみましょう。

$ npm install puppeteer@13.1.1 --save

changed 2 packages, and audited 58 packages in 12s

8 packages are looking for funding
  run `npm fund` for details

2 high severity vulnerabilities

To address all issues, run:
  npm audit fix --force

Run `npm audit` for details.

これは puppeteer 13.1.1 が依存している他のnpmパッケージに脆弱性があるものが含まれるというメッセージです。詳細も確認しましょう。

$ npm audit
# npm audit report

node-fetch  <2.6.7
Severity: high
node-fetch is vulnerable to Exposure of Sensitive Information to an Unauthorized Actor - https://github.com/advisories/GHSA-r683-j2x4-v87g
fix available via `npm audit fix`
node_modules/node-fetch
  puppeteer  10.0.0 - 13.1.1
  Depends on vulnerable versions of node-fetch
  node_modules/puppeteer

2 high severity vulnerabilities

To address all issues, run:
  npm audit fix

puppeteerで使っているnode-fetch 2.6.5に脆弱性があるということが示されました。puppeteer 13.1.1のpackage.jsonも確認してみましょう。

(省略)
  "dependencies": {
    "debug": "4.3.2",
    "devtools-protocol": "0.0.948846",
    "extract-zip": "2.0.1",
    "https-proxy-agent": "5.0.0",
    "node-fetch": "2.6.5",
    "pkg-dir": "4.2.0",
    "progress": "2.0.3",
    "proxy-from-env": "1.1.0",
    "rimraf": "3.0.2",
    "tar-fs": "2.1.1",
    "unbzip2-stream": "1.4.3",
    "ws": "8.2.3"
  },
(省略)

ここですね。ちなみに puppeteer 13.1.2 では以下のように直っています。

(省略)
  "dependencies": {
    "debug": "4.3.2",
    "devtools-protocol": "0.0.948846",
    "extract-zip": "2.0.1",
    "https-proxy-agent": "5.0.0",
    "node-fetch": "2.6.7",
    "pkg-dir": "4.2.0",
    "progress": "2.0.3",
    "proxy-from-env": "1.1.0",
    "rimraf": "3.0.2",
    "tar-fs": "2.1.1",
    "unbzip2-stream": "1.4.3",
    "ws": "8.2.3"
  },
(省略)

NodeJSのモジュールは依存するモジュールを npm install --save で手軽にインストールできます。一方でRedHat/CentOSのRPMやUbuntuのdebのように自動では更新されません。上記のpuppeteerのように依存するNodeJSモジュールのバージョンを固定してしまっていると、そのバージョンに脆弱性があったとしても、そのまま使うことになります。

一方で npm outdated などで更新できるようにする方法もあります。その場合は package.json のバージョンを固定にしないで「このバージョン以上」とすることです。

    "node-fetch": "^2.6.7",

こうすることで仮にnode-fetchの2.6.8がリリースされたら、自動的にそちらをインストールするようにできるのです。

puppeteer 13.1.1 ではこの「^」がなかったことで古い(2.6.5)node-fetchを指定したままとなりました。最終的には新しい(2.6.7)node-fetchを指定したpuppeteer 13.1.2がリリースされましたが、しばらくの間はpuppeteerのビルドが失敗するという状況が続いてしまいました。かくいう自分も、これが原因でしばらくの間CI/CDがエラーになってしまい、puppeteerを使ったテストが行えない状態にありました。もしも上記のように「^」を含めて、自動的に新しいnode-fetchを使うようになっていたらpuppeteerの更新を待つ必要はなかったですし、そもそもpuppeteerも新しいリリースを出す必要もなかったのではないかと思いました。

もちろん、バージョンが上がることで動作が変わったり、互換性がないこともあります。そうした確認をしていないのに、新しいバージョンを使うように指定することに躊躇することもあるでしょう。ですが、マイクロバージョンであれば(一般的には)大きな仕様の変更はないと考えられます。利用者の利便性を考えたら、バージョン固定ではなく、最新版を使うようにpackage.jsonを書く方がよいのでないか?と思ったケースでした。

puppeteer 13.1.0 & 13.1.1

puppeteer 13.1.1がリリースされました。

Bug Fixes

・use content box for OOPIF offset calculations

https://github.com/puppeteer/puppeteer/releases/tag/v13.1.1

・・・のですがこちらはバグ修正のみなのです。

その前にリリースされたpuppeteer 13.1.0のリリースを見ましょう。

Features

・chromium: roll to Chromium 98.0.4758.0

Bug Fixes

・apply OOPIF offsets to bounding box and box model calls

・correctly compute clickable points for elements inside OOPIFs

・error for pre-existing OOPIFs

https://github.com/puppeteer/puppeteer/releases/tag/v13.1.0

ポイントはChromiumが98になりました。現在配布されているChromeが97ですので、puppeteerのChromiumはバージョンが1つ先行することになります。

では、合わせてChromium 98の変更点をおさらいしておきましょう。

  • COLRv1 Color Gradient Vector Fonts
  • Origin Trials Region Capture
  • Adding auto Keyword for contain-intrinsic-size
  • AudioContext.outputLatency
  • CSS Color Adjust: ‘only’ Keyword for color-scheme
  • document.adoptedStyleSheets is Now Mutable
  • High Dynamic Range Color Media Queries
  • New window.open() Behavior for Popups, Tabs, and Windows
  • Private Network Access Preflight Requests for Subresources
  • structuredClone() Method on Windows and Workers
  • WebAuthn minPinLength Extension
  • Window Controls Overlay for Installed Desktop Web Apps
  • WritableStream controller AbortSignal
  • Remove SDES Key Exchange for WebRTC

この中でハイライトした興味深いもの2つについて解説します。

New window.open() Behavior for Popups, Tabs, and Windows

windows.open() はポップアップウィンドウを生成するために使われるメソッドです。

Chromium 98ではオプションに popup を指定することで、ポップアップウィンドウ (popup=1) にするか、タブ (popup=0) として開くか、を選択できるようになりました。(タブが使えない環境ではウィンドウになります)

const popup = window.open('_blank','','popup=1');  // ポップアップの場合
const tab = window.open('_blank','','popup=0');       // タブの場合

structuredClone() Method on Windows and Workers

こちらは説明するまでもないでしょう。オブジェクトのディープコピー (Deep Copy) をするメソッドが実装されました。

JavaScriptではオブジェクトの代入はリファレンスのコピーにすぎません。また、Object.assign() で元のオブジェクトをコピーしたとしても、第一階層はコピーされますが、第二階層以降は浅いコピー (Shallow Copy) になり、真にディープコピーするには自前で再帰的にassign()等をする関数を実装する必要がありました。

この structuredClone() は文字通りオブジェクトの再帰的なディープコピーを作ってくれるメソッドになります。自前でディープコピーのメソッドを実装したら自己参照して無限ループになった・・・みたいなことにならずに済むわけです。

ちなみに FireFox は94で対応済、NodeJSは17.0からの対応のようです。

詳細は web.dev を参照してください。また、MDNにも関数の概要が記載されていますので、こちらも読んでおきましょう。

Chrome 97

Google Chrome 97がリリースされました。

例によってセキュリティ対応などが中心ですが、注目するアップデートが2つあります。

1つ目はCookieなどのWebサイトごとに保存されている情報を一括で削除できるようになったことです。従来はサイト単位や保存してからの時間(1週間以内とか1ヶ月以上前とか)でしか削除できませんでした。まとめて削除できるのは、ブラウザ関連の開発やテストをしている人にはうれしい機能です。プライベートモードで代替できなくもないですが、普通のブラウザの状態でのテストも必要ですから。

2つ目はWeb Transportのサポートです。Web TransportはWeb RTCに代わる技術でHTTP(正確にはHTTP/3)の上でソケット通信を行える技術です。Web RTCが主にピア・ツー・ピアを前提にした技術であるのに対して、Web Transportはサーバ・クライアントを考慮した技術になります。これにより、Webサーバを使ってレイテンシのないサーバ・クライアント間通信が実現できるようになります。とはいうものの、HTTP/3が前提となるのでまだサーバを用意するのが難しいかもしれません。Web Socketで非同期通信を実装しているのであれば、今後はWeb Transportに注目です。

puppeteer 13.0.1

puppeteer 13.0.1がリリースされました。

今回のリリースノートは以下のとおり。

Bug Fixes

・disable a test failing on Firefox

・make sure ElementHandle.waitForSelector is evaluated in the right context

・predicate arguments for waitForFunction

https://github.com/puppeteer/puppeteer/releases/tag/v13.0.1

基本的にバグ修正です。もしも13.0.0で問題が起きている場合にはアップデートしましょう。