@checkly/playwright-core 1.42.18 → 1.47.11

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 (250) hide show
  1. package/ThirdPartyNotices.txt +144 -109
  2. package/browsers.json +15 -25
  3. package/lib/androidServerImpl.js +1 -1
  4. package/lib/browserServerImpl.js +1 -1
  5. package/lib/cli/driver.js +1 -3
  6. package/lib/cli/program.js +5 -10
  7. package/lib/client/android.js +1 -1
  8. package/lib/client/api.js +7 -0
  9. package/lib/client/browserContext.js +37 -5
  10. package/lib/client/browserType.js +19 -11
  11. package/lib/client/channelOwner.js +19 -16
  12. package/lib/client/clientInstrumentation.js +17 -7
  13. package/lib/client/clock.js +68 -0
  14. package/lib/client/connection.js +9 -6
  15. package/lib/client/electron.js +7 -5
  16. package/lib/client/elementHandle.js +44 -14
  17. package/lib/client/eventEmitter.js +314 -0
  18. package/lib/client/fetch.js +81 -28
  19. package/lib/client/frame.js +2 -4
  20. package/lib/client/jsHandle.js +7 -1
  21. package/lib/client/locator.js +9 -0
  22. package/lib/client/network.js +12 -9
  23. package/lib/client/page.js +45 -23
  24. package/lib/client/playwright.js +3 -0
  25. package/lib/client/tracing.js +7 -4
  26. package/lib/common/socksProxy.js +2 -2
  27. package/lib/generated/clockSource.js +7 -0
  28. package/lib/generated/injectedScriptSource.js +1 -1
  29. package/lib/generated/recorderSource.js +1 -1
  30. package/lib/generated/utilityScriptSource.js +1 -1
  31. package/lib/protocol/serializers.js +12 -11
  32. package/lib/protocol/validator.js +137 -55
  33. package/lib/server/bidi/bidiBrowser.js +296 -0
  34. package/lib/server/bidi/bidiConnection.js +206 -0
  35. package/lib/server/bidi/bidiExecutionContext.js +162 -0
  36. package/lib/server/bidi/bidiFirefox.js +110 -0
  37. package/lib/server/bidi/bidiInput.js +174 -0
  38. package/lib/server/bidi/bidiNetworkManager.js +304 -0
  39. package/lib/server/bidi/bidiPage.js +456 -0
  40. package/lib/server/bidi/third_party/bidiDeserializer.js +93 -0
  41. package/lib/server/bidi/third_party/bidiKeyboard.js +238 -0
  42. package/lib/server/bidi/third_party/bidiProtocol.js +139 -0
  43. package/lib/server/bidi/third_party/bidiSerializer.js +144 -0
  44. package/lib/server/browser.js +9 -1
  45. package/lib/server/browserContext.js +97 -22
  46. package/lib/server/browserType.js +27 -20
  47. package/lib/server/chromium/chromium.js +30 -15
  48. package/lib/server/chromium/chromiumSwitches.js +6 -3
  49. package/lib/server/chromium/crBrowser.js +11 -17
  50. package/lib/server/chromium/crConnection.js +2 -2
  51. package/lib/server/chromium/crDragDrop.js +28 -29
  52. package/lib/server/chromium/crNetworkManager.js +130 -84
  53. package/lib/server/chromium/crPage.js +34 -79
  54. package/lib/server/chromium/crProtocolHelper.js +3 -1
  55. package/lib/server/chromium/crServiceWorker.js +20 -23
  56. package/lib/server/chromium/videoRecorder.js +1 -1
  57. package/lib/server/clock.js +125 -0
  58. package/lib/server/codegen/csharp.js +299 -0
  59. package/lib/server/codegen/java.js +235 -0
  60. package/lib/server/codegen/javascript.js +223 -0
  61. package/lib/server/codegen/jsonl.js +47 -0
  62. package/lib/server/codegen/language.js +76 -0
  63. package/lib/server/codegen/languages.js +30 -0
  64. package/lib/server/codegen/python.js +265 -0
  65. package/lib/server/codegen/types.js +5 -0
  66. package/lib/server/debugController.js +3 -5
  67. package/lib/server/deviceDescriptors.js +9 -4
  68. package/lib/server/deviceDescriptorsSource.json +239 -119
  69. package/lib/server/dispatchers/androidDispatcher.js +1 -1
  70. package/lib/server/dispatchers/browserContextDispatcher.js +51 -7
  71. package/lib/server/dispatchers/dispatcher.js +36 -40
  72. package/lib/server/dispatchers/frameDispatcher.js +1 -2
  73. package/lib/server/dispatchers/jsHandleDispatcher.js +1 -1
  74. package/lib/server/dispatchers/jsonPipeDispatcher.js +4 -6
  75. package/lib/server/dispatchers/localUtilsDispatcher.js +19 -5
  76. package/lib/server/dispatchers/networkDispatchers.js +2 -2
  77. package/lib/server/dispatchers/pageDispatcher.js +5 -2
  78. package/lib/server/dispatchers/playwrightDispatcher.js +1 -0
  79. package/lib/server/dispatchers/writableStreamDispatcher.js +8 -5
  80. package/lib/server/dom.js +90 -53
  81. package/lib/server/electron/electron.js +21 -4
  82. package/lib/server/fetch.js +74 -25
  83. package/lib/server/fileUploadUtils.js +7 -3
  84. package/lib/server/firefox/ffBrowser.js +36 -25
  85. package/lib/server/firefox/ffConnection.js +2 -2
  86. package/lib/server/firefox/ffNetworkManager.js +6 -4
  87. package/lib/server/firefox/ffPage.js +22 -24
  88. package/lib/server/firefox/firefox.js +25 -6
  89. package/lib/server/frameSelectors.js +2 -2
  90. package/lib/server/frames.js +205 -159
  91. package/lib/server/har/harTracer.js +4 -12
  92. package/lib/server/helper.js +3 -3
  93. package/lib/server/index.js +18 -0
  94. package/lib/server/input.js +18 -8
  95. package/lib/server/instrumentation.js +0 -4
  96. package/lib/server/isomorphic/utilityScriptSerializers.js +19 -5
  97. package/lib/server/javascript.js +3 -2
  98. package/lib/server/launchApp.js +3 -2
  99. package/lib/server/network.js +14 -4
  100. package/lib/server/page.js +75 -46
  101. package/lib/server/playwright.js +5 -2
  102. package/lib/server/recorder/codeGenerator.js +2 -1
  103. package/lib/server/recorder/contextRecorder.js +316 -0
  104. package/lib/server/recorder/csharp.js +2 -1
  105. package/lib/server/recorder/java.js +2 -1
  106. package/lib/server/recorder/javascript.js +2 -1
  107. package/lib/server/recorder/jsonl.js +2 -1
  108. package/lib/server/recorder/language.js +2 -1
  109. package/lib/server/recorder/python.js +2 -1
  110. package/lib/server/recorder/recorderApp.js +14 -5
  111. package/lib/server/recorder/recorderCollection.js +127 -0
  112. package/lib/server/recorder/recorderRunner.js +177 -0
  113. package/lib/server/recorder/recorderUtils.js +23 -0
  114. package/lib/server/recorder/throttledFile.js +46 -0
  115. package/lib/server/recorder/utils.js +2 -1
  116. package/lib/server/recorder.js +42 -418
  117. package/lib/server/registry/index.js +99 -100
  118. package/lib/server/registry/nativeDeps.js +107 -0
  119. package/lib/server/screenshotter.js +6 -12
  120. package/lib/server/socksClientCertificatesInterceptor.js +328 -0
  121. package/lib/server/trace/recorder/snapshotter.js +4 -1
  122. package/lib/server/trace/recorder/tracing.js +27 -96
  123. package/lib/server/trace/viewer/traceViewer.js +54 -67
  124. package/lib/server/transport.js +1 -1
  125. package/lib/server/webkit/webkit.js +5 -5
  126. package/lib/server/webkit/wkBrowser.js +14 -14
  127. package/lib/server/webkit/wkConnection.js +3 -3
  128. package/lib/server/webkit/wkInterceptableRequest.js +8 -4
  129. package/lib/server/webkit/wkPage.js +52 -34
  130. package/lib/server/webkit/wkProvisionalPage.js +36 -1
  131. package/lib/utils/crypto.js +141 -0
  132. package/lib/utils/debugLogger.js +2 -0
  133. package/lib/utils/env.js +4 -2
  134. package/lib/utils/expectUtils.js +33 -0
  135. package/lib/utils/fileUtils.js +140 -1
  136. package/lib/utils/glob.js +2 -1
  137. package/lib/utils/happy-eyeballs.js +29 -2
  138. package/lib/utils/hostPlatform.js +13 -4
  139. package/lib/utils/httpServer.js +54 -13
  140. package/lib/utils/index.js +53 -31
  141. package/lib/utils/isomorphic/cssTokenizer.js +1 -1
  142. package/lib/utils/isomorphic/locatorParser.js +1 -1
  143. package/lib/utils/isomorphic/mimeType.js +29 -0
  144. package/lib/utils/isomorphic/stringUtils.js +28 -1
  145. package/lib/utils/isomorphic/urlMatch.js +120 -0
  146. package/lib/utils/mimeType.js +2 -1
  147. package/lib/utils/network.js +7 -35
  148. package/lib/utils/stackTrace.js +2 -4
  149. package/lib/utils/timeoutRunner.js +11 -76
  150. package/lib/utils/zones.js +23 -60
  151. package/lib/utilsBundle.js +2 -1
  152. package/lib/utilsBundleImpl/index.js +33 -31
  153. package/lib/vite/htmlReport/index.html +12 -12
  154. package/lib/vite/recorder/assets/codeMirrorModule-BN0yUF4I.js +24 -0
  155. package/lib/vite/recorder/assets/{codicon-zGuYmc9o.ttf → codicon-DCmgc-ay.ttf} +0 -0
  156. package/lib/vite/recorder/assets/index-B-MT5gKo.css +1 -0
  157. package/lib/vite/recorder/assets/index-DVt3E1Ef.js +47 -0
  158. package/lib/vite/recorder/index.html +2 -2
  159. package/lib/vite/traceViewer/assets/codeMirrorModule-5yiV-3wl.js +16831 -0
  160. package/lib/vite/traceViewer/assets/codeMirrorModule-B7Z3vq11.js +24 -0
  161. package/lib/vite/traceViewer/assets/codeMirrorModule-C6p3E9Zg.js +24 -0
  162. package/lib/vite/traceViewer/assets/codeMirrorModule-CcviAl53.js +16831 -0
  163. package/lib/vite/traceViewer/assets/codeMirrorModule-CqYUz5ms.js +24 -0
  164. package/lib/vite/traceViewer/assets/codeMirrorModule-DS3v0XrQ.js +24 -0
  165. package/lib/vite/traceViewer/assets/codeMirrorModule-Dx6AXgMV.js +16838 -0
  166. package/lib/vite/traceViewer/assets/codeMirrorModule-T_sdMrbM.js +24 -0
  167. package/lib/vite/traceViewer/assets/codeMirrorModule-V7N6ppkd.js +15585 -0
  168. package/lib/vite/traceViewer/assets/testServerConnection-D-tXL3sj.js +224 -0
  169. package/lib/vite/traceViewer/assets/testServerConnection-DeE2kSzz.js +1 -0
  170. package/lib/vite/traceViewer/assets/workbench-Bjkiwcr1.js +19119 -0
  171. package/lib/vite/traceViewer/assets/workbench-C43LWZEX.js +72 -0
  172. package/lib/vite/traceViewer/assets/workbench-C5OQh9VX.js +19119 -0
  173. package/lib/vite/traceViewer/assets/workbench-Crj6jzdv.js +19119 -0
  174. package/lib/vite/traceViewer/assets/workbench-DrQjKdyE.js +72 -0
  175. package/lib/vite/traceViewer/assets/workbench-Pa1v1Ojh.js +72 -0
  176. package/lib/vite/traceViewer/assets/workbench-caTaZnzx.js +72 -0
  177. package/lib/vite/traceViewer/assets/workbench-u2lRPMOT.js +72 -0
  178. package/lib/vite/traceViewer/assets/wsPort-EUvw-dwH.js +18540 -0
  179. package/lib/vite/traceViewer/assets/xtermModule-CZ7sDYXB.js +6529 -0
  180. package/lib/vite/traceViewer/assets/xtermModule-_6TC5FYT.js +6529 -0
  181. package/lib/vite/traceViewer/codeMirrorModule.Cy8X9Wtw.css +344 -0
  182. package/lib/vite/traceViewer/codeMirrorModule.svF_VrcJ.css +344 -0
  183. package/lib/vite/traceViewer/codicon.DCmgc-ay.ttf +0 -0
  184. package/lib/vite/traceViewer/embedded.BBZ9gQEw.js +104 -0
  185. package/lib/vite/traceViewer/embedded.BQq6Psnz.js +104 -0
  186. package/lib/vite/traceViewer/embedded.BVDVQOzc.js +2 -0
  187. package/lib/vite/traceViewer/embedded.Bn8Ptzv6.js +2 -0
  188. package/lib/vite/traceViewer/embedded.CvhnUgIi.js +2 -0
  189. package/lib/vite/traceViewer/embedded.D27cnKiB.js +104 -0
  190. package/lib/vite/traceViewer/embedded.DPqrDeET.js +2 -0
  191. package/lib/vite/traceViewer/embedded.DbzY7Q8w.js +2 -0
  192. package/lib/vite/traceViewer/embedded.DjZq4InJ.css +68 -0
  193. package/lib/vite/traceViewer/embedded.html +16 -0
  194. package/lib/vite/traceViewer/embedded.w7WN2u1R.css +1 -0
  195. package/lib/vite/traceViewer/index.5mge2rY_.css +124 -0
  196. package/lib/vite/traceViewer/index.6KJ-JQ0L.js +180 -0
  197. package/lib/vite/traceViewer/index.B8dgQwuN.js +2 -0
  198. package/lib/vite/traceViewer/index.BGj8jY3H.js +2 -0
  199. package/lib/vite/traceViewer/index.BSak5QT9.js +2 -0
  200. package/lib/vite/traceViewer/index.C0EgJ4oW.js +195 -0
  201. package/lib/vite/traceViewer/index.CUpI-BFe.js +195 -0
  202. package/lib/vite/traceViewer/{index.-g_5lMbJ.css → index.CrbWWHbf.css} +1 -1
  203. package/lib/vite/traceViewer/index.DkRbtWVo.js +195 -0
  204. package/lib/vite/traceViewer/index.QanXxRUb.css +131 -0
  205. package/lib/vite/traceViewer/index._cX8k4co.js +2 -0
  206. package/lib/vite/traceViewer/index.html +5 -4
  207. package/lib/vite/traceViewer/index.pMAN88y-.js +2 -0
  208. package/lib/vite/traceViewer/snapshot.html +1 -1
  209. package/lib/vite/traceViewer/sw.bundle.js +3 -4
  210. package/lib/vite/traceViewer/uiMode.D-tg1Oci.js +1730 -0
  211. package/lib/vite/traceViewer/uiMode.D3cNFP6u.css +1 -0
  212. package/lib/vite/traceViewer/uiMode.DKjMBMlc.js +1730 -0
  213. package/lib/vite/traceViewer/uiMode.DVWUEIHq.css +1424 -0
  214. package/lib/vite/traceViewer/uiMode.DVrL7a1K.js +10 -0
  215. package/lib/vite/traceViewer/uiMode.Dg9oJCQU.js +10 -0
  216. package/lib/vite/traceViewer/uiMode.DwZAzstF.js +10 -0
  217. package/lib/vite/traceViewer/uiMode.O07awP3T.js +10 -0
  218. package/lib/vite/traceViewer/uiMode.gGHHTsyL.js +1730 -0
  219. package/lib/vite/traceViewer/uiMode.html +5 -4
  220. package/lib/vite/traceViewer/uiMode.iq7CyYy7.js +1490 -0
  221. package/lib/vite/traceViewer/uiMode.jY2s-9ps.js +10 -0
  222. package/lib/vite/traceViewer/uiMode.xvJHbkzl.css +1324 -0
  223. package/lib/vite/traceViewer/workbench.B3X2QtYa.css +3702 -0
  224. package/lib/vite/traceViewer/workbench.DjbIuxix.css +1 -0
  225. package/lib/vite/traceViewer/workbench.DyTpxWVb.css +1 -0
  226. package/lib/vite/traceViewer/workbench.wuxQoE2z.css +3703 -0
  227. package/lib/vite/traceViewer/wsPort.p5jUwABW.css +3450 -0
  228. package/lib/vite/traceViewer/xtermModule.4oRVGWQ-.css +209 -0
  229. package/lib/vite/traceViewer/xtermModule.OKEVRlkP.css +209 -0
  230. package/package.json +2 -2
  231. package/types/protocol.d.ts +960 -78
  232. package/types/structs.d.ts +1 -1
  233. package/types/types.d.ts +3083 -2448
  234. package/lib/vite/recorder/assets/codeMirrorModule-W69B4LBB.js +0 -24
  235. package/lib/vite/recorder/assets/index-Ly3PcVUb.js +0 -47
  236. package/lib/vite/recorder/assets/index-ljsTwXtJ.css +0 -1
  237. package/lib/vite/traceViewer/assets/codeMirrorModule-0bpaqixv.js +0 -24
  238. package/lib/vite/traceViewer/assets/codeMirrorModule-wLpsbIhd.js +0 -24
  239. package/lib/vite/traceViewer/assets/wsPort-_JBDEilC.js +0 -69
  240. package/lib/vite/traceViewer/assets/wsPort-f2dAQL4I.js +0 -69
  241. package/lib/vite/traceViewer/index.-_8-eHEE.js +0 -2
  242. package/lib/vite/traceViewer/index.u51inEcm.js +0 -2
  243. package/lib/vite/traceViewer/uiMode.9CwNsWc6.js +0 -10
  244. package/lib/vite/traceViewer/uiMode.Fb0bNA4H.js +0 -10
  245. package/lib/vite/traceViewer/uiMode.pWy0Re7G.css +0 -1
  246. package/lib/vite/traceViewer/wsPort.zR1WIy9-.css +0 -1
  247. /package/lib/vite/recorder/assets/{codeMirrorModule-Hs9-1ZG4.css → codeMirrorModule-ez37Vkbh.css} +0 -0
  248. /package/lib/vite/traceViewer/assets/{xtermModule-Yt6xwiJ_.js → xtermModule-BeNbaIVa.js} +0 -0
  249. /package/lib/vite/traceViewer/{codeMirrorModule.Hs9-1ZG4.css → codeMirrorModule.ez37Vkbh.css} +0 -0
  250. /package/lib/vite/traceViewer/{xtermModule.0lwXJFHT.css → xtermModule.DSXBckUd.css} +0 -0
