playwright-core 1.54.0-alpha-2025-06-18 → 1.54.0-alpha-2025-06-20
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/browsers.json +2 -2
- package/lib/browserServerImpl.js +1 -6
- package/lib/generated/injectedScriptSource.js +1 -1
- package/lib/remote/playwrightConnection.js +30 -33
- package/lib/remote/playwrightServer.js +4 -14
- package/lib/server/bidi/bidiChromium.js +2 -2
- package/lib/server/browser.js +3 -0
- package/lib/server/browserType.js +2 -2
- package/lib/server/chromium/chromium.js +2 -2
- package/lib/server/chromium/crPage.js +1 -1
- package/lib/server/dispatchers/androidDispatcher.js +6 -1
- package/lib/server/dispatchers/browserTypeDispatcher.js +8 -1
- package/lib/server/dispatchers/electronDispatcher.js +4 -1
- package/lib/server/dispatchers/playwrightDispatcher.js +8 -7
- package/lib/server/dom.js +12 -18
- package/lib/server/frameSelectors.js +1 -1
- package/lib/server/frames.js +1 -1
- package/lib/server/page.js +2 -2
- package/lib/server/recorder/contextRecorder.js +1 -1
- package/lib/server/recorder/recorderApp.js +1 -1
- package/lib/server/trace/recorder/tracing.js +5 -2
- package/lib/server/trace/viewer/traceViewer.js +0 -1
- package/lib/server/utils/wsServer.js +0 -1
- package/lib/utils/isomorphic/protocolMetainfo.js +1 -1
- package/lib/vite/traceViewer/assets/{codeMirrorModule-BrkttCNj.js → codeMirrorModule--amfWN3K.js} +1 -1
- package/lib/vite/traceViewer/assets/{defaultSettingsView-n407vKdT.js → defaultSettingsView-BFAIqAv2.js} +73 -73
- package/lib/vite/traceViewer/{index.CdwM4SOI.js → index.amRtOpxT.js} +1 -1
- package/lib/vite/traceViewer/index.html +2 -2
- package/lib/vite/traceViewer/uiMode.html +2 -2
- package/lib/vite/traceViewer/{uiMode.Bt-oxu9U.js → uiMode.hufuL2u6.js} +1 -1
- package/package.json +1 -1
|
@@ -33,15 +33,14 @@ var import_profiler = require("../server/utils/profiler");
|
|
|
33
33
|
var import_utils = require("../utils");
|
|
34
34
|
var import_debugLogger = require("../server/utils/debugLogger");
|
|
35
35
|
class PlaywrightConnection {
|
|
36
|
-
constructor(lock, clientType, ws, options, preLaunched, id, onClose) {
|
|
36
|
+
constructor(lock, clientType, ws, options, playwright, preLaunched, id, onClose) {
|
|
37
37
|
this._cleanups = [];
|
|
38
38
|
this._disconnected = false;
|
|
39
39
|
this._ws = ws;
|
|
40
|
+
this._playwright = playwright;
|
|
40
41
|
this._preLaunched = preLaunched;
|
|
41
42
|
this._options = options;
|
|
42
43
|
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
44
|
if (clientType === "pre-launched-browser-or-android")
|
|
46
45
|
(0, import_assert.assert)(preLaunched.browser || preLaunched.androidDevice);
|
|
47
46
|
this._onClose = onClose;
|
|
@@ -78,9 +77,9 @@ class PlaywrightConnection {
|
|
|
78
77
|
this._root = new import_server.RootDispatcher(this._dispatcherConnection, async (scope, options2) => {
|
|
79
78
|
await (0, import_profiler.startProfiling)();
|
|
80
79
|
if (clientType === "reuse-browser")
|
|
81
|
-
return await this._initReuseBrowsersMode(scope);
|
|
80
|
+
return await this._initReuseBrowsersMode(scope, options2);
|
|
82
81
|
if (clientType === "pre-launched-browser-or-android")
|
|
83
|
-
return this._preLaunched.browser ? await this._initPreLaunchedBrowserMode(scope) : await this._initPreLaunchedAndroidMode(scope);
|
|
82
|
+
return this._preLaunched.browser ? await this._initPreLaunchedBrowserMode(scope, options2) : await this._initPreLaunchedAndroidMode(scope);
|
|
84
83
|
if (clientType === "launch-browser")
|
|
85
84
|
return await this._initLaunchBrowserMode(scope, options2);
|
|
86
85
|
throw new Error("Unsupported client type: " + clientType);
|
|
@@ -88,8 +87,7 @@ class PlaywrightConnection {
|
|
|
88
87
|
}
|
|
89
88
|
async _initLaunchBrowserMode(scope, options) {
|
|
90
89
|
import_debugLogger.debugLogger.log("server", `[${this._id}] engaged launch mode for "${this._options.browserName}"`);
|
|
91
|
-
const
|
|
92
|
-
const ownedSocksProxy = await this._createOwnedSocksProxy(playwright);
|
|
90
|
+
const ownedSocksProxy = await this._createOwnedSocksProxy();
|
|
93
91
|
let browserName = this._options.browserName;
|
|
94
92
|
if ("bidi" === browserName) {
|
|
95
93
|
if (this._options.launchOptions?.channel?.toLocaleLowerCase().includes("firefox"))
|
|
@@ -97,30 +95,29 @@ class PlaywrightConnection {
|
|
|
97
95
|
else
|
|
98
96
|
browserName = "bidiChromium";
|
|
99
97
|
}
|
|
100
|
-
const browser = await
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
await browser2.close({ reason: "Connection terminated" });
|
|
104
|
-
});
|
|
98
|
+
const browser = await this._playwright[browserName].launch((0, import_instrumentation.serverSideCallMetadata)(), this._options.launchOptions);
|
|
99
|
+
browser.options.sdkLanguage = options.sdkLanguage;
|
|
100
|
+
this._cleanups.push(() => browser.close({ reason: "Connection terminated" }));
|
|
105
101
|
browser.on(import_browser.Browser.Events.Disconnected, () => {
|
|
106
102
|
this.close({ code: 1001, reason: "Browser closed" });
|
|
107
103
|
});
|
|
108
|
-
return new import_server.PlaywrightDispatcher(scope,
|
|
104
|
+
return new import_server.PlaywrightDispatcher(scope, this._playwright, { socksProxy: ownedSocksProxy, preLaunchedBrowser: browser, denyLaunch: true });
|
|
109
105
|
}
|
|
110
|
-
async _initPreLaunchedBrowserMode(scope) {
|
|
106
|
+
async _initPreLaunchedBrowserMode(scope, options) {
|
|
111
107
|
import_debugLogger.debugLogger.log("server", `[${this._id}] engaged pre-launched (browser) mode`);
|
|
112
|
-
const playwright = this._preLaunched.playwright;
|
|
113
108
|
this._preLaunched.socksProxy?.setPattern(this._options.socksProxyPattern);
|
|
114
109
|
const browser = this._preLaunched.browser;
|
|
110
|
+
browser.options.sdkLanguage = options.sdkLanguage;
|
|
115
111
|
browser.on(import_browser.Browser.Events.Disconnected, () => {
|
|
116
112
|
this.close({ code: 1001, reason: "Browser closed" });
|
|
117
113
|
});
|
|
118
|
-
const playwrightDispatcher = new import_server.PlaywrightDispatcher(scope,
|
|
114
|
+
const playwrightDispatcher = new import_server.PlaywrightDispatcher(scope, this._playwright, {
|
|
119
115
|
socksProxy: this._preLaunched.socksProxy,
|
|
120
116
|
preLaunchedBrowser: browser,
|
|
121
|
-
sharedBrowser: this._options.sharedBrowser
|
|
117
|
+
sharedBrowser: this._options.sharedBrowser,
|
|
118
|
+
denyLaunch: true
|
|
122
119
|
});
|
|
123
|
-
for (const b of
|
|
120
|
+
for (const b of this._playwright.allBrowsers()) {
|
|
124
121
|
if (b !== browser)
|
|
125
122
|
await b.close({ reason: "Connection terminated" });
|
|
126
123
|
}
|
|
@@ -129,38 +126,35 @@ class PlaywrightConnection {
|
|
|
129
126
|
}
|
|
130
127
|
async _initPreLaunchedAndroidMode(scope) {
|
|
131
128
|
import_debugLogger.debugLogger.log("server", `[${this._id}] engaged pre-launched (Android) mode`);
|
|
132
|
-
const playwright = this._preLaunched.playwright;
|
|
133
129
|
const androidDevice = this._preLaunched.androidDevice;
|
|
134
130
|
androidDevice.on(import_android.AndroidDevice.Events.Close, () => {
|
|
135
131
|
this.close({ code: 1001, reason: "Android device disconnected" });
|
|
136
132
|
});
|
|
137
|
-
const playwrightDispatcher = new import_server.PlaywrightDispatcher(scope,
|
|
133
|
+
const playwrightDispatcher = new import_server.PlaywrightDispatcher(scope, this._playwright, { preLaunchedAndroidDevice: androidDevice, denyLaunch: true });
|
|
138
134
|
this._cleanups.push(() => playwrightDispatcher.cleanup());
|
|
139
135
|
return playwrightDispatcher;
|
|
140
136
|
}
|
|
141
137
|
_initDebugControllerMode() {
|
|
142
138
|
import_debugLogger.debugLogger.log("server", `[${this._id}] engaged reuse controller mode`);
|
|
143
|
-
|
|
144
|
-
return new import_debugControllerDispatcher.DebugControllerDispatcher(this._dispatcherConnection, playwright.debugController);
|
|
139
|
+
return new import_debugControllerDispatcher.DebugControllerDispatcher(this._dispatcherConnection, this._playwright.debugController);
|
|
145
140
|
}
|
|
146
|
-
async _initReuseBrowsersMode(scope) {
|
|
141
|
+
async _initReuseBrowsersMode(scope, options) {
|
|
147
142
|
import_debugLogger.debugLogger.log("server", `[${this._id}] engaged reuse browsers mode for ${this._options.browserName}`);
|
|
148
|
-
const playwright = this._preLaunched.playwright;
|
|
149
143
|
const requestedOptions = launchOptionsHash(this._options.launchOptions);
|
|
150
|
-
let browser =
|
|
144
|
+
let browser = this._playwright.allBrowsers().find((b) => {
|
|
151
145
|
if (b.options.name !== this._options.browserName)
|
|
152
146
|
return false;
|
|
153
147
|
const existingOptions = launchOptionsHash(b.options.originalLaunchOptions);
|
|
154
148
|
return existingOptions === requestedOptions;
|
|
155
149
|
});
|
|
156
|
-
for (const b of
|
|
150
|
+
for (const b of this._playwright.allBrowsers()) {
|
|
157
151
|
if (b === browser)
|
|
158
152
|
continue;
|
|
159
153
|
if (b.options.name === this._options.browserName && b.options.channel === this._options.launchOptions.channel)
|
|
160
154
|
await b.close({ reason: "Connection terminated" });
|
|
161
155
|
}
|
|
162
156
|
if (!browser) {
|
|
163
|
-
browser = await
|
|
157
|
+
browser = await this._playwright[this._options.browserName || "chromium"].launch((0, import_instrumentation.serverSideCallMetadata)(), {
|
|
164
158
|
...this._options.launchOptions,
|
|
165
159
|
headless: !!process.env.PW_DEBUG_CONTROLLER_HEADLESS
|
|
166
160
|
});
|
|
@@ -168,8 +162,9 @@ class PlaywrightConnection {
|
|
|
168
162
|
this.close({ code: 1001, reason: "Browser closed" });
|
|
169
163
|
});
|
|
170
164
|
}
|
|
165
|
+
browser.options.sdkLanguage = options.sdkLanguage;
|
|
171
166
|
this._cleanups.push(async () => {
|
|
172
|
-
for (const browser2 of
|
|
167
|
+
for (const browser2 of this._playwright.allBrowsers()) {
|
|
173
168
|
for (const context of browser2.contexts()) {
|
|
174
169
|
if (!context.pages().length)
|
|
175
170
|
await context.close({ reason: "Connection terminated" });
|
|
@@ -180,16 +175,18 @@ class PlaywrightConnection {
|
|
|
180
175
|
await browser2.close({ reason: "Connection terminated" });
|
|
181
176
|
}
|
|
182
177
|
});
|
|
183
|
-
const playwrightDispatcher = new import_server.PlaywrightDispatcher(scope,
|
|
178
|
+
const playwrightDispatcher = new import_server.PlaywrightDispatcher(scope, this._playwright, { preLaunchedBrowser: browser, denyLaunch: true });
|
|
184
179
|
return playwrightDispatcher;
|
|
185
180
|
}
|
|
186
|
-
async _createOwnedSocksProxy(
|
|
187
|
-
if (!this._options.socksProxyPattern)
|
|
181
|
+
async _createOwnedSocksProxy() {
|
|
182
|
+
if (!this._options.socksProxyPattern) {
|
|
183
|
+
this._options.launchOptions.socksProxyPort = void 0;
|
|
188
184
|
return;
|
|
185
|
+
}
|
|
189
186
|
const socksProxy = new import_socksProxy.SocksProxy();
|
|
190
187
|
socksProxy.setPattern(this._options.socksProxyPattern);
|
|
191
|
-
|
|
192
|
-
import_debugLogger.debugLogger.log("server", `[${this._id}] started socks proxy on port ${
|
|
188
|
+
this._options.launchOptions.socksProxyPort = await socksProxy.listen(0);
|
|
189
|
+
import_debugLogger.debugLogger.log("server", `[${this._id}] started socks proxy on port ${this._options.launchOptions.socksProxyPort}`);
|
|
193
190
|
this._cleanups.push(() => socksProxy.close());
|
|
194
191
|
return socksProxy;
|
|
195
192
|
}
|
|
@@ -23,7 +23,6 @@ __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");
|
|
28
27
|
var import_time = require("../utils/isomorphic/time");
|
|
29
28
|
var import_wsServer = require("../server/utils/wsServer");
|
|
@@ -33,9 +32,10 @@ class PlaywrightServer {
|
|
|
33
32
|
constructor(options) {
|
|
34
33
|
this._options = options;
|
|
35
34
|
if (options.preLaunchedBrowser)
|
|
36
|
-
this.
|
|
35
|
+
this._playwright = options.preLaunchedBrowser.attribution.playwright;
|
|
37
36
|
if (options.preLaunchedAndroidDevice)
|
|
38
|
-
this.
|
|
37
|
+
this._playwright = options.preLaunchedAndroidDevice._android.attribution.playwright;
|
|
38
|
+
this._playwright ??= (0, import_playwright.createPlaywright)({ sdkLanguage: "javascript", isServer: true });
|
|
39
39
|
const browserSemaphore = new import_semaphore.Semaphore(this._options.maxConnections);
|
|
40
40
|
const controllerSemaphore = new import_semaphore.Semaphore(1);
|
|
41
41
|
const reuseBrowserSemaphore = new import_semaphore.Semaphore(1);
|
|
@@ -75,10 +75,6 @@ ${uaError}` };
|
|
|
75
75
|
} catch (e) {
|
|
76
76
|
}
|
|
77
77
|
const isExtension = this._options.mode === "extension";
|
|
78
|
-
if (isExtension) {
|
|
79
|
-
if (!this._preLaunchedPlaywright)
|
|
80
|
-
this._preLaunchedPlaywright = (0, import_playwright.createPlaywright)({ sdkLanguage: "javascript", isServer: true });
|
|
81
|
-
}
|
|
82
78
|
let clientType = "launch-browser";
|
|
83
79
|
let semaphore = browserSemaphore;
|
|
84
80
|
if (isExtension && url.searchParams.has("debug-controller")) {
|
|
@@ -102,8 +98,8 @@ ${uaError}` };
|
|
|
102
98
|
allowFSPaths: this._options.mode === "extension",
|
|
103
99
|
sharedBrowser: this._options.mode === "launchServerShared"
|
|
104
100
|
},
|
|
101
|
+
this._playwright,
|
|
105
102
|
{
|
|
106
|
-
playwright: this._preLaunchedPlaywright,
|
|
107
103
|
browser: this._options.preLaunchedBrowser,
|
|
108
104
|
androidDevice: this._options.preLaunchedAndroidDevice,
|
|
109
105
|
socksProxy: this._options.preLaunchedSocksProxy
|
|
@@ -111,12 +107,6 @@ ${uaError}` };
|
|
|
111
107
|
id,
|
|
112
108
|
() => semaphore.release()
|
|
113
109
|
);
|
|
114
|
-
},
|
|
115
|
-
onClose: async () => {
|
|
116
|
-
import_debugLogger.debugLogger.log("server", "closing browsers");
|
|
117
|
-
if (this._preLaunchedPlaywright)
|
|
118
|
-
await Promise.all(this._preLaunchedPlaywright.allBrowsers().map((browser) => browser.close({ reason: "Playwright Server stopped" })));
|
|
119
|
-
import_debugLogger.debugLogger.log("server", "closed browsers");
|
|
120
110
|
}
|
|
121
111
|
});
|
|
122
112
|
}
|
|
@@ -130,12 +130,12 @@ class BidiChromium extends import_browserType.BrowserType {
|
|
|
130
130
|
if (proxy) {
|
|
131
131
|
const proxyURL = new URL(proxy.server);
|
|
132
132
|
const isSocks = proxyURL.protocol === "socks5:";
|
|
133
|
-
if (isSocks && !
|
|
133
|
+
if (isSocks && !options.socksProxyPort) {
|
|
134
134
|
chromeArguments.push(`--host-resolver-rules="MAP * ~NOTFOUND , EXCLUDE ${proxyURL.hostname}"`);
|
|
135
135
|
}
|
|
136
136
|
chromeArguments.push(`--proxy-server=${proxy.server}`);
|
|
137
137
|
const proxyBypassRules = [];
|
|
138
|
-
if (
|
|
138
|
+
if (options.socksProxyPort)
|
|
139
139
|
proxyBypassRules.push("<-loopback>");
|
|
140
140
|
if (proxy.bypass)
|
|
141
141
|
proxyBypassRules.push(...proxy.bypass.split(",").map((t) => t.trim()).map((t) => t.startsWith(".") ? "*" + t : t));
|
package/lib/server/browser.js
CHANGED
|
@@ -45,6 +45,9 @@ class Browser extends import_instrumentation.SdkObject {
|
|
|
45
45
|
Disconnected: "disconnected"
|
|
46
46
|
};
|
|
47
47
|
}
|
|
48
|
+
sdkLanguage() {
|
|
49
|
+
return this.options.sdkLanguage || this.attribution.playwright.options.sdkLanguage;
|
|
50
|
+
}
|
|
48
51
|
async newContext(metadata, options) {
|
|
49
52
|
(0, import_browserContext.validateBrowserContextOptions)(options, this.options);
|
|
50
53
|
let clientCertificatesProxy;
|
|
@@ -265,8 +265,8 @@ class BrowserType extends import_instrumentation.SdkObject {
|
|
|
265
265
|
headless = false;
|
|
266
266
|
if (downloadsPath && !import_path.default.isAbsolute(downloadsPath))
|
|
267
267
|
downloadsPath = import_path.default.join(process.cwd(), downloadsPath);
|
|
268
|
-
if (
|
|
269
|
-
proxy = { server: `socks5://127.0.0.1:${
|
|
268
|
+
if (options.socksProxyPort)
|
|
269
|
+
proxy = { server: `socks5://127.0.0.1:${options.socksProxyPort}` };
|
|
270
270
|
return { ...options, devtools, headless, downloadsPath, proxy };
|
|
271
271
|
}
|
|
272
272
|
_createUserDataDirArgMisuseError(userDataDirArg) {
|
|
@@ -295,12 +295,12 @@ class Chromium extends import_browserType.BrowserType {
|
|
|
295
295
|
if (proxy) {
|
|
296
296
|
const proxyURL = new URL(proxy.server);
|
|
297
297
|
const isSocks = proxyURL.protocol === "socks5:";
|
|
298
|
-
if (isSocks && !
|
|
298
|
+
if (isSocks && !options.socksProxyPort) {
|
|
299
299
|
chromeArguments.push(`--host-resolver-rules="MAP * ~NOTFOUND , EXCLUDE ${proxyURL.hostname}"`);
|
|
300
300
|
}
|
|
301
301
|
chromeArguments.push(`--proxy-server=${proxy.server}`);
|
|
302
302
|
const proxyBypassRules = [];
|
|
303
|
-
if (
|
|
303
|
+
if (options.socksProxyPort)
|
|
304
304
|
proxyBypassRules.push("<-loopback>");
|
|
305
305
|
if (proxy.bypass)
|
|
306
306
|
proxyBypassRules.push(...proxy.bypass.split(",").map((t) => t.trim()).map((t) => t.startsWith(".") ? "*" + t : t));
|
|
@@ -736,7 +736,7 @@ class FrameSession {
|
|
|
736
736
|
}
|
|
737
737
|
async _createVideoRecorder(screencastId, options) {
|
|
738
738
|
(0, import_assert.assert)(!this._screencastId);
|
|
739
|
-
const ffmpegPath = import_registry.registry.findExecutable("ffmpeg").executablePathOrDie(this._page.
|
|
739
|
+
const ffmpegPath = import_registry.registry.findExecutable("ffmpeg").executablePathOrDie(this._page.browserContext._browser.sdkLanguage());
|
|
740
740
|
this._videoRecorder = await import_videoRecorder.VideoRecorder.launch(this._crPage._page, ffmpegPath, options);
|
|
741
741
|
this._screencastId = screencastId;
|
|
742
742
|
}
|
|
@@ -29,9 +29,10 @@ var import_android = require("../android/android");
|
|
|
29
29
|
var import_eventsHelper = require("../utils/eventsHelper");
|
|
30
30
|
var import_instrumentation = require("../instrumentation");
|
|
31
31
|
class AndroidDispatcher extends import_dispatcher.Dispatcher {
|
|
32
|
-
constructor(scope, android) {
|
|
32
|
+
constructor(scope, android, denyLaunch) {
|
|
33
33
|
super(scope, android, "Android", {});
|
|
34
34
|
this._type_Android = true;
|
|
35
|
+
this._denyLaunch = denyLaunch;
|
|
35
36
|
}
|
|
36
37
|
async devices(params) {
|
|
37
38
|
const devices = await this._object.devices(params);
|
|
@@ -136,6 +137,8 @@ class AndroidDeviceDispatcher extends import_dispatcher.Dispatcher {
|
|
|
136
137
|
await this._object.push(params.file, params.path, params.mode);
|
|
137
138
|
}
|
|
138
139
|
async launchBrowser(params) {
|
|
140
|
+
if (this.parentScope()._denyLaunch)
|
|
141
|
+
throw new Error(`Launching more browsers is not allowed.`);
|
|
139
142
|
const context = await this._object.launchBrowser(params.pkg, params);
|
|
140
143
|
return { context: import_browserContextDispatcher.BrowserContextDispatcher.from(this, context) };
|
|
141
144
|
}
|
|
@@ -143,6 +146,8 @@ class AndroidDeviceDispatcher extends import_dispatcher.Dispatcher {
|
|
|
143
146
|
await this._object.close();
|
|
144
147
|
}
|
|
145
148
|
async connectToWebView(params) {
|
|
149
|
+
if (this.parentScope()._denyLaunch)
|
|
150
|
+
throw new Error(`Launching more browsers is not allowed.`);
|
|
146
151
|
return { context: import_browserContextDispatcher.BrowserContextDispatcher.from(this, await this._object.connectToWebView(params.socketName)) };
|
|
147
152
|
}
|
|
148
153
|
}
|
|
@@ -25,24 +25,31 @@ var import_browserContextDispatcher = require("./browserContextDispatcher");
|
|
|
25
25
|
var import_browserDispatcher = require("./browserDispatcher");
|
|
26
26
|
var import_dispatcher = require("./dispatcher");
|
|
27
27
|
class BrowserTypeDispatcher extends import_dispatcher.Dispatcher {
|
|
28
|
-
constructor(scope, browserType) {
|
|
28
|
+
constructor(scope, browserType, denyLaunch) {
|
|
29
29
|
super(scope, browserType, "BrowserType", {
|
|
30
30
|
executablePath: browserType.executablePath(),
|
|
31
31
|
name: browserType.name()
|
|
32
32
|
});
|
|
33
33
|
this._type_BrowserType = true;
|
|
34
|
+
this._denyLaunch = denyLaunch;
|
|
34
35
|
}
|
|
35
36
|
async launch(params, metadata) {
|
|
37
|
+
if (this._denyLaunch)
|
|
38
|
+
throw new Error(`Launching more browsers is not allowed.`);
|
|
36
39
|
const browser = await this._object.launch(metadata, params);
|
|
37
40
|
return { browser: new import_browserDispatcher.BrowserDispatcher(this, browser) };
|
|
38
41
|
}
|
|
39
42
|
async launchPersistentContext(params, metadata) {
|
|
43
|
+
if (this._denyLaunch)
|
|
44
|
+
throw new Error(`Launching more browsers is not allowed.`);
|
|
40
45
|
const browserContext = await this._object.launchPersistentContext(metadata, params.userDataDir, params);
|
|
41
46
|
const browserDispatcher = new import_browserDispatcher.BrowserDispatcher(this, browserContext._browser);
|
|
42
47
|
const contextDispatcher = import_browserContextDispatcher.BrowserContextDispatcher.from(browserDispatcher, browserContext);
|
|
43
48
|
return { browser: browserDispatcher, context: contextDispatcher };
|
|
44
49
|
}
|
|
45
50
|
async connectOverCDP(params, metadata) {
|
|
51
|
+
if (this._denyLaunch)
|
|
52
|
+
throw new Error(`Launching more browsers is not allowed.`);
|
|
46
53
|
const browser = await this._object.connectOverCDP(metadata, params.endpointURL, params);
|
|
47
54
|
const browserDispatcher = new import_browserDispatcher.BrowserDispatcher(this, browser);
|
|
48
55
|
return {
|
|
@@ -27,11 +27,14 @@ var import_dispatcher = require("./dispatcher");
|
|
|
27
27
|
var import_jsHandleDispatcher = require("./jsHandleDispatcher");
|
|
28
28
|
var import_electron = require("../electron/electron");
|
|
29
29
|
class ElectronDispatcher extends import_dispatcher.Dispatcher {
|
|
30
|
-
constructor(scope, electron) {
|
|
30
|
+
constructor(scope, electron, denyLaunch) {
|
|
31
31
|
super(scope, electron, "Electron", {});
|
|
32
32
|
this._type_Electron = true;
|
|
33
|
+
this._denyLaunch = denyLaunch;
|
|
33
34
|
}
|
|
34
35
|
async launch(params) {
|
|
36
|
+
if (this._denyLaunch)
|
|
37
|
+
throw new Error(`Launching more browsers is not allowed.`);
|
|
35
38
|
const electronApplication = await this._object.launch(params);
|
|
36
39
|
return { electronApplication: new ElectronApplicationDispatcher(this, electronApplication) };
|
|
37
40
|
}
|
|
@@ -35,12 +35,13 @@ var import_instrumentation = require("../instrumentation");
|
|
|
35
35
|
var import_eventsHelper = require("../utils/eventsHelper");
|
|
36
36
|
class PlaywrightDispatcher extends import_dispatcher.Dispatcher {
|
|
37
37
|
constructor(scope, playwright, options = {}) {
|
|
38
|
-
const
|
|
39
|
-
const
|
|
40
|
-
const
|
|
41
|
-
const
|
|
42
|
-
const
|
|
43
|
-
const
|
|
38
|
+
const denyLaunch = options.denyLaunch ?? false;
|
|
39
|
+
const chromium = new import_browserTypeDispatcher.BrowserTypeDispatcher(scope, playwright.chromium, denyLaunch);
|
|
40
|
+
const firefox = new import_browserTypeDispatcher.BrowserTypeDispatcher(scope, playwright.firefox, denyLaunch);
|
|
41
|
+
const webkit = new import_browserTypeDispatcher.BrowserTypeDispatcher(scope, playwright.webkit, denyLaunch);
|
|
42
|
+
const bidiChromium = new import_browserTypeDispatcher.BrowserTypeDispatcher(scope, playwright.bidiChromium, denyLaunch);
|
|
43
|
+
const bidiFirefox = new import_browserTypeDispatcher.BrowserTypeDispatcher(scope, playwright.bidiFirefox, denyLaunch);
|
|
44
|
+
const android = new import_androidDispatcher.AndroidDispatcher(scope, playwright.android, denyLaunch);
|
|
44
45
|
const initializer = {
|
|
45
46
|
chromium,
|
|
46
47
|
firefox,
|
|
@@ -48,7 +49,7 @@ class PlaywrightDispatcher extends import_dispatcher.Dispatcher {
|
|
|
48
49
|
bidiChromium,
|
|
49
50
|
bidiFirefox,
|
|
50
51
|
android,
|
|
51
|
-
electron: new import_electronDispatcher.ElectronDispatcher(scope, playwright.electron),
|
|
52
|
+
electron: new import_electronDispatcher.ElectronDispatcher(scope, playwright.electron, denyLaunch),
|
|
52
53
|
utils: playwright.options.isServer ? void 0 : new import_localUtilsDispatcher.LocalUtilsDispatcher(scope, playwright),
|
|
53
54
|
socksSupport: options.socksProxy ? new SocksSupportDispatcher(scope, playwright, options.socksProxy) : void 0
|
|
54
55
|
};
|
package/lib/server/dom.js
CHANGED
|
@@ -79,7 +79,7 @@ class FrameExecutionContext extends js.ExecutionContext {
|
|
|
79
79
|
const selectorsRegistry = this.frame._page.browserContext.selectors();
|
|
80
80
|
for (const [name, { source: source2 }] of selectorsRegistry._engines)
|
|
81
81
|
customEngines.push({ name, source: `(${source2})` });
|
|
82
|
-
const sdkLanguage = this.frame.
|
|
82
|
+
const sdkLanguage = this.frame._page.browserContext._browser.sdkLanguage();
|
|
83
83
|
const options = {
|
|
84
84
|
isUnderTest: (0, import_utils.isUnderTest)(),
|
|
85
85
|
sdkLanguage,
|
|
@@ -305,7 +305,7 @@ class ElementHandle extends js.JSHandle {
|
|
|
305
305
|
}
|
|
306
306
|
if (!options.skipActionPreChecks && !options.force)
|
|
307
307
|
await this._frame._page.performActionPreChecks(progress);
|
|
308
|
-
const result = await action();
|
|
308
|
+
const result = await action(retry);
|
|
309
309
|
++retry;
|
|
310
310
|
if (result === "error:notvisible") {
|
|
311
311
|
if (options.force)
|
|
@@ -336,21 +336,15 @@ class ElementHandle extends js.JSHandle {
|
|
|
336
336
|
}
|
|
337
337
|
async _retryPointerAction(progress, actionName, waitForEnabled, action, options) {
|
|
338
338
|
const skipActionPreChecks = actionName === "move and up";
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
const result = await this._performPointerAction(progress, actionName, waitForEnabled, action, forceScrollOptions, options);
|
|
349
|
-
if (typeof result === "object" && "hasPositionStickyOrFixed" in result && result.hasPositionStickyOrFixed)
|
|
350
|
-
++scrollOptionIndex;
|
|
351
|
-
else
|
|
352
|
-
scrollOptionIndex = 0;
|
|
353
|
-
return result;
|
|
339
|
+
return await this._retryAction(progress, actionName, async (retry) => {
|
|
340
|
+
const scrollOptions = [
|
|
341
|
+
void 0,
|
|
342
|
+
{ block: "end", inline: "end" },
|
|
343
|
+
{ block: "center", inline: "center" },
|
|
344
|
+
{ block: "start", inline: "start" }
|
|
345
|
+
];
|
|
346
|
+
const forceScrollOptions = scrollOptions[retry % scrollOptions.length];
|
|
347
|
+
return await this._performPointerAction(progress, actionName, waitForEnabled, action, forceScrollOptions, options);
|
|
354
348
|
}, { ...options, skipActionPreChecks });
|
|
355
349
|
}
|
|
356
350
|
async _performPointerAction(progress, actionName, waitForEnabled, action, forceScrollOptions, options) {
|
|
@@ -414,7 +408,7 @@ class ElementHandle extends js.JSHandle {
|
|
|
414
408
|
const error = handle.rawValue();
|
|
415
409
|
if (error === "error:notconnected")
|
|
416
410
|
return error;
|
|
417
|
-
return
|
|
411
|
+
return { hitTargetDescription: error };
|
|
418
412
|
}
|
|
419
413
|
hitTargetInterceptionHandle = handle;
|
|
420
414
|
progress.cleanupWhenAborted(() => {
|
|
@@ -102,7 +102,7 @@ class FrameSelectors {
|
|
|
102
102
|
for (const chunk of frameChunks) {
|
|
103
103
|
(0, import_selectorParser.visitAllSelectorParts)(chunk, (part, nested) => {
|
|
104
104
|
if (nested && part.name === "internal:control" && part.body === "enter-frame") {
|
|
105
|
-
const locator = (0, import_utils.asLocator)(this.frame._page.
|
|
105
|
+
const locator = (0, import_utils.asLocator)(this.frame._page.browserContext._browser.sdkLanguage(), selector);
|
|
106
106
|
throw new import_selectorParser.InvalidSelectorError(`Frame locators are not allowed inside composite locators, while querying "${locator}"`);
|
|
107
107
|
}
|
|
108
108
|
});
|
package/lib/server/frames.js
CHANGED
|
@@ -1434,7 +1434,7 @@ class Frame extends import_instrumentation.SdkObject {
|
|
|
1434
1434
|
});
|
|
1435
1435
|
}
|
|
1436
1436
|
_asLocator(selector) {
|
|
1437
|
-
return (0, import_utils.asLocator)(this._page.
|
|
1437
|
+
return (0, import_utils.asLocator)(this._page.browserContext._browser.sdkLanguage(), selector);
|
|
1438
1438
|
}
|
|
1439
1439
|
}
|
|
1440
1440
|
class SignalBarrier {
|
package/lib/server/page.js
CHANGED
|
@@ -348,11 +348,11 @@ class Page extends import_instrumentation.SdkObject {
|
|
|
348
348
|
}
|
|
349
349
|
if (handler.resolved) {
|
|
350
350
|
++this._locatorHandlerRunningCounter;
|
|
351
|
-
progress.log(` found ${(0, import_utils2.asLocator)(this.
|
|
351
|
+
progress.log(` found ${(0, import_utils2.asLocator)(this.browserContext._browser.sdkLanguage(), handler.selector)}, intercepting action to run the handler`);
|
|
352
352
|
const promise = handler.resolved.then(async () => {
|
|
353
353
|
progress.throwIfAborted();
|
|
354
354
|
if (!handler.noWaitAfter) {
|
|
355
|
-
progress.log(` locator handler has finished, waiting for ${(0, import_utils2.asLocator)(this.
|
|
355
|
+
progress.log(` locator handler has finished, waiting for ${(0, import_utils2.asLocator)(this.browserContext._browser.sdkLanguage(), handler.selector)} to be hidden`);
|
|
356
356
|
await this.mainFrame().waitForSelectorInternal(progress, handler.selector, false, { state: "hidden" });
|
|
357
357
|
} else {
|
|
358
358
|
progress.log(` locator handler has finished`);
|
|
@@ -57,7 +57,7 @@ class ContextRecorder extends import_events.EventEmitter {
|
|
|
57
57
|
this._params = params;
|
|
58
58
|
this._delegate = delegate;
|
|
59
59
|
this._recorderSources = [];
|
|
60
|
-
const language = params.language || context.
|
|
60
|
+
const language = params.language || context._browser.sdkLanguage();
|
|
61
61
|
this.setOutput(language, params.outputFile);
|
|
62
62
|
const languageGeneratorOptions = {
|
|
63
63
|
browserName: context._browser.options.name,
|
|
@@ -109,7 +109,7 @@ class RecorderApp extends import_events.EventEmitter {
|
|
|
109
109
|
};
|
|
110
110
|
}
|
|
111
111
|
static async _open(recorder, inspectedContext) {
|
|
112
|
-
const sdkLanguage = inspectedContext.
|
|
112
|
+
const sdkLanguage = inspectedContext._browser.sdkLanguage();
|
|
113
113
|
const headed = !!inspectedContext._browser.options.headful;
|
|
114
114
|
const recorderPlaywright = require("../playwright").createPlaywright({ sdkLanguage: "javascript", isInternalPlaywright: true });
|
|
115
115
|
const { context, page } = await (0, import_launchApp2.launchApp)(recorderPlaywright.chromium, {
|
|
@@ -78,7 +78,7 @@ class Tracing extends import_instrumentation.SdkObject {
|
|
|
78
78
|
platform: process.platform,
|
|
79
79
|
wallTime: 0,
|
|
80
80
|
monotonicTime: 0,
|
|
81
|
-
sdkLanguage:
|
|
81
|
+
sdkLanguage: this._sdkLanguage(),
|
|
82
82
|
testIdAttributeName,
|
|
83
83
|
contextId: context.guid
|
|
84
84
|
};
|
|
@@ -90,6 +90,9 @@ class Tracing extends import_instrumentation.SdkObject {
|
|
|
90
90
|
this._contextCreatedEvent.options = context._options;
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
|
+
_sdkLanguage() {
|
|
94
|
+
return this._context instanceof import_browserContext.BrowserContext ? this._context._browser.sdkLanguage() : this._context.attribution.playwright.options.sdkLanguage;
|
|
95
|
+
}
|
|
93
96
|
async resetForReuse() {
|
|
94
97
|
await this.stopChunk({ mode: "discard" }).catch(() => {
|
|
95
98
|
});
|
|
@@ -101,7 +104,7 @@ class Tracing extends import_instrumentation.SdkObject {
|
|
|
101
104
|
throw new Error("Cannot start tracing while stopping");
|
|
102
105
|
if (this._state)
|
|
103
106
|
throw new Error("Tracing has been already started");
|
|
104
|
-
this._contextCreatedEvent.sdkLanguage = this.
|
|
107
|
+
this._contextCreatedEvent.sdkLanguage = this._sdkLanguage();
|
|
105
108
|
const traceName = options.name || (0, import_crypto.createGuid)();
|
|
106
109
|
const tracesDir = this._createTracesDirIfNeeded();
|
|
107
110
|
this._state = {
|
|
@@ -148,7 +148,6 @@ async function openTraceViewerApp(url, browserName, options) {
|
|
|
148
148
|
const traceViewerPlaywright = (0, import_playwright.createPlaywright)({ sdkLanguage: "javascript", isInternalPlaywright: true });
|
|
149
149
|
const traceViewerBrowser = (0, import_utils2.isUnderTest)() ? "chromium" : browserName;
|
|
150
150
|
const { context, page } = await (0, import_launchApp2.launchApp)(traceViewerPlaywright[traceViewerBrowser], {
|
|
151
|
-
// TODO: store language in the trace.
|
|
152
151
|
sdkLanguage: traceViewerPlaywright.options.sdkLanguage,
|
|
153
152
|
windowSize: { width: 1280, height: 800 },
|
|
154
153
|
persistentContextOptions: {
|
|
@@ -112,7 +112,6 @@ class WSServer {
|
|
|
112
112
|
this._wsServer = void 0;
|
|
113
113
|
this.server = void 0;
|
|
114
114
|
import_debugLogger.debugLogger.log("server", "closed server");
|
|
115
|
-
await this._delegate.onClose?.();
|
|
116
115
|
}
|
|
117
116
|
}
|
|
118
117
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -22,7 +22,7 @@ __export(protocolMetainfo_exports, {
|
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(protocolMetainfo_exports);
|
|
24
24
|
const methodMetainfo = /* @__PURE__ */ new Map([
|
|
25
|
-
["APIRequestContext.fetch", { title: '
|
|
25
|
+
["APIRequestContext.fetch", { title: '{method} "{url}"' }],
|
|
26
26
|
["APIRequestContext.fetchResponseBody", { internal: true }],
|
|
27
27
|
["APIRequestContext.fetchLog", { internal: true }],
|
|
28
28
|
["APIRequestContext.storageState", { internal: true }],
|