patchright-core 1.48.2 → 1.49.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/README.md +2 -2
  2. package/ThirdPartyNotices.txt +70 -384
  3. package/bin/reinstall_chrome_beta_linux.sh +10 -8
  4. package/bin/reinstall_chrome_stable_linux.sh +10 -8
  5. package/bin/reinstall_msedge_beta_linux.sh +11 -9
  6. package/bin/reinstall_msedge_dev_linux.sh +11 -9
  7. package/bin/reinstall_msedge_stable_linux.sh +11 -9
  8. package/browsers.json +19 -11
  9. package/lib/cli/program.js +23 -5
  10. package/lib/client/channelOwner.js +2 -2
  11. package/lib/client/locator.js +7 -0
  12. package/lib/client/network.js +5 -0
  13. package/lib/client/page.js +4 -2
  14. package/lib/client/tracing.js +13 -0
  15. package/lib/client/waiter.js +15 -11
  16. package/lib/generated/consoleApiSource.js +1 -1
  17. package/lib/generated/injectedScriptSource.js +1 -1
  18. package/lib/generated/pollingRecorderSource.js +1 -1
  19. package/lib/generated/webSocketMockSource.js +1 -1
  20. package/lib/protocol/validator.js +23 -3
  21. package/lib/server/ariaSnapshot.js +33 -0
  22. package/lib/server/bidi/bidiChromium.js +1 -1
  23. package/lib/server/bidi/bidiConnection.js +0 -2
  24. package/lib/server/bidi/bidiExecutionContext.js +0 -3
  25. package/lib/server/browserType.js +4 -1
  26. package/lib/server/chromium/chromium.js +6 -2
  27. package/lib/server/chromium/crExecutionContext.js +0 -13
  28. package/lib/server/chromium/crNetworkManager.js +1 -1
  29. package/lib/server/chromium/crPage.js +4 -5
  30. package/lib/server/codegen/csharp.js +11 -16
  31. package/lib/server/codegen/java.js +4 -7
  32. package/lib/server/codegen/javascript.js +28 -6
  33. package/lib/server/codegen/python.js +12 -16
  34. package/lib/server/debugController.js +8 -5
  35. package/lib/server/deviceDescriptorsSource.json +127 -127
  36. package/lib/server/dispatchers/androidDispatcher.js +13 -2
  37. package/lib/server/dispatchers/debugControllerDispatcher.js +1 -1
  38. package/lib/server/dispatchers/dispatcher.js +1 -1
  39. package/lib/server/dispatchers/frameDispatcher.js +8 -1
  40. package/lib/server/dispatchers/tracingDispatcher.js +10 -0
  41. package/lib/server/dom.js +79 -36
  42. package/lib/server/fetch.js +30 -17
  43. package/lib/server/firefox/ffExecutionContext.js +0 -12
  44. package/lib/server/firefox/ffNetworkManager.js +1 -1
  45. package/lib/server/frames.js +55 -62
  46. package/lib/server/index.js +0 -6
  47. package/lib/server/javascript.js +0 -6
  48. package/lib/server/page.js +32 -5
  49. package/lib/server/progress.js +0 -3
  50. package/lib/server/recorder/recorderApp.js +6 -15
  51. package/lib/server/recorder/recorderInTraceViewer.js +3 -3
  52. package/lib/server/recorder/recorderUtils.js +2 -1
  53. package/lib/server/recorder.js +66 -31
  54. package/lib/server/registry/index.js +70 -23
  55. package/lib/server/registry/nativeDeps.js +6 -3
  56. package/lib/server/socksClientCertificatesInterceptor.js +1 -1
  57. package/lib/server/trace/recorder/snapshotter.js +1 -12
  58. package/lib/server/trace/recorder/snapshotterInjected.js +19 -1
  59. package/lib/server/trace/recorder/tracing.js +69 -15
  60. package/lib/server/trace/test/inMemorySnapshotter.js +3 -3
  61. package/lib/server/trace/viewer/traceViewer.js +2 -1
  62. package/lib/server/webkit/wkBrowser.js +2 -2
  63. package/lib/server/webkit/wkExecutionContext.js +0 -13
  64. package/lib/server/webkit/wkPage.js +4 -0
  65. package/lib/utils/comparators.js +12 -30
  66. package/lib/utils/crypto.js +1 -4
  67. package/lib/utils/hostPlatform.js +6 -0
  68. package/lib/utils/isomorphic/ariaSnapshot.js +267 -0
  69. package/lib/utils/isomorphic/locatorGenerators.js +23 -5
  70. package/lib/utils/isomorphic/recorderUtils.js +36 -4
  71. package/lib/utils/isomorphic/stringUtils.js +30 -0
  72. package/lib/utils/isomorphic/urlMatch.js +5 -1
  73. package/lib/utils/network.js +1 -1
  74. package/lib/utils/sequence.js +64 -0
  75. package/lib/utils/stackTrace.js +16 -3
  76. package/lib/utils/zones.js +32 -23
  77. package/lib/utilsBundle.js +4 -5
  78. package/lib/utilsBundleImpl/index.js +190 -33
  79. package/lib/vite/htmlReport/index.html +19 -16
  80. package/lib/vite/recorder/assets/codeMirrorModule-AFvV6hAs.js +24 -0
  81. package/lib/vite/recorder/assets/index-_cTWgVuJ.js +184 -0
  82. package/lib/vite/recorder/assets/{index-BW-aOBcL.css → index-iA1aAGZg.css} +1 -1
  83. package/lib/vite/recorder/index.html +2 -2
  84. package/lib/vite/traceViewer/assets/codeMirrorModule-BWCrdKft.js +24 -0
  85. package/lib/vite/traceViewer/assets/inspectorTab-C_9qyxv5.js +68 -0
  86. package/lib/vite/traceViewer/assets/workbench-DsQEOQud.js +9 -0
  87. package/lib/vite/traceViewer/{embedded.BlHoW5LY.js → embedded.D4x_-tXl.js} +1 -1
  88. package/lib/vite/traceViewer/embedded.html +5 -5
  89. package/lib/vite/traceViewer/{index.DaWVfou1.js → index.BskMikzx.js} +1 -1
  90. package/lib/vite/traceViewer/index.html +24 -7
  91. package/lib/vite/traceViewer/{inspectorTab.DLjBDrQR.css → inspectorTab.DEOUW62d.css} +1 -1
  92. package/lib/vite/traceViewer/recorder.Dsk1wX5k.js +2 -0
  93. package/lib/vite/traceViewer/recorder.html +3 -3
  94. package/lib/vite/traceViewer/sw.bundle.js +3 -3
  95. package/lib/vite/traceViewer/uiMode.CzKr-TMc.js +5 -0
  96. package/lib/vite/traceViewer/uiMode.html +6 -6
  97. package/lib/vite/traceViewer/{uiMode.CAYqod-m.css → uiMode.voC1ZiOQ.css} +1 -1
  98. package/lib/vite/traceViewer/workbench.C-zR9ysA.css +1 -0
  99. package/package.json +1 -1
  100. package/types/protocol.d.ts +58 -10
  101. package/types/types.d.ts +116 -20
  102. package/lib/third_party/diff_match_patch.js +0 -2222
  103. package/lib/vite/recorder/assets/codeMirrorModule-baozm8ur.js +0 -24
  104. package/lib/vite/recorder/assets/index-2ElAIWFB.js +0 -42
  105. package/lib/vite/traceViewer/assets/codeMirrorModule-Bh1rfd2w.js +0 -24
  106. package/lib/vite/traceViewer/assets/inspectorTab-7GHnKvSD.js +0 -64
  107. package/lib/vite/traceViewer/assets/workbench-DPQnTHYP.js +0 -9
  108. package/lib/vite/traceViewer/recorder.C4zxcvd2.js +0 -2
  109. package/lib/vite/traceViewer/uiMode.mTXWniJb.js +0 -5
  110. package/lib/vite/traceViewer/workbench.D3JVcA9K.css +0 -1
