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.
Files changed (218) hide show
  1. package/ThirdPartyNotices.txt +65 -123
  2. package/bin/reinstall_chrome_beta_mac.sh +1 -1
  3. package/bin/reinstall_chrome_stable_mac.sh +1 -1
  4. package/bin/reinstall_msedge_beta_mac.sh +1 -1
  5. package/bin/reinstall_msedge_dev_mac.sh +1 -1
  6. package/bin/reinstall_msedge_stable_mac.sh +1 -1
  7. package/browsers.json +14 -14
  8. package/index.js +1 -1
  9. package/lib/androidServerImpl.js +4 -2
  10. package/lib/browserServerImpl.js +47 -12
  11. package/lib/cli/program.js +116 -50
  12. package/lib/cli/programWithTestStub.js +1 -1
  13. package/lib/client/android.js +30 -34
  14. package/lib/client/browser.js +54 -17
  15. package/lib/client/browserContext.js +67 -71
  16. package/lib/client/browserType.js +25 -34
  17. package/lib/client/channelOwner.js +20 -24
  18. package/lib/client/connection.js +6 -10
  19. package/lib/client/electron.js +8 -3
  20. package/lib/client/elementHandle.js +18 -21
  21. package/lib/client/fetch.js +5 -3
  22. package/lib/client/frame.js +57 -35
  23. package/lib/client/input.js +3 -1
  24. package/lib/client/jsHandle.js +4 -0
  25. package/lib/client/localUtils.js +0 -1
  26. package/lib/client/locator.js +32 -28
  27. package/lib/client/network.js +5 -12
  28. package/lib/client/page.js +32 -32
  29. package/lib/client/playwright.js +6 -16
  30. package/lib/client/selectors.js +18 -38
  31. package/lib/client/timeoutSettings.js +12 -8
  32. package/lib/client/tracing.js +24 -20
  33. package/lib/client/waiter.js +2 -2
  34. package/lib/client/webSocket.js +4 -22
  35. package/lib/generated/bindingsControllerSource.js +28 -0
  36. package/lib/generated/clockSource.js +1 -1
  37. package/lib/generated/injectedScriptSource.js +1 -1
  38. package/lib/generated/pollingRecorderSource.js +1 -1
  39. package/lib/generated/storageScriptSource.js +28 -0
  40. package/lib/generated/utilityScriptSource.js +1 -1
  41. package/lib/generated/webSocketMockSource.js +12 -50
  42. package/lib/inProcessFactory.js +9 -6
  43. package/lib/outofprocess.js +0 -2
  44. package/lib/protocol/validator.js +423 -346
  45. package/lib/protocol/validatorPrimitives.js +18 -4
  46. package/lib/remote/playwrightConnection.js +29 -166
  47. package/lib/remote/playwrightServer.js +233 -35
  48. package/lib/server/android/android.js +97 -83
  49. package/lib/server/android/backendAdb.js +0 -2
  50. package/lib/server/bidi/bidiBrowser.js +139 -73
  51. package/lib/server/bidi/bidiChromium.js +23 -22
  52. package/lib/server/bidi/bidiExecutionContext.js +2 -1
  53. package/lib/server/bidi/bidiFirefox.js +17 -14
  54. package/lib/server/bidi/bidiInput.js +22 -22
  55. package/lib/server/bidi/bidiNetworkManager.js +8 -11
  56. package/lib/server/bidi/bidiPage.js +42 -86
  57. package/lib/server/bidi/third_party/bidiProtocol.js +5 -133
  58. package/lib/server/bidi/third_party/bidiProtocolCore.js +179 -0
  59. package/lib/server/{dispatchers/selectorsDispatcher.js → bidi/third_party/bidiProtocolPermissions.js} +20 -18
  60. package/lib/server/browser.js +30 -21
  61. package/lib/server/browserContext.js +203 -165
  62. package/lib/server/browserType.js +109 -107
  63. package/lib/server/chromium/chromium.js +84 -69
  64. package/lib/server/chromium/chromiumSwitches.js +13 -20
  65. package/lib/server/chromium/crBrowser.js +74 -40
  66. package/lib/server/chromium/crConnection.js +8 -9
  67. package/lib/server/chromium/crCoverage.js +11 -8
  68. package/lib/server/chromium/crDragDrop.js +25 -20
  69. package/lib/server/chromium/crExecutionContext.js +2 -1
  70. package/lib/server/chromium/crInput.js +32 -29
  71. package/lib/server/chromium/crNetworkManager.js +45 -33
  72. package/lib/server/chromium/crPage.js +98 -73
  73. package/lib/server/chromium/crServiceWorker.js +13 -18
  74. package/lib/server/chromium/videoRecorder.js +10 -18
  75. package/lib/server/clock.js +51 -39
  76. package/lib/server/codegen/csharp.js +10 -5
  77. package/lib/server/codegen/java.js +1 -1
  78. package/lib/server/codegen/javascript.js +1 -1
  79. package/lib/server/codegen/jsonl.js +2 -1
  80. package/lib/server/codegen/language.js +22 -1
  81. package/lib/server/codegen/languages.js +4 -4
  82. package/lib/server/codegen/python.js +1 -1
  83. package/lib/server/cookieStore.js +3 -1
  84. package/lib/server/debugController.js +105 -71
  85. package/lib/server/debugger.js +6 -23
  86. package/lib/server/deviceDescriptorsSource.json +237 -127
  87. package/lib/server/dialog.js +50 -6
  88. package/lib/server/dispatchers/androidDispatcher.js +77 -62
  89. package/lib/server/dispatchers/artifactDispatcher.js +18 -18
  90. package/lib/server/dispatchers/browserContextDispatcher.js +141 -91
  91. package/lib/server/dispatchers/browserDispatcher.js +55 -88
  92. package/lib/server/dispatchers/browserTypeDispatcher.js +18 -9
  93. package/lib/server/dispatchers/cdpSessionDispatcher.js +4 -4
  94. package/lib/server/dispatchers/debugControllerDispatcher.js +12 -21
  95. package/lib/server/dispatchers/dialogDispatcher.js +4 -4
  96. package/lib/server/dispatchers/dispatcher.js +78 -53
  97. package/lib/server/dispatchers/electronDispatcher.js +19 -20
  98. package/lib/server/dispatchers/elementHandlerDispatcher.js +83 -93
  99. package/lib/server/dispatchers/frameDispatcher.js +99 -102
  100. package/lib/server/dispatchers/jsHandleDispatcher.js +21 -16
  101. package/lib/server/dispatchers/jsonPipeDispatcher.js +4 -4
  102. package/lib/server/dispatchers/localUtilsDispatcher.js +53 -59
  103. package/lib/server/dispatchers/networkDispatchers.js +41 -35
  104. package/lib/server/dispatchers/pageDispatcher.js +156 -107
  105. package/lib/server/dispatchers/playwrightDispatcher.js +37 -25
  106. package/lib/server/dispatchers/streamDispatcher.js +15 -8
  107. package/lib/server/dispatchers/tracingDispatcher.js +22 -13
  108. package/lib/server/dispatchers/webSocketRouteDispatcher.js +46 -35
  109. package/lib/server/dispatchers/writableStreamDispatcher.js +16 -10
  110. package/lib/server/dom.js +198 -266
  111. package/lib/server/download.js +3 -3
  112. package/lib/server/electron/electron.js +96 -103
  113. package/lib/server/electron/loader.js +1 -1
  114. package/lib/server/fetch.js +22 -41
  115. package/lib/server/fileUploadUtils.js +1 -1
  116. package/lib/server/firefox/ffBrowser.js +79 -55
  117. package/lib/server/firefox/ffExecutionContext.js +2 -1
  118. package/lib/server/firefox/ffInput.js +23 -23
  119. package/lib/server/firefox/ffNetworkManager.js +8 -6
  120. package/lib/server/firefox/ffPage.js +39 -36
  121. package/lib/server/firefox/firefox.js +9 -10
  122. package/lib/server/frameSelectors.js +65 -22
  123. package/lib/server/frames.js +516 -544
  124. package/lib/server/har/harRecorder.js +1 -1
  125. package/lib/server/har/harTracer.js +4 -2
  126. package/lib/server/helper.js +3 -7
  127. package/lib/server/index.js +0 -3
  128. package/lib/server/input.js +47 -54
  129. package/lib/server/instrumentation.js +8 -14
  130. package/lib/server/javascript.js +9 -17
  131. package/lib/server/launchApp.js +48 -30
  132. package/lib/server/localUtils.js +45 -38
  133. package/lib/server/network.js +44 -10
  134. package/lib/server/page.js +233 -178
  135. package/lib/server/pageBinding.js +6 -7
  136. package/lib/server/playwright.js +4 -14
  137. package/lib/server/progress.js +57 -49
  138. package/lib/server/recorder/recorderApp.js +298 -95
  139. package/lib/server/recorder/recorderRunner.js +23 -24
  140. package/lib/server/recorder/recorderSignalProcessor.js +83 -0
  141. package/lib/server/recorder/recorderUtils.js +67 -10
  142. package/lib/server/recorder.js +284 -146
  143. package/lib/server/registry/index.js +83 -48
  144. package/lib/server/registry/nativeDeps.js +175 -0
  145. package/lib/server/registry/oopDownloadBrowserMain.js +1 -1
  146. package/lib/server/screenshotter.js +84 -83
  147. package/lib/server/selectors.js +12 -12
  148. package/lib/server/socksClientCertificatesInterceptor.js +198 -136
  149. package/lib/server/trace/recorder/snapshotter.js +12 -19
  150. package/lib/server/trace/recorder/tracing.js +36 -27
  151. package/lib/server/trace/viewer/traceViewer.js +11 -20
  152. package/lib/server/transport.js +20 -22
  153. package/lib/server/utils/comparators.js +2 -2
  154. package/lib/server/utils/debug.js +3 -8
  155. package/lib/server/utils/debugLogger.js +8 -0
  156. package/lib/server/utils/hostPlatform.js +3 -1
  157. package/lib/server/utils/network.js +35 -25
  158. package/lib/server/utils/nodePlatform.js +1 -1
  159. package/lib/server/utils/processLauncher.js +4 -1
  160. package/lib/server/utils/wsServer.js +11 -17
  161. package/lib/server/webkit/webkit.js +5 -2
  162. package/lib/server/webkit/wkBrowser.js +51 -28
  163. package/lib/server/webkit/wkExecutionContext.js +2 -1
  164. package/lib/server/webkit/wkInput.js +25 -25
  165. package/lib/server/webkit/wkInterceptableRequest.js +1 -1
  166. package/lib/server/webkit/wkPage.js +80 -59
  167. package/lib/server/webkit/wkProvisionalPage.js +1 -1
  168. package/lib/server/webkit/wkWorkers.js +7 -7
  169. package/lib/utils/isomorphic/ariaSnapshot.js +13 -7
  170. package/lib/utils/isomorphic/cssParser.js +1 -2
  171. package/lib/utils/isomorphic/locatorGenerators.js +18 -0
  172. package/lib/utils/isomorphic/manualPromise.js +1 -2
  173. package/lib/utils/isomorphic/mimeType.js +1 -2
  174. package/lib/utils/isomorphic/multimap.js +1 -2
  175. package/lib/utils/isomorphic/oldUtilityScriptSerializers.js +248 -0
  176. package/lib/utils/isomorphic/protocolFormatter.js +78 -0
  177. package/lib/utils/isomorphic/protocolMetainfo.js +318 -0
  178. package/lib/utils/isomorphic/selectorParser.js +3 -4
  179. package/lib/utils/isomorphic/stringUtils.js +3 -24
  180. package/lib/utils/isomorphic/time.js +9 -4
  181. package/lib/utils/isomorphic/timeoutRunner.js +3 -4
  182. package/lib/utils/isomorphic/traceUtils.js +2 -3
  183. package/lib/utils/isomorphic/urlMatch.js +21 -7
  184. package/lib/utils/isomorphic/utilityScriptSerializers.js +208 -205
  185. package/lib/utils.js +8 -2
  186. package/lib/utilsBundleImpl/index.js +160 -150
  187. package/lib/vite/htmlReport/index.html +17 -17
  188. package/lib/vite/recorder/assets/{codeMirrorModule-CXVeovup.js → codeMirrorModule-DzQ0k89p.js} +1 -1
  189. package/lib/vite/recorder/assets/{index-eHBmevrY.css → index-CI4HQ-Zb.css} +1 -1
  190. package/lib/vite/recorder/assets/index-D7C7daHH.js +184 -0
  191. package/lib/vite/recorder/index.html +3 -3
  192. package/lib/vite/traceViewer/assets/{codeMirrorModule-_GLjJL-7.js → codeMirrorModule-Di48jgWx.js} +1 -1
  193. package/lib/vite/traceViewer/assets/defaultSettingsView-szBn8781.js +256 -0
  194. package/lib/vite/traceViewer/defaultSettingsView.DVJHpiGt.css +1 -0
  195. package/lib/vite/traceViewer/index.BFsek2M6.css +1 -0
  196. package/lib/vite/traceViewer/index.DQvXoPLL.js +2 -0
  197. package/lib/vite/traceViewer/index.html +6 -6
  198. package/lib/vite/traceViewer/sw.bundle.js +3 -3
  199. package/lib/vite/traceViewer/uiMode.dBV3oN9h.js +5 -0
  200. package/lib/vite/traceViewer/uiMode.html +4 -4
  201. package/lib/zipBundleImpl.js +4 -4
  202. package/package.json +1 -1
  203. package/types/protocol.d.ts +712 -107
  204. package/types/types.d.ts +148 -37
  205. package/lib/generated/consoleApiSource.js +0 -28
  206. package/lib/protocol/debug.js +0 -211
  207. package/lib/server/recorder/contextRecorder.js +0 -286
  208. package/lib/server/recorder/recorderCollection.js +0 -116
  209. package/lib/server/recorder/recorderFrontend.js +0 -16
  210. package/lib/server/storageScript.js +0 -154
  211. package/lib/server/timeoutSettings.js +0 -89
  212. package/lib/utils/isomorphic/builtins.js +0 -86
  213. package/lib/vite/recorder/assets/index-BsWQsSGl.js +0 -184
  214. package/lib/vite/traceViewer/assets/defaultSettingsView-DtCQiGHe.js +0 -265
  215. package/lib/vite/traceViewer/defaultSettingsView.QdHITyLI.css +0 -1
  216. package/lib/vite/traceViewer/index.CFOW-Ezb.css +0 -1
  217. package/lib/vite/traceViewer/index.cFZzK9RN.js +0 -2
  218. package/lib/vite/traceViewer/uiMode.XVPIqBeS.js +0 -5
