patchright-core 1.49.2 → 1.50.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 (128) hide show
  1. package/ThirdPartyNotices.txt +380 -12
  2. package/bin/reinstall_msedge_beta_linux.sh +6 -0
  3. package/bin/reinstall_msedge_dev_linux.sh +6 -0
  4. package/bin/reinstall_msedge_stable_linux.sh +6 -0
  5. package/browsers.json +17 -16
  6. package/lib/androidServerImpl.js +1 -1
  7. package/lib/cli/program.js +6 -30
  8. package/lib/client/channelOwner.js +35 -55
  9. package/lib/client/clientInstrumentation.js +2 -0
  10. package/lib/client/connection.js +3 -3
  11. package/lib/client/network.js +3 -1
  12. package/lib/client/waiter.js +1 -1
  13. package/lib/generated/consoleApiSource.js +1 -1
  14. package/lib/generated/injectedScriptSource.js +1 -1
  15. package/lib/generated/pollingRecorderSource.js +1 -1
  16. package/lib/inProcessFactory.js +2 -0
  17. package/lib/protocol/debug.js +1 -1
  18. package/lib/protocol/validator.js +2 -2
  19. package/lib/remote/playwrightConnection.js +4 -3
  20. package/lib/remote/playwrightServer.js +2 -1
  21. package/lib/server/bidi/bidiBrowser.js +9 -6
  22. package/lib/server/bidi/bidiExecutionContext.js +20 -1
  23. package/lib/server/bidi/bidiInput.js +7 -5
  24. package/lib/server/bidi/bidiNetworkManager.js +8 -9
  25. package/lib/server/bidi/bidiPage.js +9 -20
  26. package/lib/server/bidi/third_party/bidiKeyboard.js +9 -7
  27. package/lib/server/browserContext.js +24 -16
  28. package/lib/server/chromium/crBrowser.js +10 -10
  29. package/lib/server/chromium/crExecutionContext.js +1 -5
  30. package/lib/server/chromium/crInput.js +15 -4
  31. package/lib/server/chromium/crPage.js +17 -31
  32. package/lib/server/codegen/csharp.js +12 -2
  33. package/lib/server/codegen/java.js +14 -3
  34. package/lib/server/codegen/javascript.js +10 -2
  35. package/lib/server/codegen/jsonl.js +1 -1
  36. package/lib/server/codegen/python.js +5 -4
  37. package/lib/server/debugController.js +15 -40
  38. package/lib/server/debugger.js +1 -1
  39. package/lib/server/deviceDescriptorsSource.json +50 -50
  40. package/lib/server/dispatchers/browserContextDispatcher.js +2 -13
  41. package/lib/server/dispatchers/debugControllerDispatcher.js +4 -2
  42. package/lib/server/dispatchers/frameDispatcher.js +3 -2
  43. package/lib/server/dispatchers/pageDispatcher.js +1 -1
  44. package/lib/server/dispatchers/webSocketRouteDispatcher.js +10 -11
  45. package/lib/server/dom.js +7 -2
  46. package/lib/server/fetch.js +14 -20
  47. package/lib/server/firefox/ffBrowser.js +9 -7
  48. package/lib/server/firefox/ffInput.js +15 -4
  49. package/lib/server/firefox/ffPage.js +13 -28
  50. package/lib/server/frames.js +25 -30
  51. package/lib/server/har/harTracer.js +1 -1
  52. package/lib/server/input.js +2 -3
  53. package/lib/server/network.js +2 -2
  54. package/lib/server/page.js +23 -16
  55. package/lib/server/recorder/chat.js +177 -0
  56. package/lib/server/recorder/contextRecorder.js +6 -15
  57. package/lib/server/recorder/recorderApp.js +1 -1
  58. package/lib/server/recorder/recorderCollection.js +5 -17
  59. package/lib/server/recorder/recorderRunner.js +7 -3
  60. package/lib/server/recorder/recorderUtils.js +5 -29
  61. package/lib/server/recorder.js +12 -9
  62. package/lib/server/registry/browserFetcher.js +1 -1
  63. package/lib/server/registry/dependencies.js +5 -5
  64. package/lib/server/registry/index.js +118 -5
  65. package/lib/server/registry/nativeDeps.js +7 -4
  66. package/lib/server/socksClientCertificatesInterceptor.js +1 -1
  67. package/lib/server/trace/recorder/snapshotterInjected.js +12 -5
  68. package/lib/server/trace/viewer/traceViewer.js +6 -1
  69. package/lib/server/transport.js +1 -0
  70. package/lib/server/webkit/webkit.js +1 -1
  71. package/lib/server/webkit/wkBrowser.js +6 -6
  72. package/lib/server/webkit/wkExecutionContext.js +1 -0
  73. package/lib/server/webkit/wkInput.js +15 -5
  74. package/lib/server/webkit/wkPage.js +7 -25
  75. package/lib/utils/comparators.js +16 -10
  76. package/lib/utils/debugLogger.js +3 -1
  77. package/lib/utils/hostPlatform.js +14 -8
  78. package/lib/utils/httpServer.js +0 -4
  79. package/lib/utils/isomorphic/ariaSnapshot.js +176 -52
  80. package/lib/utils/isomorphic/cssParser.js +4 -4
  81. package/lib/utils/isomorphic/locatorGenerators.js +2 -2
  82. package/lib/utils/isomorphic/locatorParser.js +18 -12
  83. package/lib/utils/isomorphic/urlMatch.js +2 -4
  84. package/lib/utils/network.js +1 -1
  85. package/lib/utils/processLauncher.js +1 -1
  86. package/lib/utils/wsServer.js +1 -0
  87. package/lib/utils/zones.js +18 -20
  88. package/lib/utilsBundleImpl/index.js +104 -104
  89. package/lib/vite/htmlReport/index.html +14 -14
  90. package/lib/vite/{traceViewer/assets/codeMirrorModule-VZNWuWvU.js → recorder/assets/codeMirrorModule-CNAqJrkA.js} +1 -1
  91. package/lib/vite/recorder/assets/{index-CqeZmzx8.js → index-DGS0JLxS.js} +78 -78
  92. package/lib/vite/recorder/assets/{index-iA1aAGZg.css → index-eHBmevrY.css} +1 -1
  93. package/lib/vite/recorder/index.html +2 -2
  94. package/lib/vite/{recorder/assets/codeMirrorModule-DUzBrnvO.js → traceViewer/assets/codeMirrorModule-D55P_UuL.js} +10 -10
  95. package/lib/vite/traceViewer/assets/defaultSettingsView-B-uNoFsX.js +243 -0
  96. package/lib/vite/traceViewer/defaultSettingsView.2xeEXCXv.css +1 -0
  97. package/lib/vite/traceViewer/index.BfvuujqP.js +2 -0
  98. package/lib/vite/traceViewer/index.html +4 -7
  99. package/lib/vite/traceViewer/sw.bundle.js +3 -3
  100. package/lib/vite/traceViewer/{uiMode.voC1ZiOQ.css → uiMode.BatfzHMG.css} +1 -1
  101. package/lib/vite/traceViewer/uiMode.CStJu6jo.js +5 -0
  102. package/lib/vite/traceViewer/uiMode.html +4 -7
  103. package/package.json +1 -1
  104. package/types/protocol.d.ts +269 -20
  105. package/types/types.d.ts +69 -30
  106. package/bin/PrintDeps.exe +0 -0
  107. package/bin/README.md +0 -2
  108. package/lib/server/ariaSnapshot.js +0 -33
  109. package/lib/server/recorder/recorderInTraceViewer.js +0 -144
  110. package/lib/utils/isomorphic/recorderUtils.js +0 -227
  111. package/lib/vite/traceViewer/assets/inspectorTab-BV-Uf3j9.js +0 -68
  112. package/lib/vite/traceViewer/assets/testServerConnection-DeE2kSzz.js +0 -1
  113. package/lib/vite/traceViewer/assets/workbench-B4WPcYi9.js +0 -9
  114. package/lib/vite/traceViewer/embedded.BLPSqdbm.js +0 -2
  115. package/lib/vite/traceViewer/embedded.html +0 -18
  116. package/lib/vite/traceViewer/embedded.w7WN2u1R.css +0 -1
  117. package/lib/vite/traceViewer/index.BGZfFXXF.js +0 -2
  118. package/lib/vite/traceViewer/inspectorTab.DEOUW62d.css +0 -1
  119. package/lib/vite/traceViewer/recorder.B_SY1GJM.css +0 -0
  120. package/lib/vite/traceViewer/recorder.eWs2vuTG.js +0 -2
  121. package/lib/vite/traceViewer/recorder.html +0 -17
  122. package/lib/vite/traceViewer/uiMode.CW2d9h0S.js +0 -5
  123. package/lib/vite/traceViewer/workbench.C-zR9ysA.css +0 -1
  124. /package/lib/vite/recorder/assets/{codeMirrorModule-ez37Vkbh.css → codeMirrorModule-C3UTv-Ge.css} +0 -0
  125. /package/lib/vite/traceViewer/assets/{xtermModule-BeNbaIVa.js → xtermModule-c-SNdYZy.js} +0 -0
  126. /package/lib/vite/traceViewer/{codeMirrorModule.ez37Vkbh.css → codeMirrorModule.C3UTv-Ge.css} +0 -0
  127. /package/lib/vite/traceViewer/{index.CrbWWHbf.css → index.CFOW-Ezb.css} +0 -0
  128. /package/lib/vite/traceViewer/{xtermModule.DSXBckUd.css → xtermModule.Beg8tuEN.css} +0 -0