@@ -13,6 +13,7 @@ var _debugger = require("./debugger");
13
13
  var _contextRecorder = require("./recorder/contextRecorder");
14
14
  var _recorderUtils = require("./recorder/recorderUtils");
15
15
  var _recorderUtils2 = require("../utils/isomorphic/recorderUtils");
16
+ var _selectorParser = require("../utils/isomorphic/selectorParser");
16
17
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
17
18
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
18
19
  /**
@@ -58,7 +59,7 @@ class Recorder {
58
59
  this.handleSIGINT = void 0;
59
60
  this._context = void 0;
60
61
  this._mode = void 0;
61
- this._highlightedSelector = '';
62
+ this._highlightedElement = {};
62
63
  this._overlayState = {
63
64
  offsetX: 0
64
65
  };
@@ -94,8 +95,9 @@ class Recorder {
94
95
  this.setMode(data.params.mode);
95
96
  return;
96
97
  }
97
- if (data.event === 'selectorUpdated') {
98
- this.setHighlightedSelector(this._currentLanguage, data.params.selector);
98
+ if (data.event === 'highlightRequested') {
99
+ if (data.params.selector) this.setHighlightedSelector(this._currentLanguage, data.params.selector);
100
+ if (data.params.ariaTemplate) this.setHighlightedAriaTemplate(data.params.ariaTemplate);
99
101
  return;
100
102
  }
101
103
  if (data.event === 'step') {
@@ -133,12 +135,12 @@ class Recorder {
133
135
  recorderApp.setRunningFile(undefined);
134
136
  this._pushAllSources();
135
137
  });
136
- await this._context.exposeBinding('__pw_recorderState', false, source => {
137
- let actionSelector = '';
138
+ await this._context.exposeBinding('__pw_recorderState', false, async source => {
139
+ let actionSelector;
138
140
  let actionPoint;
139
141
  const hasActiveScreenshotCommand = [...this._currentCallsMetadata.keys()].some(isScreenshotCommand);
140
142
  if (!hasActiveScreenshotCommand) {
141
- actionSelector = this._highlightedSelector;
143
+ actionSelector = await this._scopeHighlightedSelectorToFrame(source.frame);
142
144
  for (const [metadata, sdkObject] of this._currentCallsMetadata) {
143
145
  if (source.page === sdkObject.attribution.page) {
144
146
  actionPoint = metadata.point || actionPoint;
@@ -150,18 +152,22 @@ class Recorder {
150
152
  mode: this._mode,
151
153
  actionPoint,
152
154
  actionSelector,
155
+ ariaTemplate: this._highlightedElement.ariaTemplate,
153
156
  language: this._currentLanguage,
154
157
  testIdAttributeName: this._contextRecorder.testIdAttributeName(),
155
158
  overlay: this._overlayState
156
159
  };
157
160
  return uiState;
158
161
  });
159
- await this._context.exposeBinding('__pw_recorderSetSelector', false, async ({
162
+ await this._context.exposeBinding('__pw_recorderElementPicked', false, async ({
160
163
  frame
161
- }, selector) => {
164
+ }, elementInfo) => {
162
165
  var _this$_recorderApp2;
163
166
  const selectorChain = await (0, _contextRecorder.generateFrameSelector)(frame);
164
- await ((_this$_recorderApp2 = this._recorderApp) === null || _this$_recorderApp2 === void 0 ? void 0 : _this$_recorderApp2.setSelector((0, _recorderUtils2.buildFullSelector)(selectorChain, selector), true));
167
+ await ((_this$_recorderApp2 = this._recorderApp) === null || _this$_recorderApp2 === void 0 ? void 0 : _this$_recorderApp2.elementPicked({
168
+ selector: (0, _recorderUtils2.buildFullSelector)(selectorChain, elementInfo.selector),
169
+ ariaSnapshot: elementInfo.ariaSnapshot
170
+ }, true));
165
171
  });
166
172
  await this._context.exposeBinding('__pw_recorderSetMode', false, async ({
167
173
  frame
@@ -200,11 +206,11 @@ class Recorder {
200
206
  setMode(mode) {
201
207
  var _this$_recorderApp4;
202
208
  if (this._mode === mode) return;
203
- this._highlightedSelector = '';
209
+ this._highlightedElement = {};
204
210
  this._mode = mode;
205
211
  (_this$_recorderApp4 = this._recorderApp) === null || _this$_recorderApp4 === void 0 || _this$_recorderApp4.setMode(this._mode);
206
- this._contextRecorder.setEnabled(this._mode === 'recording' || this._mode === 'assertingText' || this._mode === 'assertingVisibility' || this._mode === 'assertingValue');
207
- this._debugger.setMuted(this._mode === 'recording' || this._mode === 'assertingText' || this._mode === 'assertingVisibility' || this._mode === 'assertingValue');
212
+ this._contextRecorder.setEnabled(this._isRecording());
213
+ this._debugger.setMuted(this._isRecording());
208
214
  if (this._mode !== 'none' && this._mode !== 'standby' && this._context.pages().length === 1) this._context.pages()[0].bringToFront().catch(() => {});
209
215
  this._refreshOverlay();
210
216
  }
@@ -215,40 +221,66 @@ class Recorder {
215
221
  return this._mode;
216
222
  }
217
223
  setHighlightedSelector(language, selector) {
218
- this._highlightedSelector = (0, _locatorParser.locatorOrSelectorAsSelector)(language, selector, this._context.selectors().testIdAttributeName());
224
+ this._highlightedElement = {
225
+ selector: (0, _locatorParser.locatorOrSelectorAsSelector)(language, selector, this._context.selectors().testIdAttributeName())
226
+ };
227
+ this._refreshOverlay();
228
+ }
229
+ setHighlightedAriaTemplate(ariaTemplate) {
230
+ this._highlightedElement = {
231
+ ariaTemplate
232
+ };
219
233
  this._refreshOverlay();
220
234
  }
221
235
  hideHighlightedSelector() {
222
- this._highlightedSelector = '';
236
+ this._highlightedElement = {};
223
237
  this._refreshOverlay();
224
238
  }
239
+ async _scopeHighlightedSelectorToFrame(frame) {
240
+ if (!this._highlightedElement.selector) return;
241
+ try {
242
+ const mainFrame = frame._page.mainFrame();
243
+ const resolved = await mainFrame.selectors.resolveFrameForSelector(this._highlightedElement.selector);
244
+ // selector couldn't be found, don't highlight anything
245
+ if (!resolved) return '';
246
+
247
+ // selector points to no specific frame, highlight in all frames
248
+ if ((resolved === null || resolved === void 0 ? void 0 : resolved.frame) === mainFrame) return (0, _selectorParser.stringifySelector)(resolved.info.parsed);
249
+
250
+ // selector points to this frame, highlight it
251
+ if ((resolved === null || resolved === void 0 ? void 0 : resolved.frame) === frame) return (0, _selectorParser.stringifySelector)(resolved.info.parsed);
252
+
253
+ // selector points to a different frame, highlight nothing
254
+ return '';
255
+ } catch {
256
+ return '';
257
+ }
258
+ }
225
259
  setOutput(codegenId, outputFile) {
226
260
  this._contextRecorder.setOutput(codegenId, outputFile);
227
261
  }
228
262
  _refreshOverlay() {
229
- for (const page of this._context.pages()) page.mainFrame().evaluateExpression('window.__pw_refreshOverlay()').catch(() => {});
263
+ for (const page of this._context.pages()) {
264
+ for (const frame of page.frames()) frame.evaluateExpression('window.__pw_refreshOverlay()').catch(() => {});
265
+ }
230
266
  }
231
267
  async onBeforeCall(sdkObject, metadata) {
232
- if (this._omitCallTracking || this._mode === 'recording' || this._mode === 'assertingText' || this._mode === 'assertingVisibility' || this._mode === 'assertingValue') return;
268
+ if (this._omitCallTracking || this._isRecording()) return;
233
269
  this._currentCallsMetadata.set(metadata, sdkObject);
234
270
  this._updateUserSources();
235
271
  this.updateCallLog([metadata]);
236
- if (isScreenshotCommand(metadata)) {
237
- this.hideHighlightedSelector();
238
- } else if (metadata.params && metadata.params.selector) {
239
- var _this$_recorderApp5;
240
- this._highlightedSelector = metadata.params.selector;
241
- (_this$_recorderApp5 = this._recorderApp) === null || _this$_recorderApp5 === void 0 || _this$_recorderApp5.setSelector(this._highlightedSelector).catch(() => {});
242
- }
272
+ if (isScreenshotCommand(metadata)) this.hideHighlightedSelector();else if (metadata.params && metadata.params.selector) this._highlightedElement = {
273
+ selector: metadata.params.selector
274
+ };
243
275
  }
244
276
  async onAfterCall(sdkObject, metadata) {
245
- if (this._omitCallTracking || this._mode === 'recording' || this._mode === 'assertingText' || this._mode === 'assertingVisibility' || this._mode === 'assertingValue') return;
277
+ if (this._omitCallTracking || this._isRecording()) return;
246
278
  if (!metadata.error) this._currentCallsMetadata.delete(metadata);
247
279
  this._updateUserSources();
248
280
  this.updateCallLog([metadata]);
249
281
  }
250
282
  _updateUserSources() {
251
- var _this$_recorderApp6;
283
+ var _this$_recorderApp5;
252
284
  // Remove old decorations.
253
285
  for (const source of this._userSources.values()) {
254
286
  source.highlight = [];
@@ -286,19 +318,19 @@ class Recorder {
286
318
  }
287
319
  }
288
320
  this._pushAllSources();
289
- if (fileToSelect) (_this$_recorderApp6 = this._recorderApp) === null || _this$_recorderApp6 === void 0 || _this$_recorderApp6.setRunningFile(fileToSelect);
321
+ if (fileToSelect) (_this$_recorderApp5 = this._recorderApp) === null || _this$_recorderApp5 === void 0 || _this$_recorderApp5.setRunningFile(fileToSelect);
290
322
  }
291
323
  _pushAllSources() {
292
- var _this$_recorderApp7;
293
- (_this$_recorderApp7 = this._recorderApp) === null || _this$_recorderApp7 === void 0 || _this$_recorderApp7.setSources([...this._recorderSources, ...this._userSources.values()]);
324
+ var _this$_recorderApp6;
325
+ (_this$_recorderApp6 = this._recorderApp) === null || _this$_recorderApp6 === void 0 || _this$_recorderApp6.setSources([...this._recorderSources, ...this._userSources.values()]);
294
326
  }
295
327
  async onBeforeInputAction(sdkObject, metadata) {}
296
328
  async onCallLog(sdkObject, metadata, logName, message) {
297
329
  this.updateCallLog([metadata]);
298
330
  }
299
331
  updateCallLog(metadatas) {
300
- var _this$_recorderApp8;
301
- if (this._mode === 'recording' || this._mode === 'assertingText' || this._mode === 'assertingVisibility' || this._mode === 'assertingValue') return;
332
+ var _this$_recorderApp7;
333
+ if (this._isRecording()) return;
302
334
  const logs = [];
303
335
  for (const metadata of metadatas) {
304
336
  if (!metadata.method || metadata.internal) continue;
@@ -307,7 +339,10 @@ class Recorder {
307
339
  if (this._debugger.isPaused(metadata)) status = 'paused';
308
340
  logs.push((0, _recorderUtils.metadataToCallLog)(metadata, status));
309
341
  }
310
- (_this$_recorderApp8 = this._recorderApp) === null || _this$_recorderApp8 === void 0 || _this$_recorderApp8.updateCallLogs(logs);
342
+ (_this$_recorderApp7 = this._recorderApp) === null || _this$_recorderApp7 === void 0 || _this$_recorderApp7.updateCallLogs(logs);
343
+ }
344
+ _isRecording() {
345
+ return ['recording', 'assertingText', 'assertingVisibility', 'assertingValue', 'assertingSnapshot'].includes(this._mode);
311
346
  }
312
347
  _readSource(fileName) {
313
348
  try {
@@ -8,7 +8,6 @@ exports.browserDirectoryToMarkerFilePath = browserDirectoryToMarkerFilePath;
8
8
  exports.buildPlaywrightCLICommand = buildPlaywrightCLICommand;
9
9
  exports.findChromiumChannel = findChromiumChannel;
10
10
  exports.installBrowsersForNpmInstall = installBrowsersForNpmInstall;
11
- exports.installDefaultBrowsersForNpmInstall = installDefaultBrowsersForNpmInstall;
12
11
  exports.registryDirectory = exports.registry = void 0;
13
12
  Object.defineProperty(exports, "writeDockerVersion", {
14
13
  enumerable: true,
@@ -65,6 +64,11 @@ const EXECUTABLE_PATHS = {
65
64
  'mac': ['chrome-mac', 'Chromium.app', 'Contents', 'MacOS', 'Chromium'],
66
65
  'win': ['chrome-win', 'chrome.exe']
67
66
  },
67
+ 'chromium-headless-shell': {
68
+ 'linux': ['chrome-linux', 'headless_shell'],
69
+ 'mac': ['chrome-mac', 'headless_shell'],
70
+ 'win': ['chrome-win', 'headless_shell.exe']
71
+ },
68
72
  'firefox': {
69
73
  'linux': ['firefox', 'firefox'],
70
74
  'mac': ['firefox', 'Nightly.app', 'Contents', 'MacOS', 'firefox'],
@@ -111,6 +115,35 @@ const DOWNLOAD_PATHS = {
111
115
  'mac15-arm64': 'builds/chromium/%s/chromium-mac-arm64.zip',
112
116
  'win64': 'builds/chromium/%s/chromium-win64.zip'
113
117
  },
118
+ 'chromium-headless-shell': {
119
+ '<unknown>': undefined,
120
+ 'ubuntu18.04-x64': undefined,
121
+ 'ubuntu20.04-x64': 'builds/chromium/%s/chromium-headless-shell-linux.zip',
122
+ 'ubuntu22.04-x64': 'builds/chromium/%s/chromium-headless-shell-linux.zip',
123
+ 'ubuntu24.04-x64': 'builds/chromium/%s/chromium-headless-shell-linux.zip',
124
+ 'ubuntu18.04-arm64': undefined,
125
+ 'ubuntu20.04-arm64': 'builds/chromium/%s/chromium-headless-shell-linux-arm64.zip',
126
+ 'ubuntu22.04-arm64': 'builds/chromium/%s/chromium-headless-shell-linux-arm64.zip',
127
+ 'ubuntu24.04-arm64': 'builds/chromium/%s/chromium-headless-shell-linux-arm64.zip',
128
+ 'debian11-x64': 'builds/chromium/%s/chromium-headless-shell-linux.zip',
129
+ 'debian11-arm64': 'builds/chromium/%s/chromium-headless-shell-linux-arm64.zip',
130
+ 'debian12-x64': 'builds/chromium/%s/chromium-headless-shell-linux.zip',
131
+ 'debian12-arm64': 'builds/chromium/%s/chromium-headless-shell-linux-arm64.zip',
132
+ 'mac10.13': undefined,
133
+ 'mac10.14': undefined,
134
+ 'mac10.15': undefined,
135
+ 'mac11': 'builds/chromium/%s/chromium-headless-shell-mac.zip',
136
+ 'mac11-arm64': 'builds/chromium/%s/chromium-headless-shell-mac-arm64.zip',
137
+ 'mac12': 'builds/chromium/%s/chromium-headless-shell-mac.zip',
138
+ 'mac12-arm64': 'builds/chromium/%s/chromium-headless-shell-mac-arm64.zip',
139
+ 'mac13': 'builds/chromium/%s/chromium-headless-shell-mac.zip',
140
+ 'mac13-arm64': 'builds/chromium/%s/chromium-headless-shell-mac-arm64.zip',
141
+ 'mac14': 'builds/chromium/%s/chromium-headless-shell-mac.zip',
142
+ 'mac14-arm64': 'builds/chromium/%s/chromium-headless-shell-mac-arm64.zip',
143
+ 'mac15': 'builds/chromium/%s/chromium-headless-shell-mac.zip',
144
+ 'mac15-arm64': 'builds/chromium/%s/chromium-headless-shell-mac-arm64.zip',
145
+ 'win64': 'builds/chromium/%s/chromium-headless-shell-win64.zip'
146
+ },
114
147
  'chromium-tip-of-tree': {
115
148
  '<unknown>': undefined,
116
149
  'ubuntu18.04-x64': undefined,
@@ -313,7 +346,7 @@ const registryDirectory = exports.registryDirectory = (() => {
313
346
  function isBrowserDirectory(browserDirectory) {
314
347
  const baseName = _path.default.basename(browserDirectory);
315
348
  for (const browserName of allDownloadable) {
316
- if (baseName.startsWith(browserName + '-')) return true;
349
+ if (baseName.startsWith(browserName.replace(/-/g, '_') + '-')) return true;
317
350
  }
318
351
  return false;
319
352
  }
@@ -326,6 +359,7 @@ function readDescriptors(browsersJSON) {
326
359
  const descriptor = {
327
360
  name,
328
361
  revision,
362
+ hasRevisionOverride: !!revisionOverride,
329
363
  // We only put browser version for the supported operating systems.
330
364
  browserVersion: revisionOverride ? undefined : obj.browserVersion,
331
365
  installByDefault: !!obj.installByDefault,
@@ -339,7 +373,7 @@ function readDescriptors(browsersJSON) {
339
373
  return descriptor;
340
374
  });
341
375
  }
342
- const allDownloadable = ['chromium', 'firefox', 'webkit', 'ffmpeg', 'firefox-beta', 'chromium-tip-of-tree'];
376
+ const allDownloadable = ['android', 'chromium', 'firefox', 'webkit', 'ffmpeg', 'firefox-beta', 'chromium-tip-of-tree', 'chromium-headless-shell'];
343
377
  class Registry {
344
378
  constructor(browsersJSON) {
345
379
  this._executables = void 0;
@@ -372,13 +406,30 @@ class Registry {
372
406
  executablePath: () => chromiumExecutable,
373
407
  executablePathOrDie: sdkLanguage => executablePathOrDie('chromium', chromiumExecutable, chromium.installByDefault, sdkLanguage),
374
408
  installType: chromium.installByDefault ? 'download-by-default' : 'download-on-demand',
375
- _validateHostRequirements: sdkLanguage => this._validateHostRequirements(sdkLanguage, 'chromium', chromium.dir, ['chrome-linux'], [], ['chrome-win']),
409
+ _validateHostRequirements: sdkLanguage => this._validateHostRequirements(sdkLanguage, chromium.dir, ['chrome-linux'], [], ['chrome-win']),
376
410
  downloadURLs: this._downloadURLs(chromium),
377
411
  browserVersion: chromium.browserVersion,
378
412
  _install: () => this._downloadExecutable(chromium, chromiumExecutable),
379
413
  _dependencyGroup: 'chromium',
380
414
  _isHermeticInstallation: true
381
415
  });
416
+ const chromiumHeadlessShell = descriptors.find(d => d.name === 'chromium-headless-shell');
417
+ const chromiumHeadlessShellExecutable = findExecutablePath(chromiumHeadlessShell.dir, 'chromium-headless-shell');
418
+ this._executables.push({
419
+ type: 'channel',
420
+ name: 'chromium-headless-shell',
421
+ browserName: 'chromium',
422
+ directory: chromiumHeadlessShell.dir,
423
+ executablePath: () => chromiumHeadlessShellExecutable,
424
+ executablePathOrDie: sdkLanguage => executablePathOrDie('chromium', chromiumHeadlessShellExecutable, chromiumHeadlessShell.installByDefault, sdkLanguage),
425
+ installType: chromiumHeadlessShell.installByDefault ? 'download-by-default' : 'download-on-demand',
426
+ _validateHostRequirements: sdkLanguage => this._validateHostRequirements(sdkLanguage, chromiumHeadlessShell.dir, ['chrome-linux'], [], ['chrome-win']),
427
+ downloadURLs: this._downloadURLs(chromiumHeadlessShell),
428
+ browserVersion: chromium.browserVersion,
429
+ _install: () => this._downloadExecutable(chromiumHeadlessShell, chromiumHeadlessShellExecutable),
430
+ _dependencyGroup: 'chromium',
431
+ _isHermeticInstallation: true
432
+ });
382
433
  const chromiumTipOfTree = descriptors.find(d => d.name === 'chromium-tip-of-tree');
383
434
  const chromiumTipOfTreeExecutable = findExecutablePath(chromiumTipOfTree.dir, 'chromium');
384
435
  this._executables.push({
@@ -389,7 +440,7 @@ class Registry {
389
440
  executablePath: () => chromiumTipOfTreeExecutable,
390
441
  executablePathOrDie: sdkLanguage => executablePathOrDie('chromium-tip-of-tree', chromiumTipOfTreeExecutable, chromiumTipOfTree.installByDefault, sdkLanguage),
391
442
  installType: chromiumTipOfTree.installByDefault ? 'download-by-default' : 'download-on-demand',
392
- _validateHostRequirements: sdkLanguage => this._validateHostRequirements(sdkLanguage, 'chromium', chromiumTipOfTree.dir, ['chrome-linux'], [], ['chrome-win']),
443
+ _validateHostRequirements: sdkLanguage => this._validateHostRequirements(sdkLanguage, chromiumTipOfTree.dir, ['chrome-linux'], [], ['chrome-win']),
393
444
  downloadURLs: this._downloadURLs(chromiumTipOfTree),
394
445
  browserVersion: chromiumTipOfTree.browserVersion,
395
446
  _install: () => this._downloadExecutable(chromiumTipOfTree, chromiumTipOfTreeExecutable),
@@ -489,7 +540,7 @@ class Registry {
489
540
  executablePath: () => chromiumExecutable,
490
541
  executablePathOrDie: sdkLanguage => executablePathOrDie('chromium', chromiumExecutable, chromium.installByDefault, sdkLanguage),
491
542
  installType: 'download-on-demand',
492
- _validateHostRequirements: sdkLanguage => this._validateHostRequirements(sdkLanguage, 'chromium', chromium.dir, ['chrome-linux'], [], ['chrome-win']),
543
+ _validateHostRequirements: sdkLanguage => this._validateHostRequirements(sdkLanguage, chromium.dir, ['chrome-linux'], [], ['chrome-win']),
493
544
  downloadURLs: this._downloadURLs(chromium),
494
545
  browserVersion: chromium.browserVersion,
495
546
  _install: () => this._downloadExecutable(chromium, chromiumExecutable),
@@ -506,7 +557,7 @@ class Registry {
506
557
  executablePath: () => firefoxExecutable,
507
558
  executablePathOrDie: sdkLanguage => executablePathOrDie('firefox', firefoxExecutable, firefox.installByDefault, sdkLanguage),
508
559
  installType: firefox.installByDefault ? 'download-by-default' : 'download-on-demand',
509
- _validateHostRequirements: sdkLanguage => this._validateHostRequirements(sdkLanguage, 'firefox', firefox.dir, ['firefox'], [], ['firefox']),
560
+ _validateHostRequirements: sdkLanguage => this._validateHostRequirements(sdkLanguage, firefox.dir, ['firefox'], [], ['firefox']),
510
561
  downloadURLs: this._downloadURLs(firefox),
511
562
  browserVersion: firefox.browserVersion,
512
563
  _install: () => this._downloadExecutable(firefox, firefoxExecutable),
@@ -523,7 +574,7 @@ class Registry {
523
574
  executablePath: () => firefoxBetaExecutable,
524
575
  executablePathOrDie: sdkLanguage => executablePathOrDie('firefox-beta', firefoxBetaExecutable, firefoxBeta.installByDefault, sdkLanguage),
525
576
  installType: firefoxBeta.installByDefault ? 'download-by-default' : 'download-on-demand',
526
- _validateHostRequirements: sdkLanguage => this._validateHostRequirements(sdkLanguage, 'firefox', firefoxBeta.dir, ['firefox'], [], ['firefox']),
577
+ _validateHostRequirements: sdkLanguage => this._validateHostRequirements(sdkLanguage, firefoxBeta.dir, ['firefox'], [], ['firefox']),
527
578
  downloadURLs: this._downloadURLs(firefoxBeta),
528
579
  browserVersion: firefoxBeta.browserVersion,
529
580
  _install: () => this._downloadExecutable(firefoxBeta, firefoxBetaExecutable),
@@ -541,7 +592,7 @@ class Registry {
541
592
  executablePath: () => webkitExecutable,
542
593
  executablePathOrDie: sdkLanguage => executablePathOrDie('webkit', webkitExecutable, webkit.installByDefault, sdkLanguage),
543
594
  installType: webkit.installByDefault ? 'download-by-default' : 'download-on-demand',
544
- _validateHostRequirements: sdkLanguage => this._validateHostRequirements(sdkLanguage, 'webkit', webkit.dir, webkitLinuxLddDirectories, ['libGLESv2.so.2', 'libx264.so'], ['']),
595
+ _validateHostRequirements: sdkLanguage => this._validateHostRequirements(sdkLanguage, webkit.dir, webkitLinuxLddDirectories, ['libGLESv2.so.2', 'libx264.so'], ['']),
545
596
  downloadURLs: this._downloadURLs(webkit),
546
597
  browserVersion: webkit.browserVersion,
547
598
  _install: () => this._downloadExecutable(webkit, webkitExecutable),
@@ -695,20 +746,15 @@ class Registry {
695
746
  defaultExecutables() {
696
747
  return this._executables.filter(e => e.installType === 'download-by-default');
697
748
  }
698
- _addRequirementsAndDedupe(executables) {
699
- const set = new Set();
700
- for (const executable of executables) {
701
- set.add(executable);
702
- if (executable.browserName === 'chromium') set.add(this.findExecutable('ffmpeg'));
703
- }
704
- return Array.from(set);
749
+ _dedupe(executables) {
750
+ return Array.from(new Set(executables));
705
751
  }
706
- async _validateHostRequirements(sdkLanguage, browserName, browserDirectory, linuxLddDirectories, dlOpenLibraries, windowsExeAndDllDirectories) {
752
+ async _validateHostRequirements(sdkLanguage, browserDirectory, linuxLddDirectories, dlOpenLibraries, windowsExeAndDllDirectories) {
707
753
  if (os.platform() === 'linux') return await (0, _dependencies.validateDependenciesLinux)(sdkLanguage, linuxLddDirectories.map(d => _path.default.join(browserDirectory, d)), dlOpenLibraries);
708
754
  if (os.platform() === 'win32' && os.arch() === 'x64') return await (0, _dependencies.validateDependenciesWindows)(windowsExeAndDllDirectories.map(d => _path.default.join(browserDirectory, d)));
709
755
  }
710
756
  async installDeps(executablesToInstallDeps, dryRun) {
711
- const executables = this._addRequirementsAndDedupe(executablesToInstallDeps);
757
+ const executables = this._dedupe(executablesToInstallDeps);
712
758
  const targets = new Set();
713
759
  for (const executable of executables) {
714
760
  if (executable._dependencyGroup) targets.add(executable._dependencyGroup);
@@ -718,7 +764,7 @@ class Registry {
718
764
  if (os.platform() === 'linux') return await (0, _dependencies.installDependenciesLinux)(targets, dryRun);
719
765
  }
720
766
  async install(executablesToInstall, forceReinstall) {
721
- const executables = this._addRequirementsAndDedupe(executablesToInstall);
767
+ const executables = this._dedupe(executablesToInstall);
722
768
  await fs.promises.mkdir(registryDirectory, {
723
769
  recursive: true
724
770
  });
@@ -826,6 +872,11 @@ class Registry {
826
872
  const downloadURLs = this._downloadURLs(descriptor);
827
873
  if (!downloadURLs.length) throw new Error(`ERROR: Playwright does not support ${descriptor.name} on ${_hostPlatform.hostPlatform}`);
828
874
  if (!_hostPlatform.isOfficiallySupportedPlatform) (0, _browserFetcher.logPolitely)(`BEWARE: your OS is not officially supported by Playwright; downloading fallback build for ${_hostPlatform.hostPlatform}.`);
875
+ if (descriptor.hasRevisionOverride) {
876
+ const message = `You are using a frozen ${descriptor.name} browser which does not receive updates anymore on ${_hostPlatform.hostPlatform}. Please update to the latest version of your operating system to test up-to-date browsers.`;
877
+ if (process.env.GITHUB_ACTIONS) console.log(`::warning title=Playwright::${message}`); // eslint-disable-line no-console
878
+ else (0, _browserFetcher.logPolitely)(message);
879
+ }
829
880
  const displayName = descriptor.name.split('-').map(word => {
830
881
  return word === 'ffmpeg' ? 'FFMPEG' : word.charAt(0).toUpperCase() + word.slice(1);
831
882
  }).join(' ');
@@ -959,10 +1010,6 @@ function buildPlaywrightCLICommand(sdkLanguage, parameters) {
959
1010
  }
960
1011
  }
961
1012
  }
962
- async function installDefaultBrowsersForNpmInstall() {
963
- const defaultBrowserNames = registry.defaultExecutables().map(e => e.name);
964
- return installBrowsersForNpmInstall(defaultBrowserNames);
965
- }
966
1013
  async function installBrowsersForNpmInstall(browsers) {
967
1014
  // PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD should have a value of 0 or 1
968
1015
  if ((0, _utils.getAsBooleanFromENV)('PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD')) {
@@ -129,8 +129,9 @@ const deps = exports.deps = {
129
129
  tools: ['xvfb', 'fonts-noto-color-emoji', 'fonts-unifont', 'libfontconfig1', 'libfreetype6', 'xfonts-cyrillic', 'xfonts-scalable', 'fonts-liberation', 'fonts-ipafont-gothic', 'fonts-wqy-zenhei', 'fonts-tlwg-loma-otf', 'fonts-freefont-ttf'],
130
130
  chromium: ['libasound2', 'libatk-bridge2.0-0', 'libatk1.0-0', 'libatspi2.0-0', 'libcairo2', 'libcups2', 'libdbus-1-3', 'libdrm2', 'libgbm1', 'libglib2.0-0', 'libnspr4', 'libnss3', 'libpango-1.0-0', 'libwayland-client0', 'libx11-6', 'libxcb1', 'libxcomposite1', 'libxdamage1', 'libxext6', 'libxfixes3', 'libxkbcommon0', 'libxrandr2'],
131
131
  firefox: ['ffmpeg', 'libasound2', 'libatk1.0-0', 'libcairo-gobject2', 'libcairo2', 'libdbus-1-3', 'libdbus-glib-1-2', 'libfontconfig1', 'libfreetype6', 'libgdk-pixbuf-2.0-0', 'libglib2.0-0', 'libgtk-3-0', 'libpango-1.0-0', 'libpangocairo-1.0-0', 'libx11-6', 'libx11-xcb1', 'libxcb-shm0', 'libxcb1', 'libxcomposite1', 'libxcursor1', 'libxdamage1', 'libxext6', 'libxfixes3', 'libxi6', 'libxrandr2', 'libxrender1', 'libxtst6'],
132
- webkit: ['libsoup-3.0-0', 'libenchant-2-2', 'gstreamer1.0-libav', 'gstreamer1.0-plugins-bad', 'gstreamer1.0-plugins-base', 'gstreamer1.0-plugins-good', 'libicu70', 'libatk-bridge2.0-0', 'libatk1.0-0', 'libcairo2', 'libdbus-1-3', 'libdrm2', 'libegl1', 'libepoxy0', 'libevdev2', 'libffi7', 'libfontconfig1', 'libfreetype6', 'libgbm1', 'libgdk-pixbuf-2.0-0', 'libgles2', 'libglib2.0-0', 'libglx0', 'libgstreamer-gl1.0-0', 'libgstreamer-plugins-base1.0-0', 'libgstreamer1.0-0', 'libgtk-3-0', 'libgudev-1.0-0', 'libharfbuzz-icu0', 'libharfbuzz0b', 'libhyphen0', 'libjpeg-turbo8', 'liblcms2-2', 'libmanette-0.2-0', 'libnotify4', 'libopengl0', 'libopenjp2-7', 'libopus0', 'libpango-1.0-0', 'libpng16-16', 'libproxy1v5', 'libsecret-1-0', 'libwayland-client0', 'libwayland-egl1', 'libwayland-server0', 'libwebpdemux2', 'libwoff1', 'libx11-6', 'libxcomposite1', 'libxdamage1', 'libxkbcommon0', 'libxml2', 'libxslt1.1', 'libx264-163', 'libatomic1', 'libevent-2.1-7'],
132
+ webkit: ['libsoup-3.0-0', 'libenchant-2-2', 'gstreamer1.0-libav', 'gstreamer1.0-plugins-bad', 'gstreamer1.0-plugins-base', 'gstreamer1.0-plugins-good', 'libicu70', 'libatk-bridge2.0-0', 'libatk1.0-0', 'libcairo2', 'libdbus-1-3', 'libdrm2', 'libegl1', 'libepoxy0', 'libevdev2', 'libffi7', 'libfontconfig1', 'libfreetype6', 'libgbm1', 'libgdk-pixbuf-2.0-0', 'libgles2', 'libglib2.0-0', 'libglx0', 'libgstreamer-gl1.0-0', 'libgstreamer-plugins-base1.0-0', 'libgstreamer1.0-0', 'libgtk-3-0', 'libgudev-1.0-0', 'libharfbuzz-icu0', 'libharfbuzz0b', 'libhyphen0', 'libjpeg-turbo8', 'liblcms2-2', 'libmanette-0.2-0', 'libnotify4', 'libopengl0', 'libopenjp2-7', 'libopus0', 'libpango-1.0-0', 'libpng16-16', 'libproxy1v5', 'libsecret-1-0', 'libwayland-client0', 'libwayland-egl1', 'libwayland-server0', 'libwebpdemux2', 'libwoff1', 'libx11-6', 'libxcomposite1', 'libxdamage1', 'libxkbcommon0', 'libxml2', 'libxslt1.1', 'libx264-163', 'libatomic1', 'libevent-2.1-7', 'libavif13'],
133
133
  lib2package: {
134
+ 'libavif.so.13': 'libavif13',
134
135
  'libsoup-3.0.so.0': 'libsoup-3.0-0',
135
136
  'libasound.so.2': 'libasound2',
136
137
  'libatk-1.0.so.0': 'libatk1.0-0',
@@ -224,8 +225,9 @@ const deps = exports.deps = {
224
225
  tools: ['xvfb', 'fonts-noto-color-emoji', 'fonts-unifont', 'libfontconfig1', 'libfreetype6', 'xfonts-cyrillic', 'xfonts-scalable', 'fonts-liberation', 'fonts-ipafont-gothic', 'fonts-wqy-zenhei', 'fonts-tlwg-loma-otf', 'fonts-freefont-ttf'],
225
226
  chromium: ['libasound2t64', 'libatk-bridge2.0-0t64', 'libatk1.0-0t64', 'libatspi2.0-0t64', 'libcairo2', 'libcups2t64', 'libdbus-1-3', 'libdrm2', 'libgbm1', 'libglib2.0-0t64', 'libnspr4', 'libnss3', 'libpango-1.0-0', 'libx11-6', 'libxcb1', 'libxcomposite1', 'libxdamage1', 'libxext6', 'libxfixes3', 'libxkbcommon0', 'libxrandr2'],
226
227
  firefox: ['libasound2t64', 'libatk1.0-0t64', 'libcairo-gobject2', 'libcairo2', 'libdbus-1-3', 'libfontconfig1', 'libfreetype6', 'libgdk-pixbuf-2.0-0', 'libglib2.0-0t64', 'libgtk-3-0t64', 'libpango-1.0-0', 'libpangocairo-1.0-0', 'libx11-6', 'libx11-xcb1', 'libxcb-shm0', 'libxcb1', 'libxcomposite1', 'libxcursor1', 'libxdamage1', 'libxext6', 'libxfixes3', 'libxi6', 'libxrandr2', 'libxrender1'],
227
- webkit: ['gstreamer1.0-libav', 'gstreamer1.0-plugins-bad', 'gstreamer1.0-plugins-base', 'gstreamer1.0-plugins-good', 'libicu74', 'libatomic1', 'libatk-bridge2.0-0t64', 'libatk1.0-0t64', 'libcairo-gobject2', 'libcairo2', 'libdbus-1-3', 'libdrm2', 'libenchant-2-2', 'libepoxy0', 'libevent-2.1-7t64', 'libflite1', 'libfontconfig1', 'libfreetype6', 'libgbm1', 'libgdk-pixbuf-2.0-0', 'libgles2', 'libglib2.0-0t64', 'libgstreamer-gl1.0-0', 'libgstreamer-plugins-bad1.0-0', 'libgstreamer-plugins-base1.0-0', 'libgstreamer1.0-0', 'libgtk-3-0t64', 'libharfbuzz-icu0', 'libharfbuzz0b', 'libhyphen0', 'libicu74', 'libjpeg-turbo8', 'liblcms2-2', 'libmanette-0.2-0', 'libopus0', 'libpango-1.0-0', 'libpangocairo-1.0-0', 'libpng16-16t64', 'libsecret-1-0', 'libvpx9', 'libwayland-client0', 'libwayland-egl1', 'libwayland-server0', 'libwebp7', 'libwebpdemux2', 'libwoff1', 'libx11-6', 'libxkbcommon0', 'libxml2', 'libxslt1.1', 'libx264-164'],
228
+ webkit: ['gstreamer1.0-libav', 'gstreamer1.0-plugins-bad', 'gstreamer1.0-plugins-base', 'gstreamer1.0-plugins-good', 'libicu74', 'libatomic1', 'libatk-bridge2.0-0t64', 'libatk1.0-0t64', 'libcairo-gobject2', 'libcairo2', 'libdbus-1-3', 'libdrm2', 'libenchant-2-2', 'libepoxy0', 'libevent-2.1-7t64', 'libflite1', 'libfontconfig1', 'libfreetype6', 'libgbm1', 'libgdk-pixbuf-2.0-0', 'libgles2', 'libglib2.0-0t64', 'libgstreamer-gl1.0-0', 'libgstreamer-plugins-bad1.0-0', 'libgstreamer-plugins-base1.0-0', 'libgstreamer1.0-0', 'libgtk-3-0t64', 'libharfbuzz-icu0', 'libharfbuzz0b', 'libhyphen0', 'libicu74', 'libjpeg-turbo8', 'liblcms2-2', 'libmanette-0.2-0', 'libopus0', 'libpango-1.0-0', 'libpangocairo-1.0-0', 'libpng16-16t64', 'libsecret-1-0', 'libvpx9', 'libwayland-client0', 'libwayland-egl1', 'libwayland-server0', 'libwebp7', 'libwebpdemux2', 'libwoff1', 'libx11-6', 'libxkbcommon0', 'libxml2', 'libxslt1.1', 'libx264-164', 'libavif16'],
228
229
  lib2package: {
230
+ 'libavif.so.16': 'libavif16',
229
231
  'libasound.so.2': 'libasound2t64',
230
232
  'libatk-1.0.so.0': 'libatk1.0-0t64',
231
233
  'libatk-bridge-2.0.so.0': 'libatk-bridge2.0-0t64',
@@ -412,8 +414,9 @@ const deps = exports.deps = {
412
414
  tools: ['xvfb', 'fonts-noto-color-emoji', 'fonts-unifont', 'libfontconfig1', 'libfreetype6', 'xfonts-scalable', 'fonts-liberation', 'fonts-ipafont-gothic', 'fonts-wqy-zenhei', 'fonts-tlwg-loma-otf', 'fonts-freefont-ttf'],
413
415
  chromium: ['libasound2', 'libatk-bridge2.0-0', 'libatk1.0-0', 'libatspi2.0-0', 'libcairo2', 'libcups2', 'libdbus-1-3', 'libdrm2', 'libgbm1', 'libglib2.0-0', 'libnspr4', 'libnss3', 'libpango-1.0-0', 'libx11-6', 'libxcb1', 'libxcomposite1', 'libxdamage1', 'libxext6', 'libxfixes3', 'libxkbcommon0', 'libxrandr2'],
414
416
  firefox: ['libasound2', 'libatk1.0-0', 'libcairo-gobject2', 'libcairo2', 'libdbus-1-3', 'libdbus-glib-1-2', 'libfontconfig1', 'libfreetype6', 'libgdk-pixbuf-2.0-0', 'libglib2.0-0', 'libgtk-3-0', 'libharfbuzz0b', 'libpango-1.0-0', 'libpangocairo-1.0-0', 'libx11-6', 'libx11-xcb1', 'libxcb-shm0', 'libxcb1', 'libxcomposite1', 'libxcursor1', 'libxdamage1', 'libxext6', 'libxfixes3', 'libxi6', 'libxrandr2', 'libxrender1', 'libxtst6'],
415
- webkit: ['libsoup-3.0-0', 'gstreamer1.0-libav', 'gstreamer1.0-plugins-bad', 'gstreamer1.0-plugins-base', 'gstreamer1.0-plugins-good', 'libatk-bridge2.0-0', 'libatk1.0-0', 'libcairo2', 'libdbus-1-3', 'libdrm2', 'libegl1', 'libenchant-2-2', 'libepoxy0', 'libevdev2', 'libfontconfig1', 'libfreetype6', 'libgbm1', 'libgdk-pixbuf-2.0-0', 'libgles2', 'libglib2.0-0', 'libglx0', 'libgstreamer-gl1.0-0', 'libgstreamer-plugins-base1.0-0', 'libgstreamer1.0-0', 'libgtk-3-0', 'libgudev-1.0-0', 'libharfbuzz-icu0', 'libharfbuzz0b', 'libhyphen0', 'libicu72', 'libjpeg62-turbo', 'liblcms2-2', 'libmanette-0.2-0', 'libnotify4', 'libopengl0', 'libopenjp2-7', 'libopus0', 'libpango-1.0-0', 'libpng16-16', 'libproxy1v5', 'libsecret-1-0', 'libwayland-client0', 'libwayland-egl1', 'libwayland-server0', 'libwebp7', 'libwebpdemux2', 'libwoff1', 'libx11-6', 'libxcomposite1', 'libxdamage1', 'libxkbcommon0', 'libxml2', 'libxslt1.1', 'libatomic1', 'libevent-2.1-7'],
417
+ webkit: ['libsoup-3.0-0', 'gstreamer1.0-libav', 'gstreamer1.0-plugins-bad', 'gstreamer1.0-plugins-base', 'gstreamer1.0-plugins-good', 'libatk-bridge2.0-0', 'libatk1.0-0', 'libcairo2', 'libdbus-1-3', 'libdrm2', 'libegl1', 'libenchant-2-2', 'libepoxy0', 'libevdev2', 'libfontconfig1', 'libfreetype6', 'libgbm1', 'libgdk-pixbuf-2.0-0', 'libgles2', 'libglib2.0-0', 'libglx0', 'libgstreamer-gl1.0-0', 'libgstreamer-plugins-base1.0-0', 'libgstreamer1.0-0', 'libgtk-3-0', 'libgudev-1.0-0', 'libharfbuzz-icu0', 'libharfbuzz0b', 'libhyphen0', 'libicu72', 'libjpeg62-turbo', 'liblcms2-2', 'libmanette-0.2-0', 'libnotify4', 'libopengl0', 'libopenjp2-7', 'libopus0', 'libpango-1.0-0', 'libpng16-16', 'libproxy1v5', 'libsecret-1-0', 'libwayland-client0', 'libwayland-egl1', 'libwayland-server0', 'libwebp7', 'libwebpdemux2', 'libwoff1', 'libx11-6', 'libxcomposite1', 'libxdamage1', 'libxkbcommon0', 'libxml2', 'libxslt1.1', 'libatomic1', 'libevent-2.1-7', 'libavif15'],
416
418
  lib2package: {
419
+ 'libavif.so.15': 'libavif15',
417
420
  'libsoup-3.0.so.0': 'libsoup-3.0-0',
418
421
  'libasound.so.2': 'libasound2',
419
422
  'libatk-1.0.so.0': 'libatk1.0-0',
@@ -107,7 +107,7 @@ class SocksProxyConnection {
107
107
  };
108
108
  }
109
109
  async connect() {
110
- if (this.socksProxy.proxyAgentFromOptions) this.target = await this.socksProxy.proxyAgentFromOptions.callback(new _events.EventEmitter(), {
110
+ if (this.socksProxy.proxyAgentFromOptions) this.target = await this.socksProxy.proxyAgentFromOptions.connect(new _events.EventEmitter(), {
111
111
  host: rewriteToLocalhostIfNeeded(this.host),
112
112
  port: this.port,
113
113
  secureEndpoint: false
@@ -81,21 +81,10 @@ class Snapshotter {
81
81
  dispose() {
82
82
  _eventsHelper.eventsHelper.removeEventListeners(this._eventListeners);
83
83
  }
84
- async captureSnapshot(page, callId, snapshotName, element) {
84
+ async captureSnapshot(page, callId, snapshotName) {
85
85
  // Prepare expression synchronously.
86
86
  const expression = `window["${this._snapshotStreamer}"].captureSnapshot(${JSON.stringify(snapshotName)})`;
87
87
 
88
- // In a best-effort manner, without waiting for it, mark target element.
89
- element === null || element === void 0 || element.callFunctionNoReply((element, callId) => {
90
- const customEvent = new CustomEvent('__playwright_target__', {
91
- bubbles: true,
92
- cancelable: true,
93
- detail: callId,
94
- composed: true
95
- });
96
- element.dispatchEvent(customEvent);
97
- }, callId);
98
-
99
88
  // In each frame, in a non-stalling manner, capture the snapshots.
100
89
  const snapshots = page.frames().map(async frame => {
101
90
  const data = await frame.nonStallingRawEvaluateInExistingMainContext(expression).catch(e => _debugLogger.debugLogger.log('error', e));
@@ -35,6 +35,7 @@ function frameSnapshotStreamer(snapshotStreamer, removeNoScript) {
35
35
  const kTargetAttribute = '__playwright_target__';
36
36
  const kCustomElementsAttribute = '__playwright_custom_elements__';
37
37
  const kCurrentSrcAttribute = '__playwright_current_src__';
38
+ const kBoundingRectAttribute = '__playwright_bounding_rect__';
38
39
 
39
40
  // Symbols for our own info on Nodes/StyleSheets.
40
41
  const kSnapshotFrameId = Symbol('__playwright_snapshot_frameid_');
@@ -112,11 +113,16 @@ function frameSnapshotStreamer(snapshotStreamer, removeNoScript) {
112
113
  });
113
114
  }
114
115
  _refreshListeners() {
115
- document.addEventListener('__playwright_target__', event => {
116
+ document.addEventListener('__playwright_mark_target__', event => {
116
117
  if (!event.detail) return;
117
118
  const callId = event.detail;
118
119
  event.composedPath()[0].__playwright_target__ = callId;
119
120
  });
121
+ document.addEventListener('__playwright_unmark_target__', event => {
122
+ if (!event.detail) return;
123
+ const callId = event.detail;
124
+ if (event.composedPath()[0].__playwright_target__ === callId) delete event.composedPath()[0].__playwright_target__;
125
+ });
120
126
  }
121
127
  _interceptNativeMethod(obj, method, cb) {
122
128
  const native = obj[method];
@@ -348,6 +354,18 @@ function frameSnapshotStreamer(snapshotStreamer, removeNoScript) {
348
354
  expectValue(value);
349
355
  attrs[kSelectedAttribute] = value;
350
356
  }
357
+ if (nodeName === 'CANVAS') {
358
+ const boundingRect = element.getBoundingClientRect();
359
+ const value = JSON.stringify({
360
+ left: boundingRect.left / window.innerWidth,
361
+ top: boundingRect.top / window.innerHeight,
362
+ right: boundingRect.right / window.innerWidth,
363
+ bottom: boundingRect.bottom / window.innerHeight
364
+ });
365
+ expectValue(kBoundingRectAttribute);
366
+ expectValue(value);
367
+ attrs[kBoundingRectAttribute] = value;
368
+ }
351
369
  if (element.scrollTop) {
352
370
  expectValue(kScrollTopAttribute);
353
371
  expectValue(element.scrollTop);