@smoothdeploy/playwright-core 1.57.1 → 1.58.1-beta-1770452953000

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.

Potentially problematic release.


This version of @smoothdeploy/playwright-core might be problematic. Click here for more details.

Files changed (155) hide show
  1. package/ThirdPartyNotices.txt +3223 -308
  2. package/browsers.json +21 -22
  3. package/lib/cli/program.js +4 -5
  4. package/lib/client/api.js +3 -0
  5. package/lib/client/browser.js +3 -5
  6. package/lib/client/browserContext.js +35 -0
  7. package/lib/client/browserType.js +4 -3
  8. package/lib/client/channelOwner.js +4 -3
  9. package/lib/client/clientInstrumentation.js +10 -0
  10. package/lib/client/connection.js +4 -0
  11. package/lib/client/elementHandle.js +3 -0
  12. package/lib/client/events.js +3 -0
  13. package/lib/client/fetch.js +3 -4
  14. package/lib/client/frame.js +1 -0
  15. package/lib/client/page.js +28 -1
  16. package/lib/client/pageAgent.js +64 -0
  17. package/lib/client/platform.js +3 -0
  18. package/lib/generated/injectedScriptSource.js +1 -1
  19. package/lib/generated/pollingRecorderSource.js +1 -1
  20. package/lib/mcpBundle.js +84 -0
  21. package/lib/mcpBundleImpl/index.js +147 -0
  22. package/lib/protocol/serializers.js +5 -0
  23. package/lib/protocol/validator.js +92 -3
  24. package/lib/remote/playwrightServer.js +1 -2
  25. package/lib/server/agent/actionRunner.js +335 -0
  26. package/lib/server/agent/actions.js +128 -0
  27. package/lib/server/agent/codegen.js +111 -0
  28. package/lib/server/agent/context.js +150 -0
  29. package/lib/server/agent/expectTools.js +156 -0
  30. package/lib/server/agent/pageAgent.js +204 -0
  31. package/lib/server/agent/performTools.js +262 -0
  32. package/lib/server/agent/tool.js +109 -0
  33. package/lib/server/artifact.js +1 -1
  34. package/lib/server/bidi/bidiBrowser.js +56 -12
  35. package/lib/server/bidi/bidiChromium.js +6 -11
  36. package/lib/server/bidi/bidiConnection.js +1 -0
  37. package/lib/server/bidi/bidiDeserializer.js +116 -0
  38. package/lib/server/bidi/bidiExecutionContext.js +75 -29
  39. package/lib/server/bidi/bidiFirefox.js +6 -8
  40. package/lib/server/bidi/bidiNetworkManager.js +1 -1
  41. package/lib/server/bidi/bidiPage.js +39 -28
  42. package/lib/server/bidi/third_party/bidiProtocolCore.js +1 -0
  43. package/lib/server/browserContext.js +32 -25
  44. package/lib/server/browserType.js +12 -4
  45. package/lib/server/chromium/chromium.js +14 -21
  46. package/lib/server/chromium/chromiumSwitches.js +2 -2
  47. package/lib/server/chromium/crBrowser.js +22 -12
  48. package/lib/server/chromium/crConnection.js +0 -5
  49. package/lib/server/chromium/crDevTools.js +0 -2
  50. package/lib/server/chromium/crNetworkManager.js +43 -2
  51. package/lib/server/chromium/crPage.js +19 -87
  52. package/lib/server/codegen/javascript.js +6 -29
  53. package/lib/server/deviceDescriptorsSource.json +56 -56
  54. package/lib/server/dispatchers/browserContextDispatcher.js +3 -0
  55. package/lib/server/dispatchers/dispatcher.js +6 -13
  56. package/lib/server/dispatchers/frameDispatcher.js +1 -1
  57. package/lib/server/dispatchers/pageAgentDispatcher.js +96 -0
  58. package/lib/server/dispatchers/pageDispatcher.js +4 -0
  59. package/lib/server/dom.js +12 -3
  60. package/lib/server/electron/electron.js +5 -2
  61. package/lib/server/firefox/ffBrowser.js +10 -20
  62. package/lib/server/firefox/ffConnection.js +0 -5
  63. package/lib/server/firefox/ffNetworkManager.js +2 -2
  64. package/lib/server/firefox/ffPage.js +15 -18
  65. package/lib/server/firefox/firefox.js +6 -8
  66. package/lib/server/frameSelectors.js +9 -3
  67. package/lib/server/frames.js +49 -33
  68. package/lib/server/instrumentation.js +3 -0
  69. package/lib/server/network.js +50 -12
  70. package/lib/server/page.js +33 -89
  71. package/lib/server/progress.js +26 -6
  72. package/lib/server/recorder/recorderApp.js +79 -100
  73. package/lib/server/recorder.js +55 -0
  74. package/lib/server/registry/browserFetcher.js +6 -4
  75. package/lib/server/registry/index.js +172 -149
  76. package/lib/server/registry/oopDownloadBrowserMain.js +3 -0
  77. package/lib/server/screencast.js +190 -0
  78. package/lib/server/screenshotCompositor.js +153 -0
  79. package/lib/server/trace/recorder/snapshotterInjected.js +21 -1
  80. package/lib/server/trace/recorder/tracing.js +21 -21
  81. package/lib/server/trace/viewer/traceParser.js +72 -0
  82. package/lib/server/trace/viewer/traceViewer.js +17 -13
  83. package/lib/server/utils/expectUtils.js +87 -2
  84. package/lib/server/utils/httpServer.js +4 -19
  85. package/lib/server/utils/network.js +37 -28
  86. package/lib/server/utils/nodePlatform.js +6 -0
  87. package/lib/server/videoRecorder.js +124 -0
  88. package/lib/server/webkit/webkit.js +4 -6
  89. package/lib/server/webkit/wkBrowser.js +2 -6
  90. package/lib/server/webkit/wkConnection.js +1 -6
  91. package/lib/server/webkit/wkInterceptableRequest.js +29 -1
  92. package/lib/server/webkit/wkPage.js +75 -46
  93. package/lib/utils/isomorphic/ariaSnapshot.js +60 -2
  94. package/lib/utils/isomorphic/lruCache.js +51 -0
  95. package/lib/utils/isomorphic/protocolMetainfo.js +9 -1
  96. package/lib/utils/isomorphic/stringUtils.js +49 -0
  97. package/lib/utils/isomorphic/trace/entries.js +16 -0
  98. package/lib/utils/isomorphic/trace/snapshotRenderer.js +499 -0
  99. package/lib/utils/isomorphic/trace/snapshotServer.js +120 -0
  100. package/lib/utils/isomorphic/trace/snapshotStorage.js +89 -0
  101. package/lib/utils/isomorphic/trace/traceLoader.js +131 -0
  102. package/lib/utils/isomorphic/trace/traceModel.js +365 -0
  103. package/lib/utils/isomorphic/trace/traceModernizer.js +400 -0
  104. package/lib/utils/isomorphic/trace/versions/traceV3.js +16 -0
  105. package/lib/utils/isomorphic/trace/versions/traceV4.js +16 -0
  106. package/lib/utils/isomorphic/trace/versions/traceV5.js +16 -0
  107. package/lib/utils/isomorphic/trace/versions/traceV6.js +16 -0
  108. package/lib/utils/isomorphic/trace/versions/traceV7.js +16 -0
  109. package/lib/utils/isomorphic/trace/versions/traceV8.js +16 -0
  110. package/lib/utils/isomorphic/yaml.js +84 -0
  111. package/lib/utils.js +2 -0
  112. package/lib/utilsBundle.js +2 -5
  113. package/lib/utilsBundleImpl/index.js +165 -165
  114. package/lib/vite/htmlReport/index.html +21 -21
  115. package/lib/vite/recorder/assets/{codeMirrorModule-C3UTv-Ge.css → codeMirrorModule-DYBRYzYX.css} +1 -1
  116. package/lib/vite/recorder/assets/codeMirrorModule-DadYNm1I.js +32 -0
  117. package/lib/vite/recorder/assets/{index-Ri0uHF7I.css → index-BSjZa4pk.css} +1 -1
  118. package/lib/vite/recorder/assets/index-BhTWtUlo.js +193 -0
  119. package/lib/vite/recorder/index.html +2 -2
  120. package/lib/vite/traceViewer/assets/codeMirrorModule-8UJPCtp4.js +16884 -0
  121. package/lib/vite/{recorder/assets/codeMirrorModule-BoWUGj0J.js → traceViewer/assets/codeMirrorModule-BNr6yhVP.js} +1 -1
  122. package/lib/vite/traceViewer/assets/codeMirrorModule-Dimjuz94.js +32 -0
  123. package/lib/vite/traceViewer/assets/codeMirrorModule-DkmsYcws.js +32 -0
  124. package/lib/vite/traceViewer/assets/codeMirrorModule-DySgctgr.js +16884 -0
  125. package/lib/vite/traceViewer/assets/defaultSettingsView-B1vuWQsF.js +266 -0
  126. package/lib/vite/traceViewer/assets/defaultSettingsView-CtEsdeVH.js +266 -0
  127. package/lib/vite/traceViewer/assets/defaultSettingsView-D4fm31R-.js +34087 -0
  128. package/lib/vite/traceViewer/assets/defaultSettingsView-JtyB0yzL.js +34087 -0
  129. package/lib/vite/traceViewer/assets/defaultSettingsView-tEZf-LNj.js +266 -0
  130. package/lib/vite/traceViewer/assets/xtermModule-DDw6eROI.js +6168 -0
  131. package/lib/vite/traceViewer/codeMirrorModule.DYBRYzYX.css +1 -0
  132. package/lib/vite/traceViewer/codeMirrorModule.DuST8d_k.css +344 -0
  133. package/lib/vite/traceViewer/defaultSettingsView.5FCqBwKs.css +3986 -0
  134. package/lib/vite/traceViewer/defaultSettingsView.7ch9cixO.css +1 -0
  135. package/lib/vite/traceViewer/index.BQs8gGhY.js +249 -0
  136. package/lib/vite/traceViewer/index.BVu7tZDe.css +1 -0
  137. package/lib/vite/traceViewer/index.BoLn624r.js +2 -0
  138. package/lib/vite/traceViewer/index.Bq_EaK8x.js +249 -0
  139. package/lib/vite/traceViewer/index.C8YVh4B5.js +2 -0
  140. package/lib/vite/traceViewer/index.Cr7-GRf8.js +2 -0
  141. package/lib/vite/traceViewer/index.G-7UhDxt.css +164 -0
  142. package/lib/vite/traceViewer/index.html +4 -4
  143. package/lib/vite/traceViewer/sw.bundle.js +5 -3
  144. package/lib/vite/traceViewer/uiMode.-Kflt2XM.css +1440 -0
  145. package/lib/vite/traceViewer/uiMode.BTRKnokb.js +5 -0
  146. package/lib/vite/traceViewer/uiMode.CEZ5RVHh.js +5 -0
  147. package/lib/vite/traceViewer/uiMode.CIWF23si.js +1829 -0
  148. package/lib/vite/traceViewer/uiMode.Wi-DvIEY.js +1829 -0
  149. package/lib/vite/traceViewer/uiMode.html +3 -3
  150. package/lib/vite/traceViewer/uiMode.zEH1ejvz.js +5 -0
  151. package/lib/vite/traceViewer/xtermModule.BKlWQB97.css +218 -0
  152. package/package.json +3 -1
  153. package/types/protocol.d.ts +738 -159
  154. package/types/types.d.ts +25 -38
  155. package/lib/vite/recorder/assets/index-DJqDAOZp.js +0 -193
