@checkly/playwright-core 1.42.18 → 1.47.20-alpha

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 (238) 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-C-fQ5QZD.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-D-5S5PPN.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-CqYUz5ms.js +24 -0
  163. package/lib/vite/traceViewer/assets/codeMirrorModule-Dx6AXgMV.js +16838 -0
  164. package/lib/vite/traceViewer/assets/codeMirrorModule-T_sdMrbM.js +24 -0
  165. package/lib/vite/traceViewer/assets/codeMirrorModule-V7N6ppkd.js +15585 -0
  166. package/lib/vite/traceViewer/assets/testServerConnection-D-tXL3sj.js +224 -0
  167. package/lib/vite/traceViewer/assets/testServerConnection-DeE2kSzz.js +1 -0
  168. package/lib/vite/traceViewer/assets/workbench-Bjkiwcr1.js +19119 -0
  169. package/lib/vite/traceViewer/assets/workbench-C43LWZEX.js +72 -0
  170. package/lib/vite/traceViewer/assets/workbench-C5OQh9VX.js +19119 -0
  171. package/lib/vite/traceViewer/assets/workbench-DrQjKdyE.js +72 -0
  172. package/lib/vite/traceViewer/assets/workbench-caTaZnzx.js +72 -0
  173. package/lib/vite/traceViewer/assets/workbench-u2lRPMOT.js +72 -0
  174. package/lib/vite/traceViewer/assets/wsPort-EUvw-dwH.js +18540 -0
  175. package/lib/vite/traceViewer/assets/xtermModule-CZ7sDYXB.js +6529 -0
  176. package/lib/vite/traceViewer/assets/xtermModule-_6TC5FYT.js +6529 -0
  177. package/lib/vite/traceViewer/codeMirrorModule.Cy8X9Wtw.css +344 -0
  178. package/lib/vite/traceViewer/codeMirrorModule.svF_VrcJ.css +344 -0
  179. package/lib/vite/traceViewer/codicon.DCmgc-ay.ttf +0 -0
  180. package/lib/vite/traceViewer/embedded.BQq6Psnz.js +104 -0
  181. package/lib/vite/traceViewer/embedded.BVDVQOzc.js +2 -0
  182. package/lib/vite/traceViewer/embedded.Bn8Ptzv6.js +2 -0
  183. package/lib/vite/traceViewer/embedded.CvhnUgIi.js +2 -0
  184. package/lib/vite/traceViewer/embedded.D27cnKiB.js +104 -0
  185. package/lib/vite/traceViewer/embedded.DPqrDeET.js +2 -0
  186. package/lib/vite/traceViewer/embedded.DjZq4InJ.css +68 -0
  187. package/lib/vite/traceViewer/embedded.html +16 -0
  188. package/lib/vite/traceViewer/embedded.w7WN2u1R.css +1 -0
  189. package/lib/vite/traceViewer/index.5mge2rY_.css +124 -0
  190. package/lib/vite/traceViewer/index.6KJ-JQ0L.js +180 -0
  191. package/lib/vite/traceViewer/index.B8dgQwuN.js +2 -0
  192. package/lib/vite/traceViewer/index.BGj8jY3H.js +2 -0
  193. package/lib/vite/traceViewer/index.C0EgJ4oW.js +195 -0
  194. package/lib/vite/traceViewer/index.CUpI-BFe.js +195 -0
  195. package/lib/vite/traceViewer/{index.-g_5lMbJ.css → index.CrbWWHbf.css} +1 -1
  196. package/lib/vite/traceViewer/index.QanXxRUb.css +131 -0
  197. package/lib/vite/traceViewer/index._cX8k4co.js +2 -0
  198. package/lib/vite/traceViewer/index.html +5 -4
  199. package/lib/vite/traceViewer/index.pMAN88y-.js +2 -0
  200. package/lib/vite/traceViewer/snapshot.html +1 -1
  201. package/lib/vite/traceViewer/sw.bundle.js +3 -4
  202. package/lib/vite/traceViewer/uiMode.D-tg1Oci.js +1730 -0
  203. package/lib/vite/traceViewer/uiMode.D3cNFP6u.css +1 -0
  204. package/lib/vite/traceViewer/uiMode.DKjMBMlc.js +1730 -0
  205. package/lib/vite/traceViewer/uiMode.DVWUEIHq.css +1424 -0
  206. package/lib/vite/traceViewer/uiMode.DVrL7a1K.js +10 -0
  207. package/lib/vite/traceViewer/uiMode.Dg9oJCQU.js +10 -0
  208. package/lib/vite/traceViewer/uiMode.DwZAzstF.js +10 -0
  209. package/lib/vite/traceViewer/uiMode.html +5 -4
  210. package/lib/vite/traceViewer/uiMode.iq7CyYy7.js +1490 -0
  211. package/lib/vite/traceViewer/uiMode.jY2s-9ps.js +10 -0
  212. package/lib/vite/traceViewer/uiMode.xvJHbkzl.css +1324 -0
  213. package/lib/vite/traceViewer/workbench.B3X2QtYa.css +3702 -0
  214. package/lib/vite/traceViewer/workbench.DyTpxWVb.css +1 -0
  215. package/lib/vite/traceViewer/wsPort.p5jUwABW.css +3450 -0
  216. package/lib/vite/traceViewer/xtermModule.4oRVGWQ-.css +209 -0
  217. package/lib/vite/traceViewer/xtermModule.OKEVRlkP.css +209 -0
  218. package/package.json +2 -2
  219. package/types/protocol.d.ts +960 -78
  220. package/types/structs.d.ts +1 -1
  221. package/types/types.d.ts +3083 -2448
  222. package/lib/vite/recorder/assets/codeMirrorModule-W69B4LBB.js +0 -24
  223. package/lib/vite/recorder/assets/index-Ly3PcVUb.js +0 -47
  224. package/lib/vite/recorder/assets/index-ljsTwXtJ.css +0 -1
  225. package/lib/vite/traceViewer/assets/codeMirrorModule-0bpaqixv.js +0 -24
  226. package/lib/vite/traceViewer/assets/codeMirrorModule-wLpsbIhd.js +0 -24
  227. package/lib/vite/traceViewer/assets/wsPort-_JBDEilC.js +0 -69
  228. package/lib/vite/traceViewer/assets/wsPort-f2dAQL4I.js +0 -69
  229. package/lib/vite/traceViewer/index.-_8-eHEE.js +0 -2
  230. package/lib/vite/traceViewer/index.u51inEcm.js +0 -2
  231. package/lib/vite/traceViewer/uiMode.9CwNsWc6.js +0 -10
  232. package/lib/vite/traceViewer/uiMode.Fb0bNA4H.js +0 -10
  233. package/lib/vite/traceViewer/uiMode.pWy0Re7G.css +0 -1
  234. package/lib/vite/traceViewer/wsPort.zR1WIy9-.css +0 -1
  235. /package/lib/vite/recorder/assets/{codeMirrorModule-Hs9-1ZG4.css → codeMirrorModule-ez37Vkbh.css} +0 -0
  236. /package/lib/vite/traceViewer/assets/{xtermModule-Yt6xwiJ_.js → xtermModule-BeNbaIVa.js} +0 -0
  237. /package/lib/vite/traceViewer/{codeMirrorModule.Hs9-1ZG4.css → codeMirrorModule.ez37Vkbh.css} +0 -0
  238. /package/lib/vite/traceViewer/{xtermModule.0lwXJFHT.css → xtermModule.DSXBckUd.css} +0 -0