@@ -0,0 +1,328 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.ClientCertificatesProxy = void 0;
7
+ exports.getMatchingTLSOptionsForOrigin = getMatchingTLSOptionsForOrigin;
8
+ exports.rewriteOpenSSLErrorIfNeeded = rewriteOpenSSLErrorIfNeeded;
9
+ var _net = _interopRequireDefault(require("net"));
10
+ var _http = _interopRequireDefault(require("http2"));
11
+ var _tls = _interopRequireDefault(require("tls"));
12
+ var _stream = _interopRequireDefault(require("stream"));
13
+ var _happyEyeballs = require("../utils/happy-eyeballs");
14
+ var _utils = require("../utils");
15
+ var _socksProxy = require("../common/socksProxy");
16
+ var _debugLogger = require("../utils/debugLogger");
17
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
18
+ /**
19
+ * Copyright (c) Microsoft Corporation.
20
+ *
21
+ * Licensed under the Apache License, Version 2.0 (the 'License");
22
+ * you may not use this file except in compliance with the License.
23
+ * You may obtain a copy of the License at
24
+ *
25
+ * http://www.apache.org/licenses/LICENSE-2.0
26
+ *
27
+ * Unless required by applicable law or agreed to in writing, software
28
+ * distributed under the License is distributed on an "AS IS" BASIS,
29
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
30
+ * See the License for the specific language governing permissions and
31
+ * limitations under the License.
32
+ */
33
+
34
+ let dummyServerTlsOptions = undefined;
35
+ function loadDummyServerCertsIfNeeded() {
36
+ if (dummyServerTlsOptions) return;
37
+ const {
38
+ cert,
39
+ key
40
+ } = (0, _utils.generateSelfSignedCertificate)();
41
+ dummyServerTlsOptions = {
42
+ key,
43
+ cert
44
+ };
45
+ }
46
+ class ALPNCache {
47
+ constructor() {
48
+ this._cache = new Map();
49
+ }
50
+ get(host, port, success) {
51
+ const cacheKey = `${host}:${port}`;
52
+ {
53
+ const result = this._cache.get(cacheKey);
54
+ if (result) {
55
+ result.then(success);
56
+ return;
57
+ }
58
+ }
59
+ const result = new _utils.ManualPromise();
60
+ this._cache.set(cacheKey, result);
61
+ result.then(success);
62
+ (0, _happyEyeballs.createTLSSocket)({
63
+ host,
64
+ port,
65
+ servername: _net.default.isIP(host) ? undefined : host,
66
+ ALPNProtocols: ['h2', 'http/1.1'],
67
+ rejectUnauthorized: false
68
+ }).then(socket => {
69
+ // The server may not respond with ALPN, in which case we default to http/1.1.
70
+ result.resolve(socket.alpnProtocol || 'http/1.1');
71
+ socket.end();
72
+ }).catch(error => {
73
+ _debugLogger.debugLogger.log('client-certificates', `ALPN error: ${error.message}`);
74
+ result.resolve('http/1.1');
75
+ });
76
+ }
77
+ }
78
+ class SocksProxyConnection {
79
+ constructor(socksProxy, uid, host, port) {
80
+ this.socksProxy = void 0;
81
+ this.uid = void 0;
82
+ this.host = void 0;
83
+ this.port = void 0;
84
+ this.firstPackageReceived = false;
85
+ this.target = void 0;
86
+ // In case of http, we just pipe data to the target socket and they are |undefined|.
87
+ this.internal = void 0;
88
+ this.internalTLS = void 0;
89
+ this._targetCloseEventListener = void 0;
90
+ this._dummyServer = void 0;
91
+ this._closed = false;
92
+ this.socksProxy = socksProxy;
93
+ this.uid = uid;
94
+ this.host = host;
95
+ this.port = port;
96
+ this._targetCloseEventListener = () => {
97
+ var _this$internalTLS, _this$_dummyServer;
98
+ // Close the other end and cleanup TLS resources.
99
+ this.socksProxy._socksProxy.sendSocketEnd({
100
+ uid: this.uid
101
+ });
102
+ (_this$internalTLS = this.internalTLS) === null || _this$internalTLS === void 0 || _this$internalTLS.destroy();
103
+ (_this$_dummyServer = this._dummyServer) === null || _this$_dummyServer === void 0 || _this$_dummyServer.close();
104
+ };
105
+ }
106
+ async connect() {
107
+ this.target = await (0, _happyEyeballs.createSocket)(rewriteToLocalhostIfNeeded(this.host), this.port);
108
+ this.target.once('close', this._targetCloseEventListener);
109
+ this.target.once('error', error => this.socksProxy._socksProxy.sendSocketError({
110
+ uid: this.uid,
111
+ error: error.message
112
+ }));
113
+ if (this._closed) {
114
+ this.target.destroy();
115
+ return;
116
+ }
117
+ this.socksProxy._socksProxy.socketConnected({
118
+ uid: this.uid,
119
+ host: this.target.localAddress,
120
+ port: this.target.localPort
121
+ });
122
+ }
123
+ onClose() {
124
+ var _this$internalTLS2, _this$_dummyServer2;
125
+ // Close the other end and cleanup TLS resources.
126
+ this.target.destroy();
127
+ (_this$internalTLS2 = this.internalTLS) === null || _this$internalTLS2 === void 0 || _this$internalTLS2.destroy();
128
+ (_this$_dummyServer2 = this._dummyServer) === null || _this$_dummyServer2 === void 0 || _this$_dummyServer2.close();
129
+ this._closed = true;
130
+ }
131
+ onData(data) {
132
+ // HTTP / TLS are client-hello based protocols. This allows us to detect
133
+ // the protocol on the first package and attach appropriate listeners.
134
+ if (!this.firstPackageReceived) {
135
+ this.firstPackageReceived = true;
136
+ // 0x16 is SSLv3/TLS "handshake" content type: https://en.wikipedia.org/wiki/Transport_Layer_Security#TLS_record
137
+ if (data[0] === 0x16) this._attachTLSListeners();else this.target.on('data', data => this.socksProxy._socksProxy.sendSocketData({
138
+ uid: this.uid,
139
+ data
140
+ }));
141
+ }
142
+ if (this.internal) this.internal.push(data);else this.target.write(data);
143
+ }
144
+ _attachTLSListeners() {
145
+ this.internal = new _stream.default.Duplex({
146
+ read: () => {},
147
+ write: (data, encoding, callback) => {
148
+ this.socksProxy._socksProxy.sendSocketData({
149
+ uid: this.uid,
150
+ data
151
+ });
152
+ callback();
153
+ }
154
+ });
155
+ this.socksProxy.alpnCache.get(rewriteToLocalhostIfNeeded(this.host), this.port, alpnProtocolChosenByServer => {
156
+ _debugLogger.debugLogger.log('client-certificates', `Proxy->Target ${this.host}:${this.port} chooses ALPN ${alpnProtocolChosenByServer}`);
157
+ if (this._closed) return;
158
+ this._dummyServer = _tls.default.createServer({
159
+ ...dummyServerTlsOptions,
160
+ ALPNProtocols: alpnProtocolChosenByServer === 'h2' ? ['h2', 'http/1.1'] : ['http/1.1']
161
+ });
162
+ this._dummyServer.emit('connection', this.internal);
163
+ this._dummyServer.once('secureConnection', internalTLS => {
164
+ this.internalTLS = internalTLS;
165
+ _debugLogger.debugLogger.log('client-certificates', `Browser->Proxy ${this.host}:${this.port} chooses ALPN ${internalTLS.alpnProtocol}`);
166
+ let targetTLS = undefined;
167
+ const handleError = error => {
168
+ _debugLogger.debugLogger.log('client-certificates', `error when connecting to target: ${error.message.replaceAll('\n', ' ')}`);
169
+ const responseBody = (0, _utils.escapeHTML)('Playwright client-certificate error: ' + error.message).replaceAll('\n', ' <br>');
170
+ if ((internalTLS === null || internalTLS === void 0 ? void 0 : internalTLS.alpnProtocol) === 'h2') {
171
+ // This method is available only in Node.js 20+
172
+ if ('performServerHandshake' in _http.default) {
173
+ // In case of an 'error' event on the target connection, we still need to perform the http2 handshake on the browser side.
174
+ // This is an async operation, so we need to remove the listener to prevent the socket from being closed too early.
175
+ // This means we call this._targetCloseEventListener manually.
176
+ this.target.removeListener('close', this._targetCloseEventListener);
177
+ // @ts-expect-error
178
+ const session = _http.default.performServerHandshake(internalTLS);
179
+ session.on('error', () => {
180
+ this.target.destroy();
181
+ this._targetCloseEventListener();
182
+ });
183
+ session.once('stream', stream => {
184
+ stream.respond({
185
+ 'content-type': 'text/html',
186
+ [_http.default.constants.HTTP2_HEADER_STATUS]: 503
187
+ });
188
+ const cleanup = () => {
189
+ session.close();
190
+ this.target.destroy();
191
+ this._targetCloseEventListener();
192
+ };
193
+ stream.end(responseBody, cleanup);
194
+ stream.once('error', cleanup);
195
+ });
196
+ } else {
197
+ this.target.destroy();
198
+ }
199
+ } else {
200
+ internalTLS.end(['HTTP/1.1 503 Internal Server Error', 'Content-Type: text/html; charset=utf-8', 'Content-Length: ' + Buffer.byteLength(responseBody), '', responseBody].join('\r\n'));
201
+ this.target.destroy();
202
+ }
203
+ };
204
+ if (this._closed) {
205
+ internalTLS.destroy();
206
+ return;
207
+ }
208
+ targetTLS = _tls.default.connect({
209
+ socket: this.target,
210
+ host: this.host,
211
+ port: this.port,
212
+ rejectUnauthorized: !this.socksProxy.ignoreHTTPSErrors,
213
+ ALPNProtocols: [internalTLS.alpnProtocol || 'http/1.1'],
214
+ servername: !_net.default.isIP(this.host) ? this.host : undefined,
215
+ secureContext: this.socksProxy.secureContextMap.get(new URL(`https://${this.host}:${this.port}`).origin)
216
+ });
217
+ targetTLS.once('secureConnect', () => {
218
+ internalTLS.pipe(targetTLS);
219
+ targetTLS.pipe(internalTLS);
220
+ });
221
+ internalTLS.once('error', () => this.target.destroy());
222
+ targetTLS.once('error', handleError);
223
+ });
224
+ });
225
+ }
226
+ }
227
+ class ClientCertificatesProxy {
228
+ constructor(contextOptions) {
229
+ this._socksProxy = void 0;
230
+ this._connections = new Map();
231
+ this.ignoreHTTPSErrors = void 0;
232
+ this.secureContextMap = new Map();
233
+ this.alpnCache = void 0;
234
+ this.alpnCache = new ALPNCache();
235
+ this.ignoreHTTPSErrors = contextOptions.ignoreHTTPSErrors;
236
+ this._initSecureContexts(contextOptions.clientCertificates);
237
+ this._socksProxy = new _socksProxy.SocksProxy();
238
+ this._socksProxy.setPattern('*');
239
+ this._socksProxy.addListener(_socksProxy.SocksProxy.Events.SocksRequested, async payload => {
240
+ try {
241
+ const connection = new SocksProxyConnection(this, payload.uid, payload.host, payload.port);
242
+ await connection.connect();
243
+ this._connections.set(payload.uid, connection);
244
+ } catch (error) {
245
+ this._socksProxy.socketFailed({
246
+ uid: payload.uid,
247
+ errorCode: error.code
248
+ });
249
+ }
250
+ });
251
+ this._socksProxy.addListener(_socksProxy.SocksProxy.Events.SocksData, async payload => {
252
+ var _this$_connections$ge;
253
+ (_this$_connections$ge = this._connections.get(payload.uid)) === null || _this$_connections$ge === void 0 || _this$_connections$ge.onData(payload.data);
254
+ });
255
+ this._socksProxy.addListener(_socksProxy.SocksProxy.Events.SocksClosed, payload => {
256
+ var _this$_connections$ge2;
257
+ (_this$_connections$ge2 = this._connections.get(payload.uid)) === null || _this$_connections$ge2 === void 0 || _this$_connections$ge2.onClose();
258
+ this._connections.delete(payload.uid);
259
+ });
260
+ loadDummyServerCertsIfNeeded();
261
+ }
262
+ _initSecureContexts(clientCertificates) {
263
+ // Step 1. Group certificates by origin.
264
+ const origin2certs = new Map();
265
+ for (const cert of clientCertificates || []) {
266
+ const origin = normalizeOrigin(cert.origin);
267
+ const certs = origin2certs.get(origin) || [];
268
+ certs.push(cert);
269
+ origin2certs.set(origin, certs);
270
+ }
271
+
272
+ // Step 2. Create secure contexts for each origin.
273
+ for (const [origin, certs] of origin2certs) {
274
+ try {
275
+ this.secureContextMap.set(origin, _tls.default.createSecureContext(convertClientCertificatesToTLSOptions(certs)));
276
+ } catch (error) {
277
+ error = rewriteOpenSSLErrorIfNeeded(error);
278
+ throw (0, _utils.rewriteErrorMessage)(error, `Failed to load client certificate: ${error.message}`);
279
+ }
280
+ }
281
+ }
282
+ async listen() {
283
+ const port = await this._socksProxy.listen(0, '127.0.0.1');
284
+ return `socks5://127.0.0.1:${port}`;
285
+ }
286
+ async close() {
287
+ await this._socksProxy.close();
288
+ }
289
+ }
290
+ exports.ClientCertificatesProxy = ClientCertificatesProxy;
291
+ function normalizeOrigin(origin) {
292
+ try {
293
+ return new URL(origin).origin;
294
+ } catch (error) {
295
+ return origin;
296
+ }
297
+ }
298
+ function convertClientCertificatesToTLSOptions(clientCertificates) {
299
+ if (!clientCertificates || !clientCertificates.length) return;
300
+ const tlsOptions = {
301
+ pfx: [],
302
+ key: [],
303
+ cert: []
304
+ };
305
+ for (const cert of clientCertificates) {
306
+ if (cert.cert) tlsOptions.cert.push(cert.cert);
307
+ if (cert.key) tlsOptions.key.push({
308
+ pem: cert.key,
309
+ passphrase: cert.passphrase
310
+ });
311
+ if (cert.pfx) tlsOptions.pfx.push({
312
+ buf: cert.pfx,
313
+ passphrase: cert.passphrase
314
+ });
315
+ }
316
+ return tlsOptions;
317
+ }
318
+ function getMatchingTLSOptionsForOrigin(clientCertificates, origin) {
319
+ const matchingCerts = clientCertificates === null || clientCertificates === void 0 ? void 0 : clientCertificates.filter(c => normalizeOrigin(c.origin) === origin);
320
+ return convertClientCertificatesToTLSOptions(matchingCerts);
321
+ }
322
+ function rewriteToLocalhostIfNeeded(host) {
323
+ return host === 'local.playwright' ? 'localhost' : host;
324
+ }
325
+ function rewriteOpenSSLErrorIfNeeded(error) {
326
+ if (error.message !== 'unsupported') return error;
327
+ return (0, _utils.rewriteErrorMessage)(error, ['Unsupported TLS certificate.', 'Most likely, the security algorithm of the given certificate was deprecated by OpenSSL.', 'For more details, see https://github.com/openssl/openssl/blob/master/README-PROVIDERS.md#the-legacy-provider', 'You could probably modernize the certificate by following the steps at https://github.com/nodejs/node/issues/40672#issuecomment-1243648223'].join('\n'));
328
+ }
@@ -64,7 +64,10 @@ class Snapshotter {
64
64
  async _initialize() {
65
65
  for (const page of this._context.pages()) this._onPage(page);
66
66
  this._eventListeners = [_eventsHelper.eventsHelper.addEventListener(this._context, _browserContext.BrowserContext.Events.Page, this._onPage.bind(this))];
67
- const initScript = `(${_snapshotterInjected.frameSnapshotStreamer})("${this._snapshotStreamer}", ${!!this._context._options.javaScriptEnabled})`;
67
+ const {
68
+ javaScriptEnabled
69
+ } = this._context._options;
70
+ const initScript = `(${_snapshotterInjected.frameSnapshotStreamer})("${this._snapshotStreamer}", ${javaScriptEnabled || javaScriptEnabled === undefined})`;
68
71
  await this._context.addInitScript(initScript);
69
72
  await this._runInAllFrames(initScript);
70
73
  }
@@ -9,18 +9,15 @@ var _fs = _interopRequireDefault(require("fs"));
9
9
  var _os = _interopRequireDefault(require("os"));
10
10
  var _path = _interopRequireDefault(require("path"));
11
11
  var _debug = require("../../../protocol/debug");
12
- var _manualPromise = require("../../../utils/manualPromise");
13
- var _eventsHelper = require("../../../utils/eventsHelper");
14
12
  var _utils = require("../../../utils");
15
- var _fileUtils = require("../../../utils/fileUtils");
16
13
  var _artifact = require("../../artifact");
17
14
  var _browserContext = require("../../browserContext");
18
15
  var _instrumentation = require("../../instrumentation");
19
16
  var _page = require("../../page");
20
17
  var _harTracer = require("../../har/harTracer");
21
18
  var _snapshotter = require("./snapshotter");
22
- var _zipBundle = require("../../../zipBundle");
23
19
  var _dispatcher = require("../../dispatchers/dispatcher");
20
+ var _errors = require("../../errors");
24
21
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
25
22
  /**
26
23
  * Copyright (c) Microsoft Corporation.
@@ -38,7 +35,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
38
35
  * limitations under the License.
39
36
  */
40
37
 
41
- const version = 6;
38
+ const version = 7;
42
39
  const kScreencastOptions = {
43
40
  width: 800,
44
41
  height: 600,
@@ -47,7 +44,7 @@ const kScreencastOptions = {
47
44
  class Tracing extends _instrumentation.SdkObject {
48
45
  constructor(context, tracesDir) {
49
46
  super(context, 'tracing');
50
- this._fs = new SerializedFS();
47
+ this._fs = new _utils.SerializedFS();
51
48
  this._snapshotter = void 0;
52
49
  this._harTracer = void 0;
53
50
  this._screencastListeners = [];
@@ -73,10 +70,12 @@ class Tracing extends _instrumentation.SdkObject {
73
70
  this._contextCreatedEvent = {
74
71
  version,
75
72
  type: 'context-options',
73
+ origin: 'library',
76
74
  browserName: '',
77
75
  options: {},
78
76
  platform: process.platform,
79
77
  wallTime: 0,
78
+ monotonicTime: 0,
80
79
  sdkLanguage: context.attribution.playwright.options.sdkLanguage,
81
80
  testIdAttributeName
82
81
  };
@@ -144,11 +143,12 @@ class Tracing extends _instrumentation.SdkObject {
144
143
  const event = {
145
144
  ...this._contextCreatedEvent,
146
145
  title: options.title,
147
- wallTime: Date.now()
146
+ wallTime: Date.now(),
147
+ monotonicTime: (0, _utils.monotonicTime)()
148
148
  };
149
149
  this._fs.appendFile(this._state.traceFile, JSON.stringify(event) + '\n');
150
150
  this._context.instrumentation.addListener(this, this._context);
151
- this._eventListeners.push(_eventsHelper.eventsHelper.addEventListener(this._context, _browserContext.BrowserContext.Events.Console, this._onConsoleMessage.bind(this)));
151
+ this._eventListeners.push(_utils.eventsHelper.addEventListener(this._context, _browserContext.BrowserContext.Events.Console, this._onConsoleMessage.bind(this)), _utils.eventsHelper.addEventListener(this._context, _browserContext.BrowserContext.Events.PageError, this._onPageError.bind(this)));
152
152
  if (this._state.options.screenshots) this._startScreencast();
153
153
  if (this._state.options.snapshots) await ((_this$_snapshotter2 = this._snapshotter) === null || _this$_snapshotter2 === void 0 ? void 0 : _this$_snapshotter2.start());
154
154
  return {
@@ -158,10 +158,10 @@ class Tracing extends _instrumentation.SdkObject {
158
158
  _startScreencast() {
159
159
  if (!(this._context instanceof _browserContext.BrowserContext)) return;
160
160
  for (const page of this._context.pages()) this._startScreencastInPage(page);
161
- this._screencastListeners.push(_eventsHelper.eventsHelper.addEventListener(this._context, _browserContext.BrowserContext.Events.Page, this._startScreencastInPage.bind(this)));
161
+ this._screencastListeners.push(_utils.eventsHelper.addEventListener(this._context, _browserContext.BrowserContext.Events.Page, this._startScreencastInPage.bind(this)));
162
162
  }
163
163
  _stopScreencast() {
164
- _eventsHelper.eventsHelper.removeEventListeners(this._screencastListeners);
164
+ _utils.eventsHelper.removeEventListeners(this._screencastListeners);
165
165
  if (!(this._context instanceof _browserContext.BrowserContext)) return;
166
166
  for (const page of this._context.pages()) page.setScreencastOptions(null);
167
167
  }
@@ -190,7 +190,7 @@ class Tracing extends _instrumentation.SdkObject {
190
190
  this._state = undefined;
191
191
  }
192
192
  async deleteTmpTracesDir() {
193
- if (this._tracesTmpDir) await (0, _fileUtils.removeFolders)([this._tracesTmpDir]);
193
+ if (this._tracesTmpDir) await (0, _utils.removeFolders)([this._tracesTmpDir]);
194
194
  }
195
195
  _createTracesDirIfNeeded() {
196
196
  if (this._precreatedTracesDir) return this._precreatedTracesDir;
@@ -216,7 +216,7 @@ class Tracing extends _instrumentation.SdkObject {
216
216
  return {};
217
217
  }
218
218
  this._context.instrumentation.removeListener(this);
219
- _eventsHelper.eventsHelper.removeEventListeners(this._eventListeners);
219
+ _utils.eventsHelper.removeEventListeners(this._eventListeners);
220
220
  if (this._state.options.screenshots) this._stopScreencast();
221
221
  if (this._state.options.snapshots) await ((_this$_snapshotter4 = this._snapshotter) === null || _this$_snapshotter4 === void 0 ? void 0 : _this$_snapshotter4.stop());
222
222
  this.flushHarEntries();
@@ -321,14 +321,6 @@ class Tracing extends _instrumentation.SdkObject {
321
321
  this._appendTraceEvent(event);
322
322
  return this._captureSnapshot(event.afterSnapshot, sdkObject, metadata);
323
323
  }
324
- onEvent(sdkObject, event) {
325
- if (!sdkObject.attribution.context) return;
326
- if (event.method === 'console' || event.method === '__create__' && event.class === 'ConsoleMessage' || event.method === '__create__' && event.class === 'JSHandle') {
327
- // Console messages are handled separately.
328
- return;
329
- }
330
- this._appendTraceEvent(event);
331
- }
332
324
  onEntryStarted(entry) {
333
325
  this._pendingHarEntries.add(entry);
334
326
  }
@@ -382,10 +374,23 @@ class Tracing extends _instrumentation.SdkObject {
382
374
  };
383
375
  this._appendTraceEvent(event);
384
376
  }
377
+ _onPageError(error, page) {
378
+ const event = {
379
+ type: 'event',
380
+ time: (0, _utils.monotonicTime)(),
381
+ class: 'BrowserContext',
382
+ method: 'pageError',
383
+ params: {
384
+ error: (0, _errors.serializeError)(error)
385
+ },
386
+ pageId: page.guid
387
+ };
388
+ this._appendTraceEvent(event);
389
+ }
385
390
  _startScreencastInPage(page) {
386
391
  page.setScreencastOptions(kScreencastOptions);
387
392
  const prefix = page.guid;
388
- this._screencastListeners.push(_eventsHelper.eventsHelper.addEventListener(page, _page.Page.Events.ScreencastFrame, params => {
393
+ this._screencastListeners.push(_utils.eventsHelper.addEventListener(page, _page.Page.Events.ScreencastFrame, params => {
389
394
  const suffix = params.timestamp || Date.now();
390
395
  const sha1 = `${prefix}-${suffix}.jpeg`;
391
396
  const event = {
@@ -446,7 +451,7 @@ function createBeforeActionTraceEvent(metadata) {
446
451
  class: metadata.type,
447
452
  method: metadata.method,
448
453
  params: metadata.params,
449
- wallTime: metadata.wallTime,
454
+ stepId: metadata.stepId,
450
455
  pageId: metadata.pageId
451
456
  };
452
457
  }
@@ -478,78 +483,4 @@ function createAfterActionTraceEvent(metadata) {
478
483
  result: metadata.result,
479
484
  point: metadata.point
480
485
  };
481
- }
482
- class SerializedFS {
483
- constructor() {
484
- this._writeChain = Promise.resolve();
485
- this._buffers = new Map();
486
- // Should never be accessed from within appendOperation.
487
- this._error = void 0;
488
- }
489
- mkdir(dir) {
490
- this._appendOperation(() => _fs.default.promises.mkdir(dir, {
491
- recursive: true
492
- }));
493
- }
494
- writeFile(file, content, skipIfExists) {
495
- this._buffers.delete(file); // No need to flush the buffer since we'll overwrite anyway.
496
-
497
- // Note: 'wx' flag only writes when the file does not exist.
498
- // See https://nodejs.org/api/fs.html#file-system-flags.
499
- // This way tracing never have to write the same resource twice.
500
- this._appendOperation(async () => {
501
- if (skipIfExists) await _fs.default.promises.writeFile(file, content, {
502
- flag: 'wx'
503
- }).catch(() => {});else await _fs.default.promises.writeFile(file, content);
504
- });
505
- }
506
- appendFile(file, text, flush) {
507
- if (!this._buffers.has(file)) this._buffers.set(file, []);
508
- this._buffers.get(file).push(text);
509
- if (flush) this._flushFile(file);
510
- }
511
- _flushFile(file) {
512
- const buffer = this._buffers.get(file);
513
- if (buffer === undefined) return;
514
- const text = buffer.join('');
515
- this._buffers.delete(file);
516
- this._appendOperation(() => _fs.default.promises.appendFile(file, text));
517
- }
518
- copyFile(from, to) {
519
- this._flushFile(from);
520
- this._buffers.delete(to); // No need to flush the buffer since we'll overwrite anyway.
521
- this._appendOperation(() => _fs.default.promises.copyFile(from, to));
522
- }
523
- async syncAndGetError() {
524
- for (const file of this._buffers.keys()) this._flushFile(file);
525
- await this._writeChain;
526
- return this._error;
527
- }
528
- zip(entries, zipFileName) {
529
- for (const file of this._buffers.keys()) this._flushFile(file);
530
-
531
- // Chain the export operation against write operations,
532
- // so that files do not change during the export.
533
- this._appendOperation(async () => {
534
- const zipFile = new _zipBundle.yazl.ZipFile();
535
- const result = new _manualPromise.ManualPromise();
536
- zipFile.on('error', error => result.reject(error));
537
- for (const entry of entries) zipFile.addFile(entry.value, entry.name);
538
- zipFile.end();
539
- zipFile.outputStream.pipe(_fs.default.createWriteStream(zipFileName)).on('close', () => result.resolve()).on('error', error => result.reject(error));
540
- await result;
541
- });
542
- }
543
- _appendOperation(cb) {
544
- // This method serializes all writes to the trace.
545
- this._writeChain = this._writeChain.then(async () => {
546
- // Ignore all operations after the first error.
547
- if (this._error) return;
548
- try {
549
- await cb();
550
- } catch (e) {
551
- this._error = e;
552
- }
553
- });
554
- }
555
486
  }