@rehearsal-labs/retest 0.2.0 → 0.3.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/README.md +6 -5
  2. package/dist/api/source-location.d.ts.map +1 -1
  3. package/dist/api/source-location.js +3 -1
  4. package/dist/browser/builds.d.ts +35 -6
  5. package/dist/browser/builds.d.ts.map +1 -1
  6. package/dist/browser/builds.js +115 -16
  7. package/dist/browser/cdp/transport.d.ts.map +1 -1
  8. package/dist/browser/cdp/transport.js +4 -4
  9. package/dist/browser/chromium-process.d.ts +23 -0
  10. package/dist/browser/chromium-process.d.ts.map +1 -1
  11. package/dist/browser/chromium-process.js +78 -13
  12. package/dist/browser/electron.d.ts +1 -1
  13. package/dist/browser/electron.d.ts.map +1 -1
  14. package/dist/browser/electron.js +6 -3
  15. package/dist/browser/executables.d.ts +16 -1
  16. package/dist/browser/executables.d.ts.map +1 -1
  17. package/dist/browser/executables.js +50 -18
  18. package/dist/browser/firefox/accessible-names.d.ts +5 -4
  19. package/dist/browser/firefox/accessible-names.d.ts.map +1 -1
  20. package/dist/browser/firefox/accessible-names.js +11 -6
  21. package/dist/browser/firefox/bridge.js +3 -2
  22. package/dist/browser/firefox/executable.d.ts +14 -14
  23. package/dist/browser/firefox/executable.d.ts.map +1 -1
  24. package/dist/browser/firefox/executable.js +29 -21
  25. package/dist/browser/firefox/launch.js +1 -1
  26. package/dist/browser/firefox/navigation.d.ts +5 -2
  27. package/dist/browser/firefox/navigation.d.ts.map +1 -1
  28. package/dist/browser/firefox/navigation.js +48 -14
  29. package/dist/browser/firefox/orphans.d.ts.map +1 -1
  30. package/dist/browser/firefox/orphans.js +34 -2
  31. package/dist/browser/firefox/page.d.ts.map +1 -1
  32. package/dist/browser/firefox/page.js +113 -19
  33. package/dist/browser/firefox/process.d.ts +20 -1
  34. package/dist/browser/firefox/process.d.ts.map +1 -1
  35. package/dist/browser/firefox/process.js +124 -22
  36. package/dist/browser/firefox/profile.d.ts +5 -0
  37. package/dist/browser/firefox/profile.d.ts.map +1 -1
  38. package/dist/browser/firefox/profile.js +17 -1
  39. package/dist/browser/firefox/storage.d.ts.map +1 -1
  40. package/dist/browser/firefox/storage.js +4 -2
  41. package/dist/browser/firefox/subscriptions.d.ts +26 -0
  42. package/dist/browser/firefox/subscriptions.d.ts.map +1 -0
  43. package/dist/browser/firefox/subscriptions.js +10 -0
  44. package/dist/browser/launch.d.ts +6 -0
  45. package/dist/browser/launch.d.ts.map +1 -1
  46. package/dist/browser/launch.js +14 -1
  47. package/dist/cli/commands/doctor.js +3 -3
  48. package/dist/cli/commands/inspect.js +3 -2
  49. package/dist/cli/commands/install.d.ts.map +1 -1
  50. package/dist/cli/commands/install.js +26 -13
  51. package/dist/cli/commands/licences.d.ts +22 -0
  52. package/dist/cli/commands/licences.d.ts.map +1 -1
  53. package/dist/cli/commands/licences.js +62 -20
  54. package/dist/cli/commands/run.js +2 -2
  55. package/dist/cli/doctor/checks.js +4 -1
  56. package/dist/cli/inspect/diagnostics.js +3 -3
  57. package/dist/cli/inspect/test-timeline.js +10 -10
  58. package/dist/cli/install/doctor-rows.d.ts.map +1 -1
  59. package/dist/cli/install/doctor-rows.js +5 -4
  60. package/dist/cli/install/file-changes.d.ts +44 -0
  61. package/dist/cli/install/file-changes.d.ts.map +1 -0
  62. package/dist/cli/install/file-changes.js +81 -0
  63. package/dist/cli/install/install-archive.d.ts +3 -1
  64. package/dist/cli/install/install-archive.d.ts.map +1 -1
  65. package/dist/cli/install/install-archive.js +80 -33
  66. package/dist/cli/install/lock.d.ts.map +1 -1
  67. package/dist/cli/install/lock.js +108 -21
  68. package/dist/cli/install/media-doctor.d.ts.map +1 -1
  69. package/dist/cli/install/media-doctor.js +2 -1
  70. package/dist/cli/install/media-install.d.ts.map +1 -1
  71. package/dist/cli/install/media-install.js +38 -19
  72. package/dist/cli/install/media-pins.d.ts +7 -1
  73. package/dist/cli/install/media-pins.d.ts.map +1 -1
  74. package/dist/cli/install/media-pins.js +23 -12
  75. package/dist/cli/install/media-record.d.ts.map +1 -1
  76. package/dist/cli/install/media-record.js +10 -9
  77. package/dist/cli/install/media-report.d.ts +3 -1
  78. package/dist/cli/install/media-report.d.ts.map +1 -1
  79. package/dist/cli/install/media-report.js +7 -5
  80. package/dist/cli/install/media-tools.d.ts.map +1 -1
  81. package/dist/cli/install/media-tools.js +6 -4
  82. package/dist/cli/install/process-start.d.ts +3 -2
  83. package/dist/cli/install/process-start.d.ts.map +1 -1
  84. package/dist/cli/install/process-start.js +4 -0
  85. package/dist/cli/install/report.d.ts.map +1 -1
  86. package/dist/cli/install/report.js +11 -7
  87. package/dist/cli/install/supervisor-install.d.ts +33 -0
  88. package/dist/cli/install/supervisor-install.d.ts.map +1 -0
  89. package/dist/cli/install/supervisor-install.js +158 -0
  90. package/dist/cli/install/supervisor-locate.d.ts +47 -0
  91. package/dist/cli/install/supervisor-locate.d.ts.map +1 -0
  92. package/dist/cli/install/supervisor-locate.js +113 -0
  93. package/dist/cli/install/supervisor-pins.d.ts +21 -0
  94. package/dist/cli/install/supervisor-pins.d.ts.map +1 -0
  95. package/dist/cli/install/supervisor-pins.js +28 -0
  96. package/dist/cli/install/supervisor-record.d.ts +31 -0
  97. package/dist/cli/install/supervisor-record.d.ts.map +1 -0
  98. package/dist/cli/install/supervisor-record.js +104 -0
  99. package/dist/cli/install/supervisor-report.d.ts +11 -0
  100. package/dist/cli/install/supervisor-report.d.ts.map +1 -0
  101. package/dist/cli/install/supervisor-report.js +33 -0
  102. package/dist/cli/install/supervisor-tools.d.ts +43 -0
  103. package/dist/cli/install/supervisor-tools.d.ts.map +1 -0
  104. package/dist/cli/install/supervisor-tools.js +114 -0
  105. package/dist/cli/install/unpack.d.ts +23 -3
  106. package/dist/cli/install/unpack.d.ts.map +1 -1
  107. package/dist/cli/install/unpack.js +124 -10
  108. package/dist/cli/install/zip-member.d.ts +15 -0
  109. package/dist/cli/install/zip-member.d.ts.map +1 -0
  110. package/dist/cli/install/zip-member.js +77 -0
  111. package/dist/cli/interrupt.d.ts +1 -1
  112. package/dist/cli/interrupt.d.ts.map +1 -1
  113. package/dist/cli/interrupt.js +15 -10
  114. package/dist/cli/terminal.d.ts +9 -1
  115. package/dist/cli/terminal.d.ts.map +1 -1
  116. package/dist/cli/terminal.js +14 -0
  117. package/dist/config/define.d.ts +2 -2
  118. package/dist/config/define.js +2 -2
  119. package/dist/diagnostics/firefox-collector.d.ts +11 -10
  120. package/dist/diagnostics/firefox-collector.d.ts.map +1 -1
  121. package/dist/diagnostics/firefox-collector.js +16 -11
  122. package/dist/media/client.d.ts +2 -1
  123. package/dist/media/client.d.ts.map +1 -1
  124. package/dist/media/client.js +16 -5
  125. package/dist/media/host.d.ts +32 -0
  126. package/dist/media/host.d.ts.map +1 -0
  127. package/dist/media/host.js +50 -0
  128. package/dist/media/locate.d.ts.map +1 -1
  129. package/dist/media/locate.js +4 -3
  130. package/dist/native/processes.d.ts.map +1 -1
  131. package/dist/native/processes.js +7 -3
  132. package/dist/protocol/files.d.ts +1 -1
  133. package/dist/protocol/files.d.ts.map +1 -1
  134. package/dist/protocol/files.js +10 -5
  135. package/dist/reporters/commands.d.ts +12 -3
  136. package/dist/reporters/commands.d.ts.map +1 -1
  137. package/dist/reporters/commands.js +29 -11
  138. package/dist/reporters/human-card.js +1 -1
  139. package/dist/reporters/human.d.ts +3 -1
  140. package/dist/reporters/human.d.ts.map +1 -1
  141. package/dist/reporters/human.js +8 -8
  142. package/dist/reporters/style.d.ts +21 -2
  143. package/dist/reporters/style.d.ts.map +1 -1
  144. package/dist/reporters/style.js +11 -2
  145. package/dist/runner/app-server.d.ts +27 -7
  146. package/dist/runner/app-server.d.ts.map +1 -1
  147. package/dist/runner/app-server.js +74 -24
  148. package/dist/runner/child.js +6 -2
  149. package/dist/runner/media-leftovers.d.ts +7 -3
  150. package/dist/runner/media-leftovers.d.ts.map +1 -1
  151. package/dist/runner/media-leftovers.js +27 -6
  152. package/dist/runner/resources.d.ts +8 -0
  153. package/dist/runner/resources.d.ts.map +1 -1
  154. package/dist/runner/resources.js +12 -1
  155. package/dist/runner/run-session.d.ts.map +1 -1
  156. package/dist/runner/run-session.js +9 -4
  157. package/dist/runner/run.d.ts.map +1 -1
  158. package/dist/runner/run.js +2 -1
  159. package/dist/runner/target-drivers.d.ts +5 -2
  160. package/dist/runner/target-drivers.d.ts.map +1 -1
  161. package/dist/runner/target-drivers.js +10 -1
  162. package/dist/runner/test-file-process.d.ts +8 -0
  163. package/dist/runner/test-file-process.d.ts.map +1 -1
  164. package/dist/runner/test-file-process.js +26 -3
  165. package/dist/runner/test-pages.d.ts.map +1 -1
  166. package/dist/runner/test-pages.js +5 -2
  167. package/dist/shared/environment.d.ts +17 -0
  168. package/dist/shared/environment.d.ts.map +1 -0
  169. package/dist/shared/environment.js +27 -0
  170. package/dist/shared/metadata-process-worker.js +15 -7
  171. package/dist/shared/metadata-process.d.ts +5 -0
  172. package/dist/shared/metadata-process.d.ts.map +1 -1
  173. package/dist/shared/metadata-process.js +36 -6
  174. package/dist/shared/posix-path.d.ts +12 -0
  175. package/dist/shared/posix-path.d.ts.map +1 -1
  176. package/dist/shared/posix-path.js +16 -0
  177. package/dist/shared/private-file.d.ts +38 -0
  178. package/dist/shared/private-file.d.ts.map +1 -0
  179. package/dist/shared/private-file.js +132 -0
  180. package/dist/shared/process-ownership.d.ts +52 -2
  181. package/dist/shared/process-ownership.d.ts.map +1 -1
  182. package/dist/shared/process-ownership.js +104 -11
  183. package/dist/shared/process-supervisor.d.ts +309 -0
  184. package/dist/shared/process-supervisor.d.ts.map +1 -0
  185. package/dist/shared/process-supervisor.js +737 -0
  186. package/dist/shared/process-system.d.ts +113 -0
  187. package/dist/shared/process-system.d.ts.map +1 -0
  188. package/dist/shared/process-system.js +254 -0
  189. package/dist/shared/regular-file.d.ts +2 -2
  190. package/dist/shared/regular-file.d.ts.map +1 -1
  191. package/dist/shared/regular-file.js +19 -2
  192. package/dist/store/artifacts.d.ts +5 -4
  193. package/dist/store/artifacts.d.ts.map +1 -1
  194. package/dist/store/artifacts.js +18 -5
  195. package/dist/store/run-store.d.ts +5 -2
  196. package/dist/store/run-store.d.ts.map +1 -1
  197. package/dist/store/run-store.js +48 -4
  198. package/media/Cargo.lock +16 -0
  199. package/media/Cargo.toml +16 -1
  200. package/media/src/encoder.rs +56 -12
  201. package/media/src/frame.rs +7 -1
  202. package/media/src/main.rs +20 -2
  203. package/media/src/place.rs +230 -11
  204. package/media/src/process_ownership_windows.rs +1058 -0
  205. package/media/src/recording.rs +15 -7
  206. package/media/src/replies.rs +55 -0
  207. package/media/src/server.rs +72 -2
  208. package/media/src/store.rs +71 -2
  209. package/package.json +9 -4
  210. package/src/cli/install/media-notices.txt +465 -1
  211. package/supervisor/Cargo.lock +25 -0
  212. package/supervisor/Cargo.toml +22 -0
  213. package/supervisor/NOTICES +464 -0
  214. package/supervisor/build.rs +44 -0
  215. package/supervisor/src/command.rs +612 -0
  216. package/supervisor/src/jobs.rs +1650 -0
  217. package/supervisor/src/main.rs +71 -0
  218. package/supervisor/src/reply.rs +367 -0
