rebrowser-playwright-core 1.47.2 → 1.48.2

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 (121) hide show
  1. package/README.md +2 -0
  2. package/browsers.json +14 -10
  3. package/lib/cli/program.js +26 -14
  4. package/lib/client/api.js +6 -0
  5. package/lib/client/browserContext.js +20 -2
  6. package/lib/client/channelOwner.js +5 -1
  7. package/lib/client/connection.js +3 -0
  8. package/lib/client/fetch.js +16 -21
  9. package/lib/client/jsHandle.js +0 -8
  10. package/lib/client/localUtils.js +1 -0
  11. package/lib/client/network.js +175 -17
  12. package/lib/client/page.js +21 -0
  13. package/lib/client/playwright.js +6 -3
  14. package/lib/client/tracing.js +16 -20
  15. package/lib/generated/consoleApiSource.js +1 -1
  16. package/lib/generated/injectedScriptSource.js +1 -1
  17. package/lib/generated/pollingRecorderSource.js +7 -0
  18. package/lib/generated/webSocketMockSource.js +7 -0
  19. package/lib/protocol/validator.js +80 -14
  20. package/lib/server/bidi/bidiBrowser.js +23 -8
  21. package/lib/server/bidi/bidiChromium.js +124 -0
  22. package/lib/server/bidi/bidiConnection.js +1 -1
  23. package/lib/server/bidi/bidiExecutionContext.js +0 -3
  24. package/lib/server/bidi/bidiFirefox.js +15 -21
  25. package/lib/server/bidi/bidiInput.js +16 -32
  26. package/lib/server/bidi/bidiNetworkManager.js +39 -5
  27. package/lib/server/bidi/bidiOverCdp.js +103 -0
  28. package/lib/server/bidi/bidiPage.js +98 -25
  29. package/lib/server/bidi/bidiPdf.js +140 -0
  30. package/lib/server/bidi/third_party/firefoxPrefs.js +221 -0
  31. package/lib/server/browser.js +13 -2
  32. package/lib/server/browserContext.js +6 -23
  33. package/lib/server/browserType.js +39 -11
  34. package/lib/server/chromium/chromium.js +3 -15
  35. package/lib/server/chromium/chromiumSwitches.js +3 -1
  36. package/lib/server/chromium/crBrowser.js +4 -3
  37. package/lib/server/chromium/crExecutionContext.js +0 -7
  38. package/lib/server/chromium/crPage.js +16 -6
  39. package/lib/server/chromium/videoRecorder.js +1 -1
  40. package/lib/server/codegen/csharp.js +1 -1
  41. package/lib/server/codegen/java.js +1 -1
  42. package/lib/server/codegen/javascript.js +1 -1
  43. package/lib/server/codegen/language.js +14 -2
  44. package/lib/server/codegen/python.js +1 -1
  45. package/lib/server/cookieStore.js +73 -0
  46. package/lib/server/debugController.js +2 -2
  47. package/lib/server/deviceDescriptorsSource.json +50 -50
  48. package/lib/server/dialog.js +1 -0
  49. package/lib/server/dispatchers/browserContextDispatcher.js +19 -2
  50. package/lib/server/dispatchers/jsHandleDispatcher.js +0 -5
  51. package/lib/server/dispatchers/pageDispatcher.js +9 -0
  52. package/lib/server/dispatchers/playwrightDispatcher.js +2 -1
  53. package/lib/server/dispatchers/webSocketRouteDispatcher.js +189 -0
  54. package/lib/server/download.js +9 -2
  55. package/lib/server/fetch.js +90 -94
  56. package/lib/server/firefox/ffBrowser.js +6 -4
  57. package/lib/server/firefox/ffExecutionContext.js +0 -3
  58. package/lib/server/firefox/ffPage.js +6 -3
  59. package/lib/server/firefox/firefox.js +2 -13
  60. package/lib/server/frameSelectors.js +1 -1
  61. package/lib/server/frames.js +164 -28
  62. package/lib/server/har/harTracer.js +11 -0
  63. package/lib/server/input.js +0 -1
  64. package/lib/server/javascript.js +0 -7
  65. package/lib/server/page.js +5 -1
  66. package/lib/server/playwright.js +5 -2
  67. package/lib/server/recorder/contextRecorder.js +33 -50
  68. package/lib/server/recorder/recorderApp.js +16 -10
  69. package/lib/server/recorder/recorderCollection.js +68 -79
  70. package/lib/server/recorder/recorderInTraceViewer.js +144 -0
  71. package/lib/server/recorder/recorderRunner.js +75 -97
  72. package/lib/server/recorder/recorderUtils.js +47 -6
  73. package/lib/server/recorder.js +30 -25
  74. package/lib/server/registry/index.js +85 -4
  75. package/lib/server/socksClientCertificatesInterceptor.js +15 -3
  76. package/lib/server/trace/recorder/snapshotter.js +1 -0
  77. package/lib/server/trace/recorder/snapshotterInjected.js +2 -2
  78. package/lib/server/trace/recorder/tracing.js +58 -2
  79. package/lib/server/trace/test/inMemorySnapshotter.js +1 -1
  80. package/lib/server/trace/viewer/traceViewer.js +2 -5
  81. package/lib/server/webkit/webkit.js +1 -1
  82. package/lib/server/webkit/wkBrowser.js +6 -5
  83. package/lib/server/webkit/wkExecutionContext.js +0 -3
  84. package/lib/server/webkit/wkPage.js +7 -4
  85. package/lib/utils/happy-eyeballs.js +13 -0
  86. package/lib/utils/hostPlatform.js +2 -2
  87. package/lib/utils/httpServer.js +1 -0
  88. package/lib/utils/isomorphic/locatorGenerators.js +9 -18
  89. package/lib/utils/isomorphic/locatorParser.js +2 -2
  90. package/lib/utils/isomorphic/recorderUtils.js +195 -0
  91. package/lib/vite/htmlReport/index.html +12 -12
  92. package/lib/vite/recorder/assets/{codeMirrorModule-aW6Vz3gf.js → codeMirrorModule-baozm8ur.js} +1 -1
  93. package/lib/vite/recorder/assets/{index-DCpXOVIh.js → index-2ElAIWFB.js} +10 -15
  94. package/lib/vite/recorder/assets/{index-B-MT5gKo.css → index-BW-aOBcL.css} +1 -1
  95. package/lib/vite/recorder/index.html +2 -2
  96. package/lib/vite/traceViewer/assets/{codeMirrorModule-eFKCUIu2.js → codeMirrorModule-Bh1rfd2w.js} +1 -1
  97. package/lib/vite/traceViewer/assets/inspectorTab-7GHnKvSD.js +64 -0
  98. package/lib/vite/traceViewer/assets/workbench-DPQnTHYP.js +9 -0
  99. package/lib/vite/traceViewer/embedded.BlHoW5LY.js +2 -0
  100. package/lib/vite/traceViewer/embedded.html +5 -3
  101. package/lib/vite/traceViewer/index.DaWVfou1.js +2 -0
  102. package/lib/vite/traceViewer/index.html +5 -3
  103. package/lib/vite/traceViewer/inspectorTab.DLjBDrQR.css +1 -0
  104. package/lib/vite/traceViewer/recorder.B_SY1GJM.css +0 -0
  105. package/lib/vite/traceViewer/recorder.C4zxcvd2.js +2 -0
  106. package/lib/vite/traceViewer/recorder.html +17 -0
  107. package/lib/vite/traceViewer/sw.bundle.js +3 -3
  108. package/lib/vite/traceViewer/{uiMode.D3cNFP6u.css → uiMode.CAYqod-m.css} +1 -1
  109. package/lib/vite/traceViewer/uiMode.html +6 -4
  110. package/lib/vite/traceViewer/uiMode.mTXWniJb.js +5 -0
  111. package/lib/vite/traceViewer/workbench.D3JVcA9K.css +1 -0
  112. package/package.json +1 -1
  113. package/types/protocol.d.ts +79 -8
  114. package/types/types.d.ts +2037 -949
  115. package/lib/generated/recorderSource.js +0 -7
  116. package/lib/vite/traceViewer/assets/workbench-D0cirtfA.js +0 -72
  117. package/lib/vite/traceViewer/embedded.BkuvsLJp.js +0 -2
  118. package/lib/vite/traceViewer/index.C968kAiC.js +0 -2
  119. package/lib/vite/traceViewer/uiMode.BkFnr4V0.js +0 -10
  120. package/lib/vite/traceViewer/workbench.DjbIuxix.css +0 -1
  121. /package/lib/server/recorder/{recorderActions.js → recorderFrontend.js} +0 -0