@@ -21,18 +21,20 @@ __export(recorderUtils_exports, {
21
21
  buildFullSelector: () => buildFullSelector,
22
22
  collapseActions: () => collapseActions,
23
23
  frameForAction: () => frameForAction,
24
+ generateFrameSelector: () => generateFrameSelector,
24
25
  mainFrameForAction: () => mainFrameForAction,
25
- metadataToCallLog: () => metadataToCallLog
26
+ metadataToCallLog: () => metadataToCallLog,
27
+ shouldMergeAction: () => shouldMergeAction
26
28
  });
27
29
  module.exports = __toCommonJS(recorderUtils_exports);
30
+ var import_protocolFormatter = require("../../utils/isomorphic/protocolFormatter");
31
+ var import_utils = require("../../utils");
32
+ var import_timeoutRunner = require("../../utils/isomorphic/timeoutRunner");
28
33
  function buildFullSelector(framePath, selector) {
29
34
  return [...framePath, selector].join(" >> internal:control=enter-frame >> ");
30
35
  }
31
36
  function metadataToCallLog(metadata, status) {
32
- let title = metadata.apiName || metadata.method;
33
- if (metadata.method === "waitForEventInfo")
34
- title += `(${metadata.params.info.event})`;
35
- title = title.replace("object.expect", "expect");
37
+ const title = (0, import_protocolFormatter.renderTitleForCall)(metadata);
36
38
  if (metadata.error)
37
39
  status = "error";
38
40
  const params = {
@@ -47,7 +49,7 @@ function metadataToCallLog(metadata, status) {
47
49
  const callLog = {
48
50
  id: metadata.id,
49
51
  messages: metadata.log,
50
- title,
52
+ title: title ?? "",
51
53
  status,
52
54
  error: metadata.error?.error?.message,
53
55
  params,
@@ -73,13 +75,33 @@ async function frameForAction(pageAliases, actionInContext, action) {
73
75
  throw new Error("Internal error: frame not found");
74
76
  return result.frame;
75
77
  }
78
+ function isSameAction(a, b) {
79
+ return a.action.name === b.action.name && a.frame.pageAlias === b.frame.pageAlias && a.frame.framePath.join("|") === b.frame.framePath.join("|");
80
+ }
81
+ function isSameSelector(action, lastAction) {
82
+ return "selector" in action.action && "selector" in lastAction.action && action.action.selector === lastAction.action.selector;
83
+ }
84
+ function isShortlyAfter(action, lastAction) {
85
+ return action.startTime - lastAction.startTime < 500;
86
+ }
87
+ function shouldMergeAction(action, lastAction) {
88
+ if (!lastAction)
89
+ return false;
90
+ switch (action.action.name) {
91
+ case "fill":
92
+ return isSameAction(action, lastAction) && isSameSelector(action, lastAction);
93
+ case "navigate":
94
+ return isSameAction(action, lastAction);
95
+ case "click":
96
+ return isSameAction(action, lastAction) && isSameSelector(action, lastAction) && isShortlyAfter(action, lastAction) && action.action.clickCount > lastAction.action.clickCount;
97
+ }
98
+ return false;
99
+ }
76
100
  function collapseActions(actions) {
77
101
  const result = [];
78
102
  for (const action of actions) {
79
103
  const lastAction = result[result.length - 1];
80
- const isSameAction = lastAction && lastAction.action.name === action.action.name && lastAction.frame.pageAlias === action.frame.pageAlias && lastAction.frame.framePath.join("|") === action.frame.framePath.join("|");
81
- const isSameSelector = lastAction && "selector" in lastAction.action && "selector" in action.action && action.action.selector === lastAction.action.selector;
82
- const shouldMerge = isSameAction && (action.action.name === "navigate" || action.action.name === "fill" && isSameSelector);
104
+ const shouldMerge = shouldMergeAction(action, lastAction);
83
105
  if (!shouldMerge) {
84
106
  result.push(action);
85
107
  continue;
@@ -90,11 +112,46 @@ function collapseActions(actions) {
90
112
  }
91
113
  return result;
92
114
  }
115
+ async function generateFrameSelector(frame) {
116
+ const selectorPromises = [];
117
+ while (frame) {
118
+ const parent = frame.parentFrame();
119
+ if (!parent)
120
+ break;
121
+ selectorPromises.push(generateFrameSelectorInParent(parent, frame));
122
+ frame = parent;
123
+ }
124
+ const result = await Promise.all(selectorPromises);
125
+ return result.reverse();
126
+ }
127
+ async function generateFrameSelectorInParent(parent, frame) {
128
+ const result = await (0, import_timeoutRunner.raceAgainstDeadline)(async () => {
129
+ try {
130
+ const frameElement = await frame.frameElement();
131
+ if (!frameElement || !parent)
132
+ return;
133
+ const utility = await parent._utilityContext();
134
+ const injected = await utility.injectedScript();
135
+ const selector = await injected.evaluate((injected2, element) => {
136
+ return injected2.generateSelectorSimple(element);
137
+ }, frameElement);
138
+ return selector;
139
+ } catch (e) {
140
+ }
141
+ }, (0, import_utils.monotonicTime)() + 2e3);
142
+ if (!result.timedOut && result.result)
143
+ return result.result;
144
+ if (frame.name())
145
+ return `iframe[name=${(0, import_utils.quoteCSSAttributeValue)(frame.name())}]`;
146
+ return `iframe[src=${(0, import_utils.quoteCSSAttributeValue)(frame.url())}]`;
147
+ }
93
148
  // Annotate the CommonJS export names for ESM import in node:
94
149
  0 && (module.exports = {
95
150
  buildFullSelector,
96
151
  collapseActions,
97
152
  frameForAction,
153
+ generateFrameSelector,
98
154
  mainFrameForAction,
99
- metadataToCallLog
155
+ metadataToCallLog,
156
+ shouldMergeAction
100
157
  });
@@ -28,212 +28,250 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
29
  var recorder_exports = {};
30
30
  __export(recorder_exports, {
31
- Recorder: () => Recorder
31
+ Recorder: () => Recorder,
32
+ RecorderEvent: () => RecorderEvent
32
33
  });
33
34
  module.exports = __toCommonJS(recorder_exports);
35
+ var import_events = __toESM(require("events"));
34
36
  var import_fs = __toESM(require("fs"));
35
- var consoleApiSource = __toESM(require("../generated/consoleApiSource"));
36
37
  var import_utils = require("../utils");
37
38
  var import_browserContext = require("./browserContext");
38
39
  var import_debugger = require("./debugger");
39
- var import_contextRecorder = require("./recorder/contextRecorder");
40
40
  var import_recorderUtils = require("./recorder/recorderUtils");
41
41
  var import_locatorParser = require("../utils/isomorphic/locatorParser");
42
42
  var import_selectorParser = require("../utils/isomorphic/selectorParser");
43
+ var import_progress = require("./progress");
44
+ var import_recorderSignalProcessor = require("./recorder/recorderSignalProcessor");
45
+ var rawRecorderSource = __toESM(require("./../generated/pollingRecorderSource"));
46
+ var import_utils2 = require("./../utils");
47
+ var import_frames = require("./frames");
48
+ var import_page = require("./page");
49
+ var import_recorderRunner = require("./recorder/recorderRunner");
43
50
  const recorderSymbol = Symbol("recorderSymbol");
44
- class Recorder {
51
+ const RecorderEvent = {
52
+ PausedStateChanged: "pausedStateChanged",
53
+ ModeChanged: "modeChanged",
54
+ ElementPicked: "elementPicked",
55
+ CallLogsUpdated: "callLogsUpdated",
56
+ UserSourcesChanged: "userSourcesChanged",
57
+ ActionAdded: "actionAdded",
58
+ SignalAdded: "signalAdded",
59
+ PageNavigated: "pageNavigated",
60
+ ContextClosed: "contextClosed"
61
+ };
62
+ class Recorder extends import_events.default {
45
63
  constructor(context, params) {
64
+ super();
46
65
  this._highlightedElement = {};
47
66
  this._overlayState = { offsetX: 0 };
48
- this._recorderApp = null;
49
67
  this._currentCallsMetadata = /* @__PURE__ */ new Map();
50
- this._recorderSources = [];
51
68
  this._userSources = /* @__PURE__ */ new Map();
52
69
  this._omitCallTracking = false;
70
+ this._currentLanguage = "javascript";
71
+ this._pageAliases = /* @__PURE__ */ new Map();
72
+ this._lastPopupOrdinal = 0;
73
+ this._lastDialogOrdinal = -1;
74
+ this._lastDownloadOrdinal = -1;
75
+ this._listeners = [];
76
+ this._enabled = false;
77
+ this._callLogs = [];
78
+ this._context = context;
79
+ this._params = params;
53
80
  this._mode = params.mode || "none";
81
+ this._recorderMode = params.recorderMode ?? "default";
54
82
  this.handleSIGINT = params.handleSIGINT;
55
- this._contextRecorder = new import_contextRecorder.ContextRecorder(context, params, {});
56
- this._context = context;
83
+ this._signalProcessor = new import_recorderSignalProcessor.RecorderSignalProcessor({
84
+ addAction: (actionInContext) => {
85
+ if (this._enabled)
86
+ this.emit(RecorderEvent.ActionAdded, actionInContext);
87
+ },
88
+ addSignal: (signal) => {
89
+ if (this._enabled)
90
+ this.emit(RecorderEvent.SignalAdded, signal);
91
+ }
92
+ });
93
+ context.on(import_browserContext.BrowserContext.Events.BeforeClose, () => {
94
+ this.emit(RecorderEvent.ContextClosed);
95
+ });
96
+ this._listeners.push(import_utils2.eventsHelper.addEventListener(process, "exit", () => {
97
+ this.emit(RecorderEvent.ContextClosed);
98
+ }));
99
+ this._setEnabled(params.mode === "recording");
57
100
  this._omitCallTracking = !!params.omitCallTracking;
58
101
  this._debugger = context.debugger();
59
102
  context.instrumentation.addListener(this, context);
60
- this._currentLanguage = this._contextRecorder.languageName();
61
103
  if ((0, import_utils.isUnderTest)()) {
62
104
  this._overlayState.offsetX = 200;
63
105
  }
64
106
  }
65
- static async showInspector(context, params, recorderAppFactory) {
66
- if ((0, import_utils.isUnderTest)())
67
- params.language = process.env.TEST_INSPECTOR_LANGUAGE;
68
- return await Recorder.show(context, recorderAppFactory, params);
69
- }
70
- static showInspectorNoReply(context, recorderAppFactory) {
71
- Recorder.showInspector(context, {}, recorderAppFactory).catch(() => {
72
- });
73
- }
74
- static show(context, recorderAppFactory, params) {
107
+ static forContext(context, params) {
75
108
  let recorderPromise = context[recorderSymbol];
76
109
  if (!recorderPromise) {
77
- recorderPromise = Recorder._create(context, recorderAppFactory, params);
110
+ recorderPromise = Recorder._create(context, params);
78
111
  context[recorderSymbol] = recorderPromise;
79
112
  }
80
113
  return recorderPromise;
81
114
  }
82
- static async _create(context, recorderAppFactory, params = {}) {
115
+ static existingForContext(context) {
116
+ return context[recorderSymbol];
117
+ }
118
+ static async _create(context, params = {}) {
83
119
  const recorder = new Recorder(context, params);
84
- const recorderApp = await recorderAppFactory(recorder);
85
- await recorder._install(recorderApp);
120
+ await recorder._install();
86
121
  return recorder;
87
122
  }
88
- async _install(recorderApp) {
89
- this._recorderApp = recorderApp;
90
- recorderApp.once("close", () => {
91
- this._debugger.resume(false);
92
- this._recorderApp = null;
93
- });
94
- recorderApp.on("event", (data) => {
95
- if (data.event === "setMode") {
96
- this.setMode(data.params.mode);
97
- return;
98
- }
99
- if (data.event === "highlightRequested") {
100
- if (data.params.selector)
101
- this.setHighlightedSelector(this._currentLanguage, data.params.selector);
102
- if (data.params.ariaTemplate)
103
- this.setHighlightedAriaTemplate(data.params.ariaTemplate);
104
- return;
105
- }
106
- if (data.event === "step") {
107
- this._debugger.resume(true);
108
- return;
109
- }
110
- if (data.event === "fileChanged") {
111
- this._currentLanguage = this._contextRecorder.languageName(data.params.file);
112
- this._refreshOverlay();
113
- return;
114
- }
115
- if (data.event === "resume") {
116
- this._debugger.resume(false);
117
- return;
118
- }
119
- if (data.event === "pause") {
120
- this._debugger.pauseOnNextStatement();
121
- return;
122
- }
123
- if (data.event === "clear") {
124
- this._contextRecorder.clearScript();
125
- return;
126
- }
127
- if (data.event === "runTask") {
128
- this._contextRecorder.runTask(data.params.task);
129
- return;
130
- }
131
- });
132
- await Promise.all([
133
- recorderApp.setMode(this._mode),
134
- recorderApp.setPaused(this._debugger.isPaused()),
135
- this._pushAllSources()
136
- ]);
123
+ async _install() {
124
+ this.emit(RecorderEvent.ModeChanged, this._mode);
125
+ this.emit(RecorderEvent.PausedStateChanged, this._debugger.isPaused());
137
126
  this._context.once(import_browserContext.BrowserContext.Events.Close, () => {
138
- this._contextRecorder.dispose();
127
+ import_utils2.eventsHelper.removeEventListeners(this._listeners);
139
128
  this._context.instrumentation.removeListener(this);
140
- this._recorderApp?.close().catch(() => {
141
- });
142
- });
143
- this._contextRecorder.on(import_contextRecorder.ContextRecorder.Events.Change, (data) => {
144
- this._recorderSources = data.sources;
145
- recorderApp.setActions(data.actions, data.sources);
146
- recorderApp.setRunningFile(void 0);
147
- this._pushAllSources();
129
+ this.emit(RecorderEvent.ContextClosed);
148
130
  });
149
- await this._context.exposeBinding("__pw_recorderState", false, async (source) => {
150
- let actionSelector;
151
- let actionPoint;
152
- const hasActiveScreenshotCommand = [...this._currentCallsMetadata.keys()].some(isScreenshotCommand);
153
- if (!hasActiveScreenshotCommand) {
154
- actionSelector = await this._scopeHighlightedSelectorToFrame(source.frame);
155
- for (const [metadata, sdkObject] of this._currentCallsMetadata) {
156
- if (source.page === sdkObject.attribution.page) {
157
- actionPoint = metadata.point || actionPoint;
158
- actionSelector = actionSelector || metadata.params.selector;
131
+ const controller = new import_progress.ProgressController();
132
+ await controller.run(async (progress) => {
133
+ await this._context.exposeBinding(progress, "__pw_recorderState", false, async (source) => {
134
+ let actionSelector;
135
+ let actionPoint;
136
+ const hasActiveScreenshotCommand = [...this._currentCallsMetadata.keys()].some(isScreenshotCommand);
137
+ if (!hasActiveScreenshotCommand) {
138
+ actionSelector = await this._scopeHighlightedSelectorToFrame(source.frame);
139
+ for (const [metadata, sdkObject] of this._currentCallsMetadata) {
140
+ if (source.page === sdkObject.attribution.page) {
141
+ actionPoint = metadata.point || actionPoint;
142
+ actionSelector = actionSelector || metadata.params.selector;
143
+ }
159
144
  }
160
145
  }
161
- }
162
- const uiState = {
163
- mode: this._mode,
164
- actionPoint,
165
- actionSelector,
166
- ariaTemplate: this._highlightedElement.ariaTemplate,
167
- language: this._currentLanguage,
168
- testIdAttributeName: this._contextRecorder.testIdAttributeName(),
169
- overlay: this._overlayState
170
- };
171
- return uiState;
172
- });
173
- await this._context.exposeBinding("__pw_recorderElementPicked", false, async ({ frame }, elementInfo) => {
174
- const selectorChain = await (0, import_contextRecorder.generateFrameSelector)(frame);
175
- await this._recorderApp?.elementPicked({ selector: (0, import_recorderUtils.buildFullSelector)(selectorChain, elementInfo.selector), ariaSnapshot: elementInfo.ariaSnapshot }, true);
176
- });
177
- await this._context.exposeBinding("__pw_recorderSetMode", false, async ({ frame }, mode) => {
178
- if (frame.parentFrame())
179
- return;
180
- this.setMode(mode);
181
- });
182
- await this._context.exposeBinding("__pw_recorderSetOverlayState", false, async ({ frame }, state) => {
183
- if (frame.parentFrame())
184
- return;
185
- this._overlayState = state;
186
- });
187
- await this._context.exposeBinding("__pw_resume", false, () => {
188
- this._debugger.resume(false);
146
+ const uiState = {
147
+ mode: this._mode,
148
+ actionPoint,
149
+ actionSelector,
150
+ ariaTemplate: this._highlightedElement.ariaTemplate,
151
+ language: this._currentLanguage,
152
+ testIdAttributeName: this._testIdAttributeName(),
153
+ overlay: this._overlayState
154
+ };
155
+ return uiState;
156
+ });
157
+ await this._context.exposeBinding(progress, "__pw_recorderElementPicked", false, async ({ frame }, elementInfo) => {
158
+ const selectorChain = await (0, import_recorderUtils.generateFrameSelector)(frame);
159
+ this.emit(RecorderEvent.ElementPicked, { selector: (0, import_recorderUtils.buildFullSelector)(selectorChain, elementInfo.selector), ariaSnapshot: elementInfo.ariaSnapshot }, true);
160
+ });
161
+ await this._context.exposeBinding(progress, "__pw_recorderSetMode", false, async ({ frame }, mode) => {
162
+ if (frame.parentFrame())
163
+ return;
164
+ this.setMode(mode);
165
+ });
166
+ await this._context.exposeBinding(progress, "__pw_recorderSetOverlayState", false, async ({ frame }, state) => {
167
+ if (frame.parentFrame())
168
+ return;
169
+ this._overlayState = state;
170
+ });
171
+ await this._context.exposeBinding(progress, "__pw_resume", false, () => {
172
+ this._debugger.resume(false);
173
+ });
174
+ this._context.on(import_browserContext.BrowserContext.Events.Page, (page) => this._onPage(page));
175
+ for (const page of this._context.pages())
176
+ this._onPage(page);
177
+ this._context.dialogManager.addDialogHandler((dialog) => {
178
+ this._onDialog(dialog.page());
179
+ return false;
180
+ });
181
+ await this._context.exposeBinding(
182
+ progress,
183
+ "__pw_recorderPerformAction",
184
+ false,
185
+ (source, action) => this._performAction(source.frame, action)
186
+ );
187
+ await this._context.exposeBinding(
188
+ progress,
189
+ "__pw_recorderRecordAction",
190
+ false,
191
+ (source, action) => this._recordAction(source.frame, action)
192
+ );
193
+ await this._context.extendInjectedScript(rawRecorderSource.source, { recorderMode: this._recorderMode });
189
194
  });
190
- await this._context.extendInjectedScript(consoleApiSource.source);
191
- await this._contextRecorder.install();
192
195
  if (this._debugger.isPaused())
193
196
  this._pausedStateChanged();
194
197
  this._debugger.on(import_debugger.Debugger.Events.PausedStateChanged, () => this._pausedStateChanged());
195
- this._context.recorderAppForTest = this._recorderApp;
196
198
  }
197
199
  _pausedStateChanged() {
198
200
  for (const { metadata, sdkObject } of this._debugger.pausedDetails()) {
199
201
  if (!this._currentCallsMetadata.has(metadata))
200
202
  this.onBeforeCall(sdkObject, metadata);
201
203
  }
202
- this._recorderApp?.setPaused(this._debugger.isPaused());
204
+ this.emit(RecorderEvent.PausedStateChanged, this._debugger.isPaused());
203
205
  this._updateUserSources();
204
206
  this.updateCallLog([...this._currentCallsMetadata.keys()]);
205
207
  }
208
+ mode() {
209
+ return this._mode;
210
+ }
206
211
  setMode(mode) {
207
212
  if (this._mode === mode)
208
213
  return;
209
214
  this._highlightedElement = {};
210
215
  this._mode = mode;
211
- this._recorderApp?.setMode(this._mode);
212
- this._contextRecorder.setEnabled(this._isRecording());
216
+ this.emit(RecorderEvent.ModeChanged, this._mode);
217
+ this._setEnabled(this._isRecording());
213
218
  this._debugger.setMuted(this._isRecording());
214
219
  if (this._mode !== "none" && this._mode !== "standby" && this._context.pages().length === 1)
215
220
  this._context.pages()[0].bringToFront().catch(() => {
216
221
  });
217
222
  this._refreshOverlay();
218
223
  }
219
- resume() {
220
- this._debugger.resume(false);
224
+ url() {
225
+ const page = this._context.pages()[0];
226
+ return page?.mainFrame().url();
221
227
  }
222
- mode() {
223
- return this._mode;
224
- }
225
- setHighlightedSelector(language, selector) {
226
- this._highlightedElement = { selector: (0, import_locatorParser.locatorOrSelectorAsSelector)(language, selector, this._context.selectors().testIdAttributeName()) };
228
+ setHighlightedSelector(selector) {
229
+ this._highlightedElement = { selector: (0, import_locatorParser.locatorOrSelectorAsSelector)(this._currentLanguage, selector, this._context.selectors().testIdAttributeName()) };
227
230
  this._refreshOverlay();
228
231
  }
229
232
  setHighlightedAriaTemplate(ariaTemplate) {
230
233
  this._highlightedElement = { ariaTemplate };
231
234
  this._refreshOverlay();
232
235
  }
236
+ step() {
237
+ this._debugger.resume(true);
238
+ }
239
+ setLanguage(language) {
240
+ this._currentLanguage = language;
241
+ this._refreshOverlay();
242
+ }
243
+ resume() {
244
+ this._debugger.resume(false);
245
+ }
246
+ pause() {
247
+ this._debugger.pauseOnNextStatement();
248
+ }
249
+ paused() {
250
+ return this._debugger.isPaused();
251
+ }
252
+ close() {
253
+ this._debugger.resume(false);
254
+ }
233
255
  hideHighlightedSelector() {
234
256
  this._highlightedElement = {};
235
257
  this._refreshOverlay();
236
258
  }
259
+ pausedSourceId() {
260
+ for (const { metadata } of this._debugger.pausedDetails()) {
261
+ if (!metadata.location)
262
+ continue;
263
+ const source = this._userSources.get(metadata.location.file);
264
+ if (!source)
265
+ continue;
266
+ return source.id;
267
+ }
268
+ }
269
+ userSources() {
270
+ return [...this._userSources.values()];
271
+ }
272
+ callLog() {
273
+ return this._callLogs;
274
+ }
237
275
  async _scopeHighlightedSelectorToFrame(frame) {
238
276
  if (!this._highlightedElement.selector)
239
277
  return;
@@ -251,9 +289,6 @@ class Recorder {
251
289
  return "";
252
290
  }
253
291
  }
254
- setOutput(codegenId, outputFile) {
255
- this._contextRecorder.setOutput(codegenId, outputFile);
256
- }
257
292
  _refreshOverlay() {
258
293
  for (const page of this._context.pages()) {
259
294
  for (const frame of page.frames())
@@ -285,7 +320,6 @@ class Recorder {
285
320
  source.highlight = [];
286
321
  source.revealLine = void 0;
287
322
  }
288
- let fileToSelect = void 0;
289
323
  for (const metadata of this._currentCallsMetadata.keys()) {
290
324
  if (!metadata.location)
291
325
  continue;
@@ -299,16 +333,9 @@ class Recorder {
299
333
  const paused = this._debugger.isPaused(metadata);
300
334
  source.highlight.push({ line, type: metadata.error ? "error" : paused ? "paused" : "running" });
301
335
  source.revealLine = line;
302
- fileToSelect = source.id;
303
336
  }
304
337
  }
305
- this._pushAllSources();
306
- if (fileToSelect)
307
- this._recorderApp?.setRunningFile(fileToSelect);
308
- }
309
- _pushAllSources() {
310
- const primaryPage = this._context.pages()[0];
311
- this._recorderApp?.setSources([...this._recorderSources, ...this._userSources.values()], primaryPage?.mainFrame().url());
338
+ this.emit(RecorderEvent.UserSourcesChanged, this.userSources(), this.pausedSourceId());
312
339
  }
313
340
  async onBeforeInputAction(sdkObject, metadata) {
314
341
  }
@@ -329,7 +356,8 @@ class Recorder {
329
356
  status = "paused";
330
357
  logs.push((0, import_recorderUtils.metadataToCallLog)(metadata, status));
331
358
  }
332
- this._recorderApp?.updateCallLogs(logs);
359
+ this._callLogs = logs;
360
+ this.emit(RecorderEvent.CallLogsUpdated, logs);
333
361
  }
334
362
  _isRecording() {
335
363
  return ["recording", "assertingText", "assertingVisibility", "assertingValue", "assertingSnapshot"].includes(this._mode);
@@ -341,6 +369,115 @@ class Recorder {
341
369
  return "// No source available";
342
370
  }
343
371
  }
372
+ _setEnabled(enabled) {
373
+ this._enabled = enabled;
374
+ }
375
+ async _onPage(page) {
376
+ const frame = page.mainFrame();
377
+ page.on(import_page.Page.Events.Close, () => {
378
+ this._signalProcessor.addAction({
379
+ frame: this._describeMainFrame(page),
380
+ action: {
381
+ name: "closePage",
382
+ signals: []
383
+ },
384
+ startTime: (0, import_utils2.monotonicTime)()
385
+ });
386
+ this._pageAliases.delete(page);
387
+ this._filePrimaryURLChanged();
388
+ });
389
+ frame.on(import_frames.Frame.Events.InternalNavigation, (event) => {
390
+ if (event.isPublic) {
391
+ this._onFrameNavigated(frame, page);
392
+ this._filePrimaryURLChanged();
393
+ }
394
+ });
395
+ page.on(import_page.Page.Events.Download, () => this._onDownload(page));
396
+ const suffix = this._pageAliases.size ? String(++this._lastPopupOrdinal) : "";
397
+ const pageAlias = "page" + suffix;
398
+ this._pageAliases.set(page, pageAlias);
399
+ if (page.opener()) {
400
+ this._onPopup(page.opener(), page);
401
+ } else {
402
+ this._signalProcessor.addAction({
403
+ frame: this._describeMainFrame(page),
404
+ action: {
405
+ name: "openPage",
406
+ url: page.mainFrame().url(),
407
+ signals: []
408
+ },
409
+ startTime: (0, import_utils2.monotonicTime)()
410
+ });
411
+ }
412
+ this._filePrimaryURLChanged();
413
+ }
414
+ _filePrimaryURLChanged() {
415
+ const page = this._context.pages()[0];
416
+ this.emit(RecorderEvent.PageNavigated, page?.mainFrame().url());
417
+ }
418
+ clear() {
419
+ if (this._params.mode === "recording") {
420
+ for (const page of this._context.pages())
421
+ this._onFrameNavigated(page.mainFrame(), page);
422
+ }
423
+ }
424
+ _describeMainFrame(page) {
425
+ return {
426
+ pageGuid: page.guid,
427
+ pageAlias: this._pageAliases.get(page),
428
+ framePath: []
429
+ };
430
+ }
431
+ async _describeFrame(frame) {
432
+ return {
433
+ pageGuid: frame._page.guid,
434
+ pageAlias: this._pageAliases.get(frame._page),
435
+ framePath: await (0, import_recorderUtils.generateFrameSelector)(frame)
436
+ };
437
+ }
438
+ _testIdAttributeName() {
439
+ return this._params.testIdAttributeName || this._context.selectors().testIdAttributeName() || "data-testid";
440
+ }
441
+ async _createActionInContext(frame, action) {
442
+ const frameDescription = await this._describeFrame(frame);
443
+ const actionInContext = {
444
+ frame: frameDescription,
445
+ action,
446
+ description: void 0,
447
+ startTime: (0, import_utils2.monotonicTime)()
448
+ };
449
+ return actionInContext;
450
+ }
451
+ async _performAction(frame, action) {
452
+ const actionInContext = await this._createActionInContext(frame, action);
453
+ this._signalProcessor.addAction(actionInContext);
454
+ if (actionInContext.action.name !== "openPage" && actionInContext.action.name !== "closePage")
455
+ await (0, import_recorderRunner.performAction)(this._pageAliases, actionInContext);
456
+ actionInContext.endTime = (0, import_utils2.monotonicTime)();
457
+ }
458
+ async _recordAction(frame, action) {
459
+ const actionInContext = await this._createActionInContext(frame, action);
460
+ this._signalProcessor.addAction(actionInContext);
461
+ }
462
+ _onFrameNavigated(frame, page) {
463
+ const pageAlias = this._pageAliases.get(page);
464
+ this._signalProcessor.signal(pageAlias, frame, { name: "navigation", url: frame.url() });
465
+ }
466
+ _onPopup(page, popup) {
467
+ const pageAlias = this._pageAliases.get(page);
468
+ const popupAlias = this._pageAliases.get(popup);
469
+ this._signalProcessor.signal(pageAlias, page.mainFrame(), { name: "popup", popupAlias });
470
+ }
471
+ _onDownload(page) {
472
+ const pageAlias = this._pageAliases.get(page);
473
+ ++this._lastDownloadOrdinal;
474
+ this._signalProcessor.signal(pageAlias, page.mainFrame(), { name: "download", downloadAlias: this._lastDownloadOrdinal ? String(this._lastDownloadOrdinal) : "" });
475
+ }
476
+ _onDialog(page) {
477
+ const pageAlias = this._pageAliases.get(page);
478
+ ++this._lastDialogOrdinal;
479
+ this._signalProcessor.signal(pageAlias, page.mainFrame(), { name: "dialog", dialogAlias: this._lastDialogOrdinal ? String(this._lastDialogOrdinal) : "" });
480
+ }
344
481
  }
345
482
  function isScreenshotCommand(metadata) {
346
483
  return metadata.method.toLowerCase().includes("screenshot");
@@ -356,5 +493,6 @@ function languageForFile(file) {
356
493
  }
357
494
  // Annotate the CommonJS export names for ESM import in node:
358
495
  0 && (module.exports = {
359
- Recorder
496
+ Recorder,
497
+ RecorderEvent
360
498
  });