@@ -21,26 +21,76 @@ export type ProcessOwnershipSystem = {
21
21
  readAsync?(deadline?: Deadline): Promise<readonly OwnedProcessIdentity[]>;
22
22
  /** The same immediate pre-signal reading without holding the event loop. */
23
23
  readProcessAsync?(pid: number, deadline?: Deadline): Promise<OwnedProcessIdentity | undefined>;
24
- signal(pid: number, signal: NodeJS.Signals | 0): void;
24
+ /** `expected` is the fresh reading the signal follows, for a host that checks it again as it signals. */
25
+ signal(pid: number, signal: NodeJS.Signals | 0, expected?: OwnedProcessIdentity): void;
26
+ /**
27
+ * Set where `read` lists one job's processes and nothing else, as on Windows: the job the launch `root` was put in,
28
+ * which holds every process it and its descendants started. There, a member is owned by being in the job, and the
29
+ * group is ended by ending the job.
30
+ */
31
+ job?: OwnedJob;
32
+ };
33
+ /**
34
+ * A launch's job: the pid it was made for, and its end, which ends every process in it at once. A job holds only
35
+ * processes born of the launch, so ending it ends nothing else, and nothing in it is left out.
36
+ */
37
+ export type OwnedJob = {
38
+ readonly root: number;
39
+ /**
40
+ * The launch as it was read when it was put in the job, alive. A process gone from the job is gone from its list at
41
+ * once, where Unix still shows it until it is reaped, so a launch that ended before the first reading is recorded
42
+ * from this.
43
+ */
44
+ readonly launched?: OwnedProcessIdentity;
45
+ end(deadline?: Deadline): void;
46
+ endAsync(deadline?: Deadline): Promise<void>;
47
+ /** Sends Ctrl+C to the console the job's processes are on, which is how a console program is asked to stop. */
48
+ interrupt(deadline?: Deadline): void;
49
+ /** What the job's end could not confirm, once the job was read empty: processes still running outside every job. */
50
+ unconfirmed(): readonly string[];
25
51
  };
