rebrowser-playwright-core 1.47.100 → 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.
- package/README.md +1 -1
- package/browsers.json +14 -10
- package/lib/cli/program.js +26 -14
- package/lib/client/api.js +6 -0
- package/lib/client/browserContext.js +20 -2
- package/lib/client/channelOwner.js +5 -1
- package/lib/client/connection.js +3 -0
- package/lib/client/fetch.js +16 -21
- package/lib/client/jsHandle.js +0 -8
- package/lib/client/localUtils.js +1 -0
- package/lib/client/network.js +175 -17
- package/lib/client/page.js +21 -0
- package/lib/client/playwright.js +6 -3
- package/lib/client/tracing.js +16 -20
- package/lib/generated/consoleApiSource.js +1 -1
- package/lib/generated/injectedScriptSource.js +1 -1
- package/lib/generated/pollingRecorderSource.js +7 -0
- package/lib/generated/webSocketMockSource.js +7 -0
- package/lib/protocol/validator.js +80 -14
- package/lib/server/bidi/bidiBrowser.js +23 -8
- package/lib/server/bidi/bidiChromium.js +124 -0
- package/lib/server/bidi/bidiConnection.js +1 -1
- package/lib/server/bidi/bidiExecutionContext.js +0 -3
- package/lib/server/bidi/bidiFirefox.js +15 -21
- package/lib/server/bidi/bidiInput.js +16 -32
- package/lib/server/bidi/bidiNetworkManager.js +39 -5
- package/lib/server/bidi/bidiOverCdp.js +103 -0
- package/lib/server/bidi/bidiPage.js +98 -25
- package/lib/server/bidi/bidiPdf.js +140 -0
- package/lib/server/bidi/third_party/firefoxPrefs.js +221 -0
- package/lib/server/browser.js +13 -2
- package/lib/server/browserContext.js +6 -23
- package/lib/server/browserType.js +39 -11
- package/lib/server/chromium/chromium.js +3 -15
- package/lib/server/chromium/chromiumSwitches.js +3 -1
- package/lib/server/chromium/crBrowser.js +4 -3
- package/lib/server/chromium/crExecutionContext.js +0 -7
- package/lib/server/chromium/crPage.js +16 -6
- package/lib/server/chromium/videoRecorder.js +1 -1
- package/lib/server/codegen/csharp.js +1 -1
- package/lib/server/codegen/java.js +1 -1
- package/lib/server/codegen/javascript.js +1 -1
- package/lib/server/codegen/language.js +14 -2
- package/lib/server/codegen/python.js +1 -1
- package/lib/server/cookieStore.js +73 -0
- package/lib/server/debugController.js +2 -2
- package/lib/server/deviceDescriptorsSource.json +50 -50
- package/lib/server/dialog.js +1 -0
- package/lib/server/dispatchers/browserContextDispatcher.js +19 -2
- package/lib/server/dispatchers/jsHandleDispatcher.js +0 -5
- package/lib/server/dispatchers/pageDispatcher.js +9 -0
- package/lib/server/dispatchers/playwrightDispatcher.js +2 -1
- package/lib/server/dispatchers/webSocketRouteDispatcher.js +189 -0
- package/lib/server/download.js +9 -2
- package/lib/server/fetch.js +90 -94
- package/lib/server/firefox/ffBrowser.js +6 -4
- package/lib/server/firefox/ffExecutionContext.js +0 -3
- package/lib/server/firefox/ffPage.js +6 -3
- package/lib/server/firefox/firefox.js +2 -13
- package/lib/server/frameSelectors.js +1 -1
- package/lib/server/frames.js +158 -27
- package/lib/server/har/harTracer.js +11 -0
- package/lib/server/input.js +0 -1
- package/lib/server/javascript.js +0 -7
- package/lib/server/page.js +5 -1
- package/lib/server/playwright.js +5 -2
- package/lib/server/recorder/contextRecorder.js +33 -50
- package/lib/server/recorder/recorderApp.js +16 -10
- package/lib/server/recorder/recorderCollection.js +68 -79
- package/lib/server/recorder/recorderInTraceViewer.js +144 -0
- package/lib/server/recorder/recorderRunner.js +75 -97
- package/lib/server/recorder/recorderUtils.js +47 -6
- package/lib/server/recorder.js +30 -25
- package/lib/server/registry/index.js +85 -4
- package/lib/server/socksClientCertificatesInterceptor.js +15 -3
- package/lib/server/trace/recorder/snapshotter.js +1 -0
- package/lib/server/trace/recorder/snapshotterInjected.js +2 -2
- package/lib/server/trace/recorder/tracing.js +58 -2
- package/lib/server/trace/test/inMemorySnapshotter.js +1 -1
- package/lib/server/trace/viewer/traceViewer.js +2 -5
- package/lib/server/webkit/webkit.js +1 -1
- package/lib/server/webkit/wkBrowser.js +6 -5
- package/lib/server/webkit/wkExecutionContext.js +0 -3
- package/lib/server/webkit/wkPage.js +7 -4
- package/lib/utils/happy-eyeballs.js +13 -0
- package/lib/utils/hostPlatform.js +2 -2
- package/lib/utils/httpServer.js +1 -0
- package/lib/utils/isomorphic/locatorGenerators.js +9 -18
- package/lib/utils/isomorphic/locatorParser.js +2 -2
- package/lib/utils/isomorphic/recorderUtils.js +195 -0
- package/lib/vite/htmlReport/index.html +12 -12
- package/lib/vite/recorder/assets/{codeMirrorModule-aW6Vz3gf.js → codeMirrorModule-baozm8ur.js} +1 -1
- package/lib/vite/recorder/assets/{index-DCpXOVIh.js → index-2ElAIWFB.js} +10 -15
- package/lib/vite/recorder/assets/{index-B-MT5gKo.css → index-BW-aOBcL.css} +1 -1
- package/lib/vite/recorder/index.html +2 -2
- package/lib/vite/traceViewer/assets/{codeMirrorModule-eFKCUIu2.js → codeMirrorModule-Bh1rfd2w.js} +1 -1
- package/lib/vite/traceViewer/assets/inspectorTab-7GHnKvSD.js +64 -0
- package/lib/vite/traceViewer/assets/workbench-DPQnTHYP.js +9 -0
- package/lib/vite/traceViewer/embedded.BlHoW5LY.js +2 -0
- package/lib/vite/traceViewer/embedded.html +5 -3
- package/lib/vite/traceViewer/index.DaWVfou1.js +2 -0
- package/lib/vite/traceViewer/index.html +5 -3
- package/lib/vite/traceViewer/inspectorTab.DLjBDrQR.css +1 -0
- package/lib/vite/traceViewer/recorder.B_SY1GJM.css +0 -0
- package/lib/vite/traceViewer/recorder.C4zxcvd2.js +2 -0
- package/lib/vite/traceViewer/recorder.html +17 -0
- package/lib/vite/traceViewer/sw.bundle.js +3 -3
- package/lib/vite/traceViewer/{uiMode.D3cNFP6u.css → uiMode.CAYqod-m.css} +1 -1
- package/lib/vite/traceViewer/uiMode.html +6 -4
- package/lib/vite/traceViewer/uiMode.mTXWniJb.js +5 -0
- package/lib/vite/traceViewer/workbench.D3JVcA9K.css +1 -0
- package/package.json +1 -1
- package/types/protocol.d.ts +79 -8
- package/types/types.d.ts +2037 -949
- package/lib/generated/recorderSource.js +0 -7
- package/lib/vite/traceViewer/assets/workbench-D0cirtfA.js +0 -72
- package/lib/vite/traceViewer/embedded.BkuvsLJp.js +0 -2
- package/lib/vite/traceViewer/index.C968kAiC.js +0 -2
- package/lib/vite/traceViewer/uiMode.BkFnr4V0.js +0 -10
- package/lib/vite/traceViewer/workbench.DjbIuxix.css +0 -1
- /package/lib/server/recorder/{recorderActions.js → recorderFrontend.js} +0 -0
package/lib/server/frames.js
CHANGED
|
@@ -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.
|
|
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.
|
|
432
|
+
this.__re__contexts = undefined;
|
|
433
433
|
}
|
|
434
434
|
setPendingDocument(documentInfo) {
|
|
435
435
|
this._pendingDocument = documentInfo;
|
|
@@ -584,30 +584,161 @@ 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
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
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
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
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
|
-
|
|
605
|
-
}
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
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 => {
|
|
611
742
|
if (error.message.includes('No frame for given id found')) {
|
|
612
743
|
// ignore, frame is already gone
|
|
613
744
|
return {
|
|
@@ -615,7 +746,7 @@ class Frame extends _instrumentation.SdkObject {
|
|
|
615
746
|
};
|
|
616
747
|
}
|
|
617
748
|
_debugLogger.debugLogger.log('error', error);
|
|
618
|
-
console.error('[rebrowser-patches][frames._context] cannot
|
|
749
|
+
console.error('[rebrowser-patches][frames._context] cannot get world, error:', error);
|
|
619
750
|
});
|
|
620
751
|
}
|
|
621
752
|
return this._contextData.get(world).contextPromise.then(contextOrDestroyedReason => {
|
|
@@ -659,14 +790,15 @@ class Frame extends _instrumentation.SdkObject {
|
|
|
659
790
|
if (!['attached', 'detached', 'visible', 'hidden'].includes(state)) throw new Error(`state: expected one of (attached|detached|visible|hidden)`);
|
|
660
791
|
return controller.run(async progress => {
|
|
661
792
|
progress.log(`waiting for ${this._asLocator(selector)}${state === 'attached' ? '' : ' to be ' + state}`);
|
|
662
|
-
return await this.waitForSelectorInternal(progress, selector, options, scope);
|
|
793
|
+
return await this.waitForSelectorInternal(progress, selector, true, options, scope);
|
|
663
794
|
}, this._page._timeoutSettings.timeout(options));
|
|
664
795
|
}
|
|
665
|
-
async waitForSelectorInternal(progress, selector, options, scope) {
|
|
796
|
+
async waitForSelectorInternal(progress, selector, performLocatorHandlersCheckpoint, options, scope) {
|
|
666
797
|
const {
|
|
667
798
|
state = 'visible'
|
|
668
799
|
} = options;
|
|
669
800
|
const promise = this.retryWithProgressAndTimeouts(progress, [0, 20, 50, 100, 100, 500], async continuePolling => {
|
|
801
|
+
if (performLocatorHandlersCheckpoint) await this._page.performLocatorHandlersCheckpoint(progress);
|
|
670
802
|
const resolved = await this.selectors.resolveInjectedForSelector(selector, options, scope);
|
|
671
803
|
progress.throwIfAborted();
|
|
672
804
|
if (!resolved) {
|
|
@@ -800,11 +932,10 @@ class Frame extends _instrumentation.SdkObject {
|
|
|
800
932
|
const controller = new _progress.ProgressController(metadata, this);
|
|
801
933
|
return controller.run(async progress => {
|
|
802
934
|
await this.raceNavigationAction(progress, options, async () => {
|
|
803
|
-
var _this$_page$_delegate, _this$_page$_delegate2;
|
|
804
935
|
const waitUntil = options.waitUntil === undefined ? 'load' : options.waitUntil;
|
|
805
936
|
progress.log(`setting frame content, waiting until "${waitUntil}"`);
|
|
806
937
|
const tag = `--playwright--set--content--${this._id}--${++this._setContentCounter}--`;
|
|
807
|
-
const context =
|
|
938
|
+
const context = await this._utilityContext();
|
|
808
939
|
const lifecyclePromise = new Promise((resolve, reject) => {
|
|
809
940
|
this._page._frameManager._consoleMessageTags.set(tag, () => {
|
|
810
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) {
|
package/lib/server/input.js
CHANGED
package/lib/server/javascript.js
CHANGED
|
@@ -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) {
|
package/lib/server/page.js
CHANGED
|
@@ -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,
|
package/lib/server/playwright.js
CHANGED
|
@@ -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.
|
|
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/
|
|
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
|
-
|
|
75
|
-
|
|
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)(
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
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
|
-
|
|
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
|
|
230
|
-
|
|
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
|
-
|
|
244
|
-
|
|
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
|
|
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.
|
|
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.
|
|
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:
|
|
118
|
-
handleSIGINT:
|
|
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
|
|
141
|
+
async setRunningFile(file) {
|
|
139
142
|
await this._page.mainFrame().evaluateExpression((file => {
|
|
140
|
-
window.
|
|
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)
|
|
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;
|