@@ -61,7 +61,7 @@ class FrameManager {
61
61
  this._webSockets = new Map();
62
62
  this._openedDialogs = new Set();
63
63
  this._closeAllOpeningDialogs = false;
64
- this._isolatedContext = undefined;
64
+ this.__re__contexts = undefined;
65
65
  this._page = page;
66
66
  this._mainFrame = undefined;
67
67
  }
@@ -429,7 +429,7 @@ class Frame extends _instrumentation.SdkObject {
429
429
  if (this._inflightRequests.size === 0) this._startNetworkIdleTimer();
430
430
  this._page.mainFrame()._recalculateNetworkIdle(this);
431
431
  this._onLifecycleEvent('commit');
432
- this._isolatedContext = undefined;
432
+ this.__re__contexts = undefined;
433
433
  }
434
434
  setPendingDocument(documentInfo) {
435
435
  this._pendingDocument = documentInfo;
@@ -584,33 +584,169 @@ class Frame extends _instrumentation.SdkObject {
584
584
  async frameElement() {
585
585
  return this._page._delegate.getFrameElement(this);
586
586
  }
587
+ async __re__getMainWorld({
588
+ client,
589
+ frameId
590
+ }) {
591
+ let contextId;
592
+
593
+ // random name to make it harder to detect for any 3rd party script by watching window object and events
594
+ const randomName = [...Array(Math.floor(Math.random() * (10 + 1)) + 10)].map(() => Math.random().toString(36)[2]).join('');
595
+ process.env['REBROWSER_PATCHES_DEBUG'] && console.log(`[rebrowser-patches][getMainWorld] binding name = ${randomName}`);
596
+
597
+ // add the binding
598
+ await client.send('Runtime.addBinding', {
599
+ name: randomName
600
+ });
601
+
602
+ // listen for 'Runtime.bindingCalled' event
603
+ const bindingCalledHandler = ({
604
+ name,
605
+ payload,
606
+ executionContextId
607
+ }) => {
608
+ process.env['REBROWSER_PATCHES_DEBUG'] && console.log('[rebrowser-patches][bindingCalledHandler]', {
609
+ name,
610
+ payload,
611
+ executionContextId
612
+ });
613
+ if (contextId > 0) {
614
+ // already acquired the id
615
+ return;
616
+ }
617
+ if (name !== randomName) {
618
+ // ignore irrelevant bindings
619
+ return;
620
+ }
621
+ if (payload !== frameId) {
622
+ // ignore irrelevant frames
623
+ return;
624
+ }
625
+ contextId = executionContextId;
626
+ // remove this listener
627
+ client.off('Runtime.bindingCalled', bindingCalledHandler);
628
+ };
629
+ client.on('Runtime.bindingCalled', bindingCalledHandler);
630
+
631
+ // we could call the binding right from addScriptToEvaluateOnNewDocument, but this way it will be called in all existing frames and it's hard to distinguish children from the parent
632
+ await client.send('Page.addScriptToEvaluateOnNewDocument', {
633
+ source: `document.addEventListener('${randomName}', (e) => self['${randomName}'](e.detail.frameId))`,
634
+ runImmediately: true
635
+ });
636
+
637
+ // create new isolated world for this frame
638
+ const createIsolatedWorldResult = await client.send('Page.createIsolatedWorld', {
639
+ frameId,
640
+ // use randomName for worldName to distinguish from normal utility world
641
+ worldName: randomName,
642
+ grantUniveralAccess: true
643
+ });
644
+
645
+ // emit event in the specific frame from the isolated world
646
+ await client.send('Runtime.evaluate', {
647
+ expression: `document.dispatchEvent(new CustomEvent('${randomName}', { detail: { frameId: '${frameId}' } }))`,
648
+ contextId: createIsolatedWorldResult.executionContextId
649
+ });
650
+ process.env['REBROWSER_PATCHES_DEBUG'] && console.log(`[rebrowser-patches][getMainWorld] result:`, {
651
+ contextId
652
+ });
653
+ return contextId;
654
+ }
655
+ async __re__getIsolatedWorld({
656
+ client,
657
+ frameId,
658
+ worldName
659
+ }) {
660
+ const createIsolatedWorldResult = await client.send('Page.createIsolatedWorld', {
661
+ frameId,
662
+ worldName,
663
+ grantUniveralAccess: true
664
+ });
665
+ process.env['REBROWSER_PATCHES_DEBUG'] && console.log(`[rebrowser-patches][getIsolatedWorld] result:`, createIsolatedWorldResult);
666
+ return createIsolatedWorldResult.executionContextId;
667
+ }
587
668
  _context(world) {
588
- if (process.env['REBROWSER_PATCHES_RUNTIME_FIX_MODE'] !== '0') {
589
- // rebrowser-patches: use only utility context, create it on demand and cache
590
- if (this._isolatedContext !== undefined) {
591
- return this._isolatedContext;
669
+ const fixMode = process.env['REBROWSER_PATCHES_RUNTIME_FIX_MODE'] || 'addBinding';
670
+ process.env['REBROWSER_PATCHES_DEBUG'] && console.log(`[rebrowser-patches][frames._context] frameId = ${this._id}, world = ${world}, fixMode = ${fixMode}`);
671
+ if (fixMode !== '0') {
672
+ if (typeof this.__re__contexts === 'undefined') {
673
+ this.__re__contexts = {};
592
674
  }
675
+ const frameSession = this._page._delegate._sessions.get(this._id) || this._page._delegate._mainFrameSession;
676
+ const client = frameSession._client;
593
677
  const utilityWorldName = process.env['REBROWSER_PATCHES_UTILITY_WORLD_NAME'] !== '0' ? process.env['REBROWSER_PATCHES_UTILITY_WORLD_NAME'] || 'util' : '__playwright_utility_world__';
594
- return this._page._delegate._mainFrameSession._client.send('Page.createIsolatedWorld', {
595
- frameId: this._id,
596
- grantUniveralAccess: true,
597
- worldName: utilityWorldName
598
- }).then(createIsolatedWorldResult => {
599
- const contextPayload = {
600
- id: createIsolatedWorldResult.executionContextId,
601
- name: utilityWorldName,
602
- auxData: {
678
+ let getWorldPromise;
679
+ if (fixMode === 'addBinding') {
680
+ if (this.__re__contexts[world] !== undefined) {
681
+ return Promise.resolve(this.__re__contexts[world]);
682
+ }
683
+ if (world === 'utility') {
684
+ getWorldPromise = this.__re__getIsolatedWorld({
685
+ client,
603
686
  frameId: this._id,
604
- isDefault: false
605
- }
606
- };
607
- const delegate = new _crExecutionContext.CRExecutionContext(this._page._delegate._mainFrameSession._client, contextPayload);
608
- this._isolatedContext = new dom.FrameExecutionContext(delegate, this, 'utility');
609
- return this._isolatedContext;
610
- }).catch(error => {
611
- // probably target is closed
687
+ worldName: utilityWorldName
688
+ }).then(contextId => {
689
+ return {
690
+ id: contextId,
691
+ name: utilityWorldName,
692
+ auxData: {
693
+ frameId: this._id,
694
+ isDefault: false
695
+ }
696
+ };
697
+ });
698
+ } else if (world === 'main') {
699
+ getWorldPromise = this.__re__getMainWorld({
700
+ client,
701
+ frameId: this._id
702
+ }).then(contextId => {
703
+ return {
704
+ id: contextId,
705
+ name: '',
706
+ auxData: {
707
+ frameId: this._id,
708
+ isDefault: true
709
+ }
710
+ };
711
+ });
712
+ }
713
+ getWorldPromise = getWorldPromise.then(contextPayload => {
714
+ const delegate = new _crExecutionContext.CRExecutionContext(client, contextPayload);
715
+ this.__re__contexts[world] = new dom.FrameExecutionContext(delegate, this, world);
716
+ return this.__re__contexts[world];
717
+ });
718
+ } else if (fixMode === 'alwaysIsolated') {
719
+ // use only utility context
720
+ if (this.__re__contexts.utility !== undefined) {
721
+ return Promise.resolve(this.__re__contexts.utility);
722
+ }
723
+ getWorldPromise = this.__re__getIsolatedWorld({
724
+ client,
725
+ frameId: this._id,
726
+ worldName: utilityWorldName
727
+ }).then(contextId => {
728
+ const contextPayload = {
729
+ id: contextId,
730
+ name: utilityWorldName,
731
+ auxData: {
732
+ frameId: this._id,
733
+ isDefault: false
734
+ }
735
+ };
736
+ const delegate = new _crExecutionContext.CRExecutionContext(client, contextPayload);
737
+ this.__re__contexts.utility = new dom.FrameExecutionContext(delegate, this, 'utility');
738
+ return this.__re__contexts.utility;
739
+ });
740
+ }
741
+ return getWorldPromise.catch(error => {
742
+ if (error.message.includes('No frame for given id found')) {
743
+ // ignore, frame is already gone
744
+ return {
745
+ destroyedReason: 'Frame was detached'
746
+ };
747
+ }
612
748
  _debugLogger.debugLogger.log('error', error);
613
- console.error('[rebrowser-patches][frames._context] cannot create utility world');
749
+ console.error('[rebrowser-patches][frames._context] cannot get world, error:', error);
614
750
  });
615
751
  }
616
752
  return this._contextData.get(world).contextPromise.then(contextOrDestroyedReason => {
@@ -654,14 +790,15 @@ class Frame extends _instrumentation.SdkObject {
654
790
  if (!['attached', 'detached', 'visible', 'hidden'].includes(state)) throw new Error(`state: expected one of (attached|detached|visible|hidden)`);
655
791
  return controller.run(async progress => {
656
792
  progress.log(`waiting for ${this._asLocator(selector)}${state === 'attached' ? '' : ' to be ' + state}`);
657
- return await this.waitForSelectorInternal(progress, selector, options, scope);
793
+ return await this.waitForSelectorInternal(progress, selector, true, options, scope);
658
794
  }, this._page._timeoutSettings.timeout(options));
659
795
  }
660
- async waitForSelectorInternal(progress, selector, options, scope) {
796
+ async waitForSelectorInternal(progress, selector, performLocatorHandlersCheckpoint, options, scope) {
661
797
  const {
662
798
  state = 'visible'
663
799
  } = options;
664
800
  const promise = this.retryWithProgressAndTimeouts(progress, [0, 20, 50, 100, 100, 500], async continuePolling => {
801
+ if (performLocatorHandlersCheckpoint) await this._page.performLocatorHandlersCheckpoint(progress);
665
802
  const resolved = await this.selectors.resolveInjectedForSelector(selector, options, scope);
666
803
  progress.throwIfAborted();
667
804
  if (!resolved) {
@@ -795,11 +932,10 @@ class Frame extends _instrumentation.SdkObject {
795
932
  const controller = new _progress.ProgressController(metadata, this);
796
933
  return controller.run(async progress => {
797
934
  await this.raceNavigationAction(progress, options, async () => {
798
- var _this$_page$_delegate, _this$_page$_delegate2;
799
935
  const waitUntil = options.waitUntil === undefined ? 'load' : options.waitUntil;
800
936
  progress.log(`setting frame content, waiting until "${waitUntil}"`);
801
937
  const tag = `--playwright--set--content--${this._id}--${++this._setContentCounter}--`;
802
- const context = (_this$_page$_delegate = (_this$_page$_delegate2 = this._page._delegate).useMainWorldForSetContent) !== null && _this$_page$_delegate !== void 0 && _this$_page$_delegate.call(_this$_page$_delegate2) ? await this._mainContext() : await this._utilityContext();
938
+ const context = await this._utilityContext();
803
939
  const lifecyclePromise = new Promise((resolve, reject) => {
804
940
  this._page._frameManager._consoleMessageTags.set(tag, () => {
805
941
  // Clear lifecycle right after document.open() - see 'tag' below.
@@ -156,12 +156,22 @@ class HarTracer {
156
156
  if (this._started) this._delegate.onEntryStarted(harEntry);
157
157
  }
158
158
  _onAPIRequestFinished(event) {
159
+ var _event$body$length, _event$body;
159
160
  const harEntry = this._entryForRequest(event.requestEvent);
160
161
  if (!harEntry) return;
161
162
  harEntry.response.status = event.statusCode;
162
163
  harEntry.response.statusText = event.statusMessage;
163
164
  harEntry.response.httpVersion = event.httpVersion;
164
165
  harEntry.response.redirectURL = event.headers.location || '';
166
+ if (!this._options.omitServerIP) {
167
+ harEntry.serverIPAddress = event.serverIPAddress;
168
+ harEntry._serverPort = event.serverPort;
169
+ }
170
+ if (!this._options.omitTiming) {
171
+ harEntry.timings = event.timings;
172
+ this._computeHarEntryTotalTime(harEntry);
173
+ }
174
+ if (!this._options.omitSecurityDetails) harEntry._securityDetails = event.securityDetails;
165
175
  for (let i = 0; i < event.rawHeaders.length; i += 2) {
166
176
  harEntry.response.headers.push({
167
177
  name: event.rawHeaders[i],
@@ -178,6 +188,7 @@ class HarTracer {
178
188
  const contentType = event.headers['content-type'];
179
189
  if (contentType) content.mimeType = contentType;
180
190
  this._storeResponseContent(event.body, content, 'other');
191
+ if (!this._options.omitSizes) harEntry.response.bodySize = (_event$body$length = (_event$body = event.body) === null || _event$body === void 0 ? void 0 : _event$body.length) !== null && _event$body$length !== void 0 ? _event$body$length : 0;
181
192
  if (this._started) this._delegate.onEntryFinished(harEntry);
182
193
  }
183
194
  _onRequest(request) {
@@ -189,7 +189,6 @@ class Mouse {
189
189
  x,
190
190
  y
191
191
  };
192
- if (this._raw.click) return await this._raw.click(x, y, options);
193
192
  const {
194
193
  delay = null,
195
194
  clickCount = 1
@@ -85,9 +85,6 @@ class ExecutionContext extends _instrumentation.SdkObject {
85
85
  }
86
86
  return this._utilityScriptPromise;
87
87
  }
88
- async objectCount(objectId) {
89
- return this._delegate.objectCount(objectId);
90
- }
91
88
  async doSlowMo() {
92
89
  // overridden in FrameExecutionContext
93
90
  }
@@ -189,10 +186,6 @@ class JSHandle extends _instrumentation.SdkObject {
189
186
  this._preview = preview;
190
187
  if (this._previewCallback) this._previewCallback(preview);
191
188
  }
192
- async objectCount() {
193
- if (!this._objectId) throw new Error('Can only count objects for a handle that points to the constructor prototype');
194
- return this._context.objectCount(this._objectId);
195
- }
196
189
  }
197
190
  exports.JSHandle = JSHandle;
198
191
  async function evaluate(context, returnByValue, pageFunction, ...args) {
@@ -285,6 +285,9 @@ class Page extends _instrumentation.SdkObject {
285
285
  return response;
286
286
  }), this._timeoutSettings.navigationTimeout(options));
287
287
  }
288
+ requestGC() {
289
+ return this._delegate.requestGC();
290
+ }
288
291
  registerLocatorHandler(selector, noWaitAfter) {
289
292
  const uid = ++this._lastLocatorHandlerUid;
290
293
  this._locatorHandlers.set(uid, {
@@ -324,7 +327,7 @@ class Page extends _instrumentation.SdkObject {
324
327
  progress.throwIfAborted();
325
328
  if (!handler.noWaitAfter) {
326
329
  progress.log(` locator handler has finished, waiting for ${(0, _utils.asLocator)(this.attribution.playwright.options.sdkLanguage, handler.selector)} to be hidden`);
327
- await this.mainFrame().waitForSelectorInternal(progress, handler.selector, {
330
+ await this.mainFrame().waitForSelectorInternal(progress, handler.selector, false, {
328
331
  state: 'hidden'
329
332
  });
330
333
  } else {
@@ -668,6 +671,7 @@ class PageBinding {
668
671
  context: page._browserContext
669
672
  }, handle);
670
673
  } else {
674
+ if (!Array.isArray(serializedArgs)) throw new Error(`serializedArgs is not an array. This can happen when Array.prototype.toJSON is defined incorrectly`);
671
675
  const args = serializedArgs.map(a => (0, _utilityScriptSerializers.parseEvaluationResultValue)(a));
672
676
  result = await binding.playwrightFunction({
673
677
  frame: context.frame,
@@ -15,6 +15,7 @@ var _webkit = require("./webkit/webkit");
15
15
  var _instrumentation = require("./instrumentation");
16
16
  var _utils = require("../utils");
17
17
  var _debugController = require("./debugController");
18
+ var _bidiChromium = require("./bidi/bidiChromium");
18
19
  var _bidiFirefox = require("./bidi/bidiFirefox");
19
20
  /**
20
21
  * Copyright (c) Microsoft Corporation.
@@ -42,9 +43,10 @@ class Playwright extends _instrumentation.SdkObject {
42
43
  this.chromium = void 0;
43
44
  this.android = void 0;
44
45
  this.electron = void 0;
45
- this.bidi = void 0;
46
46
  this.firefox = void 0;
47
47
  this.webkit = void 0;
48
+ this.bidiChromium = void 0;
49
+ this.bidiFirefox = void 0;
48
50
  this.options = void 0;
49
51
  this.debugController = void 0;
50
52
  this._allPages = new Set();
@@ -61,7 +63,8 @@ class Playwright extends _instrumentation.SdkObject {
61
63
  }
62
64
  }, null);
63
65
  this.chromium = new _chromium.Chromium(this);
64
- this.bidi = new _bidiFirefox.BidiFirefox(this);
66
+ this.bidiChromium = new _bidiChromium.BidiChromium(this);
67
+ this.bidiFirefox = new _bidiFirefox.BidiFirefox(this);
65
68
  this.firefox = new _firefox.Firefox(this);
66
69
  this.webkit = new _webkit.WebKit(this);
67
70
  this.electron = new _electron.Electron(this);
@@ -6,14 +6,13 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.ContextRecorder = void 0;
7
7
  exports.generateFrameSelector = generateFrameSelector;
8
8
  var _events = require("events");
9
- var recorderSource = _interopRequireWildcard(require("../../generated/recorderSource"));
9
+ var recorderSource = _interopRequireWildcard(require("../../generated/pollingRecorderSource"));
10
10
  var _utils = require("../../utils");
11
11
  var _timeoutRunner = require("../../utils/timeoutRunner");
12
12
  var _browserContext = require("../browserContext");
13
13
  var _languages = require("../codegen/languages");
14
14
  var _frames = require("../frames");
15
15
  var _page = require("../page");
16
- var _recorderRunner = require("./recorderRunner");
17
16
  var _throttledFile = require("./throttledFile");
18
17
  var _recorderCollection = require("./recorderCollection");
19
18
  var _language = require("../codegen/language");
@@ -36,14 +35,13 @@ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e;
36
35
  */
37
36
 
38
37
  class ContextRecorder extends _events.EventEmitter {
39
- constructor(context, params, delegate) {
38
+ constructor(codegenMode, context, params, delegate) {
40
39
  super();
41
40
  this._collection = void 0;
42
41
  this._pageAliases = new Map();
43
42
  this._lastPopupOrdinal = 0;
44
43
  this._lastDialogOrdinal = -1;
45
44
  this._lastDownloadOrdinal = -1;
46
- this._timers = new Set();
47
45
  this._context = void 0;
48
46
  this._params = void 0;
49
47
  this._delegate = void 0;
@@ -51,6 +49,8 @@ class ContextRecorder extends _events.EventEmitter {
51
49
  this._throttledOutputFile = null;
52
50
  this._orderedLanguages = [];
53
51
  this._listeners = [];
52
+ this._codegenMode = void 0;
53
+ this._codegenMode = codegenMode;
54
54
  this._context = context;
55
55
  this._params = params;
56
56
  this._delegate = delegate;
@@ -63,7 +63,8 @@ class ContextRecorder extends _events.EventEmitter {
63
63
  browserName: context._browser.options.name,
64
64
  launchOptions: {
65
65
  headless: false,
66
- ...params.launchOptions
66
+ ...params.launchOptions,
67
+ tracesDir: undefined
67
68
  },
68
69
  contextOptions: {
69
70
  ...params.contextOptions
@@ -71,8 +72,8 @@ class ContextRecorder extends _events.EventEmitter {
71
72
  deviceName: params.device,
72
73
  saveStorage: params.saveStorage
73
74
  };
74
- const collection = new _recorderCollection.RecorderCollection(params.mode === 'recording');
75
- collection.on('change', () => {
75
+ this._collection = new _recorderCollection.RecorderCollection(this._pageAliases);
76
+ this._collection.on('change', actions => {
76
77
  this._recorderSources = [];
77
78
  for (const languageGenerator of this._orderedLanguages) {
78
79
  var _this$_throttledOutpu;
@@ -81,7 +82,7 @@ class ContextRecorder extends _events.EventEmitter {
81
82
  footer,
82
83
  actionTexts,
83
84
  text
84
- } = (0, _language.generateCode)(collection.actions(), languageGenerator, languageGeneratorOptions);
85
+ } = (0, _language.generateCode)(actions, languageGenerator, languageGeneratorOptions);
85
86
  const source = {
86
87
  isRecorded: true,
87
88
  label: languageGenerator.name,
@@ -100,7 +101,7 @@ class ContextRecorder extends _events.EventEmitter {
100
101
  }
101
102
  this.emit(ContextRecorder.Events.Change, {
102
103
  sources: this._recorderSources,
103
- primaryFileName: this._orderedLanguages[0].id
104
+ actions
104
105
  });
105
106
  });
106
107
  context.on(_browserContext.BrowserContext.Events.BeforeClose, () => {
@@ -111,7 +112,7 @@ class ContextRecorder extends _events.EventEmitter {
111
112
  var _this$_throttledOutpu3;
112
113
  (_this$_throttledOutpu3 = this._throttledOutputFile) === null || _this$_throttledOutpu3 === void 0 || _this$_throttledOutpu3.flush();
113
114
  }));
114
- this._collection = collection;
115
+ this.setEnabled(true);
115
116
  }
116
117
  setOutput(codegenId, outputFile) {
117
118
  var _this$_collection;
@@ -144,23 +145,29 @@ class ContextRecorder extends _events.EventEmitter {
144
145
  }
145
146
  setEnabled(enabled) {
146
147
  this._collection.setEnabled(enabled);
148
+ if (this._codegenMode === 'trace-events') {
149
+ if (enabled) this._context.tracing.startChunk({
150
+ name: 'trace',
151
+ title: 'trace'
152
+ }).catch(() => {});else this._context.tracing.stopChunk({
153
+ mode: 'discard'
154
+ }).catch(() => {});
155
+ }
147
156
  }
148
157
  dispose() {
149
- for (const timer of this._timers) clearTimeout(timer);
150
- this._timers.clear();
151
158
  _utils.eventsHelper.removeEventListeners(this._listeners);
152
159
  }
153
160
  async _onPage(page) {
154
161
  // First page is called page, others are called popup1, popup2, etc.
155
162
  const frame = page.mainFrame();
156
163
  page.on('close', () => {
157
- this._collection.addAction({
164
+ this._collection.addRecordedAction({
158
165
  frame: this._describeMainFrame(page),
159
- committed: true,
160
166
  action: {
161
167
  name: 'closePage',
162
168
  signals: []
163
- }
169
+ },
170
+ startTime: (0, _utils.monotonicTime)()
164
171
  });
165
172
  this._pageAliases.delete(page);
166
173
  });
@@ -174,14 +181,14 @@ class ContextRecorder extends _events.EventEmitter {
174
181
  if (page.opener()) {
175
182
  this._onPopup(page.opener(), page);
176
183
  } else {
177
- this._collection.addAction({
184
+ this._collection.addRecordedAction({
178
185
  frame: this._describeMainFrame(page),
179
- committed: true,
180
186
  action: {
181
187
  name: 'openPage',
182
188
  url: page.mainFrame().url(),
183
189
  signals: []
184
- }
190
+ },
191
+ startTime: (0, _utils.monotonicTime)()
185
192
  });
186
193
  }
187
194
  }
@@ -206,47 +213,23 @@ class ContextRecorder extends _events.EventEmitter {
206
213
  testIdAttributeName() {
207
214
  return this._params.testIdAttributeName || this._context.selectors().testIdAttributeName() || 'data-testid';
208
215
  }
209
- async _performAction(frame, action) {
216
+ async _createActionInContext(frame, action) {
210
217
  var _this$_delegate$rewri, _this$_delegate;
211
- // Commit last action so that no further signals are added to it.
212
- this._collection.commitLastAction();
213
218
  const frameDescription = await this._describeFrame(frame);
214
219
  const actionInContext = {
215
220
  frame: frameDescription,
216
221
  action,
217
- description: undefined
222
+ description: undefined,
223
+ startTime: (0, _utils.monotonicTime)()
218
224
  };
219
225
  await ((_this$_delegate$rewri = (_this$_delegate = this._delegate).rewriteActionInContext) === null || _this$_delegate$rewri === void 0 ? void 0 : _this$_delegate$rewri.call(_this$_delegate, this._pageAliases, actionInContext));
220
- this._collection.willPerformAction(actionInContext);
221
- const success = await (0, _recorderRunner.performAction)(this._pageAliases, actionInContext);
222
- if (success) {
223
- this._collection.didPerformAction(actionInContext);
224
- this._setCommittedAfterTimeout(actionInContext);
225
- } else {
226
- this._collection.performedActionFailed(actionInContext);
227
- }
226
+ return actionInContext;
228
227
  }
229
- async _recordAction(frame, action) {
230
- var _this$_delegate$rewri2, _this$_delegate2;
231
- // Commit last action so that no further signals are added to it.
232
- this._collection.commitLastAction();
233
- const frameDescription = await this._describeFrame(frame);
234
- const actionInContext = {
235
- frame: frameDescription,
236
- action,
237
- description: undefined
238
- };
239
- await ((_this$_delegate$rewri2 = (_this$_delegate2 = this._delegate).rewriteActionInContext) === null || _this$_delegate$rewri2 === void 0 ? void 0 : _this$_delegate$rewri2.call(_this$_delegate2, this._pageAliases, actionInContext));
240
- this._setCommittedAfterTimeout(actionInContext);
241
- this._collection.addAction(actionInContext);
228
+ async _performAction(frame, action) {
229
+ await this._collection.performAction(await this._createActionInContext(frame, action));
242
230
  }
243
- _setCommittedAfterTimeout(actionInContext) {
244
- const timer = setTimeout(() => {
245
- // Commit the action after 5 seconds so that no further signals are added to it.
246
- actionInContext.committed = true;
247
- this._timers.delete(timer);
248
- }, (0, _utils.isUnderTest)() ? 500 : 5000);
249
- this._timers.add(timer);
231
+ async _recordAction(frame, action) {
232
+ this._collection.addRecordedAction(await this._createActionInContext(frame, action));
250
233
  }
251
234
  _onFrameNavigated(frame, page) {
252
235
  const pageAlias = this._pageAliases.get(page);
@@ -30,25 +30,30 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
30
30
  */
31
31
 
32
32
  class EmptyRecorderApp extends _events.EventEmitter {
33
+ constructor(...args) {
34
+ super(...args);
35
+ this.wsEndpointForTest = void 0;
36
+ }
33
37
  async close() {}
34
38
  async setPaused(paused) {}
35
39
  async setMode(mode) {}
36
- async setFileIfNeeded(file) {}
40
+ async setRunningFile(file) {}
37
41
  async setSelector(selector, userGesture) {}
38
42
  async updateCallLogs(callLogs) {}
39
43
  async setSources(sources) {}
44
+ async setActions(actions, sources) {}
40
45
  }
41
46
  exports.EmptyRecorderApp = EmptyRecorderApp;
42
47
  class RecorderApp extends _events.EventEmitter {
43
48
  constructor(recorder, page, wsEndpoint) {
44
49
  super();
45
50
  this._page = void 0;
46
- this.wsEndpoint = void 0;
51
+ this.wsEndpointForTest = void 0;
47
52
  this._recorder = void 0;
48
53
  this.setMaxListeners(0);
49
54
  this._recorder = recorder;
50
55
  this._page = page;
51
- this.wsEndpoint = wsEndpoint;
56
+ this.wsEndpointForTest = wsEndpoint;
52
57
  }
53
58
  async close() {
54
59
  await this._page.context().close({
@@ -63,7 +68,6 @@ class RecorderApp extends _events.EventEmitter {
63
68
  const file = require.resolve('../../vite/recorder/' + uri);
64
69
  _fs.default.promises.readFile(file).then(buffer => {
65
70
  route.fulfill({
66
- requestUrl: route.request().url(),
67
71
  status: 200,
68
72
  headers: [{
69
73
  name: 'Content-Type',
@@ -114,9 +118,8 @@ class RecorderApp extends _events.EventEmitter {
114
118
  persistentContextOptions: {
115
119
  noDefaultViewport: true,
116
120
  headless: !!process.env.PWTEST_CLI_HEADLESS || (0, _utils.isUnderTest)() && !headed,
117
- useWebSocket: !!process.env.PWTEST_RECORDER_PORT,
118
- handleSIGINT: false,
119
- args: process.env.PWTEST_RECORDER_PORT ? [`--remote-debugging-port=${process.env.PWTEST_RECORDER_PORT}`] : [],
121
+ useWebSocket: (0, _utils.isUnderTest)(),
122
+ handleSIGINT: recorder.handleSIGINT,
120
123
  executablePath: inspectedContext._browser.options.isChromium ? inspectedContext._browser.options.customExecutablePath : undefined
121
124
  }
122
125
  });
@@ -135,9 +138,9 @@ class RecorderApp extends _events.EventEmitter {
135
138
  isFunction: true
136
139
  }, mode).catch(() => {});
137
140
  }
138
- async setFileIfNeeded(file) {
141
+ async setRunningFile(file) {
139
142
  await this._page.mainFrame().evaluateExpression((file => {
140
- window.playwrightSetFileIfNeeded(file);
143
+ window.playwrightSetRunningFile(file);
141
144
  }).toString(), {
142
145
  isFunction: true
143
146
  }, file).catch(() => {});
@@ -157,8 +160,11 @@ class RecorderApp extends _events.EventEmitter {
157
160
  }, sources).catch(() => {});
158
161
 
159
162
  // Testing harness for runCLI mode.
160
- if (process.env.PWTEST_CLI_IS_UNDER_TEST && sources.length) process._didSetSourcesForTest(sources[0].text);
163
+ if (process.env.PWTEST_CLI_IS_UNDER_TEST && sources.length) {
164
+ if (process._didSetSourcesForTest(sources[0].text)) this.close();
165
+ }
161
166
  }
167
+ async setActions(actions, sources) {}
162
168
  async setSelector(selector, userGesture) {
163
169
  if (userGesture) {
164
170
  var _this$_recorder;