@@ -36,9 +36,9 @@ var import_utils = require("../../utils");
36
36
  var import_utilityScriptSerializers = require("../../utils/isomorphic/utilityScriptSerializers");
37
37
  var js = __toESM(require("../javascript"));
38
38
  var dom = __toESM(require("../dom"));
39
- var import_bidiDeserializer = require("./third_party/bidiDeserializer");
40
39
  var bidi = __toESM(require("./third_party/bidiProtocol"));
41
40
  var import_bidiSerializer = require("./third_party/bidiSerializer");
41
+ var import_bidiDeserializer = require("./bidiDeserializer");
42
42
  class BidiExecutionContext {
43
43
  constructor(session, realmInfo) {
44
44
  this._session = session;
@@ -65,7 +65,7 @@ class BidiExecutionContext {
65
65
  userActivation: true
66
66
  });
67
67
  if (response.type === "success")
68
- return import_bidiDeserializer.BidiDeserializer.deserialize(response.result);
68
+ return (0, import_bidiDeserializer.deserializeBidiValue)(response.result);
69
69
  if (response.type === "exception")
70
70
  throw new js.JavaScriptErrorInEvaluate(response.exceptionDetails.text);
71
71
  throw new js.JavaScriptErrorInEvaluate("Unexpected response type: " + JSON.stringify(response));
@@ -108,7 +108,7 @@ class BidiExecutionContext {
108
108
  throw new js.JavaScriptErrorInEvaluate(response.exceptionDetails.text);
109
109
  if (response.type === "success") {
110
110
  if (returnByValue)
111
- return (0, import_utilityScriptSerializers.parseEvaluationResultValue)(import_bidiDeserializer.BidiDeserializer.deserialize(response.result));
111
+ return (0, import_utilityScriptSerializers.parseEvaluationResultValue)((0, import_bidiDeserializer.deserializeBidiValue)(response.result));
112
112
  return createHandle(utilityScript._context, response.result);
113
113
  }
114
114
  throw new js.JavaScriptErrorInEvaluate("Unexpected response type: " + JSON.stringify(response));
@@ -123,7 +123,10 @@ class BidiExecutionContext {
123
123
  }
124
124
  return names2;
125
125
  });