@@ -28,8 +28,6 @@ var _class;
28
28
  */
29
29
  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); }
30
30
  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; }
31
- const kBindingInstalledSymbol = Symbol('webSocketRouteBindingInstalled');
32
- const kInitScriptInstalledSymbol = Symbol('webSocketRouteInitScriptInstalled');
33
31
  class WebSocketRouteDispatcher extends _dispatcher.Dispatcher {
34
32
  constructor(scope, id, url, frame) {
35
33
  super(scope, {
@@ -55,15 +53,16 @@ class WebSocketRouteDispatcher extends _dispatcher.Dispatcher {
55
53
  webSocketRoute: this
56
54
  });
57
55
  }
58
- static async installIfNeeded(contextDispatcher, target) {
56
+ static async installIfNeeded(target) {
57
+ const kBindingName = '__pwWebSocketBinding';
59
58
  const context = target instanceof _page.Page ? target.context() : target;
60
- if (!context[kBindingInstalledSymbol]) {
61
- context[kBindingInstalledSymbol] = true;
62
- await context.exposeBinding('__pwWebSocketBinding', false, (source, payload) => {
59
+ if (!context.hasBinding(kBindingName)) {
60
+ await context.exposeBinding(kBindingName, false, (source, payload) => {
63
61
  if (payload.type === 'onCreate') {
64
- const pageDispatcher = _pageDispatcher.PageDispatcher.fromNullable(contextDispatcher, source.page);
62
+ const contextDispatcher = (0, _dispatcher.existingDispatcher)(context);
63
+ const pageDispatcher = contextDispatcher ? _pageDispatcher.PageDispatcher.fromNullable(contextDispatcher, source.page) : undefined;
65
64
  let scope;
66
- if (pageDispatcher && matchesPattern(pageDispatcher, context._options.baseURL, payload.url)) scope = pageDispatcher;else if (matchesPattern(contextDispatcher, context._options.baseURL, payload.url)) scope = contextDispatcher;
65
+ if (pageDispatcher && matchesPattern(pageDispatcher, context._options.baseURL, payload.url)) scope = pageDispatcher;else if (contextDispatcher && matchesPattern(contextDispatcher, context._options.baseURL, payload.url)) scope = contextDispatcher;
67
66
  if (scope) {
68
67
  new WebSocketRouteDispatcher(scope, payload.id, payload.url, source.frame);
69
68
  } else {
@@ -96,15 +95,15 @@ class WebSocketRouteDispatcher extends _dispatcher.Dispatcher {
96
95
  });
97
96
  });
98
97
  }
99
- if (!target[kInitScriptInstalledSymbol]) {
100
- target[kInitScriptInstalledSymbol] = true;
98
+ const kInitScriptName = 'webSocketMockSource';
99
+ if (!target.initScripts.find(s => s.name === kInitScriptName)) {
101
100
  await target.addInitScript(`
102
101
  (() => {
103
102
  const module = {};
104
103
  ${webSocketMockSource.source}
105
104
  (module.exports.inject())(globalThis);
106
105
  })();
107
- `);
106
+ `, kInitScriptName);
108
107
  }
109
108
  }
110
109
  async connect(params) {
package/lib/server/dom.js CHANGED
@@ -7,6 +7,7 @@ exports.NonRecoverableDOMError = exports.FrameExecutionContext = exports.Element
7
7
  exports.assertDone = assertDone;
8
8
  exports.isNonRecoverableDOMError = isNonRecoverableDOMError;
9
9
  exports.kUnableToAdoptErrorMessage = void 0;
10
+ exports.throwElementIsNotAttached = throwElementIsNotAttached;
10
11
  exports.throwRetargetableDOMError = throwRetargetableDOMError;
11
12
  var _fs = _interopRequireDefault(require("fs"));
12
13
  var injectedScriptSource = _interopRequireWildcard(require("../generated/injectedScriptSource"));
@@ -711,7 +712,8 @@ class ElementHandle extends js.JSHandle {
711
712
  async _setChecked(progress, state, options) {
712
713
  const isChecked = async () => {
713
714
  const result = await this.evaluateInUtility(([injected, node]) => injected.elementState(node, 'checked'), {});
714
- return throwRetargetableDOMError(result);
715
+ if (result === 'error:notconnected' || result.received === 'error:notconnected') throwElementIsNotAttached();
716
+ return result.matches;
715
717
  };
716
718
  await this._markAsTargetElement(progress.metadata);
717
719
  if ((await isChecked()) === state) return 'done';
@@ -837,9 +839,12 @@ class ElementHandle extends js.JSHandle {
837
839
  }
838
840
  exports.ElementHandle = ElementHandle;
839
841
  function throwRetargetableDOMError(result) {
840
- if (result === 'error:notconnected') throw new Error('Element is not attached to the DOM');
842
+ if (result === 'error:notconnected') throwElementIsNotAttached();
841
843
  return result;
842
844
  }
845
+ function throwElementIsNotAttached() {
846
+ throw new Error('Element is not attached to the DOM');
847
+ }
843
848
  function assertDone(result) {
844
849
  // This function converts 'done' to void and ensures typescript catches unhandled errors.
845
850
  }
@@ -8,6 +8,7 @@ exports.createProxyAgent = createProxyAgent;
8
8
  var _http = _interopRequireDefault(require("http"));
9
9
  var _https = _interopRequireDefault(require("https"));
10
10
  var _stream = require("stream");
11
+ var _url = _interopRequireDefault(require("url"));
11
12
  var _zlib = _interopRequireDefault(require("zlib"));
12
13
  var _timeoutSettings = require("../common/timeoutSettings");
13
14
  var _userAgent = require("../utils/userAgent");
@@ -388,7 +389,6 @@ class APIRequestContext extends _instrumentation.SdkObject {
388
389
  }));
389
390
  request.on('close', () => _utils.eventsHelper.removeEventListeners(listeners));
390
391
  request.on('socket', socket => {
391
- var _tcpConnectionAt, _tcpConnectionAt3;
392
392
  if (request.reusedSocket) {
393
393
  reusedSocketAt = (0, _utils.monotonicTime)();
394
394
  return;
@@ -397,14 +397,13 @@ class APIRequestContext extends _instrumentation.SdkObject {
397
397
  // happy eyeballs don't emit lookup and connect events, so we use our custom ones
398
398
  const happyEyeBallsTimings = (0, _happyEyeballs.timingForSocket)(socket);
399
399
  dnsLookupAt = happyEyeBallsTimings.dnsLookupAt;
400
- (_tcpConnectionAt = tcpConnectionAt) !== null && _tcpConnectionAt !== void 0 ? _tcpConnectionAt : tcpConnectionAt = happyEyeBallsTimings.tcpConnectionAt;
400
+ tcpConnectionAt = happyEyeBallsTimings.tcpConnectionAt;
401
401
 
402
402
  // non-happy-eyeballs sockets
403
403
  listeners.push(_utils.eventsHelper.addEventListener(socket, 'lookup', () => {
404
404
  dnsLookupAt = (0, _utils.monotonicTime)();
405
405
  }), _utils.eventsHelper.addEventListener(socket, 'connect', () => {
406
- var _tcpConnectionAt2;
407
- (_tcpConnectionAt2 = tcpConnectionAt) !== null && _tcpConnectionAt2 !== void 0 ? _tcpConnectionAt2 : tcpConnectionAt = (0, _utils.monotonicTime)();
406
+ tcpConnectionAt = (0, _utils.monotonicTime)();
408
407
  }), _utils.eventsHelper.addEventListener(socket, 'secureConnect', () => {
409
408
  tlsHandshakeAt = (0, _utils.monotonicTime)();
410
409
  if (socket instanceof _tls.TLSSocket) {
@@ -419,21 +418,12 @@ class APIRequestContext extends _instrumentation.SdkObject {
419
418
  };
420
419
  }
421
420
  }));
422
-
423
- // when using socks proxy, having the socket means the connection got established
424
- if (agent instanceof _utilsBundle.SocksProxyAgent) (_tcpConnectionAt3 = tcpConnectionAt) !== null && _tcpConnectionAt3 !== void 0 ? _tcpConnectionAt3 : tcpConnectionAt = (0, _utils.monotonicTime)();
425
421
  serverIPAddress = socket.remoteAddress;
426
422
  serverPort = socket.remotePort;
427
423
  });
428
424
  request.on('finish', () => {
429
425
  requestFinishAt = (0, _utils.monotonicTime)();
430
426
  });
431
-
432
- // http proxy
433
- request.on('proxyConnect', () => {
434
- var _tcpConnectionAt4;
435
- (_tcpConnectionAt4 = tcpConnectionAt) !== null && _tcpConnectionAt4 !== void 0 ? _tcpConnectionAt4 : tcpConnectionAt = (0, _utils.monotonicTime)();
436
- });
437
427
  progress.log(`→ ${options.method} ${url.toString()}`);
438
428
  if (options.headers) {
439
429
  for (const [name, value] of Object.entries(options.headers)) progress.log(` ${name}: ${value}`);
@@ -579,13 +569,17 @@ class GlobalAPIRequestContext extends APIRequestContext {
579
569
  }
580
570
  exports.GlobalAPIRequestContext = GlobalAPIRequestContext;
581
571
  function createProxyAgent(proxy) {
582
- var _proxyURL$protocol;
583
- const proxyURL = new URL(proxy.server);
584
- if ((_proxyURL$protocol = proxyURL.protocol) !== null && _proxyURL$protocol !== void 0 && _proxyURL$protocol.startsWith('socks')) return new _utilsBundle.SocksProxyAgent(proxyURL);
585
- if (proxy.username) proxyURL.username = proxy.username;
586
- if (proxy.password) proxyURL.password = proxy.password;
587
- // TODO: We should use HttpProxyAgent conditional on proxyURL.protocol instead of always using CONNECT method.
588
- return new _utilsBundle.HttpsProxyAgent(proxyURL);
572
+ var _proxyOpts$protocol;
573
+ const proxyOpts = _url.default.parse(proxy.server);
574
+ if ((_proxyOpts$protocol = proxyOpts.protocol) !== null && _proxyOpts$protocol !== void 0 && _proxyOpts$protocol.startsWith('socks')) {
575
+ return new _utilsBundle.SocksProxyAgent({
576
+ host: proxyOpts.hostname,
577
+ port: proxyOpts.port || undefined
578
+ });
579
+ }
580
+ if (proxy.username) proxyOpts.auth = `${proxy.username}:${proxy.password || ''}`;
581
+ // TODO: We should use HttpProxyAgent conditional on proxyOpts.protocol instead of always using CONNECT method.
582
+ return new _utilsBundle.HttpsProxyAgent(proxyOpts);
589
583
  }
590
584
  function toHeadersArray(rawHeaders) {
591
585
  const result = [];
@@ -132,13 +132,13 @@ class FFBrowser extends _browser.Browser {
132
132
 
133
133
  // Abort the navigation that turned into download.
134
134
  ffPage._page._frameManager.frameAbortedNavigation(payload.frameId, 'Download is starting');
135
- let originPage = ffPage._initializedPage;
135
+ let originPage = ffPage._page.initializedOrUndefined();
136
136
  // If it's a new window download, report it on the opener page.
137
137
  if (!originPage) {
138
138
  // Resume the page creation with an error. The page will automatically close right
139
139
  // after the download begins.
140
140
  ffPage._markAsError(new Error('Starting new page download'));
141
- if (ffPage._opener) originPage = ffPage._opener._initializedPage;
141
+ if (ffPage._opener) originPage = ffPage._opener._page.initializedOrUndefined();
142
142
  }
143
143
  if (!originPage) return;
144
144
  this._downloadCreated(originPage, payload.uuid, payload.url, payload.suggestedFileName);
@@ -268,10 +268,10 @@ class FFBrowserContext extends _browserContext.BrowserContext {
268
268
  _ffPages() {
269
269
  return Array.from(this._browser._ffPages.values()).filter(ffPage => ffPage._browserContext === this);
270
270
  }
271
- pages() {
272
- return this._ffPages().map(ffPage => ffPage._initializedPage).filter(pageOrNull => !!pageOrNull);
271
+ possiblyUninitializedPages() {
272
+ return this._ffPages().map(ffPage => ffPage._page);
273
273
  }
274
- async newPageDelegate() {
274
+ async doCreateNewPage() {
275
275
  (0, _browserContext.assertBrowserContextIsNotOwned)(this);
276
276
  const {
277
277
  targetId
@@ -281,7 +281,7 @@ class FFBrowserContext extends _browserContext.BrowserContext {
281
281
  if (e.message.includes('Failed to override timezone')) throw new Error(`Invalid timezone ID: ${this._options.timezoneId}`);
282
282
  throw e;
283
283
  });
284
- return this._browser._ffPages.get(targetId);
284
+ return this._browser._ffPages.get(targetId)._page;
285
285
  }
286
286
  async doGetCookies(urls) {
287
287
  const {
@@ -457,4 +457,6 @@ function toJugglerProxyOptions(proxy) {
457
457
 
458
458
  // Prefs for quick fixes that didn't make it to the build.
459
459
  // Should all be moved to `playwright.cfg`.
460
- const kBandaidFirefoxUserPrefs = {};
460
+ const kBandaidFirefoxUserPrefs = {
461
+ 'dom.fetchKeepalive.enabled': false
462
+ };
@@ -47,12 +47,18 @@ class RawKeyboardImpl {
47
47
  this._client = void 0;
48
48
  this._client = client;
49
49
  }
50
- async keydown(modifiers, code, keyCode, keyCodeWithoutLocation, key, location, autoRepeat, text) {
50
+ async keydown(modifiers, keyName, description, autoRepeat) {
51
+ let text = description.text;
51
52
  // Firefox will figure out Enter by itself
52
53
  if (text === '\r') text = '';
54
+ const {
55
+ code,
56
+ key,
57
+ location
58
+ } = description;
53
59
  await this._client.send('Page.dispatchKeyEvent', {
54
60
  type: 'keydown',
55
- keyCode: keyCodeWithoutLocation,
61
+ keyCode: description.keyCodeWithoutLocation,
56
62
  code,
57
63
  key,
58
64
  repeat: autoRepeat,
@@ -60,11 +66,16 @@ class RawKeyboardImpl {
60
66
  text
61
67
  });
62
68
  }
63
- async keyup(modifiers, code, keyCode, keyCodeWithoutLocation, key, location) {
69
+ async keyup(modifiers, keyName, description) {
70
+ const {
71
+ code,
72
+ key,
73
+ location
74
+ } = description;
64
75
  await this._client.send('Page.dispatchKeyEvent', {
65
76
  type: 'keyup',
66
77
  key,
67
- keyCode: keyCodeWithoutLocation,
78
+ keyCode: description.keyCodeWithoutLocation,
68
79
  code,
69
80
  location,
70
81
  repeat: false
@@ -15,7 +15,6 @@ var _ffInput = require("./ffInput");
15
15
  var _ffNetworkManager = require("./ffNetworkManager");
16
16
  var _stackTrace = require("../../utils/stackTrace");
17
17
  var _debugLogger = require("../../utils/debugLogger");
18
- var _manualPromise = require("../../utils/manualPromise");
19
18
  var _browserContext = require("../browserContext");
20
19
  var _errors = require("../errors");
21
20
  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); }
@@ -48,9 +47,7 @@ class FFPage {
48
47
  this._page = void 0;
49
48
  this._networkManager = void 0;
50
49
  this._browserContext = void 0;
51
- this._pagePromise = new _manualPromise.ManualPromise();
52
- this._initializedPage = null;
53
- this._initializationFailed = false;
50
+ this._reportedAsNew = false;
54
51
  this._opener = void 0;
55
52
  this._contextIdToContext = void 0;
56
53
  this._eventListeners = void 0;
@@ -70,34 +67,22 @@ class FFPage {
70
67
  this._page.on(_page.Page.Events.FrameDetached, frame => this._removeContextsForFrame(frame));
71
68
  // TODO: remove Page.willOpenNewWindowAsynchronously from the protocol.
72
69
  this._eventListeners = [_eventsHelper.eventsHelper.addEventListener(this._session, 'Page.eventFired', this._onEventFired.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.frameAttached', this._onFrameAttached.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.frameDetached', this._onFrameDetached.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.navigationAborted', this._onNavigationAborted.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.navigationCommitted', this._onNavigationCommitted.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.navigationStarted', this._onNavigationStarted.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.sameDocumentNavigation', this._onSameDocumentNavigation.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Runtime.executionContextCreated', this._onExecutionContextCreated.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Runtime.executionContextDestroyed', this._onExecutionContextDestroyed.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Runtime.executionContextsCleared', this._onExecutionContextsCleared.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.linkClicked', event => this._onLinkClicked(event.phase)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.uncaughtError', this._onUncaughtError.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Runtime.console', this._onConsole.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.dialogOpened', this._onDialogOpened.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.bindingCalled', this._onBindingCalled.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.fileChooserOpened', this._onFileChooserOpened.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.workerCreated', this._onWorkerCreated.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.workerDestroyed', this._onWorkerDestroyed.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.dispatchMessageFromWorker', this._onDispatchMessageFromWorker.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.crashed', this._onCrashed.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.videoRecordingStarted', this._onVideoRecordingStarted.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.webSocketCreated', this._onWebSocketCreated.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.webSocketClosed', this._onWebSocketClosed.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.webSocketFrameReceived', this._onWebSocketFrameReceived.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.webSocketFrameSent', this._onWebSocketFrameSent.bind(this)), _eventsHelper.eventsHelper.addEventListener(this._session, 'Page.screencastFrame', this._onScreencastFrame.bind(this))];
73
- this._session.once('Page.ready', async () => {
74
- await this._page.initOpener(this._opener);
75
- if (this._initializationFailed) return;
76
- // Note: it is important to call |reportAsNew| before resolving pageOrError promise,
77
- // so that anyone who awaits pageOrError got a ready and reported page.
78
- this._initializedPage = this._page;
79
- this._page.reportAsNew();
80
- this._pagePromise.resolve(this._page);
70
+ this._session.once('Page.ready', () => {
71
+ var _this$_opener;
72
+ if (this._reportedAsNew) return;
73
+ this._reportedAsNew = true;
74
+ this._page.reportAsNew((_this$_opener = this._opener) === null || _this$_opener === void 0 ? void 0 : _this$_opener._page);
81
75
  });
82
76
  // Ideally, we somehow ensure that utility world is created before Page.ready arrives, but currently it is racy.
83
77
  // Therefore, we can end up with an initialized page without utility world, although very unlikely.
84
78
  this.addInitScript(new _page.InitScript('', true), UTILITY_WORLD_NAME).catch(e => this._markAsError(e));
85
79
  }
86
- potentiallyUninitializedPage() {
87
- return this._page;
88
- }
89
80
  async _markAsError(error) {
90
- // Same error may be report twice: channer disconnected and session.send fails.
91
- if (this._initializationFailed) return;
92
- this._initializationFailed = true;
93
- if (!this._initializedPage) {
94
- await this._page.initOpener(this._opener);
95
- this._page.reportAsNew(error);
96
- this._pagePromise.resolve(error);
97
- }
98
- }
99
- async pageOrError() {
100
- return this._pagePromise;
81
+ var _this$_opener2;
82
+ // Same error may be reported twice: channel disconnected and session.send fails.
83
+ if (this._reportedAsNew) return;
84
+ this._reportedAsNew = true;
85
+ this._page.reportAsNew((_this$_opener2 = this._opener) === null || _this$_opener2 === void 0 ? void 0 : _this$_opener2._page, error);
101
86
  }
102
87
  _onWebSocketCreated(event) {
103
88
  this._page._frameManager.onWebSocketCreated(webSocketId(event.frameId, event.wsid), event.requestURL);
@@ -213,7 +198,7 @@ class FFPage {
213
198
  }, params.defaultValue));
214
199
  }
215
200
  async _onBindingCalled(event) {
216
- const pageOrError = await this.pageOrError();
201
+ const pageOrError = await this._page.waitForInitializedOrError();
217
202
  if (!(pageOrError instanceof Error)) {
218
203
  const context = this._contextIdToContext.get(event.executionContextId);
219
204
  if (context) await this._page._onBindingCalled(event.payload, context);
@@ -286,7 +271,7 @@ class FFPage {
286
271
  this._page._didCrash();
287
272
  }
288
273
  _onVideoRecordingStarted(event) {
289
- this._browserContext._browser._videoStarted(this._browserContext, event.screencastId, event.file, this.pageOrError());
274
+ this._browserContext._browser._videoStarted(this._browserContext, event.screencastId, event.file, this._page.waitForInitializedOrError());
290
275
  }
291
276
  didClose() {
292
277
  this._markAsError(new _errors.TargetClosedError());
@@ -248,9 +248,8 @@ class FrameManager {
248
248
  request
249
249
  });
250
250
  if (request._isFavicon) {
251
- route === null || route === void 0 || route.continue({
252
- isFallback: true
253
- }).catch(() => {});
251
+ // Abort favicon requests to avoid network access in case of interception.
252
+ route === null || route === void 0 || route.abort('aborted').catch(() => {});
254
253
  return;
255
254
  }
256
255
  this._page.emitOnContext(_browserContext.BrowserContext.Events.Request, request);
@@ -915,9 +914,9 @@ class Frame extends _instrumentation.SdkObject {
915
914
  return this._url;
916
915
  }
917
916
  origin() {
918
- var _network$parsedURL;
917
+ var _network$parseURL;
919
918
  if (!this._url.startsWith('http')) return;
920
- return (_network$parsedURL = network.parsedURL(this._url)) === null || _network$parsedURL === void 0 ? void 0 : _network$parsedURL.origin;
919
+ return (_network$parseURL = network.parseURL(this._url)) === null || _network$parseURL === void 0 ? void 0 : _network$parseURL.origin;
921
920
  }
922
921
  parentFrame() {
923
922
  return this._parentFrame;
@@ -1244,7 +1243,8 @@ class Frame extends _instrumentation.SdkObject {
1244
1243
  }, {
1245
1244
  state
1246
1245
  }, options, scope);
1247
- return dom.throwRetargetableDOMError(result);
1246
+ if (result.received === 'error:notconnected') dom.throwElementIsNotAttached();
1247
+ return result.matches;
1248
1248
  }
1249
1249
  async isVisible(metadata, selector, options = {}, scope) {
1250
1250
  const controller = new _progress.ProgressController(metadata, this);
@@ -1262,8 +1262,11 @@ class Frame extends _instrumentation.SdkObject {
1262
1262
  root
1263
1263
  }) => {
1264
1264
  const element = injected.querySelector(info.parsed, root || document, info.strict);
1265
- const state = element ? injected.elementState(element, 'visible') : false;
1266
- return state === 'error:notconnected' ? false : state;
1265
+ const state = element ? injected.elementState(element, 'visible') : {
1266
+ matches: false,
1267
+ received: 'error:notconnected'
1268
+ };
1269
+ return state.matches;
1267
1270
  }, {
1268
1271
  info: resolved.info,
1269
1272
  root: resolved.frame === this ? scope : undefined
@@ -1719,21 +1722,23 @@ class Frame extends _instrumentation.SdkObject {
1719
1722
  return (0, _utils.asLocator)(this._page.attribution.playwright.options.sdkLanguage, selector);
1720
1723
  }
1721
1724
  async _getFrameMainFrameContextId(client) {
1722
- var globalDocument = await client._sendMayFail("DOM.getFrameOwner", {
1723
- frameId: this._id
1724
- });
1725
- if (globalDocument && globalDocument.nodeId) {
1726
- var descibedNode = await client._sendMayFail("DOM.describeNode", {
1727
- backendNodeId: globalDocument.backendNodeId
1725
+ try {
1726
+ var globalDocument = await client._sendMayFail("DOM.getFrameOwner", {
1727
+ frameId: this._id
1728
1728
  });
1729
- if (descibedNode) {
1730
- var resolvedNode = await client._sendMayFail("DOM.resolveNode", {
1731
- nodeId: descibedNode.node.contentDocument.nodeId
1729
+ if (globalDocument && globalDocument.nodeId) {
1730
+ var describedNode = await client._sendMayFail("DOM.describeNode", {
1731
+ backendNodeId: globalDocument.backendNodeId
1732
1732
  });
1733
- var _executionContextId = parseInt(resolvedNode.object.objectId.split(".")[1], 10);
1734
- return _executionContextId;
1733
+ if (describedNode) {
1734
+ var resolvedNode = await client._sendMayFail("DOM.resolveNode", {
1735
+ nodeId: describedNode.node.contentDocument.nodeId
1736
+ });
1737
+ var _executionContextId = parseInt(resolvedNode.object.objectId.split(".")[1], 10);
1738
+ return _executionContextId;
1739
+ }
1735
1740
  }
1736
- }
1741
+ } catch (e) {}
1737
1742
  return 0;
1738
1743
  }
1739
1744
  }
@@ -1782,16 +1787,6 @@ function verifyLifecycle(name, waitUntil) {
1782
1787
  return waitUntil;
1783
1788
  }
1784
1789
  function renderUnexpectedValue(expression, received) {
1785
- if (expression === 'to.be.checked') return received ? 'checked' : 'unchecked';
1786
- if (expression === 'to.be.unchecked') return received ? 'unchecked' : 'checked';
1787
- if (expression === 'to.be.visible') return received ? 'visible' : 'hidden';
1788
- if (expression === 'to.be.hidden') return received ? 'hidden' : 'visible';
1789
- if (expression === 'to.be.enabled') return received ? 'enabled' : 'disabled';
1790
- if (expression === 'to.be.disabled') return received ? 'disabled' : 'enabled';
1791
- if (expression === 'to.be.editable') return received ? 'editable' : 'readonly';
1792
- if (expression === 'to.be.readonly') return received ? 'readonly' : 'editable';
1793
- if (expression === 'to.be.empty') return received ? 'empty' : 'not empty';
1794
- if (expression === 'to.be.focused') return received ? 'focused' : 'not focused';
1795
1790
  if (expression === 'to.match.aria') return received ? received.raw : received;
1796
1791
  return received;
1797
1792
  }
@@ -196,7 +196,7 @@ class HarTracer {
196
196
  if (!this._shouldIncludeEntryWithUrl(request.url())) return;
197
197
  const page = (_request$frame = request.frame()) === null || _request$frame === void 0 ? void 0 : _request$frame._page;
198
198
  if (this._page && page !== this._page) return;
199
- const url = network.parsedURL(request.url());
199
+ const url = network.parseURL(request.url());
200
200
  if (!url) return;
201
201
  const pageEntry = this._createPageEntryIfNeeded(page);
202
202
  const harEntry = createHarEntry(request.method(), url, (_request$frame2 = request.frame()) === null || _request$frame2 === void 0 ? void 0 : _request$frame2.guid, this._options);
@@ -40,8 +40,7 @@ class Keyboard {
40
40
  const autoRepeat = this._pressedKeys.has(description.code);
41
41
  this._pressedKeys.add(description.code);
42
42
  if (kModifiers.includes(description.key)) this._pressedModifiers.add(description.key);
43
- const text = description.text;
44
- await this._raw.keydown(this._pressedModifiers, description.code, description.keyCode, description.keyCodeWithoutLocation, description.key, description.location, autoRepeat, text);
43
+ await this._raw.keydown(this._pressedModifiers, key, description, autoRepeat);
45
44
  }
46
45
  _keyDescriptionForString(str) {
47
46
  const keyString = resolveSmartModifierString(str);
@@ -61,7 +60,7 @@ class Keyboard {
61
60
  const description = this._keyDescriptionForString(key);
62
61
  if (kModifiers.includes(description.key)) this._pressedModifiers.delete(description.key);
63
62
  this._pressedKeys.delete(description.code);
64
- await this._raw.keyup(this._pressedModifiers, description.code, description.keyCode, description.keyCodeWithoutLocation, description.key, description.location);
63
+ await this._raw.keyup(this._pressedModifiers, key, description);
65
64
  }
66
65
  async insertText(text) {
67
66
  await this._raw.sendText(text);
@@ -7,7 +7,7 @@ exports.WebSocket = exports.Route = exports.Response = exports.Request = void 0;
7
7
  exports.filterCookies = filterCookies;
8
8
  exports.kMaxCookieExpiresDateInSeconds = void 0;
9
9
  exports.mergeHeaders = mergeHeaders;
10
- exports.parsedURL = parsedURL;
10
+ exports.parseURL = parseURL;
11
11
  exports.rewriteCookies = rewriteCookies;
12
12
  exports.singleHeader = singleHeader;
13
13
  exports.statusText = statusText;
@@ -75,7 +75,7 @@ function rewriteCookies(cookies) {
75
75
  return copy;
76
76
  });
77
77
  }
78
- function parsedURL(url) {
78
+ function parseURL(url) {
79
79
  try {
80
80
  return new URL(url);
81
81
  } catch (e) {
@@ -47,7 +47,8 @@ class Page extends _instrumentation.SdkObject {
47
47
  super(browserContext, 'page');
48
48
  this._closedState = 'open';
49
49
  this._closedPromise = new _manualPromise.ManualPromise();
50
- this._initialized = false;
50
+ this._initialized = void 0;
51
+ this._initializedPromise = new _manualPromise.ManualPromise();
51
52
  this._eventsToEmitAfterInitialized = [];
52
53
  this._crashed = false;
53
54
  this.openScope = new _utils.LongStandingScope();
@@ -72,7 +73,6 @@ class Page extends _instrumentation.SdkObject {
72
73
  this._clientRequestInterceptor = void 0;
73
74
  this._serverRequestInterceptor = void 0;
74
75
  this._ownedContext = void 0;
75
- this._pageIsError = void 0;
76
76
  this._video = null;
77
77
  this._opener = void 0;
78
78
  this._isServerSideOnly = false;
@@ -96,19 +96,21 @@ class Page extends _instrumentation.SdkObject {
96
96
  if (delegate.pdf) this.pdf = delegate.pdf.bind(delegate);
97
97
  this.coverage = delegate.coverage ? delegate.coverage() : null;
98
98
  }
99
- async initOpener(opener) {
100
- if (!opener) return;
101
- const openerPage = await opener.pageOrError();
102
- if (openerPage instanceof Page && !openerPage.isClosed()) this._opener = openerPage;
99
+ async reportAsNew(opener, error = undefined, contextEvent = _browserContext.BrowserContext.Events.Page) {
100
+ if (opener) {
101
+ const openerPageOrError = await opener.waitForInitializedOrError();
102
+ if (openerPageOrError instanceof Page && !openerPageOrError.isClosed()) this._opener = openerPageOrError;
103
+ }
104
+ this._markInitialized(error, contextEvent);
103
105
  }
104
- reportAsNew(error = undefined, contextEvent = _browserContext.BrowserContext.Events.Page) {
106
+ _markInitialized(error = undefined, contextEvent = _browserContext.BrowserContext.Events.Page) {
105
107
  if (error) {
106
108
  // Initialization error could have happened because of
107
109
  // context/browser closure. Just ignore the page.
108
110
  if (this._browserContext.isClosingOrClosed()) return;
109
- this._setIsError(error);
111
+ this._frameManager.createDummyMainFrameIfNeeded();
110
112
  }
111
- this._initialized = true;
113
+ this._initialized = error || this;
112
114
  this.emitOnContext(contextEvent, this);
113
115
  for (const {
114
116
  event,
@@ -120,10 +122,17 @@ class Page extends _instrumentation.SdkObject {
120
122
  // in that case we fire another Close event to ensure that each reported Page will have
121
123
  // corresponding Close event after it is reported on the context.
122
124
  if (this.isClosed()) this.emit(Page.Events.Close);else this.instrumentation.onPageOpen(this);
125
+
126
+ // Note: it is important to resolve _initializedPromise at the end,
127
+ // so that anyone who awaits waitForInitializedOrError got a ready and reported page.
128
+ this._initializedPromise.resolve(this._initialized);
123
129
  }
124
130
  initializedOrUndefined() {
125
131
  return this._initialized ? this : undefined;
126
132
  }
133
+ waitForInitializedOrError() {
134
+ return this._initializedPromise;
135
+ }
127
136
  emitOnContext(event, ...args) {
128
137
  if (this._isServerSideOnly) return;
129
138
  this._browserContext.emit(event, ...args);
@@ -407,8 +416,8 @@ class Page extends _instrumentation.SdkObject {
407
416
  async bringToFront() {
408
417
  await this._delegate.bringToFront();
409
418
  }
410
- async addInitScript(source) {
411
- const initScript = new InitScript(source);
419
+ async addInitScript(source, name) {
420
+ const initScript = new InitScript(source, false /* internal */, name);
412
421
  this.initScripts.push(initScript);
413
422
  await this._delegate.addInitScript(initScript);
414
423
  }
@@ -532,10 +541,6 @@ class Page extends _instrumentation.SdkObject {
532
541
  if (!runBeforeUnload) await this._closedPromise;
533
542
  if (this._ownedContext) await this._ownedContext.close(options);
534
543
  }
535
- _setIsError(error) {
536
- this._pageIsError = error;
537
- this._frameManager.createDummyMainFrameIfNeeded();
538
- }
539
544
  isClosed() {
540
545
  return this._closedState === 'closed';
541
546
  }
@@ -778,12 +783,14 @@ function addPageBinding(bindingName, needsHandle, utilityScriptSerializers) {
778
783
  };
779
784
  }
780
785
  class InitScript {
781
- constructor(source, internal) {
786
+ constructor(source, internal, name) {
782
787
  this.source = void 0;
783
788
  this.internal = void 0;
789
+ this.name = void 0;
784
790
  const guid = (0, _utils.createGuid)();
785
791
  this.source = `(() => { ${source} })();`;
786
792
  this.internal = !!internal;
793
+ this.name = name;
787
794
  }
788
795
  }
789
796
  exports.InitScript = InitScript;