patchright-core 1.52.4 → 1.55.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/ThirdPartyNotices.txt +65 -123
- package/bin/reinstall_chrome_beta_mac.sh +1 -1
- package/bin/reinstall_chrome_stable_mac.sh +1 -1
- package/bin/reinstall_msedge_beta_mac.sh +1 -1
- package/bin/reinstall_msedge_dev_mac.sh +1 -1
- package/bin/reinstall_msedge_stable_mac.sh +1 -1
- package/browsers.json +14 -14
- package/index.js +1 -1
- package/lib/androidServerImpl.js +4 -2
- package/lib/browserServerImpl.js +47 -12
- package/lib/cli/program.js +116 -50
- package/lib/cli/programWithTestStub.js +1 -1
- package/lib/client/android.js +30 -34
- package/lib/client/browser.js +54 -17
- package/lib/client/browserContext.js +67 -71
- package/lib/client/browserType.js +25 -34
- package/lib/client/channelOwner.js +20 -24
- package/lib/client/connection.js +6 -10
- package/lib/client/electron.js +8 -3
- package/lib/client/elementHandle.js +18 -21
- package/lib/client/fetch.js +5 -3
- package/lib/client/frame.js +57 -35
- package/lib/client/input.js +3 -1
- package/lib/client/jsHandle.js +4 -0
- package/lib/client/localUtils.js +0 -1
- package/lib/client/locator.js +32 -28
- package/lib/client/network.js +5 -12
- package/lib/client/page.js +32 -32
- package/lib/client/playwright.js +6 -16
- package/lib/client/selectors.js +18 -38
- package/lib/client/timeoutSettings.js +12 -8
- package/lib/client/tracing.js +24 -20
- package/lib/client/waiter.js +2 -2
- package/lib/client/webSocket.js +4 -22
- package/lib/generated/bindingsControllerSource.js +28 -0
- package/lib/generated/clockSource.js +1 -1
- package/lib/generated/injectedScriptSource.js +1 -1
- package/lib/generated/pollingRecorderSource.js +1 -1
- package/lib/generated/storageScriptSource.js +28 -0
- package/lib/generated/utilityScriptSource.js +1 -1
- package/lib/generated/webSocketMockSource.js +12 -50
- package/lib/inProcessFactory.js +9 -6
- package/lib/outofprocess.js +0 -2
- package/lib/protocol/validator.js +423 -346
- package/lib/protocol/validatorPrimitives.js +18 -4
- package/lib/remote/playwrightConnection.js +29 -166
- package/lib/remote/playwrightServer.js +233 -35
- package/lib/server/android/android.js +97 -83
- package/lib/server/android/backendAdb.js +0 -2
- package/lib/server/bidi/bidiBrowser.js +139 -73
- package/lib/server/bidi/bidiChromium.js +23 -22
- package/lib/server/bidi/bidiExecutionContext.js +2 -1
- package/lib/server/bidi/bidiFirefox.js +17 -14
- package/lib/server/bidi/bidiInput.js +22 -22
- package/lib/server/bidi/bidiNetworkManager.js +8 -11
- package/lib/server/bidi/bidiPage.js +42 -86
- package/lib/server/bidi/third_party/bidiProtocol.js +5 -133
- package/lib/server/bidi/third_party/bidiProtocolCore.js +179 -0
- package/lib/server/{dispatchers/selectorsDispatcher.js → bidi/third_party/bidiProtocolPermissions.js} +20 -18
- package/lib/server/browser.js +30 -21
- package/lib/server/browserContext.js +203 -165
- package/lib/server/browserType.js +109 -107
- package/lib/server/chromium/chromium.js +84 -69
- package/lib/server/chromium/chromiumSwitches.js +13 -20
- package/lib/server/chromium/crBrowser.js +74 -40
- package/lib/server/chromium/crConnection.js +8 -9
- package/lib/server/chromium/crCoverage.js +11 -8
- package/lib/server/chromium/crDragDrop.js +25 -20
- package/lib/server/chromium/crExecutionContext.js +2 -1
- package/lib/server/chromium/crInput.js +32 -29
- package/lib/server/chromium/crNetworkManager.js +45 -33
- package/lib/server/chromium/crPage.js +98 -73
- package/lib/server/chromium/crServiceWorker.js +13 -18
- package/lib/server/chromium/videoRecorder.js +10 -18
- package/lib/server/clock.js +51 -39
- package/lib/server/codegen/csharp.js +10 -5
- package/lib/server/codegen/java.js +1 -1
- package/lib/server/codegen/javascript.js +1 -1
- package/lib/server/codegen/jsonl.js +2 -1
- package/lib/server/codegen/language.js +22 -1
- package/lib/server/codegen/languages.js +4 -4
- package/lib/server/codegen/python.js +1 -1
- package/lib/server/cookieStore.js +3 -1
- package/lib/server/debugController.js +105 -71
- package/lib/server/debugger.js +6 -23
- package/lib/server/deviceDescriptorsSource.json +237 -127
- package/lib/server/dialog.js +50 -6
- package/lib/server/dispatchers/androidDispatcher.js +77 -62
- package/lib/server/dispatchers/artifactDispatcher.js +18 -18
- package/lib/server/dispatchers/browserContextDispatcher.js +141 -91
- package/lib/server/dispatchers/browserDispatcher.js +55 -88
- package/lib/server/dispatchers/browserTypeDispatcher.js +18 -9
- package/lib/server/dispatchers/cdpSessionDispatcher.js +4 -4
- package/lib/server/dispatchers/debugControllerDispatcher.js +12 -21
- package/lib/server/dispatchers/dialogDispatcher.js +4 -4
- package/lib/server/dispatchers/dispatcher.js +78 -53
- package/lib/server/dispatchers/electronDispatcher.js +19 -20
- package/lib/server/dispatchers/elementHandlerDispatcher.js +83 -93
- package/lib/server/dispatchers/frameDispatcher.js +99 -102
- package/lib/server/dispatchers/jsHandleDispatcher.js +21 -16
- package/lib/server/dispatchers/jsonPipeDispatcher.js +4 -4
- package/lib/server/dispatchers/localUtilsDispatcher.js +53 -59
- package/lib/server/dispatchers/networkDispatchers.js +41 -35
- package/lib/server/dispatchers/pageDispatcher.js +156 -107
- package/lib/server/dispatchers/playwrightDispatcher.js +37 -25
- package/lib/server/dispatchers/streamDispatcher.js +15 -8
- package/lib/server/dispatchers/tracingDispatcher.js +22 -13
- package/lib/server/dispatchers/webSocketRouteDispatcher.js +46 -35
- package/lib/server/dispatchers/writableStreamDispatcher.js +16 -10
- package/lib/server/dom.js +198 -266
- package/lib/server/download.js +3 -3
- package/lib/server/electron/electron.js +96 -103
- package/lib/server/electron/loader.js +1 -1
- package/lib/server/fetch.js +22 -41
- package/lib/server/fileUploadUtils.js +1 -1
- package/lib/server/firefox/ffBrowser.js +79 -55
- package/lib/server/firefox/ffExecutionContext.js +2 -1
- package/lib/server/firefox/ffInput.js +23 -23
- package/lib/server/firefox/ffNetworkManager.js +8 -6
- package/lib/server/firefox/ffPage.js +39 -36
- package/lib/server/firefox/firefox.js +9 -10
- package/lib/server/frameSelectors.js +65 -22
- package/lib/server/frames.js +516 -544
- package/lib/server/har/harRecorder.js +1 -1
- package/lib/server/har/harTracer.js +4 -2
- package/lib/server/helper.js +3 -7
- package/lib/server/index.js +0 -3
- package/lib/server/input.js +47 -54
- package/lib/server/instrumentation.js +8 -14
- package/lib/server/javascript.js +9 -17
- package/lib/server/launchApp.js +48 -30
- package/lib/server/localUtils.js +45 -38
- package/lib/server/network.js +44 -10
- package/lib/server/page.js +233 -178
- package/lib/server/pageBinding.js +6 -7
- package/lib/server/playwright.js +4 -14
- package/lib/server/progress.js +57 -49
- package/lib/server/recorder/recorderApp.js +298 -95
- package/lib/server/recorder/recorderRunner.js +23 -24
- package/lib/server/recorder/recorderSignalProcessor.js +83 -0
- package/lib/server/recorder/recorderUtils.js +67 -10
- package/lib/server/recorder.js +284 -146
- package/lib/server/registry/index.js +83 -48
- package/lib/server/registry/nativeDeps.js +175 -0
- package/lib/server/registry/oopDownloadBrowserMain.js +1 -1
- package/lib/server/screenshotter.js +84 -83
- package/lib/server/selectors.js +12 -12
- package/lib/server/socksClientCertificatesInterceptor.js +198 -136
- package/lib/server/trace/recorder/snapshotter.js +12 -19
- package/lib/server/trace/recorder/tracing.js +36 -27
- package/lib/server/trace/viewer/traceViewer.js +11 -20
- package/lib/server/transport.js +20 -22
- package/lib/server/utils/comparators.js +2 -2
- package/lib/server/utils/debug.js +3 -8
- package/lib/server/utils/debugLogger.js +8 -0
- package/lib/server/utils/hostPlatform.js +3 -1
- package/lib/server/utils/network.js +35 -25
- package/lib/server/utils/nodePlatform.js +1 -1
- package/lib/server/utils/processLauncher.js +4 -1
- package/lib/server/utils/wsServer.js +11 -17
- package/lib/server/webkit/webkit.js +5 -2
- package/lib/server/webkit/wkBrowser.js +51 -28
- package/lib/server/webkit/wkExecutionContext.js +2 -1
- package/lib/server/webkit/wkInput.js +25 -25
- package/lib/server/webkit/wkInterceptableRequest.js +1 -1
- package/lib/server/webkit/wkPage.js +80 -59
- package/lib/server/webkit/wkProvisionalPage.js +1 -1
- package/lib/server/webkit/wkWorkers.js +7 -7
- package/lib/utils/isomorphic/ariaSnapshot.js +13 -7
- package/lib/utils/isomorphic/cssParser.js +1 -2
- package/lib/utils/isomorphic/locatorGenerators.js +18 -0
- package/lib/utils/isomorphic/manualPromise.js +1 -2
- package/lib/utils/isomorphic/mimeType.js +1 -2
- package/lib/utils/isomorphic/multimap.js +1 -2
- package/lib/utils/isomorphic/oldUtilityScriptSerializers.js +248 -0
- package/lib/utils/isomorphic/protocolFormatter.js +78 -0
- package/lib/utils/isomorphic/protocolMetainfo.js +318 -0
- package/lib/utils/isomorphic/selectorParser.js +3 -4
- package/lib/utils/isomorphic/stringUtils.js +3 -24
- package/lib/utils/isomorphic/time.js +9 -4
- package/lib/utils/isomorphic/timeoutRunner.js +3 -4
- package/lib/utils/isomorphic/traceUtils.js +2 -3
- package/lib/utils/isomorphic/urlMatch.js +21 -7
- package/lib/utils/isomorphic/utilityScriptSerializers.js +208 -205
- package/lib/utils.js +8 -2
- package/lib/utilsBundleImpl/index.js +160 -150
- package/lib/vite/htmlReport/index.html +17 -17
- package/lib/vite/recorder/assets/{codeMirrorModule-CXVeovup.js → codeMirrorModule-DzQ0k89p.js} +1 -1
- package/lib/vite/recorder/assets/{index-eHBmevrY.css → index-CI4HQ-Zb.css} +1 -1
- package/lib/vite/recorder/assets/index-D7C7daHH.js +184 -0
- package/lib/vite/recorder/index.html +3 -3
- package/lib/vite/traceViewer/assets/{codeMirrorModule-_GLjJL-7.js → codeMirrorModule-Di48jgWx.js} +1 -1
- package/lib/vite/traceViewer/assets/defaultSettingsView-szBn8781.js +256 -0
- package/lib/vite/traceViewer/defaultSettingsView.DVJHpiGt.css +1 -0
- package/lib/vite/traceViewer/index.BFsek2M6.css +1 -0
- package/lib/vite/traceViewer/index.DQvXoPLL.js +2 -0
- package/lib/vite/traceViewer/index.html +6 -6
- package/lib/vite/traceViewer/sw.bundle.js +3 -3
- package/lib/vite/traceViewer/uiMode.dBV3oN9h.js +5 -0
- package/lib/vite/traceViewer/uiMode.html +4 -4
- package/lib/zipBundleImpl.js +4 -4
- package/package.json +1 -1
- package/types/protocol.d.ts +712 -107
- package/types/types.d.ts +148 -37
- package/lib/generated/consoleApiSource.js +0 -28
- package/lib/protocol/debug.js +0 -211
- package/lib/server/recorder/contextRecorder.js +0 -286
- package/lib/server/recorder/recorderCollection.js +0 -116
- package/lib/server/recorder/recorderFrontend.js +0 -16
- package/lib/server/storageScript.js +0 -154
- package/lib/server/timeoutSettings.js +0 -89
- package/lib/utils/isomorphic/builtins.js +0 -86
- package/lib/vite/recorder/assets/index-BsWQsSGl.js +0 -184
- package/lib/vite/traceViewer/assets/defaultSettingsView-DtCQiGHe.js +0 -265
- package/lib/vite/traceViewer/defaultSettingsView.QdHITyLI.css +0 -1
- package/lib/vite/traceViewer/index.CFOW-Ezb.css +0 -1
- package/lib/vite/traceViewer/index.cFZzK9RN.js +0 -2
- package/lib/vite/traceViewer/uiMode.XVPIqBeS.js +0 -5
|
@@ -29,7 +29,8 @@ __export(validatorPrimitives_exports, {
|
|
|
29
29
|
tBoolean: () => tBoolean,
|
|
30
30
|
tChannel: () => tChannel,
|
|
31
31
|
tEnum: () => tEnum,
|
|
32
|
-
|
|
32
|
+
tFloat: () => tFloat,
|
|
33
|
+
tInt: () => tInt,
|
|
33
34
|
tObject: () => tObject,
|
|
34
35
|
tOptional: () => tOptional,
|
|
35
36
|
tString: () => tString,
|
|
@@ -53,12 +54,24 @@ function maybeFindValidator(type, method, kind) {
|
|
|
53
54
|
function createMetadataValidator() {
|
|
54
55
|
return tOptional(scheme["Metadata"]);
|
|
55
56
|
}
|
|
56
|
-
const
|
|
57
|
+
const tFloat = (arg, path, context) => {
|
|
57
58
|
if (arg instanceof Number)
|
|
58
59
|
return arg.valueOf();
|
|
59
60
|
if (typeof arg === "number")
|
|
60
61
|
return arg;
|
|
61
|
-
throw new ValidationError(`${path}: expected
|
|
62
|
+
throw new ValidationError(`${path}: expected float, got ${typeof arg}`);
|
|
63
|
+
};
|
|
64
|
+
const tInt = (arg, path, context) => {
|
|
65
|
+
let value;
|
|
66
|
+
if (arg instanceof Number)
|
|
67
|
+
value = arg.valueOf();
|
|
68
|
+
else if (typeof arg === "number")
|
|
69
|
+
value = arg;
|
|
70
|
+
else
|
|
71
|
+
throw new ValidationError(`${path}: expected integer, got ${typeof arg}`);
|
|
72
|
+
if (!Number.isInteger(value))
|
|
73
|
+
throw new ValidationError(`${path}: expected integer, got float ${value}`);
|
|
74
|
+
return value;
|
|
62
75
|
};
|
|
63
76
|
const tBoolean = (arg, path, context) => {
|
|
64
77
|
if (arg instanceof Boolean)
|
|
@@ -170,7 +183,8 @@ const tType = (name) => {
|
|
|
170
183
|
tBoolean,
|
|
171
184
|
tChannel,
|
|
172
185
|
tEnum,
|
|
173
|
-
|
|
186
|
+
tFloat,
|
|
187
|
+
tInt,
|
|
174
188
|
tObject,
|
|
175
189
|
tOptional,
|
|
176
190
|
tString,
|
|
@@ -21,32 +21,22 @@ __export(playwrightConnection_exports, {
|
|
|
21
21
|
PlaywrightConnection: () => PlaywrightConnection
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(playwrightConnection_exports);
|
|
24
|
-
var import_socksProxy = require("../server/utils/socksProxy");
|
|
25
24
|
var import_server = require("../server");
|
|
26
25
|
var import_android = require("../server/android/android");
|
|
27
26
|
var import_browser = require("../server/browser");
|
|
28
27
|
var import_debugControllerDispatcher = require("../server/dispatchers/debugControllerDispatcher");
|
|
29
|
-
var import_instrumentation = require("../server/instrumentation");
|
|
30
|
-
var import_assert = require("../utils/isomorphic/assert");
|
|
31
|
-
var import_debug = require("../server/utils/debug");
|
|
32
28
|
var import_profiler = require("../server/utils/profiler");
|
|
33
29
|
var import_utils = require("../utils");
|
|
34
30
|
var import_debugLogger = require("../server/utils/debugLogger");
|
|
35
31
|
class PlaywrightConnection {
|
|
36
|
-
constructor(
|
|
32
|
+
constructor(semaphore, ws, controller, playwright, initialize, id) {
|
|
37
33
|
this._cleanups = [];
|
|
38
34
|
this._disconnected = false;
|
|
39
35
|
this._ws = ws;
|
|
40
|
-
this.
|
|
41
|
-
this._options = options;
|
|
42
|
-
options.launchOptions = filterLaunchOptions(options.launchOptions, options.allowFSPaths);
|
|
43
|
-
if (clientType === "reuse-browser" || clientType === "pre-launched-browser-or-android")
|
|
44
|
-
(0, import_assert.assert)(preLaunched.playwright);
|
|
45
|
-
if (clientType === "pre-launched-browser-or-android")
|
|
46
|
-
(0, import_assert.assert)(preLaunched.browser || preLaunched.androidDevice);
|
|
47
|
-
this._onClose = onClose;
|
|
36
|
+
this._semaphore = semaphore;
|
|
48
37
|
this._id = id;
|
|
49
|
-
this._profileName =
|
|
38
|
+
this._profileName = (/* @__PURE__ */ new Date()).toISOString();
|
|
39
|
+
const lock = this._semaphore.acquire();
|
|
50
40
|
this._dispatcherConnection = new import_server.DispatcherConnection();
|
|
51
41
|
this._dispatcherConnection.onmessage = async (message) => {
|
|
52
42
|
await lock;
|
|
@@ -71,134 +61,46 @@ class PlaywrightConnection {
|
|
|
71
61
|
});
|
|
72
62
|
ws.on("close", () => this._onDisconnect());
|
|
73
63
|
ws.on("error", (error) => this._onDisconnect(error));
|
|
74
|
-
if (
|
|
75
|
-
this.
|
|
64
|
+
if (controller) {
|
|
65
|
+
import_debugLogger.debugLogger.log("server", `[${this._id}] engaged reuse controller mode`);
|
|
66
|
+
this._root = new import_debugControllerDispatcher.DebugControllerDispatcher(this._dispatcherConnection, playwright.debugController);
|
|
76
67
|
return;
|
|
77
68
|
}
|
|
78
|
-
this._root = new import_server.RootDispatcher(this._dispatcherConnection, async (scope,
|
|
69
|
+
this._root = new import_server.RootDispatcher(this._dispatcherConnection, async (scope, params) => {
|
|
79
70
|
await (0, import_profiler.startProfiling)();
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
let browserName = this._options.browserName;
|
|
94
|
-
if ("bidi" === browserName) {
|
|
95
|
-
if (this._options.launchOptions?.channel?.toLocaleLowerCase().includes("firefox"))
|
|
96
|
-
browserName = "bidiFirefox";
|
|
97
|
-
else
|
|
98
|
-
browserName = "bidiChromium";
|
|
99
|
-
}
|
|
100
|
-
const browser = await playwright[browserName].launch((0, import_instrumentation.serverSideCallMetadata)(), this._options.launchOptions);
|
|
101
|
-
this._cleanups.push(async () => {
|
|
102
|
-
for (const browser2 of playwright.allBrowsers())
|
|
103
|
-
await browser2.close({ reason: "Connection terminated" });
|
|
104
|
-
});
|
|
105
|
-
browser.on(import_browser.Browser.Events.Disconnected, () => {
|
|
106
|
-
this.close({ code: 1001, reason: "Browser closed" });
|
|
107
|
-
});
|
|
108
|
-
return new import_server.PlaywrightDispatcher(scope, playwright, ownedSocksProxy, browser);
|
|
109
|
-
}
|
|
110
|
-
async _initPreLaunchedBrowserMode(scope) {
|
|
111
|
-
import_debugLogger.debugLogger.log("server", `[${this._id}] engaged pre-launched (browser) mode`);
|
|
112
|
-
const playwright = this._preLaunched.playwright;
|
|
113
|
-
this._preLaunched.socksProxy?.setPattern(this._options.socksProxyPattern);
|
|
114
|
-
const browser = this._preLaunched.browser;
|
|
115
|
-
browser.on(import_browser.Browser.Events.Disconnected, () => {
|
|
116
|
-
this.close({ code: 1001, reason: "Browser closed" });
|
|
117
|
-
});
|
|
118
|
-
const playwrightDispatcher = new import_server.PlaywrightDispatcher(scope, playwright, this._preLaunched.socksProxy, browser);
|
|
119
|
-
for (const b of playwright.allBrowsers()) {
|
|
120
|
-
if (b !== browser)
|
|
121
|
-
await b.close({ reason: "Connection terminated" });
|
|
122
|
-
}
|
|
123
|
-
this._cleanups.push(() => playwrightDispatcher.cleanup());
|
|
124
|
-
return playwrightDispatcher;
|
|
125
|
-
}
|
|
126
|
-
async _initPreLaunchedAndroidMode(scope) {
|
|
127
|
-
import_debugLogger.debugLogger.log("server", `[${this._id}] engaged pre-launched (Android) mode`);
|
|
128
|
-
const playwright = this._preLaunched.playwright;
|
|
129
|
-
const androidDevice = this._preLaunched.androidDevice;
|
|
130
|
-
androidDevice.on(import_android.AndroidDevice.Events.Close, () => {
|
|
131
|
-
this.close({ code: 1001, reason: "Android device disconnected" });
|
|
132
|
-
});
|
|
133
|
-
const playwrightDispatcher = new import_server.PlaywrightDispatcher(scope, playwright, void 0, void 0, androidDevice);
|
|
134
|
-
this._cleanups.push(() => playwrightDispatcher.cleanup());
|
|
135
|
-
return playwrightDispatcher;
|
|
136
|
-
}
|
|
137
|
-
_initDebugControllerMode() {
|
|
138
|
-
import_debugLogger.debugLogger.log("server", `[${this._id}] engaged reuse controller mode`);
|
|
139
|
-
const playwright = this._preLaunched.playwright;
|
|
140
|
-
return new import_debugControllerDispatcher.DebugControllerDispatcher(this._dispatcherConnection, playwright.debugController);
|
|
141
|
-
}
|
|
142
|
-
async _initReuseBrowsersMode(scope) {
|
|
143
|
-
import_debugLogger.debugLogger.log("server", `[${this._id}] engaged reuse browsers mode for ${this._options.browserName}`);
|
|
144
|
-
const playwright = this._preLaunched.playwright;
|
|
145
|
-
const requestedOptions = launchOptionsHash(this._options.launchOptions);
|
|
146
|
-
let browser = playwright.allBrowsers().find((b) => {
|
|
147
|
-
if (b.options.name !== this._options.browserName)
|
|
148
|
-
return false;
|
|
149
|
-
const existingOptions = launchOptionsHash(b.options.originalLaunchOptions);
|
|
150
|
-
return existingOptions === requestedOptions;
|
|
151
|
-
});
|
|
152
|
-
for (const b of playwright.allBrowsers()) {
|
|
153
|
-
if (b === browser)
|
|
154
|
-
continue;
|
|
155
|
-
if (b.options.name === this._options.browserName && b.options.channel === this._options.launchOptions.channel)
|
|
156
|
-
await b.close({ reason: "Connection terminated" });
|
|
157
|
-
}
|
|
158
|
-
if (!browser) {
|
|
159
|
-
browser = await playwright[this._options.browserName || "chromium"].launch((0, import_instrumentation.serverSideCallMetadata)(), {
|
|
160
|
-
...this._options.launchOptions,
|
|
161
|
-
headless: !!process.env.PW_DEBUG_CONTROLLER_HEADLESS
|
|
162
|
-
});
|
|
163
|
-
browser.on(import_browser.Browser.Events.Disconnected, () => {
|
|
164
|
-
this.close({ code: 1001, reason: "Browser closed" });
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
this._cleanups.push(async () => {
|
|
168
|
-
for (const browser2 of playwright.allBrowsers()) {
|
|
169
|
-
for (const context of browser2.contexts()) {
|
|
170
|
-
if (!context.pages().length)
|
|
171
|
-
await context.close({ reason: "Connection terminated" });
|
|
172
|
-
else
|
|
173
|
-
await context.stopPendingOperations("Connection closed");
|
|
174
|
-
}
|
|
175
|
-
if (!browser2.contexts())
|
|
176
|
-
await browser2.close({ reason: "Connection terminated" });
|
|
71
|
+
const options = await initialize();
|
|
72
|
+
if (options.preLaunchedBrowser) {
|
|
73
|
+
const browser = options.preLaunchedBrowser;
|
|
74
|
+
browser.options.sdkLanguage = params.sdkLanguage;
|
|
75
|
+
browser.on(import_browser.Browser.Events.Disconnected, () => {
|
|
76
|
+
this.close({ code: 1001, reason: "Browser closed" });
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
if (options.preLaunchedAndroidDevice) {
|
|
80
|
+
const androidDevice = options.preLaunchedAndroidDevice;
|
|
81
|
+
androidDevice.on(import_android.AndroidDevice.Events.Close, () => {
|
|
82
|
+
this.close({ code: 1001, reason: "Android device disconnected" });
|
|
83
|
+
});
|
|
177
84
|
}
|
|
85
|
+
if (options.dispose)
|
|
86
|
+
this._cleanups.push(options.dispose);
|
|
87
|
+
const dispatcher = new import_server.PlaywrightDispatcher(scope, playwright, options);
|
|
88
|
+
this._cleanups.push(() => dispatcher.cleanup());
|
|
89
|
+
return dispatcher;
|
|
178
90
|
});
|
|
179
|
-
const playwrightDispatcher = new import_server.PlaywrightDispatcher(scope, playwright, void 0, browser);
|
|
180
|
-
return playwrightDispatcher;
|
|
181
|
-
}
|
|
182
|
-
async _createOwnedSocksProxy(playwright) {
|
|
183
|
-
if (!this._options.socksProxyPattern)
|
|
184
|
-
return;
|
|
185
|
-
const socksProxy = new import_socksProxy.SocksProxy();
|
|
186
|
-
socksProxy.setPattern(this._options.socksProxyPattern);
|
|
187
|
-
playwright.options.socksProxyPort = await socksProxy.listen(0);
|
|
188
|
-
import_debugLogger.debugLogger.log("server", `[${this._id}] started socks proxy on port ${playwright.options.socksProxyPort}`);
|
|
189
|
-
this._cleanups.push(() => socksProxy.close());
|
|
190
|
-
return socksProxy;
|
|
191
91
|
}
|
|
192
92
|
async _onDisconnect(error) {
|
|
193
93
|
this._disconnected = true;
|
|
194
94
|
import_debugLogger.debugLogger.log("server", `[${this._id}] disconnected. error: ${error}`);
|
|
95
|
+
await this._root.stopPendingOperations(new Error("Disconnected")).catch(() => {
|
|
96
|
+
});
|
|
195
97
|
this._root._dispose();
|
|
196
98
|
import_debugLogger.debugLogger.log("server", `[${this._id}] starting cleanup`);
|
|
197
99
|
for (const cleanup of this._cleanups)
|
|
198
100
|
await cleanup().catch(() => {
|
|
199
101
|
});
|
|
200
102
|
await (0, import_profiler.stopProfiling)(this._profileName);
|
|
201
|
-
this.
|
|
103
|
+
this._semaphore.release();
|
|
202
104
|
import_debugLogger.debugLogger.log("server", `[${this._id}] finished cleanup`);
|
|
203
105
|
}
|
|
204
106
|
logServerMetadata(message, messageString, direction) {
|
|
@@ -221,45 +123,6 @@ class PlaywrightConnection {
|
|
|
221
123
|
}
|
|
222
124
|
}
|
|
223
125
|
}
|
|
224
|
-
function launchOptionsHash(options) {
|
|
225
|
-
const copy = { ...options };
|
|
226
|
-
for (const k of Object.keys(copy)) {
|
|
227
|
-
const key = k;
|
|
228
|
-
if (copy[key] === defaultLaunchOptions[key])
|
|
229
|
-
delete copy[key];
|
|
230
|
-
}
|
|
231
|
-
for (const key of optionsThatAllowBrowserReuse)
|
|
232
|
-
delete copy[key];
|
|
233
|
-
return JSON.stringify(copy);
|
|
234
|
-
}
|
|
235
|
-
function filterLaunchOptions(options, allowFSPaths) {
|
|
236
|
-
return {
|
|
237
|
-
channel: options.channel,
|
|
238
|
-
args: options.args,
|
|
239
|
-
ignoreAllDefaultArgs: options.ignoreAllDefaultArgs,
|
|
240
|
-
ignoreDefaultArgs: options.ignoreDefaultArgs,
|
|
241
|
-
timeout: options.timeout,
|
|
242
|
-
headless: options.headless,
|
|
243
|
-
proxy: options.proxy,
|
|
244
|
-
chromiumSandbox: options.chromiumSandbox,
|
|
245
|
-
firefoxUserPrefs: options.firefoxUserPrefs,
|
|
246
|
-
slowMo: options.slowMo,
|
|
247
|
-
executablePath: (0, import_debug.isUnderTest)() || allowFSPaths ? options.executablePath : void 0,
|
|
248
|
-
downloadsPath: allowFSPaths ? options.downloadsPath : void 0
|
|
249
|
-
};
|
|
250
|
-
}
|
|
251
|
-
const defaultLaunchOptions = {
|
|
252
|
-
ignoreAllDefaultArgs: false,
|
|
253
|
-
handleSIGINT: false,
|
|
254
|
-
handleSIGTERM: false,
|
|
255
|
-
handleSIGHUP: false,
|
|
256
|
-
headless: true,
|
|
257
|
-
devtools: false
|
|
258
|
-
};
|
|
259
|
-
const optionsThatAllowBrowserReuse = [
|
|
260
|
-
"headless",
|
|
261
|
-
"tracesDir"
|
|
262
|
-
];
|
|
263
126
|
// Annotate the CommonJS export names for ESM import in node:
|
|
264
127
|
0 && (module.exports = {
|
|
265
128
|
PlaywrightConnection
|
|
@@ -23,22 +23,40 @@ __export(playwrightServer_exports, {
|
|
|
23
23
|
module.exports = __toCommonJS(playwrightServer_exports);
|
|
24
24
|
var import_playwrightConnection = require("./playwrightConnection");
|
|
25
25
|
var import_playwright = require("../server/playwright");
|
|
26
|
-
var import_debugLogger = require("../server/utils/debugLogger");
|
|
27
26
|
var import_semaphore = require("../utils/isomorphic/semaphore");
|
|
27
|
+
var import_time = require("../utils/isomorphic/time");
|
|
28
28
|
var import_wsServer = require("../server/utils/wsServer");
|
|
29
29
|
var import_ascii = require("../server/utils/ascii");
|
|
30
30
|
var import_userAgent = require("../server/utils/userAgent");
|
|
31
|
+
var import_utils = require("../utils");
|
|
32
|
+
var import_socksProxy = require("../server/utils/socksProxy");
|
|
33
|
+
var import_browser = require("../server/browser");
|
|
34
|
+
var import_progress = require("../server/progress");
|
|
31
35
|
class PlaywrightServer {
|
|
32
36
|
constructor(options) {
|
|
37
|
+
this._dontReuseBrowsers = /* @__PURE__ */ new Set();
|
|
33
38
|
this._options = options;
|
|
34
|
-
if (options.preLaunchedBrowser)
|
|
35
|
-
this.
|
|
39
|
+
if (options.preLaunchedBrowser) {
|
|
40
|
+
this._playwright = options.preLaunchedBrowser.attribution.playwright;
|
|
41
|
+
this._dontReuse(options.preLaunchedBrowser);
|
|
42
|
+
}
|
|
36
43
|
if (options.preLaunchedAndroidDevice)
|
|
37
|
-
this.
|
|
44
|
+
this._playwright = options.preLaunchedAndroidDevice._android.attribution.playwright;
|
|
45
|
+
this._playwright ??= (0, import_playwright.createPlaywright)({ sdkLanguage: "javascript", isServer: true });
|
|
38
46
|
const browserSemaphore = new import_semaphore.Semaphore(this._options.maxConnections);
|
|
39
47
|
const controllerSemaphore = new import_semaphore.Semaphore(1);
|
|
40
48
|
const reuseBrowserSemaphore = new import_semaphore.Semaphore(1);
|
|
41
49
|
this._wsServer = new import_wsServer.WSServer({
|
|
50
|
+
onRequest: (request, response) => {
|
|
51
|
+
if (request.method === "GET" && request.url === "/json") {
|
|
52
|
+
response.setHeader("Content-Type", "application/json");
|
|
53
|
+
response.end(JSON.stringify({
|
|
54
|
+
wsEndpointPath: this._options.path
|
|
55
|
+
}));
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
response.end("Running");
|
|
59
|
+
},
|
|
42
60
|
onUpgrade: (request, socket) => {
|
|
43
61
|
const uaError = userAgentVersionMatchesErrorMessage(request.headers["user-agent"] || "");
|
|
44
62
|
if (uaError)
|
|
@@ -58,51 +76,191 @@ ${uaError}` };
|
|
|
58
76
|
const launchOptionsHeader = request.headers["x-playwright-launch-options"] || "";
|
|
59
77
|
const launchOptionsHeaderValue = Array.isArray(launchOptionsHeader) ? launchOptionsHeader[0] : launchOptionsHeader;
|
|
60
78
|
const launchOptionsParam = url.searchParams.get("launch-options");
|
|
61
|
-
let launchOptions = {};
|
|
79
|
+
let launchOptions = { timeout: import_time.DEFAULT_PLAYWRIGHT_LAUNCH_TIMEOUT };
|
|
62
80
|
try {
|
|
63
81
|
launchOptions = JSON.parse(launchOptionsParam || launchOptionsHeaderValue);
|
|
82
|
+
if (!launchOptions.timeout)
|
|
83
|
+
launchOptions.timeout = import_time.DEFAULT_PLAYWRIGHT_LAUNCH_TIMEOUT;
|
|
64
84
|
} catch (e) {
|
|
65
85
|
}
|
|
66
86
|
const isExtension = this._options.mode === "extension";
|
|
87
|
+
const allowFSPaths = isExtension;
|
|
88
|
+
launchOptions = filterLaunchOptions(launchOptions, allowFSPaths);
|
|
89
|
+
if (url.searchParams.has("debug-controller")) {
|
|
90
|
+
if (!(this._options.debugController || isExtension))
|
|
91
|
+
throw new Error("Debug controller is not enabled");
|
|
92
|
+
return new import_playwrightConnection.PlaywrightConnection(
|
|
93
|
+
controllerSemaphore,
|
|
94
|
+
ws,
|
|
95
|
+
true,
|
|
96
|
+
this._playwright,
|
|
97
|
+
async () => {
|
|
98
|
+
throw new Error("shouldnt be used");
|
|
99
|
+
},
|
|
100
|
+
id
|
|
101
|
+
);
|
|
102
|
+
}
|
|
67
103
|
if (isExtension) {
|
|
68
|
-
|
|
69
|
-
|
|
104
|
+
const connectFilter = url.searchParams.get("connect");
|
|
105
|
+
if (connectFilter) {
|
|
106
|
+
if (connectFilter !== "first")
|
|
107
|
+
throw new Error(`Unknown connect filter: ${connectFilter}`);
|
|
108
|
+
return new import_playwrightConnection.PlaywrightConnection(
|
|
109
|
+
browserSemaphore,
|
|
110
|
+
ws,
|
|
111
|
+
false,
|
|
112
|
+
this._playwright,
|
|
113
|
+
() => this._initConnectMode(id, connectFilter, browserName, launchOptions),
|
|
114
|
+
id
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
return new import_playwrightConnection.PlaywrightConnection(
|
|
118
|
+
reuseBrowserSemaphore,
|
|
119
|
+
ws,
|
|
120
|
+
false,
|
|
121
|
+
this._playwright,
|
|
122
|
+
() => this._initReuseBrowsersMode(browserName, launchOptions, id),
|
|
123
|
+
id
|
|
124
|
+
);
|
|
70
125
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
126
|
+
if (this._options.mode === "launchServer" || this._options.mode === "launchServerShared") {
|
|
127
|
+
if (this._options.preLaunchedBrowser) {
|
|
128
|
+
return new import_playwrightConnection.PlaywrightConnection(
|
|
129
|
+
browserSemaphore,
|
|
130
|
+
ws,
|
|
131
|
+
false,
|
|
132
|
+
this._playwright,
|
|
133
|
+
() => this._initPreLaunchedBrowserMode(id),
|
|
134
|
+
id
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
return new import_playwrightConnection.PlaywrightConnection(
|
|
138
|
+
browserSemaphore,
|
|
139
|
+
ws,
|
|
140
|
+
false,
|
|
141
|
+
this._playwright,
|
|
142
|
+
() => this._initPreLaunchedAndroidMode(id),
|
|
143
|
+
id
|
|
144
|
+
);
|
|
82
145
|
}
|
|
83
146
|
return new import_playwrightConnection.PlaywrightConnection(
|
|
84
|
-
|
|
85
|
-
clientType,
|
|
147
|
+
browserSemaphore,
|
|
86
148
|
ws,
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
androidDevice: this._options.preLaunchedAndroidDevice,
|
|
92
|
-
socksProxy: this._options.preLaunchedSocksProxy
|
|
93
|
-
},
|
|
94
|
-
id,
|
|
95
|
-
() => semaphore.release()
|
|
149
|
+
false,
|
|
150
|
+
this._playwright,
|
|
151
|
+
() => this._initLaunchBrowserMode(browserName, proxyValue, launchOptions, id),
|
|
152
|
+
id
|
|
96
153
|
);
|
|
97
|
-
},
|
|
98
|
-
onClose: async () => {
|
|
99
|
-
import_debugLogger.debugLogger.log("server", "closing browsers");
|
|
100
|
-
if (this._preLaunchedPlaywright)
|
|
101
|
-
await Promise.all(this._preLaunchedPlaywright.allBrowsers().map((browser) => browser.close({ reason: "Playwright Server stopped" })));
|
|
102
|
-
import_debugLogger.debugLogger.log("server", "closed browsers");
|
|
103
154
|
}
|
|
104
155
|
});
|
|
105
156
|
}
|
|
157
|
+
async _initReuseBrowsersMode(browserName, launchOptions, id) {
|
|
158
|
+
import_utils.debugLogger.log("server", `[${id}] engaged reuse browsers mode for ${browserName}`);
|
|
159
|
+
const requestedOptions = launchOptionsHash(launchOptions);
|
|
160
|
+
let browser = this._playwright.allBrowsers().find((b) => {
|
|
161
|
+
if (b.options.name !== browserName)
|
|
162
|
+
return false;
|
|
163
|
+
if (this._dontReuseBrowsers.has(b))
|
|
164
|
+
return false;
|
|
165
|
+
const existingOptions = launchOptionsHash({ ...b.options.originalLaunchOptions, timeout: import_time.DEFAULT_PLAYWRIGHT_LAUNCH_TIMEOUT });
|
|
166
|
+
return existingOptions === requestedOptions;
|
|
167
|
+
});
|
|
168
|
+
for (const b of this._playwright.allBrowsers()) {
|
|
169
|
+
if (b === browser)
|
|
170
|
+
continue;
|
|
171
|
+
if (this._dontReuseBrowsers.has(b))
|
|
172
|
+
continue;
|
|
173
|
+
if (b.options.name === browserName && b.options.channel === launchOptions.channel)
|
|
174
|
+
await b.close({ reason: "Connection terminated" });
|
|
175
|
+
}
|
|
176
|
+
if (!browser) {
|
|
177
|
+
const browserType = this._playwright[browserName || "chromium"];
|
|
178
|
+
const controller = new import_progress.ProgressController();
|
|
179
|
+
browser = await controller.run((progress) => browserType.launch(progress, {
|
|
180
|
+
...launchOptions,
|
|
181
|
+
headless: !!process.env.PW_DEBUG_CONTROLLER_HEADLESS
|
|
182
|
+
}), launchOptions.timeout);
|
|
183
|
+
}
|
|
184
|
+
return {
|
|
185
|
+
preLaunchedBrowser: browser,
|
|
186
|
+
denyLaunch: true,
|
|
187
|
+
dispose: async () => {
|
|
188
|
+
for (const context of browser.contexts()) {
|
|
189
|
+
if (!context.pages().length)
|
|
190
|
+
await context.close({ reason: "Connection terminated" });
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
async _initConnectMode(id, filter, browserName, launchOptions) {
|
|
196
|
+
browserName ??= "chromium";
|
|
197
|
+
import_utils.debugLogger.log("server", `[${id}] engaged connect mode`);
|
|
198
|
+
let browser = this._playwright.allBrowsers().find((b) => b.options.name === browserName);
|
|
199
|
+
if (!browser) {
|
|
200
|
+
const browserType = this._playwright[browserName];
|
|
201
|
+
const controller = new import_progress.ProgressController();
|
|
202
|
+
browser = await controller.run((progress) => browserType.launch(progress, launchOptions), launchOptions.timeout);
|
|
203
|
+
this._dontReuse(browser);
|
|
204
|
+
}
|
|
205
|
+
return {
|
|
206
|
+
preLaunchedBrowser: browser,
|
|
207
|
+
denyLaunch: true,
|
|
208
|
+
sharedBrowser: true
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
async _initPreLaunchedBrowserMode(id) {
|
|
212
|
+
import_utils.debugLogger.log("server", `[${id}] engaged pre-launched (browser) mode`);
|
|
213
|
+
const browser = this._options.preLaunchedBrowser;
|
|
214
|
+
for (const b of this._playwright.allBrowsers()) {
|
|
215
|
+
if (b !== browser)
|
|
216
|
+
await b.close({ reason: "Connection terminated" });
|
|
217
|
+
}
|
|
218
|
+
return {
|
|
219
|
+
preLaunchedBrowser: browser,
|
|
220
|
+
socksProxy: this._options.preLaunchedSocksProxy,
|
|
221
|
+
sharedBrowser: this._options.mode === "launchServerShared",
|
|
222
|
+
denyLaunch: true
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
async _initPreLaunchedAndroidMode(id) {
|
|
226
|
+
import_utils.debugLogger.log("server", `[${id}] engaged pre-launched (Android) mode`);
|
|
227
|
+
const androidDevice = this._options.preLaunchedAndroidDevice;
|
|
228
|
+
return {
|
|
229
|
+
preLaunchedAndroidDevice: androidDevice,
|
|
230
|
+
denyLaunch: true
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
async _initLaunchBrowserMode(browserName, proxyValue, launchOptions, id) {
|
|
234
|
+
import_utils.debugLogger.log("server", `[${id}] engaged launch mode for "${browserName}"`);
|
|
235
|
+
let socksProxy;
|
|
236
|
+
if (proxyValue) {
|
|
237
|
+
socksProxy = new import_socksProxy.SocksProxy();
|
|
238
|
+
socksProxy.setPattern(proxyValue);
|
|
239
|
+
launchOptions.socksProxyPort = await socksProxy.listen(0);
|
|
240
|
+
import_utils.debugLogger.log("server", `[${id}] started socks proxy on port ${launchOptions.socksProxyPort}`);
|
|
241
|
+
} else {
|
|
242
|
+
launchOptions.socksProxyPort = void 0;
|
|
243
|
+
}
|
|
244
|
+
const browserType = this._playwright[browserName];
|
|
245
|
+
const controller = new import_progress.ProgressController();
|
|
246
|
+
const browser = await controller.run((progress) => browserType.launch(progress, launchOptions), launchOptions.timeout);
|
|
247
|
+
this._dontReuseBrowsers.add(browser);
|
|
248
|
+
return {
|
|
249
|
+
preLaunchedBrowser: browser,
|
|
250
|
+
socksProxy,
|
|
251
|
+
denyLaunch: true,
|
|
252
|
+
dispose: async () => {
|
|
253
|
+
await browser.close({ reason: "Connection terminated" });
|
|
254
|
+
socksProxy?.close();
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
_dontReuse(browser) {
|
|
259
|
+
this._dontReuseBrowsers.add(browser);
|
|
260
|
+
browser.on(import_browser.Browser.Events.Disconnected, () => {
|
|
261
|
+
this._dontReuseBrowsers.delete(browser);
|
|
262
|
+
});
|
|
263
|
+
}
|
|
106
264
|
async listen(port = 0, hostname) {
|
|
107
265
|
return this._wsServer.listen(port, hostname, this._options.path);
|
|
108
266
|
}
|
|
@@ -133,6 +291,46 @@ function userAgentVersionMatchesErrorMessage(userAgent) {
|
|
|
133
291
|
].join("\n"), 1);
|
|
134
292
|
}
|
|
135
293
|
}
|
|
294
|
+
function launchOptionsHash(options) {
|
|
295
|
+
const copy = { ...options };
|
|
296
|
+
for (const k of Object.keys(copy)) {
|
|
297
|
+
const key = k;
|
|
298
|
+
if (copy[key] === defaultLaunchOptions[key])
|
|
299
|
+
delete copy[key];
|
|
300
|
+
}
|
|
301
|
+
for (const key of optionsThatAllowBrowserReuse)
|
|
302
|
+
delete copy[key];
|
|
303
|
+
return JSON.stringify(copy);
|
|
304
|
+
}
|
|
305
|
+
function filterLaunchOptions(options, allowFSPaths) {
|
|
306
|
+
return {
|
|
307
|
+
channel: options.channel,
|
|
308
|
+
args: options.args,
|
|
309
|
+
ignoreAllDefaultArgs: options.ignoreAllDefaultArgs,
|
|
310
|
+
ignoreDefaultArgs: options.ignoreDefaultArgs,
|
|
311
|
+
timeout: options.timeout,
|
|
312
|
+
headless: options.headless,
|
|
313
|
+
proxy: options.proxy,
|
|
314
|
+
chromiumSandbox: options.chromiumSandbox,
|
|
315
|
+
firefoxUserPrefs: options.firefoxUserPrefs,
|
|
316
|
+
slowMo: options.slowMo,
|
|
317
|
+
executablePath: (0, import_utils.isUnderTest)() || allowFSPaths ? options.executablePath : void 0,
|
|
318
|
+
downloadsPath: allowFSPaths ? options.downloadsPath : void 0
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
const defaultLaunchOptions = {
|
|
322
|
+
ignoreAllDefaultArgs: false,
|
|
323
|
+
handleSIGINT: false,
|
|
324
|
+
handleSIGTERM: false,
|
|
325
|
+
handleSIGHUP: false,
|
|
326
|
+
headless: true,
|
|
327
|
+
devtools: false
|
|
328
|
+
};
|
|
329
|
+
const optionsThatAllowBrowserReuse = [
|
|
330
|
+
"headless",
|
|
331
|
+
"timeout",
|
|
332
|
+
"tracesDir"
|
|
333
|
+
];
|
|
136
334
|
// Annotate the CommonJS export names for ESM import in node:
|
|
137
335
|
0 && (module.exports = {
|
|
138
336
|
PlaywrightServer
|