@@ -64,6 +64,7 @@ class CRPage {
64
64
  this.rawTouchscreen = void 0;
65
65
  this._targetId = void 0;
66
66
  this._opener = void 0;
67
+ this._networkManager = void 0;
67
68
  this._pdf = void 0;
68
69
  this._coverage = void 0;
69
70
  this._browserContext = void 0;
@@ -87,6 +88,13 @@ class CRPage {
87
88
  this._coverage = new _crCoverage.CRCoverage(client);
88
89
  this._browserContext = browserContext;
89
90
  this._page = new _page.Page(this, browserContext);
91
+ this._networkManager = new _crNetworkManager.CRNetworkManager(this._page, null);
92
+ // Sync any browser context state to the network manager. This does not talk over CDP because
93
+ // we have not connected any sessions to the network manager yet.
94
+ this.updateOffline();
95
+ this.updateExtraHTTPHeaders();
96
+ this.updateHttpCredentials();
97
+ this.updateRequestInterception();
90
98
  this._mainFrameSession = new FrameSession(this, client, targetId, null);
91
99
  this._sessions.set(targetId, this._mainFrameSession);
92
100
  if (opener && !browserContext._options.noDefaultViewport) {
@@ -157,24 +165,18 @@ class CRPage {
157
165
  async navigateFrame(frame, url, referrer) {
158
166
  return this._sessionForFrame(frame)._navigate(frame, url, referrer);
159
167
  }
160
- async exposeBinding(binding) {
161
- await this._forAllFrameSessions(frame => frame._initBinding(binding));
162
- await Promise.all(this._page.frames().map(frame => frame.evaluateExpression(binding.source).catch(e => {})));
163
- }
164
- async removeExposedBindings() {
165
- await this._forAllFrameSessions(frame => frame._removeExposedBindings());
166
- }
167
168
  async updateExtraHTTPHeaders() {
168
- await this._forAllFrameSessions(frame => frame._updateExtraHTTPHeaders(false));
169
+ const headers = network.mergeHeaders([this._browserContext._options.extraHTTPHeaders, this._page.extraHTTPHeaders()]);
170
+ await this._networkManager.setExtraHTTPHeaders(headers);
169
171
  }
170
172
  async updateGeolocation() {
171
173
  await this._forAllFrameSessions(frame => frame._updateGeolocation(false));
172
174
  }
173
175
  async updateOffline() {
174
- await this._forAllFrameSessions(frame => frame._updateOffline(false));
176
+ await this._networkManager.setOffline(!!this._browserContext._options.offline);
175
177
  }
176
178
  async updateHttpCredentials() {
177
- await this._forAllFrameSessions(frame => frame._updateHttpCredentials(false));
179
+ await this._networkManager.authenticate(this._browserContext._options.httpCredentials || null);
178
180
  }
179
181
  async updateEmulatedViewportSize(preserveWindowBoundaries) {
180
182
  await this._mainFrameSession._updateViewport(preserveWindowBoundaries);
@@ -189,7 +191,7 @@ class CRPage {
189
191
  await this._forAllFrameSessions(frame => frame._updateUserAgent());
190
192
  }
191
193
  async updateRequestInterception() {
192
- await this._forAllFrameSessions(frame => frame._updateRequestInterception());
194
+ await this._networkManager.setRequestInterception(this._page.needsRequestInterception());
193
195
  }
194
196
  async updateFileChooserInterception() {
195
197
  await this._forAllFrameSessions(frame => frame._updateFileChooserInterception(false));
@@ -212,10 +214,10 @@ class CRPage {
212
214
  goForward() {
213
215
  return this._go(+1);
214
216
  }
215
- async addInitScript(source, world = 'main') {
216
- await this._forAllFrameSessions(frame => frame._evaluateOnNewDocument(source, world));
217
+ async addInitScript(initScript, world = 'main') {
218
+ await this._forAllFrameSessions(frame => frame._evaluateOnNewDocument(initScript, world));
217
219
  }
218
- async removeInitScripts() {
220
+ async removeNonInternalInitScripts() {
219
221
  await this._forAllFrameSessions(frame => frame._removeEvaluatesOnNewDocument());
220
222
  }
221
223
  async closePage(runBeforeUnload) {
@@ -295,7 +297,7 @@ class CRPage {
295
297
  async setInputFiles(handle, files) {
296
298
  await handle.evaluateInUtility(([injected, node, files]) => injected.setInputFiles(node, files), files);
297
299
  }
298
- async setInputFilePaths(progress, handle, files) {
300
+ async setInputFilePaths(handle, files) {
299
301
  const frame = await handle.ownerFrame();
300
302
  if (!frame) throw new Error('Cannot set input files to detached input element');
301
303
  const parentSession = this._sessionForFrame(frame);
@@ -346,7 +348,6 @@ class FrameSession {
346
348
  this._client = void 0;
347
349
  this._crPage = void 0;
348
350
  this._page = void 0;
349
- this._networkManager = void 0;
350
351
  this._parentSession = void 0;
351
352
  this._childSessions = new Set();
352
353
  this._contextIdToContext = new Map();
@@ -363,14 +364,12 @@ class FrameSession {
363
364
  this._screencastId = null;
364
365
  this._screencastClients = new Set();
365
366
  this._evaluateOnNewDocumentIdentifiers = [];
366
- this._exposedBindingNames = [];
367
367
  this._metricsOverride = void 0;
368
368
  this._workerSessions = new Map();
369
369
  this._client = client;
370
370
  this._crPage = crPage;
371
371
  this._page = crPage._page;
372
372
  this._targetId = targetId;
373
- this._networkManager = new _crNetworkManager.CRNetworkManager(client, this._page, null, parentSession ? parentSession._networkManager : null);
374
373
  this._parentSession = parentSession;
375
374
  if (parentSession) parentSession._childSessions.add(this);
376
375
  this._firstNonInitialNavigationCommittedPromise = new Promise((f, r) => {
@@ -430,12 +429,11 @@ class FrameSession {
430
429
  grantUniveralAccess: true,
431
430
  worldName: UTILITY_WORLD_NAME
432
431
  });
433
- for (const binding of this._crPage._browserContext._pageBindings.values()) frame.evaluateExpression(binding.source).catch(e => {});
434
- for (const source of this._crPage._browserContext.initScripts) frame.evaluateExpression(source).catch(e => {});
432
+ for (const initScript of this._crPage._page.allInitScripts()) frame.evaluateExpression(initScript.source).catch(e => {});
435
433
  }
436
434
  const isInitialEmptyPage = this._isMainFrame() && this._page.mainFrame().url() === ':';
437
435
  if (isInitialEmptyPage) {
438
- // Ignore lifecycle events for the initial empty page. It is never the final page
436
+ // Ignore lifecycle events, worlds and bindings for the initial empty page. It is never the final page
439
437
  // hence we are going to get more lifecycle updates after the actual navigation has
440
438
  // started (even if the target url is about:blank).
441
439
  lifecycleEventsEnabled.catch(e => {}).then(() => {
@@ -447,10 +445,12 @@ class FrameSession {
447
445
  }
448
446
  }), this._client.send('Log.enable', {}), lifecycleEventsEnabled = this._client.send('Page.setLifecycleEventsEnabled', {
449
447
  enabled: true
450
- }), this._client.send('Runtime.enable', {}), this._client.send('Page.addScriptToEvaluateOnNewDocument', {
448
+ }), this._client.send('Runtime.enable', {}), this._client.send('Runtime.addBinding', {
449
+ name: _page.PageBinding.kPlaywrightBinding
450
+ }), this._client.send('Page.addScriptToEvaluateOnNewDocument', {
451
451
  source: '',
452
452
  worldName: UTILITY_WORLD_NAME
453
- }), this._networkManager.initialize(), this._client.send('Target.setAutoAttach', {
453
+ }), this._crPage._networkManager.addSession(this._client, undefined, this._isMainFrame()), this._client.send('Target.setAutoAttach', {
454
454
  autoAttach: true,
455
455
  waitForDebuggerOnStart: true,
456
456
  flatten: true
@@ -478,15 +478,9 @@ class FrameSession {
478
478
  if (options.timezoneId) promises.push(emulateTimezone(this._client, options.timezoneId));
479
479
  if (!this._crPage._browserContext._browser.options.headful) promises.push(this._setDefaultFontFamilies(this._client));
480
480
  promises.push(this._updateGeolocation(true));
481
- promises.push(this._updateExtraHTTPHeaders(true));
482
- promises.push(this._updateRequestInterception());
483
- promises.push(this._updateOffline(true));
484
- promises.push(this._updateHttpCredentials(true));
485
481
  promises.push(this._updateEmulateMedia());
486
482
  promises.push(this._updateFileChooserInterception(true));
487
- for (const binding of this._crPage._page.allBindings()) promises.push(this._initBinding(binding));
488
- for (const source of this._crPage._browserContext.initScripts) promises.push(this._evaluateOnNewDocument(source, 'main'));
489
- for (const source of this._crPage._page.initScripts) promises.push(this._evaluateOnNewDocument(source, 'main'));
483
+ for (const initScript of this._crPage._page.allInitScripts()) promises.push(this._evaluateOnNewDocument(initScript, 'main'));
490
484
  if (screencastOptions) promises.push(this._startVideoRecording(screencastOptions));
491
485
  }
492
486
  promises.push(this._client.send('Runtime.runIfWaitingForDebugger'));
@@ -498,7 +492,7 @@ class FrameSession {
498
492
  for (const childSession of this._childSessions) childSession.dispose();
499
493
  if (this._parentSession) this._parentSession._childSessions.delete(this);
500
494
  _eventsHelper.eventsHelper.removeEventListeners(this._eventListeners);
501
- this._networkManager.dispose();
495
+ this._crPage._networkManager.removeSession(this._client);
502
496
  this._crPage._sessions.delete(this._targetId);
503
497
  this._client.dispose();
504
498
  }
@@ -575,7 +569,7 @@ class FrameSession {
575
569
  return;
576
570
  }
577
571
  if (reason === 'swap') {
578
- // This is a local -> remote frame transtion, where
572
+ // This is a local -> remote frame transition, where
579
573
  // Page.frameDetached arrives before Target.attachedToTarget.
580
574
  // We should keep the frame in the tree, and it will be used for the new target.
581
575
  const frame = this._page._frameManager.frame(frameId);
@@ -589,11 +583,11 @@ class FrameSession {
589
583
  const frame = contextPayload.auxData ? this._page._frameManager.frame(contextPayload.auxData.frameId) : null;
590
584
  if (!frame || this._eventBelongsToStaleFrame(frame._id)) return;
591
585
  const delegate = new _crExecutionContext.CRExecutionContext(this._client, contextPayload);
592
- let worldName = null;
593
- if (contextPayload.auxData && !!contextPayload.auxData.isDefault) worldName = 'main';else if (contextPayload.name === UTILITY_WORLD_NAME) worldName = 'utility';
586
+ let worldName;
587
+ if (contextPayload.auxData && !!contextPayload.auxData.isDefault) worldName = 'main';else if (contextPayload.name === UTILITY_WORLD_NAME) worldName = 'utility';else return;
594
588
  const context = new dom.FrameExecutionContext(delegate, frame, worldName);
595
589
  context[contextDelegateSymbol] = delegate;
596
- if (worldName) frame._contextCreated(worldName, context);
590
+ frame._contextCreated(worldName, context);
597
591
  this._contextIdToContext.set(contextPayload.id, context);
598
592
  }
599
593
  _onExecutionContextDestroyed(executionContextId) {
@@ -632,7 +626,8 @@ class FrameSession {
632
626
  });
633
627
  // This might fail if the target is closed before we initialize.
634
628
  session._sendMayFail('Runtime.enable');
635
- session._sendMayFail('Network.enable');
629
+ // TODO: attribute workers to the right frame.
630
+ this._crPage._networkManager.addSession(session, (_this$_page$_frameMan = this._page._frameManager.frame(this._targetId)) !== null && _this$_page$_frameMan !== void 0 ? _this$_page$_frameMan : undefined).catch(() => {});
636
631
  session._sendMayFail('Runtime.runIfWaitingForDebugger');
637
632
  session._sendMayFail('Target.setAutoAttach', {
638
633
  autoAttach: true,
@@ -646,11 +641,6 @@ class FrameSession {
646
641
  this._page._addConsoleMessage(event.type, args, (0, _crProtocolHelper.toConsoleMessageLocation)(event.stackTrace));
647
642
  });
648
643
  session.on('Runtime.exceptionThrown', exception => this._page.emitOnContextOnceInitialized(_browserContext.BrowserContext.Events.PageError, (0, _crProtocolHelper.exceptionToError)(exception.exceptionDetails), this._page));
649
- // TODO: attribute workers to the right frame.
650
- this._networkManager.instrumentNetworkEvents({
651
- session,
652
- workerFrame: (_this$_page$_frameMan = this._page._frameManager.frame(this._targetId)) !== null && _this$_page$_frameMan !== void 0 ? _this$_page$_frameMan : undefined
653
- });
654
644
  }
655
645
  _onDetachedFromTarget(event) {
656
646
  // This might be a worker...
@@ -707,24 +697,6 @@ class FrameSession {
707
697
  const values = event.args.map(arg => context.createHandle(arg));
708
698
  this._page._addConsoleMessage(event.type, values, (0, _crProtocolHelper.toConsoleMessageLocation)(event.stackTrace));
709
699
  }
710
- async _initBinding(binding) {
711
- const [, response] = await Promise.all([this._client.send('Runtime.addBinding', {
712
- name: binding.name
713
- }), this._client.send('Page.addScriptToEvaluateOnNewDocument', {
714
- source: binding.source
715
- })]);
716
- this._exposedBindingNames.push(binding.name);
717
- if (!binding.name.startsWith('__pw')) this._evaluateOnNewDocumentIdentifiers.push(response.identifier);
718
- }
719
- async _removeExposedBindings() {
720
- const toRetain = [];
721
- const toRemove = [];
722
- for (const name of this._exposedBindingNames) (name.startsWith('__pw_') ? toRetain : toRemove).push(name);
723
- this._exposedBindingNames = toRetain;
724
- await Promise.all(toRemove.map(name => this._client.send('Runtime.removeBinding', {
725
- name
726
- })));
727
- }
728
700
  async _onBindingCalled(event) {
729
701
  const pageOrError = await this._crPage.pageOrError();
730
702
  if (!(pageOrError instanceof Error)) {
@@ -846,24 +818,10 @@ class FrameSession {
846
818
  this._screencastClients.delete(client);
847
819
  if (!this._screencastClients.size) await this._client._sendMayFail('Page.stopScreencast');
848
820
  }
849
- async _updateExtraHTTPHeaders(initial) {
850
- const headers = network.mergeHeaders([this._crPage._browserContext._options.extraHTTPHeaders, this._page.extraHTTPHeaders()]);
851
- if (!initial || headers.length) await this._client.send('Network.setExtraHTTPHeaders', {
852
- headers: (0, _utils.headersArrayToObject)(headers, false /* lowerCase */)
853
- });
854
- }
855
821
  async _updateGeolocation(initial) {
856
822
  const geolocation = this._crPage._browserContext._options.geolocation;
857
823
  if (!initial || geolocation) await this._client.send('Emulation.setGeolocationOverride', geolocation || {});
858
824
  }
859
- async _updateOffline(initial) {
860
- const offline = !!this._crPage._browserContext._options.offline;
861
- if (!initial || offline) await this._networkManager.setOffline(offline);
862
- }
863
- async _updateHttpCredentials(initial) {
864
- const credentials = this._crPage._browserContext._options.httpCredentials || null;
865
- if (!initial || credentials) await this._networkManager.authenticate(credentials);
866
- }
867
825
  async _updateViewport(preserveWindowBoundaries) {
868
826
  if (this._crPage._browserContext._browser.isClank()) return;
869
827
  (0, _utils.assert)(this._isMainFrame());
@@ -978,9 +936,6 @@ class FrameSession {
978
936
  const fontFamilies = _defaultFontFamilies.platformToFontFamilies[this._crPage._browserContext._browser._platform()];
979
937
  await session.send('Page.setFontFamilies', fontFamilies);
980
938
  }
981
- async _updateRequestInterception() {
982
- await this._networkManager.setRequestInterception(this._page.needsRequestInterception());
983
- }
984
939
  async _updateFileChooserInterception(initial) {
985
940
  const enabled = this._page.fileChooserIntercepted();
986
941
  if (initial && !enabled) return;
@@ -988,15 +943,15 @@ class FrameSession {
988
943
  enabled
989
944
  }).catch(() => {}); // target can be closed.
990
945
  }
991
- async _evaluateOnNewDocument(source, world) {
946
+ async _evaluateOnNewDocument(initScript, world) {
992
947
  const worldName = world === 'utility' ? UTILITY_WORLD_NAME : undefined;
993
948
  const {
994
949
  identifier
995
950
  } = await this._client.send('Page.addScriptToEvaluateOnNewDocument', {
996
- source,
951
+ source: initScript.source,
997
952
  worldName
998
953
  });
999
- this._evaluateOnNewDocumentIdentifiers.push(identifier);
954
+ if (!initScript.internal) this._evaluateOnNewDocumentIdentifiers.push(identifier);
1000
955
  }
1001
956
  async _removeEvaluatesOnNewDocument() {
1002
957
  const identifiers = this._evaluateOnNewDocumentIdentifiers;
@@ -94,6 +94,7 @@ function toConsoleMessageLocation(stackTrace) {
94
94
  };
95
95
  }
96
96
  function exceptionToError(exceptionDetails) {
97
+ var _exceptionDetails$exc, _nameOverride$value;
97
98
  const messageWithStack = getExceptionMessage(exceptionDetails);
98
99
  const lines = messageWithStack.split('\n');
99
100
  const firstStackTraceLine = lines.findIndex(line => line.startsWith(' at'));
@@ -111,7 +112,8 @@ function exceptionToError(exceptionDetails) {
111
112
  } = (0, _stackTrace.splitErrorMessage)(messageWithName);
112
113
  const err = new Error(message);
113
114
  err.stack = stack;
114
- err.name = name;
115
+ const nameOverride = (_exceptionDetails$exc = exceptionDetails.exception) === null || _exceptionDetails$exc === void 0 || (_exceptionDetails$exc = _exceptionDetails$exc.preview) === null || _exceptionDetails$exc === void 0 ? void 0 : _exceptionDetails$exc.properties.find(o => o.name === 'name');
116
+ err.name = nameOverride ? (_nameOverride$value = nameOverride.value) !== null && _nameOverride$value !== void 0 ? _nameOverride$value : 'Error' : name;
115
117
  return err;
116
118
  }
117
119
  function toModifiersMask(modifiers) {
@@ -9,7 +9,6 @@ var _crExecutionContext = require("./crExecutionContext");
9
9
  var _crNetworkManager = require("./crNetworkManager");
10
10
  var network = _interopRequireWildcard(require("../network"));
11
11
  var _browserContext = require("../browserContext");
12
- var _utils = require("../../utils");
13
12
  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); }
14
13
  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; }
15
14
  /**
@@ -34,19 +33,18 @@ class CRServiceWorker extends _page.Worker {
34
33
  this._browserContext = void 0;
35
34
  this._networkManager = void 0;
36
35
  this._session = void 0;
37
- this._extraHTTPHeaders = null;
38
36
  this._session = session;
39
37
  this._browserContext = browserContext;
40
- if (!!process.env.PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS) this._networkManager = new _crNetworkManager.CRNetworkManager(session, null, this, null);
38
+ if (!!process.env.PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS) this._networkManager = new _crNetworkManager.CRNetworkManager(null, this);
41
39
  session.once('Runtime.executionContextCreated', event => {
42
40
  this._createExecutionContext(new _crExecutionContext.CRExecutionContext(session, event.context));
43
41
  });
44
42
  if (this._networkManager && this._isNetworkInspectionEnabled()) {
45
- this._networkManager.initialize().catch(() => {});
46
43
  this.updateRequestInterception();
47
- this.updateExtraHTTPHeaders(true);
48
- this.updateHttpCredentials(true);
49
- this.updateOffline(true);
44
+ this.updateExtraHTTPHeaders();
45
+ this.updateHttpCredentials();
46
+ this.updateOffline();
47
+ this._networkManager.addSession(session, undefined, true /* isMain */).catch(() => {});
50
48
  }
51
49
  session.send('Runtime.enable', {}).catch(e => {});
52
50
  session.send('Runtime.runIfWaitingForDebugger').catch(e => {});
@@ -56,31 +54,30 @@ class CRServiceWorker extends _page.Worker {
56
54
  });
57
55
  }
58
56
  didClose() {
57
+ var _this$_networkManager;
58
+ (_this$_networkManager = this._networkManager) === null || _this$_networkManager === void 0 || _this$_networkManager.removeSession(this._session);
59
59
  this._session.dispose();
60
60
  super.didClose();
61
61
  }
62
- async updateOffline(initial) {
63
- var _this$_networkManager;
62
+ async updateOffline() {
63
+ var _this$_networkManager2;
64
64
  if (!this._isNetworkInspectionEnabled()) return;
65
- const offline = !!this._browserContext._options.offline;
66
- if (!initial || offline) await ((_this$_networkManager = this._networkManager) === null || _this$_networkManager === void 0 ? void 0 : _this$_networkManager.setOffline(offline));
65
+ await ((_this$_networkManager2 = this._networkManager) === null || _this$_networkManager2 === void 0 ? void 0 : _this$_networkManager2.setOffline(!!this._browserContext._options.offline).catch(() => {}));
67
66
  }
68
- async updateHttpCredentials(initial) {
69
- var _this$_networkManager2;
67
+ async updateHttpCredentials() {
68
+ var _this$_networkManager3;
70
69
  if (!this._isNetworkInspectionEnabled()) return;
71
- const credentials = this._browserContext._options.httpCredentials || null;
72
- if (!initial || credentials) await ((_this$_networkManager2 = this._networkManager) === null || _this$_networkManager2 === void 0 ? void 0 : _this$_networkManager2.authenticate(credentials));
70
+ await ((_this$_networkManager3 = this._networkManager) === null || _this$_networkManager3 === void 0 ? void 0 : _this$_networkManager3.authenticate(this._browserContext._options.httpCredentials || null).catch(() => {}));
73
71
  }
74
- async updateExtraHTTPHeaders(initial) {
72
+ async updateExtraHTTPHeaders() {
73
+ var _this$_networkManager4;
75
74
  if (!this._isNetworkInspectionEnabled()) return;
76
- const headers = network.mergeHeaders([this._browserContext._options.extraHTTPHeaders, this._extraHTTPHeaders]);
77
- if (!initial || headers.length) await this._session.send('Network.setExtraHTTPHeaders', {
78
- headers: (0, _utils.headersArrayToObject)(headers, false /* lowerCase */)
79
- });
75
+ await ((_this$_networkManager4 = this._networkManager) === null || _this$_networkManager4 === void 0 ? void 0 : _this$_networkManager4.setExtraHTTPHeaders(this._browserContext._options.extraHTTPHeaders || []).catch(() => {}));
80
76
  }
81
- updateRequestInterception() {
82
- if (!this._networkManager || !this._isNetworkInspectionEnabled()) return Promise.resolve();
83
- return this._networkManager.setRequestInterception(this.needsRequestInterception()).catch(e => {});
77
+ async updateRequestInterception() {
78
+ var _this$_networkManager5;
79
+ if (!this._isNetworkInspectionEnabled()) return;
80
+ await ((_this$_networkManager5 = this._networkManager) === null || _this$_networkManager5 === void 0 ? void 0 : _this$_networkManager5.setRequestInterception(this.needsRequestInterception()).catch(() => {}));
84
81
  }
85
82
  needsRequestInterception() {
86
83
  return this._isNetworkInspectionEnabled() && !!this._browserContext._requestInterceptor;
@@ -94,7 +94,7 @@ class VideoRecorder {
94
94
 
95
95
  const w = options.width;
96
96
  const h = options.height;
97
- const args = `-loglevel error -f image2pipe -avioflags direct -fpsprobesize 0 -probesize 32 -analyzeduration 0 -c:v mjpeg -i - -y -an -r ${fps} -c:v vp8 -qmin 0 -qmax 50 -crf 8 -deadline realtime -speed 8 -b:v 1M -threads 1 -vf pad=${w}:${h}:0:0:gray,crop=${w}:${h}:0:0`.split(' ');
97
+ const args = `-loglevel error -f image2pipe -avioflags direct -fpsprobesize 0 -probesize 32 -analyzeduration 0 -c:v mjpeg -i pipe:0 -y -an -r ${fps} -c:v vp8 -qmin 0 -qmax 50 -crf 8 -deadline realtime -speed 8 -b:v 1M -threads 1 -vf pad=${w}:${h}:0:0:gray,crop=${w}:${h}:0:0`.split(' ');
98
98
  args.push(options.outputFile);
99
99
  const progress = this._progress;
100
100
  const {
@@ -0,0 +1,125 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.Clock = void 0;
7
+ var clockSource = _interopRequireWildcard(require("../generated/clockSource"));
8
+ 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); }
9
+ 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; }
10
+ /**
11
+ * Copyright (c) Microsoft Corporation.
12
+ *
13
+ * Licensed under the Apache License, Version 2.0 (the "License");
14
+ * you may not use this file except in compliance with the License.
15
+ * You may obtain a copy of the License at
16
+ *
17
+ * http://www.apache.org/licenses/LICENSE-2.0
18
+ *
19
+ * Unless required by applicable law or agreed to in writing, software
20
+ * distributed under the License is distributed on an "AS IS" BASIS,
21
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22
+ * See the License for the specific language governing permissions and
23
+ * limitations under the License.
24
+ */
25
+
26
+ class Clock {
27
+ constructor(browserContext) {
28
+ this._browserContext = void 0;
29
+ this._scriptInstalled = false;
30
+ this._browserContext = browserContext;
31
+ }
32
+ markAsUninstalled() {
33
+ this._scriptInstalled = false;
34
+ }
35
+ async fastForward(ticks) {
36
+ await this._installIfNeeded();
37
+ const ticksMillis = parseTicks(ticks);
38
+ await this._browserContext.addInitScript(`globalThis.__pwClock.controller.log('fastForward', ${Date.now()}, ${ticksMillis})`);
39
+ await this._evaluateInFrames(`globalThis.__pwClock.controller.fastForward(${ticksMillis})`);
40
+ }
41
+ async install(time) {
42
+ await this._installIfNeeded();
43
+ const timeMillis = time !== undefined ? parseTime(time) : Date.now();
44
+ await this._browserContext.addInitScript(`globalThis.__pwClock.controller.log('install', ${Date.now()}, ${timeMillis})`);
45
+ await this._evaluateInFrames(`globalThis.__pwClock.controller.install(${timeMillis})`);
46
+ }
47
+ async pauseAt(ticks) {
48
+ await this._installIfNeeded();
49
+ const timeMillis = parseTime(ticks);
50
+ await this._browserContext.addInitScript(`globalThis.__pwClock.controller.log('pauseAt', ${Date.now()}, ${timeMillis})`);
51
+ await this._evaluateInFrames(`globalThis.__pwClock.controller.pauseAt(${timeMillis})`);
52
+ }
53
+ async resume() {
54
+ await this._installIfNeeded();
55
+ await this._browserContext.addInitScript(`globalThis.__pwClock.controller.log('resume', ${Date.now()})`);
56
+ await this._evaluateInFrames(`globalThis.__pwClock.controller.resume()`);
57
+ }
58
+ async setFixedTime(time) {
59
+ await this._installIfNeeded();
60
+ const timeMillis = parseTime(time);
61
+ await this._browserContext.addInitScript(`globalThis.__pwClock.controller.log('setFixedTime', ${Date.now()}, ${timeMillis})`);
62
+ await this._evaluateInFrames(`globalThis.__pwClock.controller.setFixedTime(${timeMillis})`);
63
+ }
64
+ async setSystemTime(time) {
65
+ await this._installIfNeeded();
66
+ const timeMillis = parseTime(time);
67
+ await this._browserContext.addInitScript(`globalThis.__pwClock.controller.log('setSystemTime', ${Date.now()}, ${timeMillis})`);
68
+ await this._evaluateInFrames(`globalThis.__pwClock.controller.setSystemTime(${timeMillis})`);
69
+ }
70
+ async runFor(ticks) {
71
+ await this._installIfNeeded();
72
+ const ticksMillis = parseTicks(ticks);
73
+ await this._browserContext.addInitScript(`globalThis.__pwClock.controller.log('runFor', ${Date.now()}, ${ticksMillis})`);
74
+ await this._evaluateInFrames(`globalThis.__pwClock.controller.runFor(${ticksMillis})`);
75
+ }
76
+ async _installIfNeeded() {
77
+ if (this._scriptInstalled) return;
78
+ this._scriptInstalled = true;
79
+ const script = `(() => {
80
+ const module = {};
81
+ ${clockSource.source}
82
+ globalThis.__pwClock = (module.exports.inject())(globalThis);
83
+ })();`;
84
+ await this._browserContext.addInitScript(script);
85
+ await this._evaluateInFrames(script);
86
+ }
87
+ async _evaluateInFrames(script) {
88
+ await this._browserContext.safeNonStallingEvaluateInAllFrames(script, 'main', {
89
+ throwOnJSErrors: true
90
+ });
91
+ }
92
+ }
93
+
94
+ /**
95
+ * Parse strings like '01:10:00' (meaning 1 hour, 10 minutes, 0 seconds) into
96
+ * number of milliseconds. This is used to support human-readable strings passed
97
+ * to clock.tick()
98
+ */
99
+ exports.Clock = Clock;
100
+ function parseTicks(value) {
101
+ if (typeof value === 'number') return value;
102
+ if (!value) return 0;
103
+ const str = value;
104
+ const strings = str.split(':');
105
+ const l = strings.length;
106
+ let i = l;
107
+ let ms = 0;
108
+ let parsed;
109
+ if (l > 3 || !/^(\d\d:){0,2}\d\d?$/.test(str)) {
110
+ throw new Error(`Clock only understands numbers, 'mm:ss' and 'hh:mm:ss'`);
111
+ }
112
+ while (i--) {
113
+ parsed = parseInt(strings[i], 10);
114
+ if (parsed >= 60) throw new Error(`Invalid time ${str}`);
115
+ ms += parsed * Math.pow(60, l - i - 1);
116
+ }
117
+ return ms * 1000;
118
+ }
119
+ function parseTime(epoch) {
120
+ if (!epoch) return 0;
121
+ if (typeof epoch === 'number') return epoch;
122
+ const parsed = new Date(epoch);
123
+ if (!isFinite(parsed.getTime())) throw new Error(`Invalid date: ${epoch}`);
124
+ return parsed.getTime();
125
+ }