phantomwright-driver-core 1.58.2 → 1.58.3
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/lib/client/browserContext.js +5 -4
- package/lib/client/frame.js +9 -1
- package/lib/client/locator.js +8 -0
- package/lib/client/network.js +5 -1
- package/lib/client/page.js +1 -0
- package/lib/client/tracing.js +1 -1
- package/lib/server/chromium/chromium.js +0 -1
- package/lib/server/chromium/crCoverage.js +13 -1
- package/lib/server/chromium/crNetworkManager.js +23 -7
- package/lib/server/chromium/crPage.js +40 -24
- package/lib/server/dispatchers/browserContextDispatcher.js +0 -2
- package/lib/server/frameSelectors.js +5 -0
- package/lib/server/frames.js +199 -48
- package/lib/server/javascript.js +4 -0
- package/lib/server/launchApp.js +2 -1
- package/lib/server/page.js +28 -2
- package/lib/server/screenshotter.js +6 -0
- package/lib/server/trace/recorder/snapshotter.js +17 -8
- package/lib/server/trace/recorder/snapshotterInjected.js +20 -82
- package/lib/server/trace/recorder/tracing.js +8 -0
- package/package.json +1 -1
|
@@ -120,11 +120,11 @@ class BrowserContext extends import_channelOwner.ChannelOwner {
|
|
|
120
120
|
hasListeners = page.emit(import_events.Events.Page.Dialog, dialogObject) || hasListeners;
|
|
121
121
|
if (!hasListeners) {
|
|
122
122
|
if (dialogObject.type() === "beforeunload")
|
|
123
|
-
dialog.accept({}).catch(() => {
|
|
124
|
-
});
|
|
123
|
+
dialogObject._wrapApiCall(() => dialog.accept({}).catch(() => {
|
|
124
|
+
}), { internal: true });
|
|
125
125
|
else
|
|
126
|
-
dialog.dismiss().catch(() => {
|
|
127
|
-
});
|
|
126
|
+
dialogObject._wrapApiCall(() => dialog.dismiss().catch(() => {
|
|
127
|
+
}), { internal: true });
|
|
128
128
|
}
|
|
129
129
|
});
|
|
130
130
|
this._channel.on("request", ({ request, page }) => this._onRequest(network.Request.from(request), import_page.Page.fromNullable(page)));
|
|
@@ -527,6 +527,7 @@ class BrowserContext extends import_channelOwner.ChannelOwner {
|
|
|
527
527
|
await route.fallback();
|
|
528
528
|
}
|
|
529
529
|
});
|
|
530
|
+
this.routeInjecting = true;
|
|
530
531
|
}
|
|
531
532
|
}
|
|
532
533
|
async function prepareStorageState(platform, storageState) {
|
package/lib/client/frame.js
CHANGED
|
@@ -162,7 +162,15 @@ class Frame extends import_channelOwner.ChannelOwner {
|
|
|
162
162
|
async waitForURL(url, options = {}) {
|
|
163
163
|
if ((0, import_urlMatch.urlMatches)(this._page?.context()._options.baseURL, this.url(), url))
|
|
164
164
|
return await this.waitForLoadState(options.waitUntil, options);
|
|
165
|
-
|
|
165
|
+
try {
|
|
166
|
+
await this.waitForNavigation({ url, ...options });
|
|
167
|
+
} catch (error) {
|
|
168
|
+
if ((0, import_urlMatch.urlMatches)(this._page?.context()._options.baseURL, this.url(), url)) {
|
|
169
|
+
await this.waitForLoadState(options.waitUntil, options);
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
throw error;
|
|
173
|
+
}
|
|
166
174
|
}
|
|
167
175
|
async frameElement() {
|
|
168
176
|
return import_elementHandle.ElementHandle.from((await this._channel.frameElement()).element);
|
package/lib/client/locator.js
CHANGED
|
@@ -99,6 +99,10 @@ class Locator {
|
|
|
99
99
|
});
|
|
100
100
|
}
|
|
101
101
|
async evaluate(pageFunction, arg, options, isolatedContext = true) {
|
|
102
|
+
if (typeof options === "boolean") {
|
|
103
|
+
isolatedContext = options;
|
|
104
|
+
options = void 0;
|
|
105
|
+
}
|
|
102
106
|
return await this._withElement(
|
|
103
107
|
async (h) => (0, import_jsHandle.parseResult)(
|
|
104
108
|
(await h._channel.evaluateExpression({
|
|
@@ -118,6 +122,10 @@ class Locator {
|
|
|
118
122
|
return await this._frame.$$eval(this._selector, pageFunction, arg, isolatedContext);
|
|
119
123
|
}
|
|
120
124
|
async evaluateHandle(pageFunction, arg, options, isolatedContext = true) {
|
|
125
|
+
if (typeof options === "boolean") {
|
|
126
|
+
isolatedContext = options;
|
|
127
|
+
options = void 0;
|
|
128
|
+
}
|
|
121
129
|
return await this._withElement(
|
|
122
130
|
async (h) => import_jsHandle.JSHandle.from(
|
|
123
131
|
(await h._channel.evaluateExpressionHandle({
|
package/lib/client/network.js
CHANGED
|
@@ -128,7 +128,11 @@ class Request extends import_channelOwner.ChannelOwner {
|
|
|
128
128
|
return await this._actualHeadersPromise;
|
|
129
129
|
}
|
|
130
130
|
async allHeaders() {
|
|
131
|
-
|
|
131
|
+
const headers = await this._actualHeaders();
|
|
132
|
+
const page = this._safePage();
|
|
133
|
+
if (page?._closeWasCalled)
|
|
134
|
+
throw new import_errors.TargetClosedError();
|
|
135
|
+
return headers.headers();
|
|
132
136
|
}
|
|
133
137
|
async headersArray() {
|
|
134
138
|
return (await this._actualHeaders()).headersArray();
|
package/lib/client/page.js
CHANGED
package/lib/client/tracing.js
CHANGED
|
@@ -34,7 +34,7 @@ class Tracing extends import_channelOwner.ChannelOwner {
|
|
|
34
34
|
return channel._object;
|
|
35
35
|
}
|
|
36
36
|
async start(options = {}) {
|
|
37
|
-
await this._parent.installInjectRoute();
|
|
37
|
+
if (typeof this._parent.installInjectRoute === "function") await this._parent.installInjectRoute();
|
|
38
38
|
await this._wrapApiCall(async () => {
|
|
39
39
|
this._includeSources = !!options.sources;
|
|
40
40
|
this._isLive = !!options._live;
|
|
@@ -277,7 +277,6 @@ class Chromium extends import_browserType.BrowserType {
|
|
|
277
277
|
if (args.find((arg) => !arg.startsWith("-")))
|
|
278
278
|
throw new Error("Arguments can not specify page to be opened");
|
|
279
279
|
const chromeArguments = [...(0, import_chromiumSwitches.chromiumSwitches)(options.assistantMode, options.channel)];
|
|
280
|
-
chromeArguments.push("--enable-unsafe-swiftshader");
|
|
281
280
|
if (options.headless) {
|
|
282
281
|
chromeArguments.push("--headless");
|
|
283
282
|
chromeArguments.push(
|
|
@@ -66,6 +66,7 @@ class JSCoverage {
|
|
|
66
66
|
this._eventListeners = [
|
|
67
67
|
import_eventsHelper.eventsHelper.addEventListener(this._client, "Debugger.scriptParsed", this._onScriptParsed.bind(this)),
|
|
68
68
|
import_eventsHelper.eventsHelper.addEventListener(this._client, "Runtime.executionContextsCleared", this._onExecutionContextsCleared.bind(this)),
|
|
69
|
+
import_eventsHelper.eventsHelper.addEventListener(this._client, "Page.frameNavigated", this._onFrameNavigated.bind(this)),
|
|
69
70
|
import_eventsHelper.eventsHelper.addEventListener(this._client, "Debugger.paused", this._onDebuggerPaused.bind(this))
|
|
70
71
|
];
|
|
71
72
|
await Promise.all([
|
|
@@ -117,6 +118,11 @@ class JSCoverage {
|
|
|
117
118
|
}
|
|
118
119
|
return coverage;
|
|
119
120
|
}
|
|
121
|
+
_onFrameNavigated(event) {
|
|
122
|
+
if (event.frame.parentId)
|
|
123
|
+
return;
|
|
124
|
+
this._onExecutionContextsCleared();
|
|
125
|
+
}
|
|
120
126
|
}
|
|
121
127
|
class CSSCoverage {
|
|
122
128
|
constructor(client) {
|
|
@@ -136,7 +142,8 @@ class CSSCoverage {
|
|
|
136
142
|
this._stylesheetSources.clear();
|
|
137
143
|
this._eventListeners = [
|
|
138
144
|
import_eventsHelper.eventsHelper.addEventListener(this._client, "CSS.styleSheetAdded", this._onStyleSheet.bind(this)),
|
|
139
|
-
import_eventsHelper.eventsHelper.addEventListener(this._client, "Runtime.executionContextsCleared", this._onExecutionContextsCleared.bind(this))
|
|
145
|
+
import_eventsHelper.eventsHelper.addEventListener(this._client, "Runtime.executionContextsCleared", this._onExecutionContextsCleared.bind(this)),
|
|
146
|
+
import_eventsHelper.eventsHelper.addEventListener(this._client, "Page.frameNavigated", this._onFrameNavigated.bind(this))
|
|
140
147
|
];
|
|
141
148
|
await Promise.all([
|
|
142
149
|
this._client.send("DOM.enable"),
|
|
@@ -192,6 +199,11 @@ class CSSCoverage {
|
|
|
192
199
|
}
|
|
193
200
|
return coverage;
|
|
194
201
|
}
|
|
202
|
+
_onFrameNavigated(event) {
|
|
203
|
+
if (event.frame.parentId)
|
|
204
|
+
return;
|
|
205
|
+
this._onExecutionContextsCleared();
|
|
206
|
+
}
|
|
195
207
|
}
|
|
196
208
|
function convertToDisjointRanges(nestedRanges) {
|
|
197
209
|
const points = [];
|
|
@@ -141,6 +141,8 @@ class CRNetworkManager {
|
|
|
141
141
|
async setRequestInterception(value) {
|
|
142
142
|
this._userRequestInterceptionEnabled = value;
|
|
143
143
|
await this._updateProtocolRequestInterception();
|
|
144
|
+
if (this._page)
|
|
145
|
+
await this._forEachSession((info) => info.session.send("Network.setCacheDisabled", { cacheDisabled: this._page.needsRequestInterception() }));
|
|
144
146
|
}
|
|
145
147
|
async _updateProtocolRequestInterception() {
|
|
146
148
|
const enabled = this._userRequestInterceptionEnabled || !!this._credentials;
|
|
@@ -153,7 +155,9 @@ class CRNetworkManager {
|
|
|
153
155
|
const enabled = this._protocolRequestInterceptionEnabled;
|
|
154
156
|
if (initial && !enabled)
|
|
155
157
|
return;
|
|
156
|
-
const
|
|
158
|
+
const hasHarRecorders = !!this._page?.browserContext?._harRecorders?.size;
|
|
159
|
+
const userInterception = this._page ? this._page.needsRequestInterception() : false;
|
|
160
|
+
const cachePromise = info.session.send("Network.setCacheDisabled", { cacheDisabled: userInterception || hasHarRecorders });
|
|
157
161
|
let fetchPromise = Promise.resolve(void 0);
|
|
158
162
|
if (!info.workerFrame) {
|
|
159
163
|
if (enabled)
|
|
@@ -265,13 +269,17 @@ class CRNetworkManager {
|
|
|
265
269
|
redirectedFrom = request2;
|
|
266
270
|
}
|
|
267
271
|
}
|
|
272
|
+
const isInterceptedOptionsPreflight = !!requestPausedEvent && requestPausedEvent.request.method === "OPTIONS" && requestWillBeSentEvent.initiator.type === "preflight";
|
|
273
|
+
if (isInterceptedOptionsPreflight && !(this._page || this._serviceWorker).needsRequestInterception()) {
|
|
274
|
+
requestPausedSessionInfo.session._sendMayFail("Fetch.continueRequest", { requestId: requestPausedEvent.requestId });
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
268
277
|
let frame = requestWillBeSentEvent.frameId ? this._page?.frameManager.frame(requestWillBeSentEvent.frameId) : requestWillBeSentSessionInfo.workerFrame;
|
|
269
278
|
if (!frame && this._page && requestPausedEvent && requestPausedEvent.frameId)
|
|
270
279
|
frame = this._page.frameManager.frame(requestPausedEvent.frameId);
|
|
271
280
|
if (!frame && this._page && requestWillBeSentEvent.frameId === (this._page?.delegate)._targetId) {
|
|
272
281
|
frame = this._page.frameManager.frameAttached(requestWillBeSentEvent.frameId, null);
|
|
273
282
|
}
|
|
274
|
-
const isInterceptedOptionsPreflight = !!requestPausedEvent && requestPausedEvent.request.method === "OPTIONS" && requestWillBeSentEvent.initiator.type === "preflight";
|
|
275
283
|
if (isInterceptedOptionsPreflight && (this._page || this._serviceWorker).needsRequestInterception()) {
|
|
276
284
|
const requestHeaders = requestPausedEvent.request.headers;
|
|
277
285
|
const responseHeaders = [
|
|
@@ -518,7 +526,7 @@ class RouteImpl {
|
|
|
518
526
|
method: overrides.method,
|
|
519
527
|
postData: overrides.postData ? overrides.postData.toString("base64") : void 0
|
|
520
528
|
};
|
|
521
|
-
if (overrides.url && (overrides.url
|
|
529
|
+
if (overrides.url && (overrides.url.startsWith("http://patchright-init-script-inject.internal") || overrides.url.startsWith("https://patchright-init-script-inject.internal"))) {
|
|
522
530
|
await catchDisallowedErrors(async () => {
|
|
523
531
|
this._sessionManager._alreadyTrackedNetworkIds.add(this._networkId);
|
|
524
532
|
this._session._sendMayFail("Fetch.continueRequest", { requestId: this._interceptionId, interceptResponse: true });
|
|
@@ -531,8 +539,12 @@ class RouteImpl {
|
|
|
531
539
|
}
|
|
532
540
|
async fulfill(response) {
|
|
533
541
|
const isTextHtml = response.headers.some((header) => header.name.toLowerCase() === "content-type" && header.value.includes("text/html"));
|
|
534
|
-
|
|
535
|
-
|
|
542
|
+
const pageDelegate = this._page?.delegate || null;
|
|
543
|
+
const initScriptTag = pageDelegate?.initScriptTag || "";
|
|
544
|
+
let allInjections = [];
|
|
545
|
+
if (pageDelegate)
|
|
546
|
+
allInjections = [...pageDelegate._mainFrameSession._evaluateOnNewDocumentScripts];
|
|
547
|
+
if (isTextHtml && allInjections.length && initScriptTag) {
|
|
536
548
|
let useNonce = false;
|
|
537
549
|
let scriptNonce = null;
|
|
538
550
|
if (response.isBase64) {
|
|
@@ -583,7 +595,7 @@ class RouteImpl {
|
|
|
583
595
|
let scriptId = import_crypto.default.randomBytes(22).toString("hex");
|
|
584
596
|
let scriptSource = script.source || script;
|
|
585
597
|
const nonceAttr = useNonce ? `nonce="${scriptNonce}"` : "";
|
|
586
|
-
injectionHTML += `<script class="${
|
|
598
|
+
injectionHTML += `<script class="${initScriptTag}" ${nonceAttr} id="${scriptId}" type="text/javascript">document.getElementById("${scriptId}")?.remove();${scriptSource}</script>`;
|
|
587
599
|
});
|
|
588
600
|
const lower = response.body.toLowerCase();
|
|
589
601
|
const headStartIndex = lower.indexOf("<head");
|
|
@@ -771,7 +783,11 @@ class RouteImpl {
|
|
|
771
783
|
});
|
|
772
784
|
}
|
|
773
785
|
} catch (error) {
|
|
774
|
-
|
|
786
|
+
if (error.message.includes("Can only get response body on HeadersReceived pattern matched requests.")) {
|
|
787
|
+
await this._session.send("Fetch.continueRequest", { requestId: event.requestId, interceptResponse: true });
|
|
788
|
+
} else {
|
|
789
|
+
await this._session._sendMayFail("Fetch.continueRequest", { requestId: event.requestId });
|
|
790
|
+
}
|
|
775
791
|
}
|
|
776
792
|
}
|
|
777
793
|
}
|
|
@@ -110,7 +110,7 @@ class CRPage {
|
|
|
110
110
|
while (!this._sessions.has(frame._id)) {
|
|
111
111
|
const parent = frame.parentFrame();
|
|
112
112
|
if (!parent)
|
|
113
|
-
throw new Error(`Frame
|
|
113
|
+
throw new Error(`Frame was detached`);
|
|
114
114
|
frame = parent;
|
|
115
115
|
}
|
|
116
116
|
return this._sessions.get(frame._id);
|
|
@@ -368,6 +368,7 @@ class FrameSession {
|
|
|
368
368
|
]);
|
|
369
369
|
}
|
|
370
370
|
async _initialize(hasUIWindow) {
|
|
371
|
+
const pageEnablePromise = this._client.send("Page.enable");
|
|
371
372
|
if (!this._page.isStorageStatePage && hasUIWindow && !this._crPage._browserContext._browser.isClank() && !this._crPage._browserContext._options.noDefaultViewport) {
|
|
372
373
|
const { windowId } = await this._client.send("Browser.getWindowForTarget");
|
|
373
374
|
this._windowId = windowId;
|
|
@@ -378,14 +379,21 @@ class FrameSession {
|
|
|
378
379
|
let lifecycleEventsEnabled;
|
|
379
380
|
if (!this._isMainFrame())
|
|
380
381
|
this._addRendererListeners();
|
|
382
|
+
let bufferedDialogEvents = this._isMainFrame() ? [] : void 0;
|
|
383
|
+
if (bufferedDialogEvents)
|
|
384
|
+
this._eventListeners.push(import_eventsHelper.eventsHelper.addEventListener(this._client, "Page.javascriptDialogOpening", (event) => bufferedDialogEvents ? bufferedDialogEvents.push(event) : void 0));
|
|
381
385
|
this._addBrowserListeners();
|
|
382
386
|
this._bufferedAttachedToTargetEvents = [];
|
|
383
387
|
const promises = [
|
|
384
|
-
|
|
388
|
+
pageEnablePromise,
|
|
385
389
|
this._client.send("Page.getFrameTree").then(({ frameTree }) => {
|
|
386
390
|
if (this._isMainFrame()) {
|
|
387
391
|
this._handleFrameTree(frameTree);
|
|
388
392
|
this._addRendererListeners();
|
|
393
|
+
const pendingDialogEvents = bufferedDialogEvents || [];
|
|
394
|
+
bufferedDialogEvents = void 0;
|
|
395
|
+
for (const event of pendingDialogEvents)
|
|
396
|
+
this._onDialog(event);
|
|
389
397
|
}
|
|
390
398
|
const attachedToTargetEvents = this._bufferedAttachedToTargetEvents || [];
|
|
391
399
|
this._bufferedAttachedToTargetEvents = void 0;
|
|
@@ -400,12 +408,16 @@ class FrameSession {
|
|
|
400
408
|
} else {
|
|
401
409
|
const localFrames = this._isMainFrame() ? this._page.frames() : [this._page.frameManager.frame(this._targetId)];
|
|
402
410
|
for (const frame of localFrames) {
|
|
403
|
-
this._page.frameManager.frame(frame._id)._context("utility")
|
|
411
|
+
this._page.frameManager.frame(frame._id)._context("utility").catch(() => {
|
|
412
|
+
});
|
|
404
413
|
for (const binding of this._crPage._browserContext._pageBindings.values())
|
|
405
414
|
frame.evaluateExpression(binding.source).catch((e) => {
|
|
406
415
|
});
|
|
407
416
|
for (const source of this._crPage._browserContext.initScripts)
|
|
408
|
-
frame.evaluateExpression(source).catch((e) => {
|
|
417
|
+
frame.evaluateExpression(source.source).catch((e) => {
|
|
418
|
+
});
|
|
419
|
+
for (const source of this._crPage._page.initScripts)
|
|
420
|
+
frame.evaluateExpression(source.source).catch((e) => {
|
|
409
421
|
});
|
|
410
422
|
}
|
|
411
423
|
this._firstNonInitialNavigationCommittedFulfill();
|
|
@@ -484,6 +496,10 @@ class FrameSession {
|
|
|
484
496
|
this._page.frameManager.frameLifecycleEvent(event.frameId, "load");
|
|
485
497
|
else if (event.name === "DOMContentLoaded")
|
|
486
498
|
this._page.frameManager.frameLifecycleEvent(event.frameId, "domcontentloaded");
|
|
499
|
+
if (event.name !== "load") {
|
|
500
|
+
await this._client._sendMayFail("Runtime.runIfWaitingForDebugger");
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
487
503
|
await this._client._sendMayFail("Runtime.runIfWaitingForDebugger");
|
|
488
504
|
var document = await this._client._sendMayFail("DOM.getDocument");
|
|
489
505
|
if (!document) return;
|
|
@@ -536,6 +552,14 @@ class FrameSession {
|
|
|
536
552
|
if (!initial)
|
|
537
553
|
this._firstNonInitialNavigationCommittedFulfill();
|
|
538
554
|
await this._client._sendMayFail("Runtime.runIfWaitingForDebugger");
|
|
555
|
+
if (!initial) {
|
|
556
|
+
try {
|
|
557
|
+
await this._page.frameManager.frame(this._targetId)._context("utility");
|
|
558
|
+
} catch {
|
|
559
|
+
}
|
|
560
|
+
;
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
539
563
|
var document = await this._client._sendMayFail("DOM.getDocument");
|
|
540
564
|
if (!document) return;
|
|
541
565
|
var query = await this._client._sendMayFail("DOM.querySelectorAll", {
|
|
@@ -584,7 +608,7 @@ class FrameSession {
|
|
|
584
608
|
const delegate = new import_crExecutionContext.CRExecutionContext(this._client, contextPayload);
|
|
585
609
|
let worldName = contextPayload.name;
|
|
586
610
|
const context = new dom.FrameExecutionContext(delegate, frame, worldName);
|
|
587
|
-
if (worldName)
|
|
611
|
+
if (worldName && (worldName === "main" || worldName === "utility"))
|
|
588
612
|
frame._contextCreated(worldName, context);
|
|
589
613
|
this._contextIdToContext.set(contextPayload.id, context);
|
|
590
614
|
for (const source of this._exposedBindingScripts) {
|
|
@@ -978,28 +1002,20 @@ class FrameSession {
|
|
|
978
1002
|
return (0, import_crExecutionContext.createHandle)(to, result.object).asElement();
|
|
979
1003
|
}
|
|
980
1004
|
async _initBinding(binding = import_page.PageBinding) {
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
worldName: "utility"
|
|
985
|
-
});
|
|
986
|
-
if (!result) return;
|
|
987
|
-
var isolatedContextId = result.executionContextId;
|
|
988
|
-
var globalThis = await this._client._sendMayFail("Runtime.evaluate", {
|
|
989
|
-
expression: "globalThis",
|
|
990
|
-
serializationOptions: { serialization: "idOnly" }
|
|
991
|
-
});
|
|
992
|
-
if (!globalThis) return;
|
|
993
|
-
var globalThisObjId = globalThis["result"]["objectId"];
|
|
994
|
-
var mainContextId = parseInt(globalThisObjId.split(".")[1], 10);
|
|
1005
|
+
this._exposedBindingNames.push(binding.name);
|
|
1006
|
+
this._exposedBindingScripts.push(binding.source);
|
|
1007
|
+
const contextIds = Array.from(this._contextIdToContext.keys());
|
|
995
1008
|
await Promise.all([
|
|
996
1009
|
this._client._sendMayFail("Runtime.addBinding", { name: binding.name }),
|
|
997
|
-
this._client._sendMayFail("Runtime.addBinding", { name: binding.name, executionContextId
|
|
998
|
-
this._client._sendMayFail("Runtime.addBinding", { name: binding.name, executionContextId: isolatedContextId })
|
|
999
|
-
// this._client._sendMayFail("Runtime.evaluate", { expression: binding.source, contextId: mainContextId, awaitPromise: true })
|
|
1010
|
+
...contextIds.map((executionContextId) => this._client._sendMayFail("Runtime.addBinding", { name: binding.name, executionContextId }))
|
|
1000
1011
|
]);
|
|
1001
|
-
|
|
1002
|
-
|
|
1012
|
+
for (const contextId of contextIds) {
|
|
1013
|
+
this._client._sendMayFail("Runtime.evaluate", {
|
|
1014
|
+
expression: binding.source,
|
|
1015
|
+
contextId,
|
|
1016
|
+
awaitPromise: true
|
|
1017
|
+
});
|
|
1018
|
+
}
|
|
1003
1019
|
}
|
|
1004
1020
|
async _removeExposedBindings() {
|
|
1005
1021
|
const toRetain = [];
|
|
@@ -116,8 +116,6 @@ class BrowserContextDispatcher extends import_dispatcher.Dispatcher {
|
|
|
116
116
|
}
|
|
117
117
|
});
|
|
118
118
|
this._dialogHandler = (dialog) => {
|
|
119
|
-
if (!this._shouldDispatchEvent(dialog.page(), "dialog"))
|
|
120
|
-
return false;
|
|
121
119
|
this._dispatchEvent("dialog", { dialog: new import_dialogDispatcher.DialogDispatcher(this, dialog) });
|
|
122
120
|
return true;
|
|
123
121
|
};
|
|
@@ -304,6 +304,11 @@ class FrameSelectors {
|
|
|
304
304
|
const childIndex = this._findElementPositionInDomTree(element, shadowRootHandle, documentScope, currentIndex);
|
|
305
305
|
if (childIndex !== null) return childIndex;
|
|
306
306
|
}
|
|
307
|
+
for (const shadowChild of shadowRoot.children || []) {
|
|
308
|
+
const shadowChildIndex = (shadowRoot.children || []).indexOf(shadowChild);
|
|
309
|
+
const childIndex = this._findElementPositionInDomTree(element, shadowChild, documentScope, currentIndex + "." + shadowChildIndex.toString());
|
|
310
|
+
if (childIndex !== null) return childIndex;
|
|
311
|
+
}
|
|
307
312
|
}
|
|
308
313
|
}
|
|
309
314
|
return null;
|
package/lib/server/frames.js
CHANGED
|
@@ -457,7 +457,11 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
457
457
|
});
|
|
458
458
|
}
|
|
459
459
|
nonStallingEvaluateInExistingContext(expression, world) {
|
|
460
|
-
return this.raceAgainstEvaluationStallingEvents(() => {
|
|
460
|
+
return this.raceAgainstEvaluationStallingEvents(async () => {
|
|
461
|
+
try {
|
|
462
|
+
await this._context(world);
|
|
463
|
+
} catch {
|
|
464
|
+
}
|
|
461
465
|
const context = this._contextData.get(world)?.context;
|
|
462
466
|
if (!context)
|
|
463
467
|
throw new Error("Frame does not yet have the execution context");
|
|
@@ -596,7 +600,7 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
596
600
|
var executionContextId = iframeExecutionContextId;
|
|
597
601
|
var crContext = new import_crExecutionContext.CRExecutionContext(client, { id: executionContextId }, this._id);
|
|
598
602
|
this._iframeWorld = new import_dom.FrameExecutionContext(crContext, this, world);
|
|
599
|
-
this._page.delegate.
|
|
603
|
+
this._page.delegate._sessionForFrame(this)._onExecutionContextCreated({
|
|
600
604
|
id: executionContextId,
|
|
601
605
|
origin: world,
|
|
602
606
|
name: world,
|
|
@@ -608,13 +612,14 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
608
612
|
serializationOptions: { serialization: "idOnly" }
|
|
609
613
|
});
|
|
610
614
|
if (!globalThis2) {
|
|
615
|
+
if (this.isDetached()) throw new Error("Frame was detached");
|
|
611
616
|
return;
|
|
612
617
|
}
|
|
613
618
|
var globalThisObjId = globalThis2["result"]["objectId"];
|
|
614
619
|
var executionContextId = parseInt(globalThisObjId.split(".")[1], 10);
|
|
615
620
|
var crContext = new import_crExecutionContext.CRExecutionContext(client, { id: executionContextId }, this._id);
|
|
616
621
|
this._mainWorld = new import_dom.FrameExecutionContext(crContext, this, world);
|
|
617
|
-
this._page.delegate.
|
|
622
|
+
this._page.delegate._sessionForFrame(this)._onExecutionContextCreated({
|
|
618
623
|
id: executionContextId,
|
|
619
624
|
origin: world,
|
|
620
625
|
name: world,
|
|
@@ -630,12 +635,13 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
630
635
|
worldName: world
|
|
631
636
|
});
|
|
632
637
|
if (!result) {
|
|
638
|
+
if (this.isDetached()) throw new Error("Frame was detached");
|
|
633
639
|
return;
|
|
634
640
|
}
|
|
635
641
|
var executionContextId = result.executionContextId;
|
|
636
642
|
var crContext = new import_crExecutionContext.CRExecutionContext(client, { id: executionContextId }, this._id);
|
|
637
643
|
this._isolatedWorld = new import_dom.FrameExecutionContext(crContext, this, world);
|
|
638
|
-
this._page.delegate.
|
|
644
|
+
this._page.delegate._sessionForFrame(this)._onExecutionContextCreated({
|
|
639
645
|
id: executionContextId,
|
|
640
646
|
origin: world,
|
|
641
647
|
name: world,
|
|
@@ -644,7 +650,7 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
644
650
|
}
|
|
645
651
|
if (world != "main") {
|
|
646
652
|
return this._isolatedWorld;
|
|
647
|
-
} else if (this != this._page.mainFrame() &&
|
|
653
|
+
} else if (this != this._page.mainFrame() && this._iframeWorld) {
|
|
648
654
|
return this._iframeWorld;
|
|
649
655
|
} else {
|
|
650
656
|
return this._mainWorld;
|
|
@@ -660,13 +666,13 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
660
666
|
return this._context("utility");
|
|
661
667
|
}
|
|
662
668
|
async evaluateExpression(expression, options = {}, arg) {
|
|
663
|
-
const context = await this._context(options.world ?? "main");
|
|
664
|
-
const value = await context.evaluateExpression(expression, options, arg);
|
|
669
|
+
const context = await this._detachedScope.race(this._context(options.world ?? "main"));
|
|
670
|
+
const value = await this._detachedScope.race(context.evaluateExpression(expression, options, arg));
|
|
665
671
|
return value;
|
|
666
672
|
}
|
|
667
673
|
async evaluateExpressionHandle(expression, options = {}, arg) {
|
|
668
|
-
const context = await this._context(options.world ?? "utility");
|
|
669
|
-
const value = await context.evaluateExpressionHandle(expression, options, arg);
|
|
674
|
+
const context = await this._detachedScope.race(this._context(options.world ?? "utility"));
|
|
675
|
+
const value = await this._detachedScope.race(context.evaluateExpressionHandle(expression, options, arg));
|
|
670
676
|
return value;
|
|
671
677
|
}
|
|
672
678
|
async querySelector(selector, options) {
|
|
@@ -688,7 +694,15 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
688
694
|
throw new Error(`state: expected one of (attached|detached|visible|hidden)`);
|
|
689
695
|
if (performActionPreChecksAndLog)
|
|
690
696
|
progress.log(`waiting for ${this._asLocator(selector)}${state === "attached" ? "" : " to be " + state}`);
|
|
691
|
-
const promise = this._retryWithProgressIfNotConnected(progress, selector, options
|
|
697
|
+
const promise = this._retryWithProgressIfNotConnected(progress, selector, { ...options, performActionPreChecks: true, __patchrightWaitForSelector: true, __patchrightInitialScope: scope }, async (handle) => {
|
|
698
|
+
if (scope) {
|
|
699
|
+
const scopeIsConnected = await scope.evaluateInUtility(([injected, node]) => node.isConnected, {}).catch(() => false);
|
|
700
|
+
if (scopeIsConnected !== true) {
|
|
701
|
+
if (state === "hidden" || state === "detached")
|
|
702
|
+
return null;
|
|
703
|
+
throw new dom.NonRecoverableDOMError("Element is not attached to the DOM");
|
|
704
|
+
}
|
|
705
|
+
}
|
|
692
706
|
const attached = !!handle;
|
|
693
707
|
var visible = false;
|
|
694
708
|
if (attached) {
|
|
@@ -719,12 +733,50 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
719
733
|
return "internal:continuepolling";
|
|
720
734
|
}
|
|
721
735
|
}, "returnOnNotResolved");
|
|
722
|
-
|
|
736
|
+
const resultPromise = scope ? scope._context._raceAgainstContextDestroyed(promise) : promise;
|
|
737
|
+
return resultPromise.catch((e) => {
|
|
738
|
+
if (this.isDetached() && e?.message?.includes("Execution context was destroyed"))
|
|
739
|
+
throw new Error("Frame was detached");
|
|
740
|
+
throw e;
|
|
741
|
+
});
|
|
723
742
|
}
|
|
724
743
|
async dispatchEvent(progress, selector, type, eventInit = {}, options, scope) {
|
|
725
|
-
|
|
744
|
+
const eventInitHandles = [];
|
|
745
|
+
const visited = /* @__PURE__ */ new WeakSet();
|
|
746
|
+
const collectHandles = (value) => {
|
|
747
|
+
if (!value || typeof value !== "object")
|
|
748
|
+
return;
|
|
749
|
+
if (value instanceof js.JSHandle) {
|
|
750
|
+
eventInitHandles.push(value);
|
|
751
|
+
return;
|
|
752
|
+
}
|
|
753
|
+
if (visited.has(value))
|
|
754
|
+
return;
|
|
755
|
+
visited.add(value);
|
|
756
|
+
if (Array.isArray(value)) {
|
|
757
|
+
for (const item of value)
|
|
758
|
+
collectHandles(item);
|
|
759
|
+
return;
|
|
760
|
+
}
|
|
761
|
+
for (const propertyValue of Object.values(value))
|
|
762
|
+
collectHandles(propertyValue);
|
|
763
|
+
};
|
|
764
|
+
collectHandles(eventInit);
|
|
765
|
+
const allHandlesFromSameFrame = eventInitHandles.length > 0 && eventInitHandles.every((handle) => handle._context?.frame === eventInitHandles[0]?._context?.frame);
|
|
766
|
+
const handlesFrame = eventInitHandles[0]?._context?.frame;
|
|
767
|
+
const canRetryInSecondaryContext = allHandlesFromSameFrame && (handlesFrame !== this || !selector.includes("internal:control=enter-frame"));
|
|
768
|
+
const callback = (injectedScript, element, data) => {
|
|
726
769
|
injectedScript.dispatchEvent(element, data.type, data.eventInit);
|
|
727
|
-
}
|
|
770
|
+
};
|
|
771
|
+
try {
|
|
772
|
+
await this._callOnElementOnceMatches(progress, selector, callback, { type, eventInit }, { mainWorld: true, ...options }, scope);
|
|
773
|
+
} catch (e) {
|
|
774
|
+
if ("JSHandles can be evaluated only in the context they were created!" === e.message && canRetryInSecondaryContext) {
|
|
775
|
+
await this._callOnElementOnceMatches(progress, selector, callback, { type, eventInit }, { ...options }, scope);
|
|
776
|
+
return;
|
|
777
|
+
}
|
|
778
|
+
throw e;
|
|
779
|
+
}
|
|
728
780
|
}
|
|
729
781
|
async evalOnSelector(selector, strict, expression, isFunction, arg, scope) {
|
|
730
782
|
const handle = await this.selectors.query(selector, { strict }, scope);
|
|
@@ -760,7 +812,7 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
760
812
|
metadata,
|
|
761
813
|
race: (promise) => Promise.race(Array.isArray(promise) ? promise : [promise])
|
|
762
814
|
};
|
|
763
|
-
return await this._retryWithoutProgress(progress, selector, null, false, async (result) => {
|
|
815
|
+
return await this._retryWithoutProgress(progress, selector, { strict: null, performActionPreChecks: false }, async (result) => {
|
|
764
816
|
if (!result || !result[0]) return [];
|
|
765
817
|
return result[1];
|
|
766
818
|
}, "returnAll", null);
|
|
@@ -772,7 +824,7 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
772
824
|
metadata,
|
|
773
825
|
race: (promise) => Promise.race(Array.isArray(promise) ? promise : [promise])
|
|
774
826
|
};
|
|
775
|
-
return await this._retryWithoutProgress(progress, selector, null, false, async (result) => {
|
|
827
|
+
return await this._retryWithoutProgress(progress, selector, { strict: null, performActionPreChecks: false }, async (result) => {
|
|
776
828
|
if (!result) return 0;
|
|
777
829
|
const handle = result[0];
|
|
778
830
|
const handles = result[1];
|
|
@@ -804,7 +856,7 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
804
856
|
this._onClearLifecycle();
|
|
805
857
|
this.waitForLoadState(progress, waitUntil).then(resolve).catch(reject);
|
|
806
858
|
});
|
|
807
|
-
const setContentPromise = this._page.delegate.
|
|
859
|
+
const setContentPromise = this._page.delegate._sessionForFrame(this)._client.send("Page.setDocumentContent", {
|
|
808
860
|
frameId: this._id,
|
|
809
861
|
html
|
|
810
862
|
});
|
|
@@ -969,10 +1021,11 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
969
1021
|
return true;
|
|
970
1022
|
return false;
|
|
971
1023
|
}
|
|
972
|
-
async _retryWithProgressIfNotConnected(progress, selector, options,
|
|
973
|
-
|
|
1024
|
+
async _retryWithProgressIfNotConnected(progress, selector, options, action, returnAction) {
|
|
1025
|
+
if (!options?.__patchrightSkipRetryLogWaiting)
|
|
1026
|
+
progress.log("waiting for " + this._asLocator(selector));
|
|
974
1027
|
return this.retryWithProgressAndTimeouts(progress, [0, 20, 50, 100, 100, 500], async (continuePolling) => {
|
|
975
|
-
return this._retryWithoutProgress(progress, selector,
|
|
1028
|
+
return this._retryWithoutProgress(progress, selector, options, action, returnAction, continuePolling);
|
|
976
1029
|
});
|
|
977
1030
|
}
|
|
978
1031
|
async rafrafTimeoutScreenshotElementWithProgress(progress, selector, timeout, options) {
|
|
@@ -1132,7 +1185,7 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
1132
1185
|
}, { scope });
|
|
1133
1186
|
}
|
|
1134
1187
|
} else {
|
|
1135
|
-
return await this._retryWithoutProgress(progress2, selector, options
|
|
1188
|
+
return await this._retryWithoutProgress(progress2, selector, { ...options, performActionPreChecks: false }, async (handle) => {
|
|
1136
1189
|
if (!handle) return false;
|
|
1137
1190
|
if (handle.parentNode.constructor.name == "ElementHandle") {
|
|
1138
1191
|
return await handle.parentNode.evaluateInUtility(([injected, node, { handle: handle2 }]) => {
|
|
@@ -1253,11 +1306,17 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
1253
1306
|
const isArray = options.expression === "to.have.count" || options.expression.endsWith(".array");
|
|
1254
1307
|
var log, matches, received, missingReceived;
|
|
1255
1308
|
if (selector) {
|
|
1256
|
-
|
|
1309
|
+
var frame, info;
|
|
1310
|
+
try {
|
|
1311
|
+
var { frame, info } = await race(this.selectors.resolveFrameForSelector(selector, { strict: true }));
|
|
1312
|
+
} catch (e) {
|
|
1313
|
+
}
|
|
1257
1314
|
const action = async (result) => {
|
|
1258
1315
|
if (!result) {
|
|
1259
1316
|
if (options.expectedNumber === 0)
|
|
1260
1317
|
return { matches: true };
|
|
1318
|
+
if (options.isNot && options.expectedNumber)
|
|
1319
|
+
return { matches: false, received: 0 };
|
|
1261
1320
|
if (!options.isNot && options.expression === "to.be.hidden")
|
|
1262
1321
|
return { matches: true };
|
|
1263
1322
|
if (options.isNot && options.expression === "to.be.visible")
|
|
@@ -1268,6 +1327,12 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
1268
1327
|
return { matches: false };
|
|
1269
1328
|
if (options.isNot && options.expression === "to.be.in.viewport")
|
|
1270
1329
|
return { matches: false };
|
|
1330
|
+
if (options.expression === "to.have.text.array") {
|
|
1331
|
+
if (options.expectedText.length === 0)
|
|
1332
|
+
return { matches: true, received: [] };
|
|
1333
|
+
if (options.isNot && options.expectedText.length !== 0)
|
|
1334
|
+
return { matches: false, received: [] };
|
|
1335
|
+
}
|
|
1271
1336
|
return { matches: options.isNot, missingReceived: true };
|
|
1272
1337
|
}
|
|
1273
1338
|
const handle = result[0];
|
|
@@ -1283,9 +1348,9 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
1283
1348
|
}
|
|
1284
1349
|
};
|
|
1285
1350
|
if (noAbort) {
|
|
1286
|
-
var { log, matches, received, missingReceived } = await this._retryWithoutProgress(progress, selector, !isArray, false, action, "returnAll", null);
|
|
1351
|
+
var { log, matches, received, missingReceived } = await this._retryWithoutProgress(progress, selector, { strict: !isArray, performActionPreChecks: false }, action, "returnAll", null);
|
|
1287
1352
|
} else {
|
|
1288
|
-
var { log, matches, received, missingReceived } = await race(this._retryWithProgressIfNotConnected(progress, selector, !isArray, false, action, "returnAll"));
|
|
1353
|
+
var { log, matches, received, missingReceived } = await race(this._retryWithProgressIfNotConnected(progress, selector, { strict: !isArray, performActionPreChecks: false, __patchrightSkipRetryLogWaiting: true }, action, "returnAll"));
|
|
1289
1354
|
}
|
|
1290
1355
|
} else {
|
|
1291
1356
|
const world = options.expression === "to.have.property" ? "main" : "utility";
|
|
@@ -1298,10 +1363,18 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
1298
1363
|
if (log)
|
|
1299
1364
|
progress.log(log);
|
|
1300
1365
|
if (matches === options.isNot) {
|
|
1301
|
-
|
|
1366
|
+
if (missingReceived) {
|
|
1367
|
+
lastIntermediateResult.errorMessage = "Error: element(s) not found";
|
|
1368
|
+
} else {
|
|
1369
|
+
lastIntermediateResult.errorMessage = void 0;
|
|
1370
|
+
lastIntermediateResult.received = received;
|
|
1371
|
+
}
|
|
1302
1372
|
lastIntermediateResult.isSet = true;
|
|
1303
|
-
if (!missingReceived
|
|
1304
|
-
|
|
1373
|
+
if (!missingReceived) {
|
|
1374
|
+
const rendered = renderUnexpectedValue(options.expression, received);
|
|
1375
|
+
if (rendered !== void 0)
|
|
1376
|
+
progress.log(' unexpected value "' + rendered + '"');
|
|
1377
|
+
}
|
|
1305
1378
|
}
|
|
1306
1379
|
return { matches, received };
|
|
1307
1380
|
}
|
|
@@ -1357,7 +1430,7 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
1357
1430
|
return { result, abort: () => aborted = true };
|
|
1358
1431
|
}, { expression, isFunction, polling: options.pollingInterval, arg }));
|
|
1359
1432
|
try {
|
|
1360
|
-
return await progress.race(handle.evaluateHandle((h) => h.result));
|
|
1433
|
+
return await progress.race(this._detachedScope.race(handle.evaluateHandle((h) => h.result)));
|
|
1361
1434
|
} catch (error) {
|
|
1362
1435
|
await handle.evaluate((h) => h.abort()).catch(() => {
|
|
1363
1436
|
});
|
|
@@ -1403,6 +1476,12 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
1403
1476
|
data.context.contextDestroyed("Frame was detached");
|
|
1404
1477
|
data.contextPromise.resolve({ destroyedReason: "Frame was detached" });
|
|
1405
1478
|
}
|
|
1479
|
+
if (this._mainWorld)
|
|
1480
|
+
this._mainWorld.contextDestroyed("Frame was detached");
|
|
1481
|
+
if (this._iframeWorld)
|
|
1482
|
+
this._iframeWorld.contextDestroyed("Frame was detached");
|
|
1483
|
+
if (this._isolatedWorld)
|
|
1484
|
+
this._isolatedWorld.contextDestroyed("Frame was detached");
|
|
1406
1485
|
if (this._parentFrame)
|
|
1407
1486
|
this._parentFrame._childFrames.delete(this);
|
|
1408
1487
|
this._parentFrame = null;
|
|
@@ -1414,14 +1493,33 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
1414
1493
|
if (selector === ":scope") {
|
|
1415
1494
|
const scopeParentNode = scope.parentNode || scope;
|
|
1416
1495
|
if (scopeParentNode.constructor.name == "ElementHandle") {
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1496
|
+
if (options?.mainWorld) {
|
|
1497
|
+
promise = (async () => {
|
|
1498
|
+
const mainContext = await this._mainContext();
|
|
1499
|
+
const adoptedScope = await this._page.delegate.adoptElementHandle(scope, mainContext);
|
|
1500
|
+
try {
|
|
1501
|
+
return await mainContext.evaluate(([injected, node, { callbackText: callbackText2, scope: handle2, taskData: taskData2 }]) => {
|
|
1502
|
+
const callback = injected.eval(callbackText2);
|
|
1503
|
+
return callback(injected, handle2, taskData2);
|
|
1504
|
+
}, [
|
|
1505
|
+
await mainContext.injectedScript(),
|
|
1506
|
+
adoptedScope,
|
|
1507
|
+
{ callbackText, scope: adoptedScope, taskData }
|
|
1508
|
+
]);
|
|
1509
|
+
} finally {
|
|
1510
|
+
adoptedScope.dispose();
|
|
1511
|
+
}
|
|
1512
|
+
})();
|
|
1513
|
+
} else {
|
|
1514
|
+
promise = scopeParentNode.evaluateInUtility(([injected, node, { callbackText: callbackText2, scope: handle2, taskData: taskData2 }]) => {
|
|
1515
|
+
const callback = injected.eval(callbackText2);
|
|
1516
|
+
return callback(injected, handle2, taskData2);
|
|
1517
|
+
}, {
|
|
1518
|
+
callbackText,
|
|
1519
|
+
scope,
|
|
1520
|
+
taskData
|
|
1521
|
+
});
|
|
1522
|
+
}
|
|
1425
1523
|
} else {
|
|
1426
1524
|
promise = scopeParentNode.evaluate((injected, { callbackText: callbackText2, scope: handle2, taskData: taskData2 }) => {
|
|
1427
1525
|
const callback = injected.eval(callbackText2);
|
|
@@ -1433,8 +1531,24 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
1433
1531
|
});
|
|
1434
1532
|
}
|
|
1435
1533
|
} else {
|
|
1436
|
-
promise = this._retryWithProgressIfNotConnected(progress, selector, options
|
|
1534
|
+
promise = this._retryWithProgressIfNotConnected(progress, selector, { ...options, performActionPreChecks: false }, async (handle) => {
|
|
1437
1535
|
if (handle.parentNode.constructor.name == "ElementHandle") {
|
|
1536
|
+
if (options?.mainWorld) {
|
|
1537
|
+
const mainContext = await handle._frame._mainContext();
|
|
1538
|
+
const adoptedHandle = await this._page.delegate.adoptElementHandle(handle, mainContext);
|
|
1539
|
+
try {
|
|
1540
|
+
return await mainContext.evaluate(([injected, node, { callbackText: callbackText2, handle: handle2, taskData: taskData2 }]) => {
|
|
1541
|
+
const callback = injected.eval(callbackText2);
|
|
1542
|
+
return callback(injected, handle2, taskData2);
|
|
1543
|
+
}, [
|
|
1544
|
+
await mainContext.injectedScript(),
|
|
1545
|
+
adoptedHandle,
|
|
1546
|
+
{ callbackText, handle: adoptedHandle, taskData }
|
|
1547
|
+
]);
|
|
1548
|
+
} finally {
|
|
1549
|
+
adoptedHandle.dispose();
|
|
1550
|
+
}
|
|
1551
|
+
}
|
|
1438
1552
|
const [taskScope] = Object.values(taskData?.eventInit ?? {});
|
|
1439
1553
|
if (taskScope) {
|
|
1440
1554
|
const taskScopeContext = taskScope._context;
|
|
@@ -1527,21 +1641,23 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
1527
1641
|
var describedNode = await client._sendMayFail("DOM.describeNode", {
|
|
1528
1642
|
backendNodeId: globalDocument.backendNodeId
|
|
1529
1643
|
});
|
|
1530
|
-
if (describedNode) {
|
|
1644
|
+
if (describedNode && describedNode.node.contentDocument) {
|
|
1531
1645
|
var resolvedNode = await client._sendMayFail("DOM.resolveNode", {
|
|
1532
|
-
|
|
1646
|
+
backendNodeId: describedNode.node.contentDocument.backendNodeId
|
|
1533
1647
|
});
|
|
1534
|
-
|
|
1535
|
-
|
|
1648
|
+
if (resolvedNode && resolvedNode.object && resolvedNode.object.objectId) {
|
|
1649
|
+
var _executionContextId = parseInt(resolvedNode.object.objectId.split(".")[1], 10);
|
|
1650
|
+
return _executionContextId;
|
|
1651
|
+
}
|
|
1536
1652
|
}
|
|
1537
1653
|
}
|
|
1538
1654
|
} catch (e) {
|
|
1539
1655
|
}
|
|
1540
1656
|
return 0;
|
|
1541
1657
|
}
|
|
1542
|
-
async _retryWithoutProgress(progress, selector,
|
|
1543
|
-
if (performActionPreChecks) await this._page.performActionPreChecks(progress);
|
|
1544
|
-
const resolved = await this.selectors.resolveInjectedForSelector(selector, { strict });
|
|
1658
|
+
async _retryWithoutProgress(progress, selector, options, action, returnAction, continuePolling) {
|
|
1659
|
+
if (options.performActionPreChecks) await this._page.performActionPreChecks(progress);
|
|
1660
|
+
const resolved = await this.selectors.resolveInjectedForSelector(selector, { strict: options.strict }, options.__patchrightInitialScope);
|
|
1545
1661
|
if (!resolved) {
|
|
1546
1662
|
if (returnAction === "returnOnNotResolved" || returnAction === "returnAll") {
|
|
1547
1663
|
const result2 = await action(null);
|
|
@@ -1564,24 +1680,51 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
1564
1680
|
contextId: utilityContext.delegate._contextId
|
|
1565
1681
|
});
|
|
1566
1682
|
if (!documentNode) return continuePolling;
|
|
1567
|
-
|
|
1683
|
+
let documentScope = new dom.ElementHandle(utilityContext, documentNode.result.objectId);
|
|
1684
|
+
let initialScope = documentScope;
|
|
1685
|
+
if (resolved.scope) {
|
|
1686
|
+
const scopeBackendNodeId = resolved.scope._objectId ? (await client._sendMayFail("DOM.describeNode", { objectId: resolved.scope._objectId }))?.node?.backendNodeId : null;
|
|
1687
|
+
if (scopeBackendNodeId) {
|
|
1688
|
+
const scopeInUtility = await client._sendMayFail("DOM.resolveNode", { backendNodeId: scopeBackendNodeId, executionContextId: utilityContext.delegate._contextId });
|
|
1689
|
+
if (scopeInUtility?.object?.objectId)
|
|
1690
|
+
initialScope = new dom.ElementHandle(utilityContext, scopeInUtility.object.objectId);
|
|
1691
|
+
}
|
|
1692
|
+
}
|
|
1693
|
+
progress.__patchrightInitialScope = resolved.scope;
|
|
1694
|
+
const parsedSnapshot = options.__patchrightWaitForSelector ? JSON.parse(JSON.stringify(resolved.info.parsed)) : null;
|
|
1568
1695
|
let currentScopingElements;
|
|
1569
1696
|
try {
|
|
1570
|
-
currentScopingElements = await this._customFindElementsByParsed(resolved, client, mainContext,
|
|
1697
|
+
currentScopingElements = await this._customFindElementsByParsed(resolved, client, mainContext, initialScope, progress, resolved.info.parsed);
|
|
1571
1698
|
} catch (e) {
|
|
1572
|
-
if ("JSHandles can be evaluated only in the context they were created!" === e.message) return
|
|
1699
|
+
if ("JSHandles can be evaluated only in the context they were created!" === e.message) return continuePolling;
|
|
1700
|
+
if (e instanceof TypeError && e.message.includes("is not a function")) return continuePolling;
|
|
1573
1701
|
await progress.race(resolved.injected.evaluateHandle((injected, { error }) => {
|
|
1574
1702
|
throw error;
|
|
1575
1703
|
}, { error: e }));
|
|
1576
1704
|
}
|
|
1577
1705
|
if (currentScopingElements.length == 0) {
|
|
1706
|
+
if (options.__testHookNoAutoWaiting || options.noAutoWaiting)
|
|
1707
|
+
throw new dom.NonRecoverableDOMError("Element(s) not found");
|
|
1708
|
+
if (parsedSnapshot && (returnAction === "returnOnNotResolved" || returnAction === "returnAll")) {
|
|
1709
|
+
const elementCount = await resolved.injected.evaluate((injected, { parsed }) => {
|
|
1710
|
+
return injected.querySelectorAll(parsed, document).length;
|
|
1711
|
+
}, { parsed: parsedSnapshot }).catch(() => 0);
|
|
1712
|
+
if (elementCount > 0)
|
|
1713
|
+
return continuePolling;
|
|
1714
|
+
}
|
|
1578
1715
|
if (returnAction === "returnOnNotResolved" || returnAction === "returnAll") {
|
|
1579
1716
|
const result2 = await action(null);
|
|
1580
|
-
return result2 === "internal:continuepolling" ?
|
|
1717
|
+
return result2 === "internal:continuepolling" ? continuePolling : result2;
|
|
1581
1718
|
}
|
|
1582
1719
|
return continuePolling;
|
|
1583
1720
|
}
|
|
1584
1721
|
const resultElement = currentScopingElements[0];
|
|
1722
|
+
await resultElement._initializePreview().catch(() => {
|
|
1723
|
+
});
|
|
1724
|
+
let visibilityQualifier = "";
|
|
1725
|
+
if (options && options.__patchrightWaitForSelector) {
|
|
1726
|
+
visibilityQualifier = await resultElement.evaluateInUtility(([injected, node]) => injected.utils.isElementVisible(node) ? "visible" : "hidden", {}).catch(() => "");
|
|
1727
|
+
}
|
|
1585
1728
|
if (currentScopingElements.length > 1) {
|
|
1586
1729
|
if (resolved.info.strict) {
|
|
1587
1730
|
await progress.race(resolved.injected.evaluateHandle((injected, {
|
|
@@ -1596,7 +1739,7 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
1596
1739
|
}
|
|
1597
1740
|
progress.log(" locator resolved to " + currentScopingElements.length + " elements. Proceeding with the first one: " + resultElement.preview());
|
|
1598
1741
|
} else if (resultElement) {
|
|
1599
|
-
progress.log(" locator resolved to " + resultElement.preview());
|
|
1742
|
+
progress.log(" locator resolved to " + (visibilityQualifier ? visibilityQualifier + " " : "") + resultElement.preview().replace("JSHandle@", ""));
|
|
1600
1743
|
}
|
|
1601
1744
|
try {
|
|
1602
1745
|
var result = null;
|
|
@@ -1611,6 +1754,14 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
1611
1754
|
} else if (result === "internal:continuepolling") {
|
|
1612
1755
|
return continuePolling;
|
|
1613
1756
|
}
|
|
1757
|
+
if (parsedSnapshot && result === null && (options.state === "hidden" || options.state === "detached")) {
|
|
1758
|
+
const visibleCount = await resolved.injected.evaluate((injected, { parsed }) => {
|
|
1759
|
+
const elements = injected.querySelectorAll(parsed, document);
|
|
1760
|
+
return elements.filter((e) => injected.utils.isElementVisible(e)).length;
|
|
1761
|
+
}, { parsed: parsedSnapshot }).catch(() => 0);
|
|
1762
|
+
if (visibleCount > 0)
|
|
1763
|
+
return continuePolling;
|
|
1764
|
+
}
|
|
1614
1765
|
return result;
|
|
1615
1766
|
} finally {
|
|
1616
1767
|
}
|
package/lib/server/javascript.js
CHANGED
|
@@ -122,6 +122,8 @@ class JSHandle extends import_instrumentation.SdkObject {
|
|
|
122
122
|
else if (isolatedContext === false) context = await frame._mainContext();
|
|
123
123
|
}
|
|
124
124
|
}
|
|
125
|
+
if (context !== this._context && context.adoptIfNeeded(this) === null)
|
|
126
|
+
context = this._context;
|
|
125
127
|
const value = await evaluateExpression(context, expression, { ...options, returnByValue: true }, this, arg);
|
|
126
128
|
await context.doSlowMo();
|
|
127
129
|
return value;
|
|
@@ -135,6 +137,8 @@ class JSHandle extends import_instrumentation.SdkObject {
|
|
|
135
137
|
else if (isolatedContext === false) context = await frame._mainContext();
|
|
136
138
|
}
|
|
137
139
|
}
|
|
140
|
+
if (context !== this._context && context.adoptIfNeeded(this) === null)
|
|
141
|
+
context = this._context;
|
|
138
142
|
const value = await evaluateExpression(context, expression, { ...options, returnByValue: false }, this, arg);
|
|
139
143
|
await context.doSlowMo();
|
|
140
144
|
return value;
|
package/lib/server/launchApp.js
CHANGED
|
@@ -114,7 +114,8 @@ async function syncLocalStorageWithSettings(page, appName) {
|
|
|
114
114
|
return;
|
|
115
115
|
Object.entries(settings2).map(([k, v]) => localStorage[k] = v);
|
|
116
116
|
window.saveSettings = () => {
|
|
117
|
-
window._saveSerializedSettings
|
|
117
|
+
if (typeof window._saveSerializedSettings === "function")
|
|
118
|
+
window._saveSerializedSettings(JSON.stringify({ ...localStorage }));
|
|
118
119
|
};
|
|
119
120
|
})})(${settings});
|
|
120
121
|
`
|
package/lib/server/page.js
CHANGED
|
@@ -711,6 +711,32 @@ class PageBinding {
|
|
|
711
711
|
}
|
|
712
712
|
static async dispatch(page, payload, context) {
|
|
713
713
|
const { name, seq, serializedArgs } = JSON.parse(payload);
|
|
714
|
+
const deliver = async (deliverPayload) => {
|
|
715
|
+
let deliveryError;
|
|
716
|
+
try {
|
|
717
|
+
await context.evaluate(import_pageBinding.deliverBindingResult, deliverPayload);
|
|
718
|
+
return;
|
|
719
|
+
} catch (e) {
|
|
720
|
+
deliveryError = e;
|
|
721
|
+
}
|
|
722
|
+
const frame = context.frame;
|
|
723
|
+
if (!frame) {
|
|
724
|
+
import_debugLogger.debugLogger.log("error", deliveryError);
|
|
725
|
+
return;
|
|
726
|
+
}
|
|
727
|
+
const mainContext = await frame._mainContext().catch(() => null);
|
|
728
|
+
const utilityContext = await frame._utilityContext().catch(() => null);
|
|
729
|
+
for (const ctx of [mainContext, utilityContext]) {
|
|
730
|
+
if (!ctx || ctx === context)
|
|
731
|
+
continue;
|
|
732
|
+
try {
|
|
733
|
+
await ctx.evaluate(import_pageBinding.deliverBindingResult, deliverPayload);
|
|
734
|
+
return;
|
|
735
|
+
} catch {
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
import_debugLogger.debugLogger.log("error", deliveryError);
|
|
739
|
+
};
|
|
714
740
|
try {
|
|
715
741
|
(0, import_utils.assert)(context.world);
|
|
716
742
|
const binding = page.getBinding(name);
|
|
@@ -726,9 +752,9 @@ class PageBinding {
|
|
|
726
752
|
const args = serializedArgs.map((a) => (0, import_utilityScriptSerializers.parseEvaluationResultValue)(a));
|
|
727
753
|
result = await binding.playwrightFunction({ frame: context.frame, page, context: page._browserContext }, ...args);
|
|
728
754
|
}
|
|
729
|
-
|
|
755
|
+
await deliver({ name, seq, result });
|
|
730
756
|
} catch (error) {
|
|
731
|
-
|
|
757
|
+
await deliver({ name, seq, error });
|
|
732
758
|
}
|
|
733
759
|
}
|
|
734
760
|
}
|
|
@@ -213,6 +213,12 @@ class Screenshotter {
|
|
|
213
213
|
if (disableAnimations)
|
|
214
214
|
progress.log(" disabled all CSS animations");
|
|
215
215
|
const syncAnimations = this._page.delegate.shouldToggleStyleSheetToSyncAnimations();
|
|
216
|
+
await Promise.all(this._page.frames().map(async (f) => {
|
|
217
|
+
try {
|
|
218
|
+
await f._utilityContext();
|
|
219
|
+
} catch {
|
|
220
|
+
}
|
|
221
|
+
}));
|
|
216
222
|
await progress.race(this._page.safeNonStallingEvaluateInAllFrames("(" + inPagePrepareForScreenshots.toString() + `)(${JSON.stringify(screenshotStyle)}, ${hideCaret}, ${disableAnimations}, ${syncAnimations})`, "utility"));
|
|
217
223
|
try {
|
|
218
224
|
if (!process.env.PW_TEST_SCREENSHOT_NO_FONTS_READY) {
|
|
@@ -49,7 +49,7 @@ class Snapshotter {
|
|
|
49
49
|
}
|
|
50
50
|
async reset() {
|
|
51
51
|
if (this._started)
|
|
52
|
-
await this._context.safeNonStallingEvaluateInAllFrames(`window["${this._snapshotStreamer}"].reset()`, "
|
|
52
|
+
await this._context.safeNonStallingEvaluateInAllFrames(`window["${this._snapshotStreamer}"].reset()`, "utility");
|
|
53
53
|
}
|
|
54
54
|
stop() {
|
|
55
55
|
this._started = false;
|
|
@@ -57,20 +57,20 @@ class Snapshotter {
|
|
|
57
57
|
async resetForReuse() {
|
|
58
58
|
if (this._initScript) {
|
|
59
59
|
import_eventsHelper.eventsHelper.removeEventListeners(this._eventListeners);
|
|
60
|
-
await this._context.removeInitScripts([this._initScript]);
|
|
61
60
|
this._initScript = void 0;
|
|
61
|
+
this._initScriptSource = void 0;
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
async _initialize() {
|
|
65
|
+
const { javaScriptEnabled } = this._context._options;
|
|
66
|
+
this._initScriptSource = `(${import_snapshotterInjected.frameSnapshotStreamer})("${this._snapshotStreamer}", ${javaScriptEnabled || javaScriptEnabled === void 0})`;
|
|
67
|
+
this._initScript = true;
|
|
65
68
|
for (const page of this._context.pages())
|
|
66
69
|
this._onPage(page);
|
|
67
70
|
this._eventListeners = [
|
|
68
71
|
import_eventsHelper.eventsHelper.addEventListener(this._context, import_browserContext.BrowserContext.Events.Page, this._onPage.bind(this))
|
|
69
72
|
];
|
|
70
|
-
|
|
71
|
-
const initScriptSource = `(${import_snapshotterInjected.frameSnapshotStreamer})("${this._snapshotStreamer}", ${javaScriptEnabled || javaScriptEnabled === void 0})`;
|
|
72
|
-
this._initScript = await this._context.addInitScript(void 0, initScriptSource);
|
|
73
|
-
await this._context.safeNonStallingEvaluateInAllFrames(initScriptSource, "main");
|
|
73
|
+
await this._context.safeNonStallingEvaluateInAllFrames(this._initScriptSource, "utility");
|
|
74
74
|
}
|
|
75
75
|
dispose() {
|
|
76
76
|
import_eventsHelper.eventsHelper.removeEventListeners(this._eventListeners);
|
|
@@ -80,7 +80,7 @@ class Snapshotter {
|
|
|
80
80
|
frame[kNeedsResetSymbol] = false;
|
|
81
81
|
const expression = `window["${this._snapshotStreamer}"].captureSnapshot(${needsReset ? "true" : "false"})`;
|
|
82
82
|
try {
|
|
83
|
-
return await frame.
|
|
83
|
+
return await frame.nonStallingEvaluateInExistingContext(expression, "utility");
|
|
84
84
|
} catch (e) {
|
|
85
85
|
frame[kNeedsResetSymbol] = true;
|
|
86
86
|
import_debugLogger.debugLogger.log("error", e);
|
|
@@ -124,6 +124,7 @@ class Snapshotter {
|
|
|
124
124
|
for (const frame of page.frames())
|
|
125
125
|
this._annotateFrameHierarchy(frame);
|
|
126
126
|
this._eventListeners.push(import_eventsHelper.eventsHelper.addEventListener(page, import_page.Page.Events.FrameAttached, (frame) => this._annotateFrameHierarchy(frame)));
|
|
127
|
+
this._eventListeners.push(import_eventsHelper.eventsHelper.addEventListener(page, import_page.Page.Events.InternalFrameNavigatedToNewDocument, (frame) => this._onFrameNavigated(frame)));
|
|
127
128
|
}
|
|
128
129
|
async _annotateFrameHierarchy(frame) {
|
|
129
130
|
try {
|
|
@@ -131,7 +132,7 @@ class Snapshotter {
|
|
|
131
132
|
const parent = frame.parentFrame();
|
|
132
133
|
if (!parent)
|
|
133
134
|
return;
|
|
134
|
-
const context = await parent.
|
|
135
|
+
const context = await parent._utilityContext();
|
|
135
136
|
await context?.evaluate(({ snapshotStreamer, frameElement: frameElement2, frameId }) => {
|
|
136
137
|
window[snapshotStreamer].markIframe(frameElement2, frameId);
|
|
137
138
|
}, { snapshotStreamer: this._snapshotStreamer, frameElement, frameId: frame.guid });
|
|
@@ -139,6 +140,14 @@ class Snapshotter {
|
|
|
139
140
|
} catch (e) {
|
|
140
141
|
}
|
|
141
142
|
}
|
|
143
|
+
async _onFrameNavigated(frame) {
|
|
144
|
+
if (!this._initScriptSource)
|
|
145
|
+
return;
|
|
146
|
+
try {
|
|
147
|
+
await frame.nonStallingEvaluateInExistingContext(this._initScriptSource, "utility");
|
|
148
|
+
} catch (e) {
|
|
149
|
+
}
|
|
150
|
+
}
|
|
142
151
|
}
|
|
143
152
|
const kNeedsResetSymbol = Symbol("kNeedsReset");
|
|
144
153
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -60,28 +60,11 @@ function frameSnapshotStreamer(snapshotStreamer, removeNoScript) {
|
|
|
60
60
|
class Streamer {
|
|
61
61
|
constructor() {
|
|
62
62
|
this._lastSnapshotNumber = 0;
|
|
63
|
-
this._staleStyleSheets = /* @__PURE__ */ new Set();
|
|
64
63
|
this._modifiedStyleSheets = /* @__PURE__ */ new Set();
|
|
65
|
-
this._readingStyleSheet = false;
|
|
66
|
-
const invalidateCSSGroupingRule = (rule) => {
|
|
67
|
-
if (rule.parentStyleSheet)
|
|
68
|
-
this._invalidateStyleSheet(rule.parentStyleSheet);
|
|
69
|
-
};
|
|
70
|
-
this._interceptNativeMethod(window.CSSStyleSheet.prototype, "insertRule", (sheet) => this._invalidateStyleSheet(sheet));
|
|
71
|
-
this._interceptNativeMethod(window.CSSStyleSheet.prototype, "deleteRule", (sheet) => this._invalidateStyleSheet(sheet));
|
|
72
|
-
this._interceptNativeMethod(window.CSSStyleSheet.prototype, "addRule", (sheet) => this._invalidateStyleSheet(sheet));
|
|
73
|
-
this._interceptNativeMethod(window.CSSStyleSheet.prototype, "removeRule", (sheet) => this._invalidateStyleSheet(sheet));
|
|
74
|
-
this._interceptNativeGetter(window.CSSStyleSheet.prototype, "rules", (sheet) => this._invalidateStyleSheet(sheet));
|
|
75
|
-
this._interceptNativeGetter(window.CSSStyleSheet.prototype, "cssRules", (sheet) => this._invalidateStyleSheet(sheet));
|
|
76
|
-
this._interceptNativeMethod(window.CSSStyleSheet.prototype, "replaceSync", (sheet) => this._invalidateStyleSheet(sheet));
|
|
77
|
-
this._interceptNativeMethod(window.CSSGroupingRule.prototype, "insertRule", invalidateCSSGroupingRule);
|
|
78
|
-
this._interceptNativeMethod(window.CSSGroupingRule.prototype, "deleteRule", invalidateCSSGroupingRule);
|
|
79
|
-
this._interceptNativeGetter(window.CSSGroupingRule.prototype, "cssRules", invalidateCSSGroupingRule);
|
|
80
64
|
this._interceptNativeSetter(window.StyleSheet.prototype, "disabled", (sheet) => {
|
|
81
65
|
if (sheet instanceof CSSStyleSheet)
|
|
82
66
|
this._invalidateStyleSheet(sheet);
|
|
83
67
|
});
|
|
84
|
-
this._interceptNativeAsyncMethod(window.CSSStyleSheet.prototype, "replace", (sheet) => this._invalidateStyleSheet(sheet));
|
|
85
68
|
this._fakeBase = document.createElement("base");
|
|
86
69
|
this._observer = new MutationObserver((list) => this._handleMutations(list));
|
|
87
70
|
const observerConfig = { attributes: true, subtree: true };
|
|
@@ -122,37 +105,6 @@ function frameSnapshotStreamer(snapshotStreamer, removeNoScript) {
|
|
|
122
105
|
delete event.composedPath()[0].__playwright_target__;
|
|
123
106
|
});
|
|
124
107
|
}
|
|
125
|
-
_interceptNativeMethod(obj, method, cb) {
|
|
126
|
-
const native = obj[method];
|
|
127
|
-
if (!native)
|
|
128
|
-
return;
|
|
129
|
-
obj[method] = function(...args) {
|
|
130
|
-
const result = native.call(this, ...args);
|
|
131
|
-
cb(this, result);
|
|
132
|
-
return result;
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
_interceptNativeAsyncMethod(obj, method, cb) {
|
|
136
|
-
const native = obj[method];
|
|
137
|
-
if (!native)
|
|
138
|
-
return;
|
|
139
|
-
obj[method] = async function(...args) {
|
|
140
|
-
const result = await native.call(this, ...args);
|
|
141
|
-
cb(this, result);
|
|
142
|
-
return result;
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
_interceptNativeGetter(obj, prop, cb) {
|
|
146
|
-
const descriptor = Object.getOwnPropertyDescriptor(obj, prop);
|
|
147
|
-
Object.defineProperty(obj, prop, {
|
|
148
|
-
...descriptor,
|
|
149
|
-
get: function() {
|
|
150
|
-
const result = descriptor.get.call(this);
|
|
151
|
-
cb(this, result);
|
|
152
|
-
return result;
|
|
153
|
-
}
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
108
|
_interceptNativeSetter(obj, prop, cb) {
|
|
157
109
|
const descriptor = Object.getOwnPropertyDescriptor(obj, prop);
|
|
158
110
|
Object.defineProperty(obj, prop, {
|
|
@@ -168,44 +120,37 @@ function frameSnapshotStreamer(snapshotStreamer, removeNoScript) {
|
|
|
168
120
|
for (const mutation of list)
|
|
169
121
|
ensureCachedData(mutation.target).attributesCached = void 0;
|
|
170
122
|
}
|
|
171
|
-
_invalidateStyleSheet(sheet) {
|
|
172
|
-
if (this._readingStyleSheet)
|
|
173
|
-
return;
|
|
174
|
-
this._staleStyleSheets.add(sheet);
|
|
175
|
-
if (sheet.href !== null)
|
|
176
|
-
this._modifiedStyleSheets.add(sheet);
|
|
177
|
-
}
|
|
178
123
|
_updateStyleElementStyleSheetTextIfNeeded(sheet, forceText) {
|
|
179
124
|
const data = ensureCachedData(sheet);
|
|
180
|
-
|
|
181
|
-
this.
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
} catch (e) {
|
|
185
|
-
data.cssText = "";
|
|
186
|
-
}
|
|
125
|
+
try {
|
|
126
|
+
data.cssText = this._getSheetText(sheet);
|
|
127
|
+
} catch (e) {
|
|
128
|
+
data.cssText = "";
|
|
187
129
|
}
|
|
188
130
|
return data.cssText;
|
|
189
131
|
}
|
|
190
132
|
// Returns either content, ref, or no override.
|
|
191
133
|
_updateLinkStyleSheetTextIfNeeded(sheet, snapshotNumber) {
|
|
192
134
|
const data = ensureCachedData(sheet);
|
|
193
|
-
|
|
194
|
-
this.
|
|
195
|
-
|
|
196
|
-
data.cssText =
|
|
197
|
-
|
|
198
|
-
return data.cssText;
|
|
199
|
-
} catch (e) {
|
|
135
|
+
try {
|
|
136
|
+
const currentText = this._getSheetText(sheet);
|
|
137
|
+
if (data.cssText === void 0) {
|
|
138
|
+
data.cssText = currentText;
|
|
139
|
+
return void 0;
|
|
200
140
|
}
|
|
141
|
+
if (currentText === data.cssText)
|
|
142
|
+
return data.cssRef === void 0 ? void 0 : snapshotNumber - data.cssRef;
|
|
143
|
+
data.cssText = currentText;
|
|
144
|
+
data.cssRef = snapshotNumber;
|
|
145
|
+
return data.cssText;
|
|
146
|
+
} catch (e) {
|
|
147
|
+
return void 0;
|
|
201
148
|
}
|
|
202
|
-
return data.cssRef === void 0 ? void 0 : snapshotNumber - data.cssRef;
|
|
203
149
|
}
|
|
204
150
|
markIframe(iframeElement, frameId) {
|
|
205
151
|
iframeElement[kSnapshotFrameId] = frameId;
|
|
206
152
|
}
|
|
207
153
|
reset() {
|
|
208
|
-
this._staleStyleSheets.clear();
|
|
209
154
|
const visitNode = (node) => {
|
|
210
155
|
resetCachedData(node);
|
|
211
156
|
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
@@ -264,17 +209,10 @@ function frameSnapshotStreamer(snapshotStreamer, removeNoScript) {
|
|
|
264
209
|
return document.baseURI;
|
|
265
210
|
}
|
|
266
211
|
_getSheetText(sheet) {
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
const rules = [];
|
|
272
|
-
for (const rule of sheet.cssRules)
|
|
273
|
-
rules.push(rule.cssText);
|
|
274
|
-
return rules.join("\n");
|
|
275
|
-
} finally {
|
|
276
|
-
this._readingStyleSheet = false;
|
|
277
|
-
}
|
|
212
|
+
const rules = [];
|
|
213
|
+
for (const rule of sheet.cssRules)
|
|
214
|
+
rules.push(rule.cssText);
|
|
215
|
+
return rules.join("\n");
|
|
278
216
|
}
|
|
279
217
|
captureSnapshot(needsReset) {
|
|
280
218
|
const timestamp = performance.now();
|
|
@@ -550,6 +550,8 @@ function shouldCaptureSnapshot(metadata) {
|
|
|
550
550
|
return !!metainfo?.snapshot;
|
|
551
551
|
}
|
|
552
552
|
function createBeforeActionTraceEvent(metadata, parentId) {
|
|
553
|
+
if (metadata.type === "Route" && metadata.method === "continue" && metadata.params?.isFallback)
|
|
554
|
+
return null;
|
|
553
555
|
if (metadata.internal || metadata.method.startsWith("tracing"))
|
|
554
556
|
return null;
|
|
555
557
|
const event = {
|
|
@@ -568,6 +570,8 @@ function createBeforeActionTraceEvent(metadata, parentId) {
|
|
|
568
570
|
return event;
|
|
569
571
|
}
|
|
570
572
|
function createInputActionTraceEvent(metadata) {
|
|
573
|
+
if (metadata.type === "Route" && metadata.method === "continue" && metadata.params?.isFallback)
|
|
574
|
+
return null;
|
|
571
575
|
if (metadata.internal || metadata.method.startsWith("tracing"))
|
|
572
576
|
return null;
|
|
573
577
|
return {
|
|
@@ -577,6 +581,8 @@ function createInputActionTraceEvent(metadata) {
|
|
|
577
581
|
};
|
|
578
582
|
}
|
|
579
583
|
function createActionLogTraceEvent(metadata, message) {
|
|
584
|
+
if (metadata.type === "Route" && metadata.method === "continue" && metadata.params?.isFallback)
|
|
585
|
+
return null;
|
|
580
586
|
if (metadata.internal || metadata.method.startsWith("tracing"))
|
|
581
587
|
return null;
|
|
582
588
|
return {
|
|
@@ -587,6 +593,8 @@ function createActionLogTraceEvent(metadata, message) {
|
|
|
587
593
|
};
|
|
588
594
|
}
|
|
589
595
|
function createAfterActionTraceEvent(metadata) {
|
|
596
|
+
if (metadata.type === "Route" && metadata.method === "continue" && metadata.params?.isFallback)
|
|
597
|
+
return null;
|
|
590
598
|
if (metadata.internal || metadata.method.startsWith("tracing"))
|
|
591
599
|
return null;
|
|
592
600
|
return {
|