brave-real-playwright-core 1.55.1-patch.1 → 1.56.0
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 +5 -5
- package/advanced-stealth.js +1 -1
- package/lib/browserServerImpl.js +3 -6
- package/lib/client/browser.js +0 -10
- package/lib/client/browserContext.js +2 -8
- package/lib/client/channelOwner.js +0 -7
- package/lib/client/consoleMessage.js +2 -3
- package/lib/client/electron.js +1 -1
- package/lib/client/events.js +1 -0
- package/lib/client/network.js +3 -0
- package/lib/client/page.js +13 -1
- package/lib/generated/bindingsControllerSource.js +1 -1
- package/lib/generated/injectedScriptSource.js +1 -1
- package/lib/generated/pollingRecorderSource.js +1 -1
- package/lib/generated/utilityScriptSource.js +1 -1
- package/lib/protocol/validator.js +26 -15
- package/lib/remote/playwrightServer.js +12 -14
- package/lib/server/bidi/bidiBrowser.js +54 -10
- package/lib/server/bidi/bidiChromium.js +1 -1
- package/lib/server/bidi/bidiConnection.js +31 -6
- package/lib/server/bidi/bidiExecutionContext.js +4 -4
- package/lib/server/bidi/bidiFirefox.js +16 -1
- package/lib/server/bidi/bidiNetworkManager.js +82 -16
- package/lib/server/bidi/bidiPage.js +84 -18
- package/lib/server/browserType.js +3 -3
- package/lib/server/chromium/chromium.js +1 -1
- package/lib/server/chromium/chromiumSwitches.js +3 -1
- package/lib/server/chromium/crBrowser.js +2 -33
- package/lib/server/chromium/crPage.js +22 -31
- package/lib/server/codegen/csharp.js +19 -26
- package/lib/server/codegen/java.js +4 -0
- package/lib/server/codegen/javascript.js +3 -1
- package/lib/server/codegen/python.js +2 -0
- package/lib/server/debugController.js +8 -36
- package/lib/server/deviceDescriptorsSource.json +62 -62
- package/lib/server/dispatchers/androidDispatcher.js +17 -0
- package/lib/server/dispatchers/browserContextDispatcher.js +1 -15
- package/lib/server/dispatchers/networkDispatchers.js +6 -3
- package/lib/server/dispatchers/pageDispatcher.js +24 -0
- package/lib/server/dom.js +8 -3
- package/lib/server/firefox/ffPage.js +1 -2
- package/lib/server/firefox/firefox.js +1 -1
- package/lib/server/frames.js +12 -4
- package/lib/server/har/harTracer.js +7 -8
- package/lib/server/network.js +12 -0
- package/lib/server/page.js +39 -17
- package/lib/server/recorder/chat.js +2 -2
- package/lib/server/recorder/recorderRunner.js +4 -0
- package/lib/server/registry/browserFetcher.js +3 -3
- package/lib/server/registry/index.js +27 -0
- package/lib/server/trace/recorder/snapshotter.js +13 -2
- package/lib/server/trace/recorder/snapshotterInjected.js +3 -1
- package/lib/server/utils/comparators.js +2 -2
- package/lib/server/utils/env.js +7 -2
- package/lib/server/utils/wsServer.js +2 -7
- package/lib/server/webkit/webkit.js +24 -8
- package/lib/server/webkit/wkBrowser.js +7 -3
- package/lib/server/webkit/wkPage.js +7 -8
- package/lib/server/webkit/wsl/webkit-wsl-transport-client.js +74 -0
- package/lib/server/webkit/wsl/webkit-wsl-transport-server.js +113 -0
- package/lib/utils/isomorphic/ariaSnapshot.js +12 -10
- package/lib/utils/isomorphic/protocolMetainfo.js +3 -0
- package/lib/utils/isomorphic/urlMatch.js +3 -8
- package/lib/utilsBundle.js +3 -0
- package/lib/utilsBundleImpl/index.js +80 -80
- package/lib/vite/htmlReport/index.html +37 -28
- package/lib/vite/recorder/assets/codeMirrorModule-RJCXzfmE.js +24 -0
- package/lib/vite/recorder/assets/index-Ri0uHF7I.css +1 -0
- package/lib/vite/recorder/assets/index-Y-X2TGJv.js +193 -0
- package/lib/vite/recorder/index.html +2 -2
- package/lib/vite/traceViewer/assets/codeMirrorModule-eyVcHN77.js +24 -0
- package/lib/vite/traceViewer/assets/defaultSettingsView-w0zYjHsW.js +265 -0
- package/lib/vite/traceViewer/assets/xtermModule-CsJ4vdCR.js +9 -0
- package/lib/vite/traceViewer/defaultSettingsView.TQ8_7ybu.css +1 -0
- package/lib/vite/traceViewer/index.Bx16ehp1.js +2 -0
- package/lib/vite/traceViewer/index.I8N9v4jT.css +1 -0
- package/lib/vite/traceViewer/index.html +4 -4
- package/lib/vite/traceViewer/sw.bundle.js +3 -3
- package/lib/vite/traceViewer/uiMode.Btcz36p_.css +1 -0
- package/lib/vite/traceViewer/uiMode.DRQ310U5.js +5 -0
- package/lib/vite/traceViewer/uiMode.html +4 -4
- package/lib/vite/traceViewer/{xtermModule.Beg8tuEN.css → xtermModule.DYP7pi_n.css} +1 -1
- package/package.json +9 -9
- package/lib/vite/recorder/assets/codeMirrorModule-DzQ0k89p.js +0 -24
- package/lib/vite/recorder/assets/index-CI4HQ-Zb.css +0 -1
- package/lib/vite/recorder/assets/index-D7C7daHH.js +0 -184
- package/lib/vite/traceViewer/assets/codeMirrorModule-CEFqZ5b3.js +0 -24
- package/lib/vite/traceViewer/assets/defaultSettingsView-BA25Usqk.js +0 -256
- package/lib/vite/traceViewer/assets/xtermModule-BoAIEibi.js +0 -9
- package/lib/vite/traceViewer/defaultSettingsView.DVJHpiGt.css +0 -1
- package/lib/vite/traceViewer/index.BFsek2M6.css +0 -1
- package/lib/vite/traceViewer/index.CheexZ4_.js +0 -2
- package/lib/vite/traceViewer/uiMode.BatfzHMG.css +0 -1
- package/lib/vite/traceViewer/uiMode.Dy4dnPNW.js +0 -5
|
@@ -103,6 +103,19 @@ class PageDispatcher extends import_dispatcher.Dispatcher {
|
|
|
103
103
|
page() {
|
|
104
104
|
return this._page;
|
|
105
105
|
}
|
|
106
|
+
serializeConsoleMessage(message) {
|
|
107
|
+
return {
|
|
108
|
+
type: message.type(),
|
|
109
|
+
text: message.text(),
|
|
110
|
+
args: message.args().map((a) => {
|
|
111
|
+
const elementHandle = a.asElement();
|
|
112
|
+
if (elementHandle)
|
|
113
|
+
return import_elementHandlerDispatcher.ElementHandleDispatcher.from(import_frameDispatcher.FrameDispatcher.from(this.parentScope(), elementHandle._frame), elementHandle);
|
|
114
|
+
return import_jsHandleDispatcher.JSHandleDispatcher.fromJSHandle(this, a);
|
|
115
|
+
}),
|
|
116
|
+
location: message.location()
|
|
117
|
+
};
|
|
118
|
+
}
|
|
106
119
|
async exposeBinding(params, progress) {
|
|
107
120
|
const binding = await this._page.exposeBinding(progress, params.name, !!params.needsHandle, (source, ...args) => {
|
|
108
121
|
if (this._disposed)
|
|
@@ -222,6 +235,13 @@ class PageDispatcher extends import_dispatcher.Dispatcher {
|
|
|
222
235
|
async keyboardPress(params, progress) {
|
|
223
236
|
await this._page.keyboard.press(progress, params.key, params);
|
|
224
237
|
}
|
|
238
|
+
async consoleMessages(params, progress) {
|
|
239
|
+
this._subscriptions.add("console");
|
|
240
|
+
return { messages: this._page.consoleMessages().map((message) => this.serializeConsoleMessage(message)) };
|
|
241
|
+
}
|
|
242
|
+
async pageErrors(params, progress) {
|
|
243
|
+
return { errors: this._page.pageErrors().map((error) => (0, import_errors.serializeError)(error)) };
|
|
244
|
+
}
|
|
225
245
|
async mouseMove(params, progress) {
|
|
226
246
|
progress.metadata.point = { x: params.x, y: params.y };
|
|
227
247
|
await this._page.mouse.move(progress, params.x, params.y, params);
|
|
@@ -258,6 +278,10 @@ class PageDispatcher extends import_dispatcher.Dispatcher {
|
|
|
258
278
|
const buffer = await progress.race(this._page.pdf(params));
|
|
259
279
|
return { pdf: buffer };
|
|
260
280
|
}
|
|
281
|
+
async requests(params, progress) {
|
|
282
|
+
this._subscriptions.add("request");
|
|
283
|
+
return { requests: this._page.networkRequests().map((request) => import_networkDispatchers.RequestDispatcher.from(this.parentScope(), request)) };
|
|
284
|
+
}
|
|
261
285
|
async snapshotForAI(params, progress) {
|
|
262
286
|
return { snapshot: await this._page.snapshotForAI(progress) };
|
|
263
287
|
}
|
package/lib/server/dom.js
CHANGED
|
@@ -84,6 +84,7 @@ class FrameExecutionContext extends js.ExecutionContext {
|
|
|
84
84
|
testIdAttributeName: selectorsRegistry.testIdAttributeName(),
|
|
85
85
|
stableRafCount: this.frame._page.delegate.rafCountForStablePosition(),
|
|
86
86
|
browserName: this.frame._page.browserContext._browser.options.name,
|
|
87
|
+
isUtilityWorld: this.world === "utility",
|
|
87
88
|
customEngines
|
|
88
89
|
};
|
|
89
90
|
const source = `
|
|
@@ -635,17 +636,21 @@ class ElementHandle extends js.JSHandle {
|
|
|
635
636
|
const result2 = await progress.race(this.evaluateInUtility(([injected, node]) => injected.elementState(node, "checked"), {}));
|
|
636
637
|
if (result2 === "error:notconnected" || result2.received === "error:notconnected")
|
|
637
638
|
throwElementIsNotAttached();
|
|
638
|
-
return result2.matches;
|
|
639
|
+
return { matches: result2.matches, isRadio: result2.isRadio };
|
|
639
640
|
};
|
|
640
641
|
await this._markAsTargetElement(progress);
|
|
641
|
-
|
|
642
|
+
const checkedState = await isChecked();
|
|
643
|
+
if (checkedState.matches === state)
|
|
642
644
|
return "done";
|
|
645
|
+
if (!state && checkedState.isRadio)
|
|
646
|
+
throw new NonRecoverableDOMError("Cannot uncheck radio button. Radio buttons can only be unchecked by selecting another radio button in the same group.");
|
|
643
647
|
const result = await this._click(progress, { ...options, waitAfter: "disabled" });
|
|
644
648
|
if (result !== "done")
|
|
645
649
|
return result;
|
|
646
650
|
if (options.trial)
|
|
647
651
|
return "done";
|
|
648
|
-
|
|
652
|
+
const finalState = await isChecked();
|
|
653
|
+
if (finalState.matches !== state)
|
|
649
654
|
throw new NonRecoverableDOMError("Clicking the checkbox did not change its state");
|
|
650
655
|
return "done";
|
|
651
656
|
}
|
|
@@ -44,7 +44,6 @@ var import_ffInput = require("./ffInput");
|
|
|
44
44
|
var import_ffNetworkManager = require("./ffNetworkManager");
|
|
45
45
|
var import_debugLogger = require("../utils/debugLogger");
|
|
46
46
|
var import_stackTrace = require("../../utils/isomorphic/stackTrace");
|
|
47
|
-
var import_browserContext = require("../browserContext");
|
|
48
47
|
var import_errors = require("../errors");
|
|
49
48
|
const UTILITY_WORLD_NAME = "__playwright_utility_world__";
|
|
50
49
|
class FFPage {
|
|
@@ -195,7 +194,7 @@ class FFPage {
|
|
|
195
194
|
const error = new Error(message);
|
|
196
195
|
error.stack = params.message + "\n" + params.stack.split("\n").filter(Boolean).map((a) => a.replace(/([^@]*)@(.*)/, " at $1 ($2)")).join("\n");
|
|
197
196
|
error.name = name;
|
|
198
|
-
this._page.
|
|
197
|
+
this._page.addPageError(error);
|
|
199
198
|
}
|
|
200
199
|
_onConsole(payload) {
|
|
201
200
|
const { type, args, executionContextId, location } = payload;
|
|
@@ -67,7 +67,7 @@ Workaround: Set the HOME=/root environment variable${process.env.GITHUB_ACTION ?
|
|
|
67
67
|
const message = { method: "Browser.close", params: {}, id: import_ffConnection.kBrowserCloseMessageId };
|
|
68
68
|
transport.send(message);
|
|
69
69
|
}
|
|
70
|
-
defaultArgs(options, isPersistent, userDataDir) {
|
|
70
|
+
async defaultArgs(options, isPersistent, userDataDir) {
|
|
71
71
|
const { args = [], headless } = options;
|
|
72
72
|
const userDataDirArg = args.find((arg) => arg.startsWith("-profile") || arg.startsWith("--profile"));
|
|
73
73
|
if (userDataDirArg)
|
package/lib/server/frames.js
CHANGED
|
@@ -231,6 +231,7 @@ class FrameManager {
|
|
|
231
231
|
});
|
|
232
232
|
return;
|
|
233
233
|
}
|
|
234
|
+
this._page.addNetworkRequest(request);
|
|
234
235
|
this._page.emitOnContext(import_browserContext.BrowserContext.Events.Request, request);
|
|
235
236
|
if (route)
|
|
236
237
|
new network.Route(request, route).handle([...this._page.requestInterceptors, ...this._page.browserContext.requestInterceptors]);
|
|
@@ -1180,11 +1181,15 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
1180
1181
|
fixupMetadataError(result);
|
|
1181
1182
|
return result;
|
|
1182
1183
|
} catch (e) {
|
|
1183
|
-
if (js.isJavaScriptErrorInEvaluate(e) || (0, import_selectorParser.isInvalidSelectorError)(e))
|
|
1184
|
-
throw e;
|
|
1185
1184
|
const result = { matches: options.isNot, log: (0, import_callLog.compressCallLog)(progress.metadata.log) };
|
|
1186
|
-
if (
|
|
1185
|
+
if ((0, import_selectorParser.isInvalidSelectorError)(e)) {
|
|
1186
|
+
result.errorMessage = "Error: " + e.message;
|
|
1187
|
+
} else if (js.isJavaScriptErrorInEvaluate(e)) {
|
|
1188
|
+
result.errorMessage = e.message;
|
|
1189
|
+
} else if (lastIntermediateResult.isSet) {
|
|
1187
1190
|
result.received = lastIntermediateResult.received;
|
|
1191
|
+
result.errorMessage = lastIntermediateResult.errorMessage;
|
|
1192
|
+
}
|
|
1188
1193
|
if (e instanceof import_errors.TimeoutError)
|
|
1189
1194
|
result.timedOut = true;
|
|
1190
1195
|
fixupMetadataError(result);
|
|
@@ -1215,7 +1220,10 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
1215
1220
|
if (log)
|
|
1216
1221
|
progress.log(log);
|
|
1217
1222
|
if (matches === options.isNot) {
|
|
1218
|
-
|
|
1223
|
+
if (missingReceived)
|
|
1224
|
+
lastIntermediateResult.errorMessage = "Error: element(s) not found";
|
|
1225
|
+
else
|
|
1226
|
+
lastIntermediateResult.received = received;
|
|
1219
1227
|
lastIntermediateResult.isSet = true;
|
|
1220
1228
|
if (!missingReceived && !Array.isArray(received))
|
|
1221
1229
|
progress.log(` unexpected value "${renderUnexpectedValue(options.expression, received)}"`);
|
|
@@ -165,7 +165,7 @@ class HarTracer {
|
|
|
165
165
|
_onAPIRequest(event) {
|
|
166
166
|
if (!this._shouldIncludeEntryWithUrl(event.url.toString()))
|
|
167
167
|
return;
|
|
168
|
-
const harEntry = createHarEntry(event.method, event.url, void 0, this._options);
|
|
168
|
+
const harEntry = createHarEntry(void 0, event.method, event.url, void 0, this._options);
|
|
169
169
|
harEntry._apiRequest = true;
|
|
170
170
|
if (!this._options.omitCookies)
|
|
171
171
|
harEntry.request.cookies = event.cookies;
|
|
@@ -227,9 +227,7 @@ class HarTracer {
|
|
|
227
227
|
if (!url)
|
|
228
228
|
return;
|
|
229
229
|
const pageEntry = this._createPageEntryIfNeeded(page);
|
|
230
|
-
const harEntry = createHarEntry(request.method(), url, request.frame()?.guid, this._options);
|
|
231
|
-
if (pageEntry)
|
|
232
|
-
harEntry.pageref = pageEntry.id;
|
|
230
|
+
const harEntry = createHarEntry(pageEntry?.id, request.method(), url, request.frame()?.guid, this._options);
|
|
233
231
|
this._recordRequestHeadersAndCookies(harEntry, request.headers());
|
|
234
232
|
harEntry.request.postData = this._postDataForRequest(request, this._options.content);
|
|
235
233
|
if (!this._options.omitSizes)
|
|
@@ -522,10 +520,9 @@ class HarTracer {
|
|
|
522
520
|
return result;
|
|
523
521
|
}
|
|
524
522
|
}
|
|
525
|
-
function createHarEntry(method, url, frameref, options) {
|
|
523
|
+
function createHarEntry(pageRef, method, url, frameref, options) {
|
|
526
524
|
const harEntry = {
|
|
527
|
-
|
|
528
|
-
_monotonicTime: options.includeTraceInfo ? (0, import_utils.monotonicTime)() : void 0,
|
|
525
|
+
pageref: pageRef,
|
|
529
526
|
startedDateTime: (/* @__PURE__ */ new Date()).toISOString(),
|
|
530
527
|
time: -1,
|
|
531
528
|
request: {
|
|
@@ -558,7 +555,9 @@ function createHarEntry(method, url, frameref, options) {
|
|
|
558
555
|
send: -1,
|
|
559
556
|
wait: -1,
|
|
560
557
|
receive: -1
|
|
561
|
-
}
|
|
558
|
+
},
|
|
559
|
+
_frameref: options.includeTraceInfo ? frameref : void 0,
|
|
560
|
+
_monotonicTime: options.includeTraceInfo ? (0, import_utils.monotonicTime)() : void 0
|
|
562
561
|
};
|
|
563
562
|
return harEntry;
|
|
564
563
|
}
|
package/lib/server/network.js
CHANGED
|
@@ -121,6 +121,11 @@ class Request extends import_instrumentation.SdkObject {
|
|
|
121
121
|
this._updateHeadersMap();
|
|
122
122
|
this._isFavicon = url.endsWith("/favicon.ico") || !!redirectedFrom?._isFavicon;
|
|
123
123
|
}
|
|
124
|
+
static {
|
|
125
|
+
this.Events = {
|
|
126
|
+
Response: "response"
|
|
127
|
+
};
|
|
128
|
+
}
|
|
124
129
|
_setFailureText(failureText) {
|
|
125
130
|
this._failureText = failureText;
|
|
126
131
|
this._waitForResponsePromise.resolve(null);
|
|
@@ -172,6 +177,7 @@ class Request extends import_instrumentation.SdkObject {
|
|
|
172
177
|
_setResponse(response) {
|
|
173
178
|
this._response = response;
|
|
174
179
|
this._waitForResponsePromise.resolve(response);
|
|
180
|
+
this.emit(Request.Events.Response, response);
|
|
175
181
|
}
|
|
176
182
|
_finalRequest() {
|
|
177
183
|
return this._redirectedTo ? this._redirectedTo._finalRequest() : this;
|
|
@@ -264,6 +270,8 @@ class Route extends import_instrumentation.SdkObject {
|
|
|
264
270
|
body = "";
|
|
265
271
|
isBase64 = false;
|
|
266
272
|
}
|
|
273
|
+
} else if (!overrides.status || overrides.status < 200 || overrides.status >= 400) {
|
|
274
|
+
this._request._responseBodyOverride = { body, isBase64 };
|
|
267
275
|
}
|
|
268
276
|
const headers = [...overrides.headers || []];
|
|
269
277
|
this._maybeAddCorsHeaders(headers);
|
|
@@ -416,6 +424,10 @@ class Response extends import_instrumentation.SdkObject {
|
|
|
416
424
|
this._contentPromise = this._finishedPromise.then(async () => {
|
|
417
425
|
if (this._status >= 300 && this._status <= 399)
|
|
418
426
|
throw new Error("Response body is unavailable for redirect responses");
|
|
427
|
+
if (this._request._responseBodyOverride) {
|
|
428
|
+
const { body, isBase64 } = this._request._responseBodyOverride;
|
|
429
|
+
return Buffer.from(body, isBase64 ? "base64" : "utf-8");
|
|
430
|
+
}
|
|
419
431
|
return this._getResponseBodyCallback();
|
|
420
432
|
});
|
|
421
433
|
}
|
package/lib/server/page.js
CHANGED
|
@@ -60,7 +60,8 @@ class Page extends import_instrumentation.SdkObject {
|
|
|
60
60
|
this._closedState = "open";
|
|
61
61
|
this._closedPromise = new import_manualPromise.ManualPromise();
|
|
62
62
|
this._initializedPromise = new import_manualPromise.ManualPromise();
|
|
63
|
-
this.
|
|
63
|
+
this._consoleMessages = [];
|
|
64
|
+
this._pageErrors = [];
|
|
64
65
|
this._crashed = false;
|
|
65
66
|
this.openScope = new import_utils.LongStandingScope();
|
|
66
67
|
this._emulatedMedia = {};
|
|
@@ -73,6 +74,7 @@ class Page extends import_instrumentation.SdkObject {
|
|
|
73
74
|
this._locatorHandlers = /* @__PURE__ */ new Map();
|
|
74
75
|
this._lastLocatorHandlerUid = 0;
|
|
75
76
|
this._locatorHandlerRunningCounter = 0;
|
|
77
|
+
this._networkRequests = [];
|
|
76
78
|
// Aiming at 25 fps by default - each frame is 40ms, but we give some slack with 35ms.
|
|
77
79
|
// When throttling for tracing, 200ms between frames, except for 10 frames around the action.
|
|
78
80
|
this._frameThrottler = new FrameThrottler(10, 35, 200);
|
|
@@ -108,25 +110,26 @@ class Page extends import_instrumentation.SdkObject {
|
|
|
108
110
|
Worker: "worker"
|
|
109
111
|
};
|
|
110
112
|
}
|
|
111
|
-
async reportAsNew(opener, error
|
|
113
|
+
async reportAsNew(opener, error) {
|
|
112
114
|
if (opener) {
|
|
113
115
|
const openerPageOrError = await opener.waitForInitializedOrError();
|
|
114
116
|
if (openerPageOrError instanceof Page && !openerPageOrError.isClosed())
|
|
115
117
|
this._opener = openerPageOrError;
|
|
116
118
|
}
|
|
117
|
-
this._markInitialized(error
|
|
119
|
+
this._markInitialized(error);
|
|
118
120
|
}
|
|
119
|
-
_markInitialized(error = void 0
|
|
121
|
+
_markInitialized(error = void 0) {
|
|
120
122
|
if (error) {
|
|
121
123
|
if (this.browserContext.isClosingOrClosed())
|
|
122
124
|
return;
|
|
123
125
|
this.frameManager.createDummyMainFrameIfNeeded();
|
|
124
126
|
}
|
|
125
127
|
this._initialized = error || this;
|
|
126
|
-
this.emitOnContext(
|
|
127
|
-
for (const
|
|
128
|
-
this.
|
|
129
|
-
this.
|
|
128
|
+
this.emitOnContext(import_browserContext.BrowserContext.Events.Page, this);
|
|
129
|
+
for (const pageError of this._pageErrors)
|
|
130
|
+
this.emitOnContext(import_browserContext.BrowserContext.Events.PageError, pageError, this);
|
|
131
|
+
for (const message of this._consoleMessages)
|
|
132
|
+
this.emitOnContext(import_browserContext.BrowserContext.Events.Console, message);
|
|
130
133
|
if (this.isClosed())
|
|
131
134
|
this.emit(Page.Events.Close);
|
|
132
135
|
else
|
|
@@ -144,14 +147,6 @@ class Page extends import_instrumentation.SdkObject {
|
|
|
144
147
|
return;
|
|
145
148
|
this.browserContext.emit(event, ...args);
|
|
146
149
|
}
|
|
147
|
-
emitOnContextOnceInitialized(event, ...args) {
|
|
148
|
-
if (this.isStorageStatePage)
|
|
149
|
-
return;
|
|
150
|
-
if (this._initialized)
|
|
151
|
-
this.browserContext.emit(event, ...args);
|
|
152
|
-
else
|
|
153
|
-
this._eventsToEmitAfterInitialized.push({ event, args });
|
|
154
|
-
}
|
|
155
150
|
async resetForReuse(progress) {
|
|
156
151
|
await this.mainFrame().gotoImpl(progress, "about:blank", {});
|
|
157
152
|
this._emulatedSize = void 0;
|
|
@@ -246,6 +241,13 @@ class Page extends import_instrumentation.SdkObject {
|
|
|
246
241
|
extraHTTPHeaders() {
|
|
247
242
|
return this._extraHTTPHeaders;
|
|
248
243
|
}
|
|
244
|
+
addNetworkRequest(request) {
|
|
245
|
+
this._networkRequests.push(request);
|
|
246
|
+
ensureArrayLimit(this._networkRequests, 100);
|
|
247
|
+
}
|
|
248
|
+
networkRequests() {
|
|
249
|
+
return this._networkRequests;
|
|
250
|
+
}
|
|
249
251
|
async onBindingCalled(payload, context) {
|
|
250
252
|
if (this._closedState === "closed")
|
|
251
253
|
return;
|
|
@@ -258,7 +260,22 @@ class Page extends import_instrumentation.SdkObject {
|
|
|
258
260
|
args.forEach((arg) => arg.dispose());
|
|
259
261
|
return;
|
|
260
262
|
}
|
|
261
|
-
this.
|
|
263
|
+
this._consoleMessages.push(message);
|
|
264
|
+
ensureArrayLimit(this._consoleMessages, 200);
|
|
265
|
+
if (this._initialized)
|
|
266
|
+
this.emitOnContext(import_browserContext.BrowserContext.Events.Console, message);
|
|
267
|
+
}
|
|
268
|
+
consoleMessages() {
|
|
269
|
+
return this._consoleMessages;
|
|
270
|
+
}
|
|
271
|
+
addPageError(pageError) {
|
|
272
|
+
this._pageErrors.push(pageError);
|
|
273
|
+
ensureArrayLimit(this._pageErrors, 200);
|
|
274
|
+
if (this._initialized)
|
|
275
|
+
this.emitOnContext(import_browserContext.BrowserContext.Events.PageError, pageError, this);
|
|
276
|
+
}
|
|
277
|
+
pageErrors() {
|
|
278
|
+
return this._pageErrors;
|
|
262
279
|
}
|
|
263
280
|
async reload(progress, options) {
|
|
264
281
|
return this.mainFrame().raceNavigationAction(progress, async () => {
|
|
@@ -853,6 +870,11 @@ async function snapshotFrameForAI(progress, frame, frameOrdinal, frameIds) {
|
|
|
853
870
|
}
|
|
854
871
|
return result;
|
|
855
872
|
}
|
|
873
|
+
function ensureArrayLimit(array, limit) {
|
|
874
|
+
if (array.length > limit)
|
|
875
|
+
return array.splice(0, limit / 10);
|
|
876
|
+
return [];
|
|
877
|
+
}
|
|
856
878
|
// Annotate the CommonJS export names for ESM import in node:
|
|
857
879
|
0 && (module.exports = {
|
|
858
880
|
InitScript,
|
|
@@ -85,7 +85,7 @@ async function asString(stream) {
|
|
|
85
85
|
function iterablePump() {
|
|
86
86
|
let controller;
|
|
87
87
|
const stream = new ReadableStream({ start: (c) => controller = c });
|
|
88
|
-
const iterable = async function* () {
|
|
88
|
+
const iterable = (async function* () {
|
|
89
89
|
const reader = stream.getReader();
|
|
90
90
|
while (true) {
|
|
91
91
|
const { done, value } = await reader.read();
|
|
@@ -93,7 +93,7 @@ function iterablePump() {
|
|
|
93
93
|
break;
|
|
94
94
|
yield value;
|
|
95
95
|
}
|
|
96
|
-
}();
|
|
96
|
+
})();
|
|
97
97
|
return {
|
|
98
98
|
iterable,
|
|
99
99
|
addChunk: (chunk) => {
|
|
@@ -50,6 +50,10 @@ async function performActionImpl(progress, mainFrame, actionInContext) {
|
|
|
50
50
|
await mainFrame.click(progress, selector, { ...options, strict: true });
|
|
51
51
|
return;
|
|
52
52
|
}
|
|
53
|
+
if (action.name === "hover") {
|
|
54
|
+
await mainFrame.hover(progress, selector, { position: action.position, strict: true });
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
53
57
|
if (action.name === "press") {
|
|
54
58
|
const modifiers = (0, import_language.toKeyboardModifiers)(action.modifiers);
|
|
55
59
|
const shortcut = [...modifiers, action.key].join("+");
|
|
@@ -47,7 +47,8 @@ async function downloadBrowserWithProgressBar(title, browserDirectory, executabl
|
|
|
47
47
|
import_debugLogger.debugLogger.log("install", `${title} is already downloaded.`);
|
|
48
48
|
return false;
|
|
49
49
|
}
|
|
50
|
-
const
|
|
50
|
+
const uniqueTempDir = await import_fs.default.promises.mkdtemp(import_path.default.join(import_os.default.tmpdir(), "playwright-download-"));
|
|
51
|
+
const zipPath = import_path.default.join(uniqueTempDir, downloadFileName);
|
|
51
52
|
try {
|
|
52
53
|
const retryCount = 5;
|
|
53
54
|
for (let attempt = 1; attempt <= retryCount; ++attempt) {
|
|
@@ -73,8 +74,7 @@ async function downloadBrowserWithProgressBar(title, browserDirectory, executabl
|
|
|
73
74
|
process.exitCode = 1;
|
|
74
75
|
throw e;
|
|
75
76
|
} finally {
|
|
76
|
-
|
|
77
|
-
await import_fs.default.promises.unlink(zipPath);
|
|
77
|
+
await (0, import_fileUtils.removeFolders)([uniqueTempDir]);
|
|
78
78
|
}
|
|
79
79
|
logPolitely(`${title} downloaded to ${browserDirectory}`);
|
|
80
80
|
return true;
|
|
@@ -749,6 +749,33 @@ ${(0, import_ascii.wrapInASCIIBox)(prettyMessage, 1)}`);
|
|
|
749
749
|
_dependencyGroup: "webkit",
|
|
750
750
|
_isHermeticInstallation: true
|
|
751
751
|
});
|
|
752
|
+
this._executables.push({
|
|
753
|
+
type: "channel",
|
|
754
|
+
name: "webkit-wsl",
|
|
755
|
+
browserName: "webkit",
|
|
756
|
+
directory: webkit.dir,
|
|
757
|
+
executablePath: () => process.execPath,
|
|
758
|
+
executablePathOrDie: () => process.execPath,
|
|
759
|
+
wslExecutablePath: `/home/pwuser/.cache/ms-playwright/webkit-${webkit.revision}/pw_run.sh`,
|
|
760
|
+
installType: "download-on-demand",
|
|
761
|
+
_validateHostRequirements: (sdkLanguage) => Promise.resolve(),
|
|
762
|
+
_isHermeticInstallation: true,
|
|
763
|
+
_install: async () => {
|
|
764
|
+
if (process.platform !== "win32")
|
|
765
|
+
throw new Error(`WebKit via WSL is only supported on Windows`);
|
|
766
|
+
const script = import_path.default.join(BIN_PATH, "install_webkit_wsl.ps1");
|
|
767
|
+
const { code } = await (0, import_spawnAsync.spawnAsync)("powershell.exe", [
|
|
768
|
+
"-ExecutionPolicy",
|
|
769
|
+
"Bypass",
|
|
770
|
+
"-File",
|
|
771
|
+
script
|
|
772
|
+
], {
|
|
773
|
+
stdio: "inherit"
|
|
774
|
+
});
|
|
775
|
+
if (code !== 0)
|
|
776
|
+
throw new Error(`Failed to install WebKit via WSL`);
|
|
777
|
+
}
|
|
778
|
+
});
|
|
752
779
|
const ffmpeg = descriptors.find((d) => d.name === "ffmpeg");
|
|
753
780
|
const ffmpegExecutable = findExecutablePath(ffmpeg.dir, "ffmpeg");
|
|
754
781
|
this._executables.push({
|
|
@@ -75,10 +75,20 @@ class Snapshotter {
|
|
|
75
75
|
dispose() {
|
|
76
76
|
import_eventsHelper.eventsHelper.removeEventListeners(this._eventListeners);
|
|
77
77
|
}
|
|
78
|
+
async _captureFrameSnapshot(frame) {
|
|
79
|
+
const needsReset = !!frame[kNeedsResetSymbol];
|
|
80
|
+
frame[kNeedsResetSymbol] = false;
|
|
81
|
+
const expression = `window["${this._snapshotStreamer}"].captureSnapshot(${needsReset ? "true" : "false"})`;
|
|
82
|
+
try {
|
|
83
|
+
return await frame.nonStallingRawEvaluateInExistingMainContext(expression);
|
|
84
|
+
} catch (e) {
|
|
85
|
+
frame[kNeedsResetSymbol] = true;
|
|
86
|
+
import_debugLogger.debugLogger.log("error", e);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
78
89
|
async captureSnapshot(page, callId, snapshotName) {
|
|
79
|
-
const expression = `window["${this._snapshotStreamer}"].captureSnapshot(${JSON.stringify(snapshotName)})`;
|
|
80
90
|
const snapshots = page.frames().map(async (frame) => {
|
|
81
|
-
const data = await
|
|
91
|
+
const data = await this._captureFrameSnapshot(frame);
|
|
82
92
|
if (!data || !this._started)
|
|
83
93
|
return;
|
|
84
94
|
const snapshot = {
|
|
@@ -130,6 +140,7 @@ class Snapshotter {
|
|
|
130
140
|
}
|
|
131
141
|
}
|
|
132
142
|
}
|
|
143
|
+
const kNeedsResetSymbol = Symbol("kNeedsReset");
|
|
133
144
|
// Annotate the CommonJS export names for ESM import in node:
|
|
134
145
|
0 && (module.exports = {
|
|
135
146
|
Snapshotter
|
|
@@ -256,9 +256,11 @@ function frameSnapshotStreamer(snapshotStreamer, removeNoScript) {
|
|
|
256
256
|
this._readingStyleSheet = false;
|
|
257
257
|
}
|
|
258
258
|
}
|
|
259
|
-
captureSnapshot() {
|
|
259
|
+
captureSnapshot(needsReset) {
|
|
260
260
|
const timestamp = performance.now();
|
|
261
261
|
const snapshotNumber = ++this._lastSnapshotNumber;
|
|
262
|
+
if (needsReset)
|
|
263
|
+
this.reset();
|
|
262
264
|
let nodeCounter = 0;
|
|
263
265
|
let shadowDomNesting = 0;
|
|
264
266
|
let headNesting = 0;
|
|
@@ -101,11 +101,11 @@ function validateBuffer(buffer, mimeType) {
|
|
|
101
101
|
if (mimeType === "image/png") {
|
|
102
102
|
const pngMagicNumber = [137, 80, 78, 71, 13, 10, 26, 10];
|
|
103
103
|
if (buffer.length < pngMagicNumber.length || !pngMagicNumber.every((byte, index) => buffer[index] === byte))
|
|
104
|
-
throw new Error("
|
|
104
|
+
throw new Error("Could not decode expected image as PNG.");
|
|
105
105
|
} else if (mimeType === "image/jpeg") {
|
|
106
106
|
const jpegMagicNumber = [255, 216];
|
|
107
107
|
if (buffer.length < jpegMagicNumber.length || !jpegMagicNumber.every((byte, index) => buffer[index] === byte))
|
|
108
|
-
throw new Error("
|
|
108
|
+
throw new Error("Could not decode expected image as JPEG.");
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
111
|
function compareText(actual, expectedBuffer) {
|
package/lib/server/utils/env.js
CHANGED
|
@@ -22,7 +22,8 @@ __export(env_exports, {
|
|
|
22
22
|
getFromENV: () => getFromENV,
|
|
23
23
|
getPackageManager: () => getPackageManager,
|
|
24
24
|
getPackageManagerExecCommand: () => getPackageManagerExecCommand,
|
|
25
|
-
isLikelyNpxGlobal: () => isLikelyNpxGlobal
|
|
25
|
+
isLikelyNpxGlobal: () => isLikelyNpxGlobal,
|
|
26
|
+
setPlaywrightTestProcessEnv: () => setPlaywrightTestProcessEnv
|
|
26
27
|
});
|
|
27
28
|
module.exports = __toCommonJS(env_exports);
|
|
28
29
|
function getFromENV(name) {
|
|
@@ -58,11 +59,15 @@ function getPackageManagerExecCommand() {
|
|
|
58
59
|
function isLikelyNpxGlobal() {
|
|
59
60
|
return process.argv.length >= 2 && process.argv[1].includes("_npx");
|
|
60
61
|
}
|
|
62
|
+
function setPlaywrightTestProcessEnv() {
|
|
63
|
+
return process.env["PLAYWRIGHT_TEST"] = "1";
|
|
64
|
+
}
|
|
61
65
|
// Annotate the CommonJS export names for ESM import in node:
|
|
62
66
|
0 && (module.exports = {
|
|
63
67
|
getAsBooleanFromENV,
|
|
64
68
|
getFromENV,
|
|
65
69
|
getPackageManager,
|
|
66
70
|
getPackageManagerExecCommand,
|
|
67
|
-
isLikelyNpxGlobal
|
|
71
|
+
isLikelyNpxGlobal,
|
|
72
|
+
setPlaywrightTestProcessEnv
|
|
68
73
|
});
|
|
@@ -85,13 +85,8 @@ class WSServer {
|
|
|
85
85
|
const url = new URL("http://localhost" + (request.url || ""));
|
|
86
86
|
const id = String(++lastConnectionId);
|
|
87
87
|
import_debugLogger.debugLogger.log("server", `[${id}] serving connection: ${request.url}`);
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
ws[kConnectionSymbol] = connection;
|
|
91
|
-
} catch (error) {
|
|
92
|
-
import_debugLogger.debugLogger.log("server", `[${id}] connection error: ${error}`);
|
|
93
|
-
ws.close(1011, String(error));
|
|
94
|
-
}
|
|
88
|
+
const connection = this._delegate.onConnection(request, url, ws, id);
|
|
89
|
+
ws[kConnectionSymbol] = connection;
|
|
95
90
|
});
|
|
96
91
|
return wsEndpoint;
|
|
97
92
|
}
|
|
@@ -28,7 +28,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
28
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
29
|
var webkit_exports = {};
|
|
30
30
|
__export(webkit_exports, {
|
|
31
|
-
WebKit: () => WebKit
|
|
31
|
+
WebKit: () => WebKit,
|
|
32
|
+
translatePathToWSL: () => translatePathToWSL
|
|
32
33
|
});
|
|
33
34
|
module.exports = __toCommonJS(webkit_exports);
|
|
34
35
|
var import_path = __toESM(require("path"));
|
|
@@ -36,6 +37,8 @@ var import_wkConnection = require("./wkConnection");
|
|
|
36
37
|
var import_ascii = require("../utils/ascii");
|
|
37
38
|
var import_browserType = require("../browserType");
|
|
38
39
|
var import_wkBrowser = require("../webkit/wkBrowser");
|
|
40
|
+
var import_spawnAsync = require("../utils/spawnAsync");
|
|
41
|
+
var import_registry = require("../registry");
|
|
39
42
|
class WebKit extends import_browserType.BrowserType {
|
|
40
43
|
constructor(parent) {
|
|
41
44
|
super(parent, "webkit");
|
|
@@ -43,10 +46,11 @@ class WebKit extends import_browserType.BrowserType {
|
|
|
43
46
|
connectToTransport(transport, options) {
|
|
44
47
|
return import_wkBrowser.WKBrowser.connect(this.attribution.playwright, transport, options);
|
|
45
48
|
}
|
|
46
|
-
amendEnvironment(env, userDataDir, isPersistent) {
|
|
49
|
+
amendEnvironment(env, userDataDir, isPersistent, options) {
|
|
47
50
|
return {
|
|
48
51
|
...env,
|
|
49
|
-
CURL_COOKIE_JAR_PATH: process.platform === "win32" && isPersistent ? import_path.default.join(userDataDir, "cookiejar.db") : void 0
|
|
52
|
+
CURL_COOKIE_JAR_PATH: process.platform === "win32" && isPersistent ? import_path.default.join(userDataDir, "cookiejar.db") : void 0,
|
|
53
|
+
WEBKIT_EXECUTABLE: options.channel === "webkit-wsl" ? import_registry.registry.findExecutable("webkit-wsl").wslExecutablePath : void 0
|
|
50
54
|
};
|
|
51
55
|
}
|
|
52
56
|
doRewriteStartupLog(error) {
|
|
@@ -59,7 +63,7 @@ class WebKit extends import_browserType.BrowserType {
|
|
|
59
63
|
attemptToGracefullyCloseBrowser(transport) {
|
|
60
64
|
transport.send({ method: "Playwright.close", params: {}, id: import_wkConnection.kBrowserCloseMessageId });
|
|
61
65
|
}
|
|
62
|
-
defaultArgs(options, isPersistent, userDataDir) {
|
|
66
|
+
async defaultArgs(options, isPersistent, userDataDir) {
|
|
63
67
|
const { args = [], headless } = options;
|
|
64
68
|
const userDataDirArg = args.find((arg) => arg.startsWith("--user-data-dir"));
|
|
65
69
|
if (userDataDirArg)
|
|
@@ -67,12 +71,19 @@ class WebKit extends import_browserType.BrowserType {
|
|
|
67
71
|
if (args.find((arg) => !arg.startsWith("-")))
|
|
68
72
|
throw new Error("Arguments can not specify page to be opened");
|
|
69
73
|
const webkitArguments = ["--inspector-pipe"];
|
|
70
|
-
if (
|
|
74
|
+
if (options.channel === "webkit-wsl") {
|
|
75
|
+
if (options.executablePath)
|
|
76
|
+
throw new Error('Cannot specify executablePath when using the "webkit-wsl" channel.');
|
|
77
|
+
webkitArguments.unshift(
|
|
78
|
+
import_path.default.join(__dirname, "wsl/webkit-wsl-transport-server.js")
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
if (process.platform === "win32" && options.channel !== "webkit-wsl")
|
|
71
82
|
webkitArguments.push("--disable-accelerated-compositing");
|
|
72
83
|
if (headless)
|
|
73
84
|
webkitArguments.push("--headless");
|
|
74
85
|
if (isPersistent)
|
|
75
|
-
webkitArguments.push(`--user-data-dir=${userDataDir}`);
|
|
86
|
+
webkitArguments.push(`--user-data-dir=${options.channel === "webkit-wsl" ? await translatePathToWSL(userDataDir) : userDataDir}`);
|
|
76
87
|
else
|
|
77
88
|
webkitArguments.push(`--no-startup-window`);
|
|
78
89
|
const proxy = options.proxyOverride || options.proxy;
|
|
@@ -81,7 +92,7 @@ class WebKit extends import_browserType.BrowserType {
|
|
|
81
92
|
webkitArguments.push(`--proxy=${proxy.server}`);
|
|
82
93
|
if (proxy.bypass)
|
|
83
94
|
webkitArguments.push(`--proxy-bypass-list=${proxy.bypass}`);
|
|
84
|
-
} else if (process.platform === "linux") {
|
|
95
|
+
} else if (process.platform === "linux" || process.platform === "win32" && options.channel === "webkit-wsl") {
|
|
85
96
|
webkitArguments.push(`--proxy=${proxy.server}`);
|
|
86
97
|
if (proxy.bypass)
|
|
87
98
|
webkitArguments.push(...proxy.bypass.split(",").map((t) => `--ignore-host=${t}`));
|
|
@@ -97,7 +108,12 @@ class WebKit extends import_browserType.BrowserType {
|
|
|
97
108
|
return webkitArguments;
|
|
98
109
|
}
|
|
99
110
|
}
|
|
111
|
+
async function translatePathToWSL(path2) {
|
|
112
|
+
const { stdout } = await (0, import_spawnAsync.spawnAsync)("wsl.exe", ["-d", "playwright", "--cd", "/home/pwuser", "wslpath", path2.replace(/\\/g, "\\\\")]);
|
|
113
|
+
return stdout.toString().trim();
|
|
114
|
+
}
|
|
100
115
|
// Annotate the CommonJS export names for ESM import in node:
|
|
101
116
|
0 && (module.exports = {
|
|
102
|
-
WebKit
|
|
117
|
+
WebKit,
|
|
118
|
+
translatePathToWSL
|
|
103
119
|
});
|
|
@@ -39,6 +39,7 @@ var network = __toESM(require("../network"));
|
|
|
39
39
|
var import_wkConnection = require("./wkConnection");
|
|
40
40
|
var import_wkPage = require("./wkPage");
|
|
41
41
|
var import_errors = require("../errors");
|
|
42
|
+
var import_webkit = require("./webkit");
|
|
42
43
|
const BROWSER_VERSION = "26.0";
|
|
43
44
|
const DEFAULT_USER_AGENT = `Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/${BROWSER_VERSION} Safari/605.1.15`;
|
|
44
45
|
class WKBrowser extends import_browser.Browser {
|
|
@@ -87,7 +88,7 @@ class WKBrowser extends import_browser.Browser {
|
|
|
87
88
|
const createOptions = proxy ? {
|
|
88
89
|
// Enable socks5 hostname resolution on Windows.
|
|
89
90
|
// See https://github.com/microsoft/playwright/issues/20451
|
|
90
|
-
proxyServer: process.platform === "win32" ? proxy.server.replace(/^socks5:\/\//, "socks5h://") : proxy.server,
|
|
91
|
+
proxyServer: process.platform === "win32" && this.attribution.browser?.options.channel !== "webkit-wsl" ? proxy.server.replace(/^socks5:\/\//, "socks5h://") : proxy.server,
|
|
91
92
|
proxyBypassList: proxy.bypass
|
|
92
93
|
} : void 0;
|
|
93
94
|
const { browserContextId } = await this._browserSession.send("Playwright.createContext", createOptions);
|
|
@@ -110,7 +111,10 @@ class WKBrowser extends import_browser.Browser {
|
|
|
110
111
|
const page = this._wkPages.get(payload.pageProxyId);
|
|
111
112
|
if (!page)
|
|
112
113
|
return;
|
|
113
|
-
|
|
114
|
+
let frameId = payload.frameId;
|
|
115
|
+
if (!page._page.frameManager.frame(frameId))
|
|
116
|
+
frameId = page._page.mainFrame()._id;
|
|
117
|
+
page._page.frameManager.frameAbortedNavigation(frameId, "Download is starting");
|
|
114
118
|
let originPage = page._page.initializedOrUndefined();
|
|
115
119
|
if (!originPage) {
|
|
116
120
|
page._firstNonInitialNavigationCommittedReject(new Error("Starting new page download"));
|
|
@@ -189,7 +193,7 @@ class WKBrowserContext extends import_browserContext.BrowserContext {
|
|
|
189
193
|
const promises = [super._initialize()];
|
|
190
194
|
promises.push(this._browser._browserSession.send("Playwright.setDownloadBehavior", {
|
|
191
195
|
behavior: this._options.acceptDownloads === "accept" ? "allow" : "deny",
|
|
192
|
-
downloadPath: this._browser.options.downloadsPath,
|
|
196
|
+
downloadPath: this._browser.options.channel === "webkit-wsl" ? await (0, import_webkit.translatePathToWSL)(this._browser.options.downloadsPath) : this._browser.options.downloadsPath,
|
|
193
197
|
browserContextId
|
|
194
198
|
}));
|
|
195
199
|
if (this._options.ignoreHTTPSErrors || this._options.internalIgnoreHTTPSErrors)
|