126
- const values = await Promise.all(names.map((name) => handle.evaluateHandle((object, name2) => object[name2], name)));
126
+ const values = await Promise.all(names.map(async (name) => {
127
+ const value = await this._rawCallFunction("(object, name) => object[name]", [{ handle: handle._objectId }, { type: "string", value: name }], true, false);
128
+ return createHandle(handle._context, value);
129
+ }));
127
130
  const map = /* @__PURE__ */ new Map();
128
131
  for (let i = 0; i < names.length; i++)
129
132
  map.set(names[i], values[i]);
@@ -152,7 +155,7 @@ class BidiExecutionContext {
152
155
  return createHandle(context, result);
153
156
  }
154
157
  async contentFrameIdForFrame(handle) {
155
- const contentWindow = await this._rawCallFunction("e => e.contentWindow", { handle: handle._objectId });
158
+ const contentWindow = await this._rawCallFunction("e => e.contentWindow", [{ handle: handle._objectId }]);
156
159
  if (contentWindow?.type === "window")
157
160
  return contentWindow.value.context;
158
161
  return null;
@@ -166,17 +169,17 @@ class BidiExecutionContext {
166
169
  return null;
167
170
  }
168
171
  async _remoteValueForReference(reference, createHandle2) {
169
- return await this._rawCallFunction("e => e", reference, createHandle2);
172
+ return await this._rawCallFunction("e => e", [reference], createHandle2);
170
173
  }
171
- async _rawCallFunction(functionDeclaration, arg, createHandle2) {
174
+ async _rawCallFunction(functionDeclaration, args, createHandle2, awaitPromise = true) {
172
175
  const response = await this._session.send("script.callFunction", {
173
176
  functionDeclaration,
174
177
  target: this._target,
175
- arguments: [arg],
178
+ arguments: args,
176
179
  // "Root" is necessary for the handle to be returned.
177
180
  resultOwnership: createHandle2 ? bidi.Script.ResultOwnership.Root : bidi.Script.ResultOwnership.None,
178
181
  serializationOptions: { maxObjectDepth: 0, maxDomDepth: 0 },
179
- awaitPromise: true,
182
+ awaitPromise,
180
183
  userActivation: true
181
184
  });
182
185
  if (response.type === "exception")
@@ -186,25 +189,65 @@ class BidiExecutionContext {
186
189
  throw new js.JavaScriptErrorInEvaluate("Unexpected response type: " + JSON.stringify(response));
187
190
  }
188
191
  }
189
- function renderPreview(remoteObject) {
190
- if (remoteObject.type === "undefined")
191
- return "undefined";
192
- if (remoteObject.type === "null")
193
- return "null";
194
- if ("value" in remoteObject)
195
- return String(remoteObject.value);
196
- return `<${remoteObject.type}>`;
197
- }
198
- function remoteObjectValue(remoteObject) {
199
- if (remoteObject.type === "undefined")
200
- return void 0;
201
- if (remoteObject.type === "null")
202
- return null;
203
- if (remoteObject.type === "number" && typeof remoteObject.value === "string")
204
- return js.parseUnserializableValue(remoteObject.value);
205
- if ("value" in remoteObject)
206
- return remoteObject.value;
207
- return void 0;
192
+ function renderPreview(remoteObject, nested = false) {
193
+ switch (remoteObject.type) {
194
+ case "undefined":
195
+ case "null":
196
+ return remoteObject.type;
197
+ case "number":
198
+ case "boolean":
199
+ case "string":
200
+ return String(remoteObject.value);
201
+ case "bigint":
202
+ return `${remoteObject.value}n`;
203
+ case "date":
204
+ return String(new Date(remoteObject.value));
205
+ case "regexp":
206
+ return String(new RegExp(remoteObject.value.pattern, remoteObject.value.flags));
207
+ case "node":
208
+ return remoteObject.value?.localName || "Node";
209
+ case "object":
210
+ if (nested)
211
+ return "Object";
212
+ const tokens = [];
213
+ for (const [name, value] of remoteObject.value || []) {
214
+ if (typeof name === "string")
215
+ tokens.push(`${name}: ${renderPreview(value, true)}`);
216
+ }
217
+ return `{${tokens.join(", ")}}`;
218
+ case "array":
219
+ case "htmlcollection":
220
+ case "nodelist":
221
+ if (nested || !remoteObject.value)
222
+ return remoteObject.value ? `Array(${remoteObject.value.length})` : "Array";
223
+ return `[${remoteObject.value.map((v) => renderPreview(v, true)).join(", ")}]`;
224
+ case "map":
225
+ return remoteObject.value ? `Map(${remoteObject.value.length})` : "Map";
226
+ case "set":
227
+ return remoteObject.value ? `Set(${remoteObject.value.length})` : "Set";
228
+ case "arraybuffer":
229
+ return "ArrayBuffer";
230
+ case "error":
231
+ return "Error";
232
+ case "function":
233
+ return "Function";
234
+ case "generator":
235
+ return "Generator";
236
+ case "promise":
237
+ return "Promise";
238
+ case "proxy":
239
+ return "Proxy";
240
+ case "symbol":
241
+ return "Symbol()";
242
+ case "typedarray":
243
+ return "TypedArray";
244
+ case "weakmap":
245
+ return "WeakMap";
246
+ case "weakset":
247
+ return "WeakSet";
248
+ case "window":
249
+ return "Window";
250
+ }
208
251
  }
209
252
  function createHandle(context, remoteObject) {
210
253
  if (remoteObject.type === "node") {
@@ -212,7 +255,10 @@ function createHandle(context, remoteObject) {
212
255
  return new dom.ElementHandle(context, remoteObject.handle);
213
256
  }
214
257
  const objectId = "handle" in remoteObject ? remoteObject.handle : void 0;
215
- return new js.JSHandle(context, remoteObject.type, renderPreview(remoteObject), objectId, remoteObjectValue(remoteObject));
258
+ const preview = renderPreview(remoteObject);
259
+ const handle = new js.JSHandle(context, remoteObject.type, preview, objectId, (0, import_bidiDeserializer.deserializeBidiValue)(remoteObject));
260
+ handle._setPreview(preview);
261
+ return handle;
216
262
  }
217
263
  // Annotate the CommonJS export names for ESM import in node:
218
264
  0 && (module.exports = {
@@ -49,15 +49,13 @@ class BidiFirefox extends import_browserType.BrowserType {
49
49
  async connectToTransport(transport, options) {
50
50
  return import_bidiBrowser.BidiBrowser.connect(this.attribution.playwright, transport, options);
51
51
  }
52
- doRewriteStartupLog(error) {
53
- if (!error.logs)
54
- return error;
55
- if (error.logs.includes(`as root in a regular user's session is not supported.`))
56
- error.logs = "\n" + (0, import_ascii.wrapInASCIIBox)(`Firefox is unable to launch if the $HOME folder isn't owned by the current user.
52
+ doRewriteStartupLog(logs) {
53
+ if (logs.includes(`as root in a regular user's session is not supported.`))
54
+ logs = "\n" + (0, import_ascii.wrapInASCIIBox)(`Firefox is unable to launch if the $HOME folder isn't owned by the current user.
57
55
  Workaround: Set the HOME=/root environment variable${process.env.GITHUB_ACTION ? " in your GitHub Actions workflow file" : ""} when running Playwright.`, 1);
58
- if (error.logs.includes("no DISPLAY environment variable specified"))
59
- error.logs = "\n" + (0, import_ascii.wrapInASCIIBox)(import_browserType.kNoXServerRunningError, 1);
60
- return error;
56
+ if (logs.includes("no DISPLAY environment variable specified"))
57
+ logs = "\n" + (0, import_ascii.wrapInASCIIBox)(import_browserType.kNoXServerRunningError, 1);
58
+ return logs;
61
59
  }
62
60
  amendEnvironment(env) {
63
61
  if (!import_path.default.isAbsolute(import_os.default.homedir()))
@@ -342,7 +342,7 @@ function resourceTypeFromBidi(requestDestination, requestInitiatorType, eventIni
342
342
  case "image":
343
343
  return "image";
344
344
  case "object":
345
- return "object";
345
+ return "other";
346
346
  case "paintworklet":
347
347
  return "script";
348
348
  case "script":
@@ -32,6 +32,7 @@ __export(bidiPage_exports, {
32
32
  kPlaywrightBindingChannel: () => kPlaywrightBindingChannel
33
33
  });
34
34
  module.exports = __toCommonJS(bidiPage_exports);
35
+ var import_debugLogger = require("../utils/debugLogger");
35
36
  var import_eventsHelper = require("../utils/eventsHelper");
36
37
  var dialog = __toESM(require("../dialog"));
37
38
  var dom = __toESM(require("../dom"));
@@ -87,8 +88,7 @@ class BidiPage {
87
88
  async _initialize() {
88
89
  this._onFrameAttached(this._session.sessionId, null);
89
90
  await Promise.all([
90
- this.updateHttpCredentials(),
91
- this.updateRequestInterception()
91
+ this.updateHttpCredentials()
92
92
  // If the page is created by the Playwright client's call, some initialization
93
93
  // may be pending. Wait for it to complete before reporting the page as new.
94
94
  ]);
@@ -179,10 +179,12 @@ class BidiPage {
179
179
  }
180
180
  _onNavigationCommitted(params) {
181
181
  const frameId = params.context;
182
+ const frame = this._page.frameManager.frame(frameId);
183
+ this._browserContext.doGrantGlobalPermissionsForURL(params.url).catch((error) => import_debugLogger.debugLogger.log("error", error));
182
184
  this._page.frameManager.frameCommittedNewDocumentNavigation(
183
185
  frameId,
184
186
  params.url,
185
- "",
187
+ frame._name,
186
188
  params.navigation,
187
189
  /* initial */
188
190
  false
@@ -263,7 +265,7 @@ ${params.stackTrace?.callFrames.map((f) => {
263
265
  return;
264
266
  const callFrame = params.stackTrace?.callFrames[0];
265
267
  const location = callFrame ?? { url: "", lineNumber: 1, columnNumber: 1 };
266
- this._page.addConsoleMessage(null, entry.method, entry.args.map((arg) => (0, import_bidiExecutionContext.createHandle)(context, arg)), location, params.text || void 0);
268
+ this._page.addConsoleMessage(null, entry.method, entry.args.map((arg) => (0, import_bidiExecutionContext.createHandle)(context, arg)), location);
267
269
  }
268
270
  async _onFileDialogOpened(params) {
269
271
  if (!params.element)
@@ -272,8 +274,11 @@ ${params.stackTrace?.callFrames.map((f) => {
272
274
  if (!frame)
273
275
  return;
274
276
  const executionContext = await frame._mainContext();
275
- const handle = await toBidiExecutionContext(executionContext).remoteObjectForNodeId(executionContext, { sharedId: params.element.sharedId });
276
- await this._page._onFileChooserOpened(handle);
277
+ try {
278
+ const handle = await toBidiExecutionContext(executionContext).remoteObjectForNodeId(executionContext, { sharedId: params.element.sharedId });
279
+ await this._page._onFileChooserOpened(handle);
280
+ } catch {
281
+ }
277
282
  }
278
283
  async navigateFrame(frame, url, referrer) {
279
284
  const { navigation } = await this._session.send("browsingContext.navigate", {
@@ -306,6 +311,7 @@ ${params.stackTrace?.callFrames.map((f) => {
306
311
  const emulatedSize = this._page.emulatedSize();
307
312
  if (!emulatedSize)
308
313
  return;
314
+ const screenSize = emulatedSize.screen;
309
315
  const viewportSize = emulatedSize.viewport;
310
316
  await Promise.all([
311
317
  this._session.send("browsingContext.setViewport", {
@@ -318,12 +324,19 @@ ${params.stackTrace?.callFrames.map((f) => {
318
324
  }),
319
325
  this._session.send("emulation.setScreenOrientationOverride", {
320
326
  contexts: [this._session.sessionId],
321
- screenOrientation: (0, import_bidiBrowser.getScreenOrientation)(!!options.isMobile, viewportSize)
327
+ screenOrientation: (0, import_bidiBrowser.getScreenOrientation)(!!options.isMobile, screenSize)
328
+ }),
329
+ this._session.send("emulation.setScreenSettingsOverride", {
330
+ contexts: [this._session.sessionId],
331
+ screenArea: {
332
+ width: screenSize.width,
333
+ height: screenSize.height
334
+ }
322
335
  })
323
336
  ]);
324
337
  }
325
338
  async updateRequestInterception() {
326
- await this._networkManager.setRequestInterception(this._page.needsRequestInterception());
339
+ await this._networkManager.setRequestInterception(this._page.requestInterceptors.length > 0);
327
340
  }
328
341
  async updateOffline() {
329
342
  }
@@ -482,7 +495,9 @@ ${params.stackTrace?.callFrames.map((f) => {
482
495
  throw e;
483
496
  });
484
497
  }
485
- async setScreencastOptions(options) {
498
+ async startScreencast(options) {
499
+ }
500
+ async stopScreencast() {
486
501
  }
487
502
  rafCountForStablePosition() {
488
503
  return 1;
@@ -537,26 +552,22 @@ ${params.stackTrace?.callFrames.map((f) => {
537
552
  const parent = frame.parentFrame();
538
553
  if (!parent)
539
554
  throw new Error("Frame has been detached.");
540
- const parentContext = await parent._mainContext();
541
- const list = await parentContext.evaluateHandle(() => {
542
- return [...document.querySelectorAll("iframe,frame")];
543
- });
544
- const length = await list.evaluate((list2) => list2.length);
545
- let foundElement = null;
546
- for (let i = 0; i < length; i++) {
547
- const element = await list.evaluateHandle((list2, i2) => list2[i2], i);
548
- const candidate = await element.contentFrame();
549
- if (frame === candidate) {
550
- foundElement = element;
551
- break;
552
- } else {
553
- element.dispose();
554
- }
555
- }
556
- list.dispose();
557
- if (!foundElement)
555
+ const node = await this._getFrameNode(frame);
556
+ if (!node?.sharedId)
558
557
  throw new Error("Frame has been detached.");
559
- return foundElement;
558
+ const parentFrameExecutionContext = await parent._mainContext();
559
+ return await toBidiExecutionContext(parentFrameExecutionContext).remoteObjectForNodeId(parentFrameExecutionContext, { sharedId: node.sharedId });
560
+ }
561
+ async _getFrameNode(frame) {
562
+ const parent = frame.parentFrame();
563
+ if (!parent)
564
+ return void 0;
565
+ const result = await this._session.send("browsingContext.locateNodes", {
566
+ context: parent._id,
567
+ locator: { type: "context", value: { context: frame._id } }
568
+ });
569
+ const node = result.nodes[0];
570
+ return node;
560
571
  }
561
572
  shouldToggleStyleSheetToSyncAnimations() {
562
573
  return true;
@@ -128,6 +128,7 @@ var Network;
128
128
  ((Network2) => {
129
129
  let DataType;
130
130
  ((DataType2) => {
131
+ DataType2["Request"] = "request";
131
132
  DataType2["Response"] = "response";
132
133
  })(DataType = Network2.DataType || (Network2.DataType = {}));
133
134
  })(Network || (Network = {}));
@@ -55,6 +55,24 @@ var import_recorderApp = require("./recorder/recorderApp");
55
55
  var import_selectors = require("./selectors");
56
56
  var import_tracing = require("./trace/recorder/tracing");
57
57
  var rawStorageSource = __toESM(require("../generated/storageScriptSource"));
58
+ const BrowserContextEvent = {
59
+ Console: "console",
60
+ Close: "close",
61
+ Page: "page",
62
+ // Can't use just 'error' due to node.js special treatment of error events.
63
+ // @see https://nodejs.org/api/events.html#events_error_events
64
+ PageError: "pageerror",
65
+ Request: "request",
66
+ Response: "response",
67
+ RequestFailed: "requestfailed",
68
+ RequestFinished: "requestfinished",
69
+ RequestAborted: "requestaborted",
70
+ RequestFulfilled: "requestfulfilled",
71
+ RequestContinued: "requestcontinued",
72
+ BeforeClose: "beforeclose",
73
+ VideoStarted: "videostarted",
74
+ RecorderEvent: "recorderevent"
75
+ };
58
76
  class BrowserContext extends import_instrumentation.SdkObject {
59
77
  constructor(browser, options, browserContextId) {
60
78
  super(browser, "browser-context");
@@ -69,6 +87,7 @@ class BrowserContext extends import_instrumentation.SdkObject {
69
87
  this._creatingStorageStatePage = false;
70
88
  this.initScripts = [];
71
89
  this._routesInFlight = /* @__PURE__ */ new Set();
90
+ this._consoleApiExposed = false;
72
91
  this.attribution.context = this;
73
92
  this._browser = browser;
74
93
  this._options = options;
@@ -82,24 +101,7 @@ class BrowserContext extends import_instrumentation.SdkObject {
82
101
  this.dialogManager = new import_dialog.DialogManager(this.instrumentation);
83
102
  }
84
103
  static {
85
- this.Events = {
86
- Console: "console",
87
- Close: "close",
88
- Page: "page",
89
- // Can't use just 'error' due to node.js special treatment of error events.
90
- // @see https://nodejs.org/api/events.html#events_error_events
91
- PageError: "pageerror",
92
- Request: "request",
93
- Response: "response",
94
- RequestFailed: "requestfailed",
95
- RequestFinished: "requestfinished",
96
- RequestAborted: "requestaborted",
97
- RequestFulfilled: "requestfulfilled",
98
- RequestContinued: "requestcontinued",
99
- BeforeClose: "beforeclose",
100
- VideoStarted: "videostarted",
101
- RecorderEvent: "recorderevent"
102
- };
104
+ this.Events = BrowserContextEvent;
103
105
  }
104
106
  isPersistentContext() {
105
107
  return this._isPersistentContext;
@@ -119,12 +121,8 @@ class BrowserContext extends import_instrumentation.SdkObject {
119
121
  if (this._debugger.isPaused())
120
122
  import_recorderApp.RecorderApp.showInspectorNoReply(this);
121
123
  });
122
- if ((0, import_debug.debugMode)() === "console") {
123
- await this.extendInjectedScript(`
124
- function installConsoleApi(injectedScript) { injectedScript.consoleApi.install(); }
125
- module.exports = { default: () => installConsoleApi };
126
- `);
127
- }
124
+ if ((0, import_debug.debugMode)() === "console")
125
+ await this.exposeConsoleApi();
128
126
  if (this._options.serviceWorkers === "block")
129
127
  await this.addInitScript(void 0, `
130
128
  if (navigator.serviceWorker) navigator.serviceWorker.register = async () => { console.warn('Service Worker registration blocked by Playwright'); };
@@ -135,6 +133,15 @@ if (navigator.serviceWorker) navigator.serviceWorker.register = async () => { co
135
133
  debugger() {
136
134
  return this._debugger;
137
135
  }
136
+ async exposeConsoleApi() {
137
+ if (this._consoleApiExposed)
138
+ return;
139
+ this._consoleApiExposed = true;
140
+ await this.extendInjectedScript(`
141
+ function installConsoleApi(injectedScript) { injectedScript.consoleApi.install(); }
142
+ module.exports = { default: () => installConsoleApi };
143
+ `);
144
+ }
138
145
  async _ensureVideosPath() {
139
146
  if (this._options.recordVideo)
140
147
  await (0, import_fileUtils.mkdirIfNeeded)(import_path.default.join(this._options.recordVideo.dir, "dummy"));
@@ -322,7 +329,7 @@ if (navigator.serviceWorker) navigator.serviceWorker.register = async () => { co
322
329
  const pageOrError = await progress.race(page.waitForInitializedOrError());
323
330
  if (pageOrError instanceof Error)
324
331
  throw pageOrError;
325
- await page.mainFrame()._waitForLoadState(progress, "load");
332
+ await page.mainFrame().waitForLoadState(progress, "load");
326
333
  return page;
327
334
  }
328
335
  async _loadDefaultContext(progress) {
@@ -250,6 +250,13 @@ class BrowserType extends import_instrumentation.SdkObject {
250
250
  this.waitForReadyState(options, browserLogsCollector),
251
251
  exitPromise.then(() => ({ wsEndpoint: void 0 }))
252
252
  ]);
253
+ if (exitPromise.isDone()) {
254
+ const log = import_helper.helper.formatBrowserLogs(browserLogsCollector.recentLogs());
255
+ const updatedLog = this.doRewriteStartupLog(log);
256
+ throw new Error(`Failed to launch the browser process.
257
+ Browser logs:
258
+ ${updatedLog}`);
259
+ }
253
260
  if (options.cdpPort !== void 0 || !this.supportsPipeTransport()) {
254
261
  transport = await import_transport.WebSocketTransport.connect(progress, wsEndpoint);
255
262
  } else {
@@ -276,15 +283,14 @@ class BrowserType extends import_instrumentation.SdkObject {
276
283
  throw new Error("Connecting to SELENIUM_REMOTE_URL is only supported by Chromium");
277
284
  }
278
285
  _validateLaunchOptions(options) {
279
- const { devtools = false } = options;
280
- let { headless = !devtools, downloadsPath, proxy } = options;
286
+ let { headless = true, downloadsPath, proxy } = options;
281
287
  if ((0, import_debug.debugMode)() === "inspector")
282
288
  headless = false;
283
289
  if (downloadsPath && !import_path.default.isAbsolute(downloadsPath))
284
290
  downloadsPath = import_path.default.join(process.cwd(), downloadsPath);
285
291
  if (options.socksProxyPort)
286
292
  proxy = { server: `socks5://127.0.0.1:${options.socksProxyPort}` };
287
- return { ...options, devtools, headless, downloadsPath, proxy };
293
+ return { ...options, headless, downloadsPath, proxy };
288
294
  }
289
295
  _createUserDataDirArgMisuseError(userDataDirArg) {
290
296
  switch (this.attribution.playwright.options.sdkLanguage) {
@@ -301,7 +307,9 @@ class BrowserType extends import_instrumentation.SdkObject {
301
307
  _rewriteStartupLog(error) {
302
308
  if (!(0, import_protocolError.isProtocolError)(error))
303
309
  return error;
304
- return this.doRewriteStartupLog(error);
310
+ if (error.logs)
311
+ error.logs = this.doRewriteStartupLog(error.logs);
312
+ return error;
305
313
  }
306
314
  async waitForReadyState(options, browserLogsCollector) {
307
315
  return {};
@@ -114,7 +114,8 @@ class Chromium extends import_browserType.BrowserType {
114
114
  };
115
115
  (0, import_browserContext.validateBrowserContextOptions)(persistent, browserOptions);
116
116
  const browser = await progress.race(import_crBrowser.CRBrowser.connect(this.attribution.playwright, chromeTransport, browserOptions));
117
- browser._isCollocatedWithServer = false;
117
+ if (!options.isLocal)
118
+ browser._isCollocatedWithServer = false;
118
119
  browser.on(import_browser.Browser.Events.Disconnected, doCleanup);
119
120
  return browser;
120
121
  } catch (error) {
@@ -128,13 +129,8 @@ class Chromium extends import_browserType.BrowserType {
128
129
  return directory ? new import_crDevTools.CRDevTools(import_path.default.join(directory, "devtools-preferences.json")) : void 0;
129
130
  }
130
131
  async connectToTransport(transport, options, browserLogsCollector) {
131
- let devtools = this._devtools;
132
- if (options.__testHookForDevTools) {
133
- devtools = this._createDevTools();
134
- await options.__testHookForDevTools(devtools);
135
- }
136
132
  try {
137
- return await import_crBrowser.CRBrowser.connect(this.attribution.playwright, transport, options, devtools);
133
+ return await import_crBrowser.CRBrowser.connect(this.attribution.playwright, transport, options, this._devtools);
138
134
  } catch (e) {
139
135
  if (browserLogsCollector.recentLogs().some((log) => log.includes("Failed to create a ProcessSingleton for your profile directory."))) {
140
136
  throw new Error(
@@ -144,14 +140,12 @@ class Chromium extends import_browserType.BrowserType {
144
140
  throw e;
145
141
  }
146
142
  }
147
- doRewriteStartupLog(error) {
148
- if (!error.logs)
149
- return error;
150
- if (error.logs.includes("Missing X server"))
151
- error.logs = "\n" + (0, import_ascii.wrapInASCIIBox)(import_browserType.kNoXServerRunningError, 1);
152
- if (!error.logs.includes("crbug.com/357670") && !error.logs.includes("No usable sandbox!") && !error.logs.includes("crbug.com/638180"))
153
- return error;
154
- error.logs = [
143
+ doRewriteStartupLog(logs) {
144
+ if (logs.includes("Missing X server"))
145
+ logs = "\n" + (0, import_ascii.wrapInASCIIBox)(import_browserType.kNoXServerRunningError, 1);
146
+ if (!logs.includes("crbug.com/357670") && !logs.includes("No usable sandbox!") && !logs.includes("crbug.com/638180"))
147
+ return logs;
148
+ return [
155
149
  `Chromium sandboxing failed!`,
156
150
  `================================`,
157
151
  `To avoid the sandboxing issue, do either of the following:`,
@@ -160,7 +154,6 @@ class Chromium extends import_browserType.BrowserType {
160
154
  `================================`,
161
155
  ``
162
156
  ].join("\n");
163
- return error;
164
157
  }
165
158
  amendEnvironment(env) {
166
159
  return env;
@@ -284,11 +277,7 @@ class Chromium extends import_browserType.BrowserType {
284
277
  if (args.find((arg) => !arg.startsWith("-")))
285
278
  throw new Error("Arguments can not specify page to be opened");
286
279
  const chromeArguments = [...(0, import_chromiumSwitches.chromiumSwitches)(options.assistantMode, options.channel)];
287
- if (import_os.default.platform() === "darwin") {
288
- chromeArguments.push("--enable-unsafe-swiftshader");
289
- }
290
- if (options.devtools)
291
- chromeArguments.push("--auto-open-devtools-for-tabs");
280
+ chromeArguments.push("--enable-unsafe-swiftshader");
292
281
  if (options.headless) {
293
282
  chromeArguments.push("--headless");
294
283
  chromeArguments.push(
@@ -324,6 +313,10 @@ class Chromium extends import_browserType.BrowserType {
324
313
  return waitForReadyState(options, browserLogsCollector);
325
314
  }
326
315
  getExecutableName(options) {
316
+ if (options.channel && import_registry.registry.isChromiumAlias(options.channel))
317
+ return "chromium";
318
+ if (options.channel === "chromium-tip-of-tree")
319
+ return options.headless ? "chromium-tip-of-tree-headless-shell" : "chromium-tip-of-tree";
327
320
  if (options.channel)
328
321
  return options.channel;
329
322
  return options.headless ? "chromium-headless-shell" : "chromium";
@@ -22,10 +22,10 @@ __export(chromiumSwitches_exports, {
22
22
  });
23
23
  module.exports = __toCommonJS(chromiumSwitches_exports);
24
24
  const disabledFeatures = (assistantMode) => [
25
- // See https://github.com/microsoft/playwright/pull/10380
26
- "AcceptCHFrame",
27
25
  // See https://github.com/microsoft/playwright/issues/14047
28
26
  "AvoidUnnecessaryBeforeUnloadCheckSync",
27
+ // See https://github.com/microsoft/playwright/issues/38568
28
+ "BoundaryEventDispatchTracksNodeRemoval",
29
29
  "DestroyProfileOnBrowserClose",
30
30
  // See https://github.com/microsoft/playwright/pull/13854
31
31
  "DialMediaRouteProvider",
@@ -284,11 +284,12 @@ class CRBrowser extends import_browser.Browser {
284
284
  return this._clientRootSessionPromise;
285
285
  }
286
286
  }
287
+ const CREvents = {
288
+ ServiceWorker: "serviceworker"
289
+ };
287
290
  class CRBrowserContext extends import_browserContext.BrowserContext {
288
291
  static {
289
- this.CREvents = {
290
- ServiceWorker: "serviceworker"
291
- };
292
+ this.CREvents = CREvents;
292
293
  }
293
294
  constructor(browser, browserContextId, options) {
294
295
  super(browser, options, browserContextId);
@@ -388,15 +389,24 @@ class CRBrowserContext extends import_browserContext.BrowserContext {
388
389
  ["midi-sysex", "midiSysex"],
389
390
  ["storage-access", "storageAccess"],
390
391
  ["local-fonts", "localFonts"],
391
- ["local-network-access", "localNetworkAccess"]
392
+ ["local-network-access", ["localNetworkAccess", "localNetwork", "loopbackNetwork"]]
392
393
  ]);
393
- const filtered = permissions.map((permission) => {
394
- const protocolPermission = webPermissionToProtocol.get(permission);
395
- if (!protocolPermission)
396
- throw new Error("Unknown permission: " + permission);
397
- return protocolPermission;
398
- });
399
- await this._browser._session.send("Browser.grantPermissions", { origin: origin === "*" ? void 0 : origin, browserContextId: this._browserContextId, permissions: filtered });
394
+ const grantPermissions = async (mapping) => {
395
+ const filtered = permissions.flatMap((permission) => {
396
+ const protocolPermission = mapping.get(permission);
397
+ if (!protocolPermission)
398
+ throw new Error("Unknown permission: " + permission);
399
+ return typeof protocolPermission === "string" ? [protocolPermission] : protocolPermission;
400
+ });
401
+ await this._browser._session.send("Browser.grantPermissions", { origin: origin === "*" ? void 0 : origin, browserContextId: this._browserContextId, permissions: filtered });
402
+ };
403
+ try {
404
+ await grantPermissions(webPermissionToProtocol);
405
+ } catch (e) {
406
+ const fallbackMapping = new Map(webPermissionToProtocol);
407
+ fallbackMapping.set("local-network-access", ["localNetworkAccess"]);
408
+ await grantPermissions(fallbackMapping);
409
+ }
400
410
  }
401
411
  async doClearPermissions() {
402
412
  await this._browser._session.send("Browser.resetPermissions", { browserContextId: this._browserContextId });
@@ -470,7 +480,7 @@ class CRBrowserContext extends import_browserContext.BrowserContext {
470
480
  }
471
481
  }
472
482
  async stopVideoRecording() {
473
- await Promise.all(this._crPages().map((crPage) => crPage._mainFrameSession._stopVideoRecording()));
483
+ await Promise.all(this._crPages().map((crPage) => crPage._page.screencast.stopVideoRecording()));
474
484
  }
475
485
  onClosePersistent() {
476
486
  }
@@ -94,11 +94,6 @@ class CRSession extends import_instrumentation.SdkObject {
94
94
  this._parentSession = parentSession;
95
95
  this._sessionId = sessionId;
96
96
  this._eventListener = eventListener;
97
- this.on = super.on;
98
- this.addListener = super.addListener;
99
- this.off = super.removeListener;
100
- this.removeListener = super.removeListener;
101
- this.once = super.once;
102
97
  }
103
98
  _markAsCrashed() {
104
99
  this._crashed = true;
@@ -44,8 +44,6 @@ class CRDevTools {
44
44
  return;
45
45
  const parsed = JSON.parse(event.payload);
46
46
  let result = void 0;
47
- if (this.__testHookOnBinding)
48
- this.__testHookOnBinding(parsed);
49
47
  if (parsed.method === "getPreferences") {
50
48
  if (this._prefs === void 0) {
51
49
  try {