26
52
  /** Signal failures stay failures; identity refusals can be reconciled only by a later proof of absence. */
27
53
  export type ProcessSignalReport = {
28
54
  readonly problems: readonly string[];
29
55
  readonly identityRefusals: readonly string[];
30
56
  };
57
+ /** What one reading of whether a group remains said: the processes of the group it found running, or why it failed. */
58
+ export type LivenessReading = {
59
+ readonly running: readonly OwnedProcessIdentity[];
60
+ } | {
61
+ readonly problem: string;
62
+ };
31
63
  /**
32
64
  * Records a launched process and the descendants observed beneath a still-verified owned process. Group membership
33
65
  * alone never establishes ownership. Signals are sent to recorded, freshly verified pids, never to a numeric group.
66
+ * A launch held in a job of its own, as on Windows, is the exception the job makes possible: the job holds nothing but
67
+ * what the launch started, so its members are owned by being there, and it is ended whole.
34
68
  */
35
69
  export declare class OwnedProcessGroup {
36
70
  #private;
37
71
  constructor(pid: number, parentPid?: number, system?: ProcessOwnershipSystem);
38
72
  /** The first successful host reading found no launched pid. A failed reading never sets this fact. */
39
73
  get initialProcessAbsent(): boolean;
40
- /** Failed metadata readings remain visible even when a later reading proves the launch ended. */
74
+ /**
75
+ * Failed metadata readings remain visible even when a later reading proves the launch ended, as does, for a launch
76
+ * held in a job, anything its job's end could not confirm.
77
+ */
41
78
  get readProblems(): readonly string[];
42
79
  /** Whether the launch has been read once, whatever the reading found or however it failed. */
43
80
  get captured(): boolean;
81
+ /** Whether this group is a launch held in a job of its own, which ends it whole rather than one signal at a time. */
82
+ get heldByJob(): boolean;
83
+ /**
84
+ * The processes of the group on record, recorded or not traced to the launch, as the newest reading that succeeded
85
+ * left them. A reading that failed changes nothing here, so this is no proof that they still run. Empty once a reading
86
+ * found the group gone.
87
+ */
88
+ get stillThere(): readonly OwnedProcessIdentity[];
89
+ /**
90
+ * What the newest reading of whether the group remains said: the processes of the group it found still running, or
91
+ * the problem it failed with. Undefined before the first.
92
+ */
93
+ get lastLook(): LivenessReading | undefined;
44
94
  /** Records descendants only while their chain reaches an already verified process this owner launched. */
45
95
  capture(deadline?: Deadline): string[];
46
96
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"process-ownership.d.ts","sourceRoot":"","sources":["../../src/shared/process-ownership.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"process-ownership.d.ts","sourceRoot":"","sources":["../../src/shared/process-ownership.ts"],"names":[],"mappings":"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"}
@@ -11,6 +11,8 @@ const host = {
11
11
  /**
12
12
  * Records a launched process and the descendants observed beneath a still-verified owned process. Group membership
13
13
  * alone never establishes ownership. Signals are sent to recorded, freshly verified pids, never to a numeric group.
14
+ * A launch held in a job of its own, as on Windows, is the exception the job makes possible: the job holds nothing but
15
+ * what the launch started, so its members are owned by being there, and it is ended whole.
14
16
  */
15
17
  export class OwnedProcessGroup {
16
18
  #pid;
@@ -19,6 +21,7 @@ export class OwnedProcessGroup {
19
21
  #records = new Map();
20
22
  #unowned = new Map();
21
23
  #readProblems = new Set();
24
+ #lastLook;
22
25
  #initialized = false;
23
26
  #retired = false;
24
27
  #initialProcessAbsent = false;
@@ -43,14 +46,41 @@ export class OwnedProcessGroup {
43
46
  get initialProcessAbsent() {
44
47
  return this.#initialProcessAbsent;
45
48
  }
46
- /** Failed metadata readings remain visible even when a later reading proves the launch ended. */
49
+ /**
50
+ * Failed metadata readings remain visible even when a later reading proves the launch ended, as does, for a launch
51
+ * held in a job, anything its job's end could not confirm.
52
+ */
47
53
  get readProblems() {
48
- return [...this.#readProblems];
54
+ return [...this.#readProblems, ...(this.#ownJob()?.unconfirmed() ?? [])];
49
55
  }
50
56
  /** Whether the launch has been read once, whatever the reading found or however it failed. */
51
57
  get captured() {
52
58
  return this.#initialized;
53
59
  }
60
+ /** Whether this group is a launch held in a job of its own, which ends it whole rather than one signal at a time. */
61
+ get heldByJob() {
62
+ return this.#ownJob() !== undefined;
63
+ }
64
+ /**
65
+ * The processes of the group on record, recorded or not traced to the launch, as the newest reading that succeeded
66
+ * left them. A reading that failed changes nothing here, so this is no proof that they still run. Empty once a reading
67
+ * found the group gone.
68
+ */
69
+ get stillThere() {
70
+ return [...this.#records.values(), ...this.#unowned.values()];
71
+ }
72
+ /**
73
+ * What the newest reading of whether the group remains said: the processes of the group it found still running, or
74
+ * the problem it failed with. Undefined before the first.
75
+ */
76
+ get lastLook() {
77
+ return this.#lastLook;
78
+ }
79
+ // The job of this very launch; a descendant handed off by `groupFor` shares the system but is not its job's root.
80
+ #ownJob() {
81
+ const { job } = this.#system;
82
+ return job?.root === this.#pid ? job : undefined;
83
+ }
54
84
  #failedRead(error) {
55
85
  const problem = `Could not read ownership of process ${this.#pid}: ${errorMessage(error)}`;
56
86
  this.#readProblems.add(problem);
@@ -104,7 +134,7 @@ export class OwnedProcessGroup {
104
134
  this.#newest = Math.max(this.#newest, sequence);
105
135
  const initial = !this.#initialized;
106
136
  this.#initialized = true;
107
- const root = processes.find((entry) => entry.pid === this.#pid);
137
+ const root = processes.find((entry) => entry.pid === this.#pid) ?? (initial ? this.#ownJob()?.launched : undefined);
108
138
  if (initial) {
109
139
  if (root === undefined) {
110
140
  this.#initialProcessAbsent = true;
@@ -115,6 +145,12 @@ export class OwnedProcessGroup {
115
145
  this.#records.set(root.pid, root);
116
146
  this.#launchIdentity = root;
117
147
  }
148
+ // A job lists only processes born of its launch, even one whose parent is gone, so its members need no ancestry.
149
+ if (this.#ownJob() !== undefined) {
150
+ for (const entry of processes)
151
+ if (running(entry) && entry.groupId === this.#pid && !this.#records.has(entry.pid))
152
+ this.#records.set(entry.pid, entry);
153
+ }
118
154
  for (const entry of processes) {
119
155
  const record = this.#records.get(entry.pid);
120
156
  // A process recorded while its command could not be read keeps the first readable one, so a later change is seen.
@@ -217,6 +253,11 @@ export class OwnedProcessGroup {
217
253
  signalReport(signal, deadline) {
218
254
  if (this.#retired)
219
255
  return { problems: [], identityRefusals: [] };
256
+ const job = this.#ownJob();
257
+ if (job !== undefined && endsProcess(signal))
258
+ return this.#endJob(job, deadline);
259
+ if (job !== undefined && signal === 'SIGINT')
260
+ return this.#interruptJob(job, deadline);
220
261
  let processes;
221
262
  try {
222
263
  checkDeadline(deadline);
@@ -252,6 +293,11 @@ export class OwnedProcessGroup {
252
293
  async signalReportAsync(signal, deadline) {
253
294
  if (this.#retired)
254
295
  return { problems: [], identityRefusals: [] };
296
+ const job = this.#ownJob();
297
+ if (job !== undefined && endsProcess(signal))
298
+ return this.#endJobAsync(job, deadline);
299
+ if (job !== undefined && signal === 'SIGINT')
300
+ return this.#interruptJob(job, deadline);
255
301
  const asked = this.#sequence;
256
302
  let read;
257
303
  try {
@@ -285,6 +331,41 @@ export class OwnedProcessGroup {
285
331
  }
286
332
  return { problems, identityRefusals };
287
333
  }
334
+ // Windows has no SIGINT to send; a console program is asked to stop by Ctrl+C on its console, which reaches every
335
+ // process on it at once, so it is sent once for the launch. It is only asked: one that cannot be asked, as one with no
336
+ // console left, is ended when its grace runs out, as one that ignores Ctrl+C is, and that end is what cleanup reports.
337
+ #interruptJob(job, deadline) {
338
+ try {
339
+ checkDeadline(deadline);
340
+ job.interrupt(deadline);
341
+ }
342
+ catch {
343
+ // As above: the end that follows is the outcome.
344
+ }
345
+ return { problems: [], identityRefusals: [] };
346
+ }
347
+ // A job is ended whole, without a reading first: it holds only what the launch started, so nothing else can be in it,
348
+ // and a helper born a moment ago is in it too. Whether it is then gone is for `remains` to read.
349
+ #endJob(job, deadline) {
350
+ try {
351
+ checkDeadline(deadline);
352
+ job.end(deadline);
353
+ }
354
+ catch (error) {
355
+ return { problems: [endProblem(this.#pid, error)], identityRefusals: [] };
356
+ }
357
+ return { problems: [], identityRefusals: [] };
358
+ }
359
+ async #endJobAsync(job, deadline) {
360
+ try {
361
+ checkDeadline(deadline);
362
+ await job.endAsync(deadline);
363
+ }
364
+ catch (error) {
365
+ return { problems: [endProblem(this.#pid, error)], identityRefusals: [] };
366
+ }
367
+ return { problems: [], identityRefusals: [] };
368
+ }
288
369
  #signalCurrent(record, current, signal, problems, identityRefusals, deadline) {
289
370
  // Another awaited cleanup may already have confirmed this record gone. It must not be restored by a late reply.
290
371
  if (this.#retired || !sameProcess(this.#records.get(record.pid), record))
@@ -310,7 +391,7 @@ export class OwnedProcessGroup {
310
391
  }
311
392
  try {
312
393
  checkDeadline(deadline);
313
- this.#system.signal(record.pid, signal);
394
+ this.#system.signal(record.pid, signal, current);
314
395
  }
315
396
  catch (error) {
316
397
  if (errorCode(error) !== 'ESRCH')
@@ -411,7 +492,7 @@ export class OwnedProcessGroup {
411
492
  checkDeadline(deadline);
412
493
  }
413
494
  catch (error) {
414
- this.#failedRead(error);
495
+ this.#lastLook = { problem: this.#failedRead(error) };
415
496
  return true;
416
497
  }
417
498
  return this.#remainsFrom(processes, this.#next());
@@ -432,7 +513,7 @@ export class OwnedProcessGroup {
432
513
  checkDeadline(deadline);
433
514
  }
434
515
  catch (error) {
435
- this.#failedRead(error);
516
+ this.#lastLook = { problem: this.#failedRead(error) };
436
517
  return true;
437
518
  }
438
519
  if (this.#retired || read === undefined)
@@ -443,8 +524,12 @@ export class OwnedProcessGroup {
443
524
  this.#newest = Math.max(this.#newest, sequence);
444
525
  // A failed first reading never grants signal authority, and an empty ledger is no proof that the launched
445
526
  // child ended. Until its pid and group are absent, that unresolved launch continues to hold its resource.
446
- if (this.#launchIdentity === undefined && processes.some((entry) => running(entry) && (entry.pid === this.#pid || entry.groupId === this.#pid)))
447
- return true;
527
+ if (this.#launchIdentity === undefined) {
528
+ const unresolved = processes.filter((entry) => running(entry) && (entry.pid === this.#pid || entry.groupId === this.#pid));
529
+ this.#lastLook = { running: unresolved };
530
+ if (unresolved.length > 0)
531
+ return true;
532
+ }
448
533
  const root = processes.find((entry) => entry.pid === this.#pid);
449
534
  const reusedGroup = root !== undefined && this.#launchIdentity !== undefined && !sameBirth(this.#launchIdentity, root);
450
535
  if (!reusedGroup)
@@ -453,9 +538,10 @@ export class OwnedProcessGroup {
453
538
  this.#unowned.set(current.pid, current);
454
539
  }
455
540
  this.#forgetGone(processes);
456
- for (const current of processes)
457
- if (running(current) && (sameBirth(this.#records.get(current.pid), current) || sameBirth(this.#unowned.get(current.pid), current)))
458
- return true;
541
+ const left = processes.filter((current) => running(current) && (sameBirth(this.#records.get(current.pid), current) || sameBirth(this.#unowned.get(current.pid), current)));
542
+ this.#lastLook = { running: left };
543
+ if (left.length > 0)
544
+ return true;
459
545
  this.#retired = true;
460
546
  this.#records.clear();
461
547
  this.#unowned.clear();
@@ -471,6 +557,13 @@ export class OwnedProcessGroup {
471
557
  export function unverifiedMembersProblem(groupId) {
472
558
  return `Process group ${groupId} contains processes whose launch ownership could not be verified; they were left alone.`;
473
559
  }
560
+ // The signals a job's end stands for. Windows has no gentler end than its job's, so SIGTERM ends a job as SIGKILL does.
561
+ function endsProcess(signal) {
562
+ return signal === 'SIGKILL' || signal === 'SIGTERM';
563
+ }
564
+ function endProblem(pid, error) {
565
+ return `Could not end the job holding process ${pid} and what it started: ${errorMessage(error)}`;
566
+ }
474
567
  function sameProcess(record, current) {
475
568
  return record !== undefined && sameProcessIdentity(record, current);
476
569
  }
@@ -0,0 +1,309 @@
1
+ import type { OwnedJob, ProcessOwnershipSystem } from './process-ownership.ts';
2
+ import type { Deadline } from '../protocol/deadline.ts';
3
+ /** How to run the supervisor: its executable, the arguments before each command, and its whole environment. */
4
+ export type SupervisorProgram = {
5
+ readonly command: string;
6
+ readonly args: readonly string[];
7
+ readonly environment: Readonly<Record<string, string>>;
8
+ };
9
+ /**
10
+ * One process as the supervisor read it, every field from one handle on it. `startedAt` is the 100 ns ticks since 1601
11
+ * Windows keeps, as digits; `commandLine` what it was started with.
12
+ */
13
+ export type SupervisedProcess = {
14
+ readonly pid: number;
15
+ readonly parentPid: number | undefined;
16
+ readonly startedAt: string;
17
+ readonly image: string | undefined;
18
+ readonly commandLine: string | undefined;
19
+ };
20
+ /** The runner's own job: its name, and the value of the runner's handle that keeps it. */
21
+ export type HeldRunner = {
22
+ readonly job: string;
23
+ readonly handle: number;
24
+ };
25
+ /**
26
+ * A launch held in a job of its own: the job, the runner's handle to it, the launched process, whether it had already
27
+ * ended, so only what it started is in the job, the processes it had already started before it was held, which the
28
+ * supervisor held then, those it found already in a job of their own inside the runner's, which the process that
29
+ * started them holds, any it could not hold, and whether the search for them finished.
30
+ */
31
+ export type HeldLaunch = {
32
+ readonly job: string;
33
+ readonly handle: number;
34
+ readonly root: SupervisedProcess;
35
+ readonly ended: boolean;
36
+ readonly late: readonly SupervisedProcess[];
37
+ readonly byParent: readonly SupervisedProcess[];
38
+ readonly unheld: readonly number[];
39
+ readonly complete: boolean;
40
+ };
41
+ /** The console Ctrl+C went to, by the job's process it was reached through, and every process on that console. */
42
+ export type Interrupted = {
43
+ readonly console: number;
44
+ readonly reached: readonly number[];
45
+ };
46
+ /** What `terminate` found under the pid: the recorded process, ended; nothing; or another process. */
47
+ export type TerminateOutcome = 'terminated' | 'absent' | 'different';
48
+ /** One process in a reply, as the supervisor prints it. */
49
+ type Identity = {
50
+ pid: number;
51
+ parentPid: number | null;
52
+ startedAt: string;
53
+ image: string | null;
54
+ commandLine: string | null;
55
+ };
56
+ /** The one line the supervisor prints for each command, a refusal included. */
57
+ export type SupervisorReply = {
58
+ schemaVersion: 1;
59
+ type: 'held';
60
+ job: string;
61
+ runner: number;
62
+ handle: number;
63
+ } | {
64
+ schemaVersion: 1;
65
+ type: 'adopted';
66
+ job: string;
67
+ handle: number;
68
+ root: Identity;
69
+ ended: boolean;
70
+ late: Identity[];
71
+ byParent: Identity[];
72
+ unheld: number[];
73
+ complete: boolean;
74
+ } | {
75
+ schemaVersion: 1;
76
+ type: 'members';
77
+ job: string;
78
+ processes: Identity[];
79
+ } | {
80
+ schemaVersion: 1;
81
+ type: 'process';
82
+ process: Identity | null;
83
+ inJob: boolean | null;
84
+ } | {
85
+ schemaVersion: 1;
86
+ type: 'ended';
87
+ job: string;
88
+ } | {
89
+ schemaVersion: 1;
90
+ type: 'terminated';
91
+ pid: number;
92
+ outcome: TerminateOutcome;
93
+ } | {
94
+ schemaVersion: 1;
95
+ type: 'released';
96
+ job: string;
97
+ } | {
98
+ schemaVersion: 1;
99
+ type: 'strays';
100
+ job: string;
101
+ processes: Identity[];
102
+ } | {
103
+ schemaVersion: 1;
104
+ type: 'interrupted';
105
+ job: string;
106
+ console: number;
107
+ reached: number[];
108
+ } | {
109
+ schemaVersion: 1;
110
+ type: 'refused';
111
+ problem: string;
112
+ detail: string | null;
113
+ };
114
+ type Reply = SupervisorReply;
115
+ /**
116
+ * The supervisor's answers for one runner, the process that asks. Every job it makes is named after the runner and a
117
+ * random word chosen here, so the names are new and nobody else's; a name already taken is refused by the supervisor.
118
+ * A launch's job also carries the launch's pid and a count, so a later launch given the same pid gets a name of its
119
+ * own. Each method runs the supervisor once; a refusal throws with the supervisor's own sentence, and the Windows call
120
+ * behind it, when one failed, as the error's cause.
121
+ *
122
+ * @example const supervisor = new Supervisor(program); supervisor.hold(); const launch = supervisor.adopt(child.pid)
123
+ */
124
+ export declare class Supervisor {
125
+ #private;
126
+ readonly program: SupervisorProgram;
127
+ readonly runner: number;
128
+ constructor(program: SupervisorProgram, runner?: number, word?: string);
129
+ /** The name of the runner's own job. */
130
+ get runnerJob(): string;
131
+ /** The name the next launch with this pid is held under. */
132
+ launchJob(pid: number): string;
133
+ /** The jobs of launches the runner holds a handle to, oldest first. */
134
+ get launchJobs(): readonly string[];
135
+ /**
136
+ * The launches the runner holds a handle to, each by its job, the process it was made for, what that held by its
137
+ * parent when it was held, and the markers it was held with.
138
+ */
139
+ get launches(): readonly {
140
+ readonly job: string;
141
+ readonly root: SupervisedProcess;
142
+ readonly byParent: readonly SupervisedProcess[];
143
+ readonly markers: readonly string[];
144
+ }[];
145
+ /** The processes named so far, by pid and start, as they stand now: what a later `forgetEnded` may forget. */
146
+ get named(): ReadonlySet<string>;
147
+ /**
148
+ * Forgets those of `named`, taken before `runnerJob` was read, that this reading of the runner's job no longer holds:
149
+ * each has ended, and a process given its pid later is another one. A process named after `named` was taken is kept,
150
+ * whatever the reading says, since the reading may be older than its naming.
151
+ */
152
+ forgetEnded(named: ReadonlySet<string>, runnerJob: readonly SupervisedProcess[]): void;
153
+ /** How many processes are named now, which `forgetEnded` keeps to those still running. */
154
+ get namedCount(): number;
155
+ /**
156
+ * Of these processes, those not named before, each counted as named from now on. One no handle could read, whose
157
+ * start is 0, is named by its pid alone, and a later reading of the same pid is that process, named already.
158
+ */
159
+ firstNamed(processes: readonly SupervisedProcess[]): readonly SupervisedProcess[];
160
+ /** Puts the runner in its own job, which ends everything in it once the runner ends. */
161
+ hold(deadline?: Deadline): HeldRunner;
162
+ /**
163
+ * Puts a child the runner just started in a job of its own, with whatever it already started. When no answer says it
164
+ * was held, whatever the job came to hold is ended: a reply lost after the job was made leaves only an empty job,
165
+ * whose handle goes with the runner.
166
+ */
167
+ adopt(pid: number, deadline?: Deadline, markers?: readonly string[]): HeldLaunch;
168
+ /** The processes a job holds now. */
169
+ members(job: string, deadline?: Deadline): readonly SupervisedProcess[];
170
+ membersAsync(job: string, deadline?: Deadline): Promise<readonly SupervisedProcess[]>;
171
+ /** One process as it is now, or undefined when no process runs under the pid, and whether the job, if named, holds it. */
172
+ process(pid: number, job?: string, deadline?: Deadline): {
173
+ readonly process: SupervisedProcess | undefined;
174
+ readonly inJob: boolean;
175
+ };
176
+ processAsync(pid: number, job?: string, deadline?: Deadline): Promise<{
177
+ readonly process: SupervisedProcess | undefined;
178
+ readonly inJob: boolean;
179
+ }>;
180
+ /** Ends every process a launch's job holds. The supervisor refuses a job that holds the runner. */
181
+ end(job: string, deadline?: Deadline): void;
182
+ endAsync(job: string, deadline?: Deadline): Promise<void>;
183
+ /** Ends one process of a job only while it is the process that started at `startedAt`. */
184
+ terminate(job: string, pid: number, startedAt: string, deadline?: Deadline): TerminateOutcome;
185
+ terminateAsync(job: string, pid: number, startedAt: string, deadline?: Deadline): Promise<TerminateOutcome>;
186
+ /**
187
+ * The pids every launch but `job`'s holds now, in its job or, as it was held, by its parent, for a claim that rests on
188
+ * a marker or on a browser read one reading late, which must never take another launch's process; undefined when a
189
+ * job still held could not be read.
190
+ */
191
+ otherLaunchMembers(job: string, deadline?: Deadline): ReadonlySet<number> | undefined;
192
+ otherLaunchMembersAsync(job: string, deadline?: Deadline): Promise<ReadonlySet<number> | undefined>;
193
+ /** Closes the runner's handle to a job that holds nothing any more, which frees the job. */
194
+ release(job: string, handle: number, deadline?: Deadline): void;
195
+ releaseAsync(job: string, handle: number, deadline?: Deadline): Promise<void>;
196
+ /**
197
+ * At the end of a run, each process still running in a job of a launch whose own process has ended, as a helper a test
198
+ * file left running is, with the launch's pid, leaving out console hosts; and each such launch's job that could not be
199
+ * read. A job given back meanwhile holds nothing, and one whose answer was lost may be gone too, its processes ended
200
+ * with its last handle; leaving the unread ones out of `straysAsync` names whatever they still hold there instead.
201
+ * `only`, when given, names the launches' jobs to read, such as one run's own among several a host holds at once.
202
+ */
203
+ leftoversAsync(deadline?: Deadline, only?: ReadonlySet<string>): Promise<{
204
+ readonly found: readonly {
205
+ readonly root: number;
206
+ readonly process: SupervisedProcess;
207
+ }[];
208
+ readonly unread: readonly string[];
209
+ }>;
210
+ /**
211
+ * What the runner's job holds that no launch's job does and that nothing still running stands behind: a process left
212
+ * by one that had ended before its launch was held, which no launch's job took, and which runs until the runner ends.
213
+ * Console hosts are left out. `leaveOut` names launches' jobs to read as no launch's, so what they hold is named.
214
+ */
215
+ strays(deadline?: Deadline): readonly SupervisedProcess[];
216
+ straysAsync(deadline?: Deadline, leaveOut?: readonly string[]): Promise<readonly SupervisedProcess[]>;
217
+ /**
218
+ * Sends Ctrl+C to the console of a launch's processes, or of `pid` among them, unless Retest itself is on that console;
219
+ * Ctrl+Break with `key: 'break'`, which a console program cannot be set to ignore.
220
+ */
221
+ interrupt(job: string, options?: {
222
+ readonly pid?: number;
223
+ readonly key?: 'c' | 'break';
224
+ readonly deadline?: Deadline;
225
+ }): Interrupted;
226
+ }
227
+ /**
228
+ * The supervisor's one line of output as a checked reply. Anything else, a second line included, is no answer.
229
+ *
230
+ * @example readReply('{"schemaVersion":1,"type":"ended","job":"Local\\\\retest-1-ab-2"}\n').type // 'ended'
231
+ */
232
+ export declare function readReply(text: string): Reply;
233
+ /**
234
+ * Whether a process is the console host Windows starts beside a console program given a console of its own, as each test
235
+ * file's process, app server and media process is. It belongs to the programs on that console, runs nothing anyone gave
236
+ * it and ends a moment after the last of them, so it is never named as left running: a program still on its console is
237
+ * named itself.
238
+ *
239
+ * @example consoleHost({ pid: 7300, parentPid: 7200, startedAt: '1', image: 'C:\\Windows\\System32\\conhost.exe' }) // true
240
+ */
241
+ export declare function consoleHost(process: SupervisedProcess): boolean;
242
+ /** Processes by pid and start, as a launch keeps what it has read as its own. */
243
+ export type ProcessRecords = ReadonlyMap<number, string>;
244
+ /**
245
+ * Whether a command line names `marker` as a folder of its own: between two separators, or after one at the end of a
246
+ * path, never as part of a longer name. Windows compares names whatever their case.
247
+ *
248
+ * @example namesFolder('firefox.exe --profile "C:\\Temp\\retest-firefox-1-a\\profile"', 'retest-firefox-1-a') // true
249
+ */
250
+ export declare function namesFolder(commandLine: string | undefined, marker: string): boolean;
251
+ /** What a launch of a run has on record, and the markers that name its processes, for the run's end to tie strays by. */
252
+ export type LaunchRecord = {
253
+ readonly onRecord: () => ProcessRecords;
254
+ readonly markers: readonly string[];
255
+ };
256
+ /**
257
+ * Of the processes no launch's job holds and nothing running stands behind, those a run can tie to itself by the facts
258
+ * a launch's own reading goes by: each one on a launch's record by its pid and start, each one whose parent runs in this
259
+ * reading on such a record, and each one whose command line names a launch's marker. A record of any age is only ever
260
+ * its own process, so nothing is tied through a process that has ended.
261
+ *
262
+ * @example tiedTo([{ onRecord: () => new Map([[5001, '13437009000005001']]), markers: [] }], strays) // 5001, and what 5001 runs
263
+ */
264
+ export declare function tiedTo(launches: readonly LaunchRecord[], strays: readonly SupervisedProcess[]): SupervisedProcess[];
265
+ /**
266
+ * A process left running, as cleanup names it; `when` says when it was seen, such as `after process 5000 ended`.
267
+ *
268
+ * @example stillRunningProblem({ pid: 6100, parentPid: 6050, startedAt: '1', image: 'C:\\Apps\\helper.exe' }, 'after process 5000 ended') // 'Process 6100 (helper.exe) is still running after process 5000 ended. Retest ends it when Retest exits.'
269
+ */
270
+ export declare function stillRunningProblem(process: SupervisedProcess, when: string): string;
271
+ /** What cleanup says when it could not look for processes left running; `when` as for `stillRunningProblem`. */
272
+ export declare function leftoversUnreadProblem(error: unknown, when: string): string;
273
+ /**
274
+ * The command a process stands under when Windows would not name its executable. It has the shape the ownership rule
275
+ * reads as a command that cannot be read, so it is never compared as one.
276
+ */
277
+ export declare const unreadableImage = "(unreadable)";
278
+ /**
279
+ * A launch's ownership readings on Windows, its job, what it has on record by pid and start (its job's members as its
280
+ * newest reading of the job found them, and those it holds by their parents as its newest reading of the runner's job
281
+ * left them), and its markers.
282
+ */
283
+ export type JobOwnershipSystem = ProcessOwnershipSystem & LaunchRecord & {
284
+ readonly job: OwnedJob;
285
+ };
286
+ /**
287
+ * A launch's ownership readings on Windows: its job's own process list, where every member has the launch's pid as its
288
+ * group, a pid read with whether the job holds it, and the job's end, which ends every member at once. A job that was
289
+ * read empty holds nothing from then on, since only Retest puts processes in it and only when it is made, so its
290
+ * handle is given back and every later reading answers empty without asking.
291
+ *
292
+ * A process held by its parent, already in a job of its own when the launch was held, as the browser Firefox's Windows
293
+ * launcher starts is, belongs to the launch as well, with everything it starts while it runs: they are read from the
294
+ * runner's job as members, by the starts on record, through parents running in the same reading, and by `markers`, the
295
+ * names in a command line only this launch's processes carry, such as its profile folder.
296
+ *
297
+ * An empty job is not yet proof that the launch left nothing. A process whose own parent had ended before the launch
298
+ * was held cannot be tied to it, and stays in the runner's job only; so once the job is read empty, the runner's job is
299
+ * read too, and anything there that no launch's job holds and nothing running stands behind leaves the launch's
300
+ * cleanup unconfirmed, naming it. Each such process is named once in the host, for the first launch it is seen after.
301
+ *
302
+ * @example const ownership = new OwnedProcessGroup(child.pid, process.pid, jobSystem(supervisor, supervisor.adopt(child.pid)))
303
+ */
304
+ export declare function jobSystem(supervisor: Supervisor, launch: HeldLaunch, options?: {
305
+ readonly markers?: readonly string[];
306
+ readonly lateParentMs?: number;
307
+ }): JobOwnershipSystem;
308
+ export {};
309
+ //# sourceMappingURL=process-supervisor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-supervisor.d.ts","sourceRoot":"","sources":["../../src/shared/process-supervisor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAwB,sBAAsB,EAAE,MAAM,wBAAwB,CAAA;AACpG,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAgBvD,+GAA+G;AAC/G,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;IAChC,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CACvD,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;IACtC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAA;IAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAA;CACzC,CAAA;AAED,0FAA0F;AAC1F,MAAM,MAAM,UAAU,GAAG;IAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAE1E;;;;;GAKG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAA;IAChC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;IACvB,QAAQ,CAAC,IAAI,EAAE,SAAS,iBAAiB,EAAE,CAAA;IAC3C,QAAQ,CAAC,QAAQ,EAAE,SAAS,iBAAiB,EAAE,CAAA;IAC/C,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;IAClC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;CAC3B,CAAA;AAED,kHAAkH;AAClH,MAAM,MAAM,WAAW,GAAG;IAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAA;AAE3F,sGAAsG;AACtG,MAAM,MAAM,gBAAgB,GAAG,YAAY,GAAG,QAAQ,GAAG,WAAW,CAAA;AAOpE,2DAA2D;AAC3D,KAAK,QAAQ,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAA;AAE9H,+EAA+E;AAC/E,MAAM,MAAM,eAAe,GACvB;IAAE,aAAa,EAAE,CAAC,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC/E;IAAE,aAAa,EAAE,CAAC,CAAC;IAAC,IAAI,EAAE,SAAS,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,QAAQ,EAAE,CAAC;IAAC,QAAQ,EAAE,QAAQ,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,GAC/K;IAAE,aAAa,EAAE,CAAC,CAAC;IAAC,IAAI,EAAE,SAAS,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,QAAQ,EAAE,CAAA;CAAE,GACzE;IAAE,aAAa,EAAE,CAAC,CAAC;IAAC,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,QAAQ,GAAG,IAAI,CAAC;IAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAA;CAAE,GACtF;IAAE,aAAa,EAAE,CAAC,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAChD;IAAE,aAAa,EAAE,CAAC,CAAC;IAAC,IAAI,EAAE,YAAY,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,gBAAgB,CAAA;CAAE,GAChF;IAAE,aAAa,EAAE,CAAC,CAAC;IAAC,IAAI,EAAE,UAAU,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GACnD;IAAE,aAAa,EAAE,CAAC,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,QAAQ,EAAE,CAAA;CAAE,GACxE;IAAE,aAAa,EAAE,CAAC,CAAC;IAAC,IAAI,EAAE,aAAa,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,GAC1F;IAAE,aAAa,EAAE,CAAC,CAAC;IAAC,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAA;AAejF,KAAK,KAAK,GAAG,eAAe,CAAA;AAE5B;;;;;;;;GAQG;AACH,qBAAa,UAAU;;IACrB,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAA;IACnC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;gBAUX,OAAO,EAAE,iBAAiB,EAAE,MAAM,GAAE,MAAoB,EAAE,IAAI,GAAE,MAAuC;IAOnH,wCAAwC;IACxC,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,4DAA4D;IAC5D,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAI9B,uEAAuE;IACvE,IAAI,UAAU,IAAI,SAAS,MAAM,EAAE,CAElC;IAED;;;OAGG;IACH,IAAI,QAAQ,IAAI,SAAS;QAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;QAAC,QAAQ,CAAC,QAAQ,EAAE,SAAS,iBAAiB,EAAE,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,EAAE,CAE1K;IAED,8GAA8G;IAC9G,IAAI,KAAK,IAAI,WAAW,CAAC,MAAM,CAAC,CAE/B;IAED;;;;OAIG;IACH,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,SAAS,iBAAiB,EAAE,GAAG,IAAI;IAKtF,0FAA0F;IAC1F,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED;;;OAGG;IACH,UAAU,CAAC,SAAS,EAAE,SAAS,iBAAiB,EAAE,GAAG,SAAS,iBAAiB,EAAE;IAejF,wFAAwF;IACxF,IAAI,CAAC,QAAQ,CAAC,EAAE,QAAQ,GAAG,UAAU;IAMrC;;;;OAIG;IACH,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,QAAQ,EAAE,OAAO,GAAE,SAAS,MAAM,EAAO,GAAG,UAAU;IAwCpF,qCAAqC;IACrC,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,SAAS,iBAAiB,EAAE;IAIjE,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,SAAS,iBAAiB,EAAE,CAAC;IAI3F,0HAA0H;IAC1H,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG;QAAE,QAAQ,CAAC,OAAO,EAAE,iBAAiB,GAAG,SAAS,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;KAAE;IAI/H,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;QAAE,QAAQ,CAAC,OAAO,EAAE,iBAAiB,GAAG,SAAS,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC;IAIzJ,mGAAmG;IACnG,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,IAAI;IAKrC,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAK/D,0FAA0F;IAC1F,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,gBAAgB;IAIvF,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAIjH;;;;OAIG;IACH,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,WAAW,CAAC,MAAM,CAAC,GAAG,SAAS;IAe/E,uBAAuB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC;IAczG,4FAA4F;IAC5F,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,IAAI;IAMzD,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAMnF;;;;;;OAMG;IACG,cAAc,CAAC,QAAQ,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC;QAAE,QAAQ,CAAC,KAAK,EAAE,SAAS;YAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAA;SAAE,EAAE,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,CAAC;IAkBjN;;;;OAIG;IACH,MAAM,CAAC,QAAQ,CAAC,EAAE,QAAQ,GAAG,SAAS,iBAAiB,EAAE;IAInD,WAAW,CAAC,QAAQ,CAAC,EAAE,QAAQ,EAAE,QAAQ,GAAE,SAAS,MAAM,EAAO,GAAG,OAAO,CAAC,SAAS,iBAAiB,EAAE,CAAC;IAW/G;;;OAGG;IACH,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE;QAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC;QAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAA;KAAO,GAAG,WAAW;CAuBzI;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAY7C;AAcD;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAE/D;AA8BD,iFAAiF;AACjF,MAAM,MAAM,cAAc,GAAG,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AA0DxD;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAUpF;AAED,yHAAyH;AACzH,MAAM,MAAM,YAAY,GAAG;IAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,cAAc,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAA;AAE3G;;;;;;;GAOG;AACH,wBAAgB,MAAM,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,EAAE,MAAM,EAAE,SAAS,iBAAiB,EAAE,GAAG,iBAAiB,EAAE,CAMnH;AAMD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,iBAAiB,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAEpF;AAED,gHAAgH;AAChH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE3E;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,iBAAiB,CAAA;AAE7C;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG,sBAAsB,GAAG,YAAY,GAAG;IACvE,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAA;CACvB,CAAA;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,SAAS,CAAC,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,GAAE;IAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,kBAAkB,CA2LhL"}