apex-mutation-testing 1.6.0 → 1.7.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 (46) hide show
  1. package/README.md +34 -3
  2. package/lib/adapter/apexClassRepository.d.ts +14 -1
  3. package/lib/adapter/apexClassRepository.js +93 -31
  4. package/lib/adapter/apexClassRepository.js.map +1 -1
  5. package/lib/commands/apex/mutation/test/run.d.ts +1 -0
  6. package/lib/commands/apex/mutation/test/run.js +4 -0
  7. package/lib/commands/apex/mutation/test/run.js.map +1 -1
  8. package/lib/mutator/experimentalSwitchMutator.d.ts +7 -0
  9. package/lib/mutator/experimentalSwitchMutator.js +18 -1
  10. package/lib/mutator/experimentalSwitchMutator.js.map +1 -1
  11. package/lib/mutator/mutationListener.d.ts +2 -0
  12. package/lib/mutator/mutationListener.js +20 -8
  13. package/lib/mutator/mutationListener.js.map +1 -1
  14. package/lib/reporter/HTMLReporter.js +68 -12
  15. package/lib/reporter/HTMLReporter.js.map +1 -1
  16. package/lib/service/configReader.js +9 -1
  17. package/lib/service/configReader.js.map +1 -1
  18. package/lib/service/exactColoring.d.ts +25 -0
  19. package/lib/service/exactColoring.js +143 -0
  20. package/lib/service/exactColoring.js.map +1 -0
  21. package/lib/service/groupExecutor.d.ts +29 -0
  22. package/lib/service/groupExecutor.js +194 -0
  23. package/lib/service/groupExecutor.js.map +1 -0
  24. package/lib/service/mutantGenerator.d.ts +14 -4
  25. package/lib/service/mutantGenerator.js +42 -13
  26. package/lib/service/mutantGenerator.js.map +1 -1
  27. package/lib/service/mutationGrouper.d.ts +22 -0
  28. package/lib/service/mutationGrouper.js +130 -0
  29. package/lib/service/mutationGrouper.js.map +1 -0
  30. package/lib/service/mutationLocation.d.ts +12 -0
  31. package/lib/service/mutationLocation.js +54 -0
  32. package/lib/service/mutationLocation.js.map +1 -0
  33. package/lib/service/mutationTestingService.d.ts +3 -7
  34. package/lib/service/mutationTestingService.js +83 -158
  35. package/lib/service/mutationTestingService.js.map +1 -1
  36. package/lib/service/timeUtils.d.ts +1 -0
  37. package/lib/service/timeUtils.js +8 -0
  38. package/lib/service/timeUtils.js.map +1 -1
  39. package/lib/service/typeDiscoverer.d.ts +12 -0
  40. package/lib/service/typeDiscoverer.js +46 -2
  41. package/lib/service/typeDiscoverer.js.map +1 -1
  42. package/lib/type/ApexMutationParameter.d.ts +1 -0
  43. package/messages/apex.mutation.test.run.md +13 -1
  44. package/npm-shrinkwrap.json +1528 -1353
  45. package/oclif.manifest.json +7 -1
  46. package/package.json +18 -17
package/README.md CHANGED
@@ -113,7 +113,8 @@ The config file supports the following attributes:
113
113
  },
114
114
  "threshold": 80,
115
115
  "skipPatterns": ["System\\.debug", "Logger\\."],
116
- "lines": ["1-10", "25-30", "42"]
116
+ "lines": ["1-10", "25-30", "42"],
117
+ "mutationGrouping": true
117
118
  }
118
119
  ```
119
120
 
@@ -126,6 +127,7 @@ The config file supports the following attributes:
126
127
  | `threshold` | `number` | Minimum mutation score (0–100) required for the command to succeed |
127
128
  | `skipPatterns` | `string[]` | RE2 regex patterns to skip lines from mutation (e.g., `System\\.debug`) |
128
129
  | `lines` | `string[]` | Line ranges to restrict mutation to (e.g., `1-10`, `42`) |
130
+ | `mutationGrouping` | `boolean` | Pack mutations whose covering tests are disjoint into a single deploy + test run; runs the full pipeline (test-induced clique lower bound → DSATUR → exact backtracking coloring). Off by default. |
129
131
 
130
132
  **Mutual exclusivity:** You cannot specify both `include` and `exclude` within the same group.
131
133
  For example, setting both `mutators.include` and `mutators.exclude` will result in an error.
@@ -217,6 +219,31 @@ Config file equivalent:
217
219
  }
218
220
  ```
219
221
 
222
+ #### Mutation Grouping
223
+
224
+ Run multiple independent mutations in a single deployment + test run by passing `--mutation-grouping`. The flag turns on a three-stage pipeline:
225
+
226
+ 1. **Lower-bound clique** — for every test method, gather the mutations it covers; the largest such set is a clique in the conflict graph and a free lower bound on the chromatic number.
227
+ 2. **DSATUR** — pre-color the witness clique, then partition the remaining mutations with the strongest polynomial-time graph-coloring heuristic (Brélaz 1979). Two mutations share a group iff their covering tests are pairwise disjoint.
228
+ 3. **Exact backtracking coloring** — binary-search for the chromatic number using DSATUR-style backtracking, seeded by the witness clique. Confirms DSATUR was already optimal or finds a strictly smaller partition. No external solver, no runtime dependency — pure TypeScript.
229
+
230
+ Each group is then deployed once and its union of covering tests run once; per-method test outcomes are reverse-mapped back to individual mutations. This reduces the number of Tooling-API class updates and async test-run kickoffs (the network-bound dominant cost) without changing test execution time. Off by default.
231
+
232
+ ```sh
233
+ # Enable mutation grouping
234
+ sf apex mutation test run --apex-class MyClass --test-class MyClassTest --mutation-grouping
235
+ ```
236
+
237
+ Config file equivalent:
238
+
239
+ ```json
240
+ {
241
+ "mutationGrouping": true
242
+ }
243
+ ```
244
+
245
+ If a batched deploy or test run fails, the affected group automatically falls back to per-mutant evaluation — so worst case is identical to today's behavior plus one wasted batch attempt.
246
+
220
247
  ##### Diff-Based Mutation Testing with Git
221
248
 
222
249
  You can derive line ranges from `git diff` to focus mutation testing on recently changed code. This is particularly useful in CI pipelines to only test mutations on lines affected by a pull request.
@@ -337,7 +364,7 @@ USAGE
337
364
  $ sf apex mutation test run -c <value> -t <value> -o <value> [--json] [--flags-dir <value>] [-r <value>] [-d]
338
365
  [--include-mutators <value>... | --exclude-mutators <value>...] [--include-test-methods <value>... |
339
366
  --exclude-test-methods <value>...] [--threshold <value>] [-s <value>...] [-l <value>...] [--config-file <value>]
340
- [--api-version <value>]
367
+ [--mutation-grouping] [--api-version <value>]
341
368
 
342
369
  FLAGS
343
370
  -c, --apex-class=<value> (required) Apex class name to mutate
@@ -356,6 +383,10 @@ FLAGS
356
383
  --exclude-test-methods=<value>... Test method names to exclude
357
384
  --include-mutators=<value>... Mutator names to include (e.g. ArithmeticOperator, BoundaryCondition)
358
385
  --include-test-methods=<value>... Test method names to include
386
+ --mutation-grouping Group mutations whose covering tests are disjoint into a single deploy + test
387
+ run. Reduces deployments and async test-run kickoffs at the cost of larger
388
+ blast radius on compile errors. Runs the full pipeline: test-induced clique
389
+ lower bound → DSATUR heuristic → exact backtracking coloring. Off by default.
359
390
  --threshold=<value> Minimum mutation score (0-100) required for the command to succeed
360
391
 
361
392
  GLOBAL FLAGS
@@ -381,7 +412,7 @@ EXAMPLES
381
412
  $ sf apex mutation test run --apex-class MyClass --test-class MyClassTest --dry-run
382
413
  ```
383
414
 
384
- _See code: [src/commands/apex/mutation/test/run.ts](https://github.com/scolladon/apex-mutation-testing/blob/v1.6.0/src/commands/apex/mutation/test/run.ts)_
415
+ _See code: [src/commands/apex/mutation/test/run.ts](https://github.com/scolladon/apex-mutation-testing/blob/v1.7.0/src/commands/apex/mutation/test/run.ts)_
385
416
  <!-- commandsstop -->
386
417
  <!-- markdownlint-enable MD040 -->
387
418
 
@@ -1,9 +1,20 @@
1
1
  import { Connection } from '@salesforce/core';
2
2
  import { ApexClass } from '../type/ApexClass.js';
3
3
  import { MetadataComponentDependency } from '../type/MetadataComponentDependency.js';
4
+ interface PollOptions {
5
+ initialIntervalMs?: number;
6
+ maxIntervalMs?: number;
7
+ timeoutMs?: number;
8
+ }
9
+ export declare class PollTimeoutError extends Error {
10
+ readonly requestId: string;
11
+ readonly lastState: string;
12
+ constructor(requestId: string, lastState: string);
13
+ }
4
14
  export declare class ApexClassRepository {
5
15
  protected readonly connection: Connection;
6
- constructor(connection: Connection);
16
+ private readonly pollOptions;
17
+ constructor(connection: Connection, pollOptions?: PollOptions);
7
18
  read(name: string): Promise<{
8
19
  [name: string]: import("@jsforce/jsforce-node").SObjectFieldType | null;
9
20
  } & import("@jsforce/jsforce-node").Record>;
@@ -11,6 +22,8 @@ export declare class ApexClassRepository {
11
22
  update(apexClass: ApexClass): Promise<{
12
23
  [name: string]: import("@jsforce/jsforce-node").SObjectFieldType | null;
13
24
  } & import("@jsforce/jsforce-node").Record>;
25
+ private deleteContainer;
14
26
  private pollForCompletion;
15
27
  private delay;
16
28
  }
29
+ export {};
@@ -1,7 +1,43 @@
1
+ const DEFAULT_POLL_INITIAL_INTERVAL_MS = 100;
2
+ const DEFAULT_POLL_MAX_INTERVAL_MS = 2000;
3
+ const DEFAULT_POLL_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes
4
+ const POLL_BACKOFF_FACTOR = 1.5;
5
+ const TERMINAL_STATES = new Set([
6
+ 'Completed',
7
+ 'Failed',
8
+ 'Error',
9
+ 'Aborted',
10
+ ]);
11
+ export class PollTimeoutError extends Error {
12
+ requestId;
13
+ lastState;
14
+ constructor(requestId, lastState) {
15
+ super(`Tooling API ContainerAsyncRequest ${requestId} did not reach a terminal state within the poll timeout (last state: ${lastState})`);
16
+ this.requestId = requestId;
17
+ this.lastState = lastState;
18
+ this.name = 'PollTimeoutError';
19
+ }
20
+ }
1
21
  export class ApexClassRepository {
2
22
  connection;
3
- constructor(connection) {
23
+ pollOptions;
24
+ constructor(connection, pollOptions = {}) {
4
25
  this.connection = connection;
26
+ this.pollOptions = pollOptions;
27
+ // Validate poll configuration eagerly so misconfiguration fails fast
28
+ // at construction rather than mid-deploy with non-deterministic behaviour.
29
+ const { initialIntervalMs, maxIntervalMs, timeoutMs } = pollOptions;
30
+ if (initialIntervalMs !== undefined && initialIntervalMs < 0) {
31
+ throw new Error(`pollOptions.initialIntervalMs must be >= 0 (got ${initialIntervalMs})`);
32
+ }
33
+ if (maxIntervalMs !== undefined && maxIntervalMs < 0) {
34
+ throw new Error(`pollOptions.maxIntervalMs must be >= 0 (got ${maxIntervalMs})`);
35
+ }
36
+ // timeoutMs <= 0 allowed only for test harnesses that want an instant
37
+ // timeout; reject 0 which is the racy value (deadline == now).
38
+ if (timeoutMs !== undefined && timeoutMs === 0) {
39
+ throw new Error(`pollOptions.timeoutMs must be non-zero (0 is racy); use a negative value for immediate timeout or a positive value for a real budget`);
40
+ }
5
41
  }
6
42
  async read(name) {
7
43
  return (await this.connection.tooling
@@ -21,43 +57,69 @@ export class ApexClassRepository {
21
57
  .create({
22
58
  Name: `MutationTest_${Date.now()}`,
23
59
  });
24
- // Create ApexClassMember for the mutated version
25
- await this.connection.tooling.sobject('ApexClassMember').create({
26
- MetadataContainerId: container.id,
27
- ContentEntityId: apexClass.Id,
28
- Body: apexClass.Body,
29
- });
30
- // Create ContainerAsyncRequest to deploy
31
- const asyncRequest = await this.connection.tooling
32
- .sobject('ContainerAsyncRequest')
33
- .create({
34
- IsCheckOnly: false,
35
- MetadataContainerId: container.id,
36
- IsRunTests: true,
37
- });
38
- if (!asyncRequest.id) {
39
- throw new Error('ContainerAsyncRequest did not return an ID');
60
+ if (!container.id) {
61
+ throw new Error('MetadataContainer did not return an ID');
62
+ }
63
+ const containerId = container.id;
64
+ try {
65
+ await this.connection.tooling.sobject('ApexClassMember').create({
66
+ MetadataContainerId: containerId,
67
+ ContentEntityId: apexClass.Id,
68
+ Body: apexClass.Body,
69
+ });
70
+ const asyncRequest = await this.connection.tooling
71
+ .sobject('ContainerAsyncRequest')
72
+ .create({
73
+ IsCheckOnly: false,
74
+ MetadataContainerId: containerId,
75
+ IsRunTests: true,
76
+ });
77
+ if (!asyncRequest.id) {
78
+ throw new Error('ContainerAsyncRequest did not return an ID');
79
+ }
80
+ const result = await this.pollForCompletion(asyncRequest.id);
81
+ if (result['State'] === 'Failed') {
82
+ const messages = result['DeployDetails']?.['allComponentMessages'];
83
+ const formattedErrors = Array.isArray(messages)
84
+ ? messages
85
+ .map(m => `[${m.fileName}:${m.lineNumber}:${m.columnNumber}] ${m.problem}`)
86
+ .join('\n')
87
+ : result['ErrorMsg'] || 'Unknown error';
88
+ throw new Error(`Deployment failed:\n${formattedErrors}`);
89
+ }
90
+ return result;
40
91
  }
41
- // Poll for deployment completion
42
- const result = await this.pollForCompletion(asyncRequest.id);
43
- if (result['State'] === 'Failed') {
44
- const messages = result['DeployDetails']?.['allComponentMessages'];
45
- const formattedErrors = Array.isArray(messages)
46
- ? messages
47
- .map(m => `[${m.fileName}:${m.lineNumber}:${m.columnNumber}] ${m.problem}`)
48
- .join('\n')
49
- : result['ErrorMsg'] || 'Unknown error';
50
- throw new Error(`Deployment failed:\n${formattedErrors}`);
92
+ finally {
93
+ // Fire-and-forget cleanup: awaiting this would add a full Tooling API
94
+ // round-trip to every deploy (500 extra calls on a 500-mutant run).
95
+ // If the delete fails, Salesforce reaps the MetadataContainer after 24h.
96
+ this.deleteContainer(containerId);
51
97
  }
52
- return result;
98
+ }
99
+ deleteContainer(containerId) {
100
+ this.connection.tooling
101
+ .sobject('MetadataContainer')
102
+ .delete(containerId)
103
+ .catch(() => {
104
+ // Non-fatal: swallow so the unhandled rejection does not surface
105
+ // and the container gets reaped by Salesforce after 24h.
106
+ });
53
107
  }
54
108
  async pollForCompletion(requestId) {
55
- const terminalStates = new Set(['Completed', 'Failed', 'Error', 'Aborted']);
109
+ const initialIntervalMs = this.pollOptions.initialIntervalMs ?? DEFAULT_POLL_INITIAL_INTERVAL_MS;
110
+ const maxIntervalMs = this.pollOptions.maxIntervalMs ?? DEFAULT_POLL_MAX_INTERVAL_MS;
111
+ const timeoutMs = this.pollOptions.timeoutMs ?? DEFAULT_POLL_TIMEOUT_MS;
112
+ const deadline = Date.now() + timeoutMs;
113
+ let intervalMs = initialIntervalMs;
56
114
  let result = await this.connection.tooling
57
115
  .sobject('ContainerAsyncRequest')
58
116
  .retrieve(requestId);
59
- while (!terminalStates.has(result['State'])) {
60
- await this.delay(100);
117
+ while (!TERMINAL_STATES.has(result['State'])) {
118
+ if (Date.now() > deadline) {
119
+ throw new PollTimeoutError(requestId, String(result['State']));
120
+ }
121
+ await this.delay(intervalMs);
122
+ intervalMs = Math.min(Math.floor(intervalMs * POLL_BACKOFF_FACTOR), maxIntervalMs);
61
123
  result = await this.connection.tooling
62
124
  .sobject('ContainerAsyncRequest')
63
125
  .retrieve(requestId);
@@ -1 +1 @@
1
- {"version":3,"file":"apexClassRepository.js","sourceRoot":"","sources":["../../src/adapter/apexClassRepository.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"apexClassRepository.js","sourceRoot":"","sources":["../../src/adapter/apexClassRepository.ts"],"names":[],"mappings":"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"}
@@ -19,6 +19,7 @@ export default class ApexMutationTest extends SfCommand<ApexMutationTestResult>
19
19
  'skip-patterns': import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
20
20
  lines: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
21
21
  'config-file': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
22
+ 'mutation-grouping': import("@oclif/core/interfaces").BooleanFlag<boolean>;
22
23
  'target-org': import("@oclif/core/interfaces").OptionFlag<import("@salesforce/core").Org, import("@oclif/core/interfaces").CustomOptions>;
23
24
  'api-version': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
24
25
  };
@@ -71,6 +71,9 @@ export default class ApexMutationTest extends SfCommand {
71
71
  summary: messages.getMessage('flags.config-file.summary'),
72
72
  exists: true,
73
73
  }),
74
+ 'mutation-grouping': Flags.boolean({
75
+ summary: messages.getMessage('flags.mutation-grouping.summary'),
76
+ }),
74
77
  'target-org': Flags.requiredOrg(),
75
78
  'api-version': Flags.orgApiVersion(),
76
79
  };
@@ -90,6 +93,7 @@ export default class ApexMutationTest extends SfCommand {
90
93
  skipPatterns: flags['skip-patterns'],
91
94
  lines: flags['lines'],
92
95
  configFile: flags['config-file'],
96
+ mutationGrouping: flags['mutation-grouping'],
93
97
  };
94
98
  const configReader = new ConfigReader();
95
99
  const resolvedParameters = await configReader.resolve(parameters);
@@ -1 +1 @@
1
- {"version":3,"file":"run.js","sourceRoot":"","sources":["../../../../../src/commands/apex/mutation/test/run.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../../../../src/commands/apex/mutation/test/run.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAC3C,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAA;AAC9D,OAAO,EAAE,wBAAwB,EAAE,MAAM,sCAAsC,CAAA;AAC/E,OAAO,EAAE,kBAAkB,EAAE,MAAM,2CAA2C,CAAA;AAC9E,OAAO,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAA;AAClE,OAAO,EAAE,sBAAsB,EAAE,MAAM,+CAA+C,CAAA;AAGtF,QAAQ,CAAC,kCAAkC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AAC5D,MAAM,QAAQ,GAAG,QAAQ,CAAC,YAAY,CACpC,uBAAuB,EACvB,wBAAwB,CACzB,CAAA;AAMD,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,SAAiC;IACtE,MAAM,CAAmB,OAAO,GAAG,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC,CAAA;IACjE,MAAM,CAAmB,WAAW,GACzC,QAAQ,CAAC,UAAU,CAAC,aAAa,CAAC,CAAA;IAC7B,MAAM,CAAmB,QAAQ,GAAG,QAAQ,CAAC,WAAW,CAAC,UAAU,CAAC,CAAA;IAEpE,MAAM,CAAmB,KAAK,GAAG;QACtC,YAAY,EAAE,KAAK,CAAC,MAAM,CAAC;YACzB,IAAI,EAAE,GAAG;YACT,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,0BAA0B,CAAC;YACxD,QAAQ,EAAE,IAAI;SACf,CAAC;QACF,YAAY,EAAE,KAAK,CAAC,MAAM,CAAC;YACzB,IAAI,EAAE,GAAG;YACT,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,0BAA0B,CAAC;YACxD,QAAQ,EAAE,IAAI;SACf,CAAC;QACF,YAAY,EAAE,KAAK,CAAC,SAAS,CAAC;YAC5B,IAAI,EAAE,GAAG;YACT,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,0BAA0B,CAAC;YACxD,MAAM,EAAE,IAAI;YACZ,OAAO,EAAE,WAAW;SACrB,CAAC;QACF,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC;YACvB,IAAI,EAAE,GAAG;YACT,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,uBAAuB,CAAC;YACrD,OAAO,EAAE,KAAK;SACf,CAAC;QACF,kBAAkB,EAAE,KAAK,CAAC,MAAM,CAAC;YAC/B,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,gCAAgC,CAAC;YAC9D,SAAS,EAAE,CAAC,kBAAkB,CAAC;YAC/B,QAAQ,EAAE,IAAI;SACf,CAAC;QACF,kBAAkB,EAAE,KAAK,CAAC,MAAM,CAAC;YAC/B,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,gCAAgC,CAAC;YAC9D,SAAS,EAAE,CAAC,kBAAkB,CAAC;YAC/B,QAAQ,EAAE,IAAI;SACf,CAAC;QACF,sBAAsB,EAAE,KAAK,CAAC,MAAM,CAAC;YACnC,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,oCAAoC,CAAC;YAClE,SAAS,EAAE,CAAC,sBAAsB,CAAC;YACnC,QAAQ,EAAE,IAAI;SACf,CAAC;QACF,sBAAsB,EAAE,KAAK,CAAC,MAAM,CAAC;YACnC,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,oCAAoC,CAAC;YAClE,SAAS,EAAE,CAAC,sBAAsB,CAAC;YACnC,QAAQ,EAAE,IAAI;SACf,CAAC;QACF,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC;YACvB,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,yBAAyB,CAAC;YACvD,GAAG,EAAE,CAAC;YACN,GAAG,EAAE,GAAG;SACT,CAAC;QACF,eAAe,EAAE,KAAK,CAAC,MAAM,CAAC;YAC5B,IAAI,EAAE,GAAG;YACT,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,6BAA6B,CAAC;YAC3D,QAAQ,EAAE,IAAI;SACf,CAAC;QACF,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC;YAClB,IAAI,EAAE,GAAG;YACT,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,qBAAqB,CAAC;YACnD,QAAQ,EAAE,IAAI;SACf,CAAC;QACF,aAAa,EAAE,KAAK,CAAC,IAAI,CAAC;YACxB,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,2BAA2B,CAAC;YACzD,MAAM,EAAE,IAAI;SACb,CAAC;QACF,mBAAmB,EAAE,KAAK,CAAC,OAAO,CAAC;YACjC,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,iCAAiC,CAAC;SAChE,CAAC;QACF,YAAY,EAAE,KAAK,CAAC,WAAW,EAAE;QACjC,aAAa,EAAE,KAAK,CAAC,aAAa,EAAE;KACrC,CAAA;IAEM,KAAK,CAAC,GAAG;QACd,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAA;QACpD,MAAM,UAAU,GAAG,KAAK,CAAC,YAAY,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAA;QAE1E,MAAM,UAAU,GAA0B;YACxC,aAAa,EAAE,KAAK,CAAC,YAAY,CAAC;YAClC,iBAAiB,EAAE,KAAK,CAAC,YAAY,CAAC;YACtC,SAAS,EAAE,KAAK,CAAC,YAAY,CAAC;YAC9B,MAAM,EAAE,KAAK,CAAC,SAAS,CAAC;YACxB,eAAe,EAAE,KAAK,CAAC,kBAAkB,CAAC;YAC1C,eAAe,EAAE,KAAK,CAAC,kBAAkB,CAAC;YAC1C,kBAAkB,EAAE,KAAK,CAAC,sBAAsB,CAAC;YACjD,kBAAkB,EAAE,KAAK,CAAC,sBAAsB,CAAC;YACjD,SAAS,EAAE,KAAK,CAAC,WAAW,CAAC;YAC7B,YAAY,EAAE,KAAK,CAAC,eAAe,CAAC;YACpC,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC;YACrB,UAAU,EAAE,KAAK,CAAC,aAAa,CAAC;YAChC,gBAAgB,EAAE,KAAK,CAAC,mBAAmB,CAAC;SAC7C,CAAA;QAED,MAAM,YAAY,GAAG,IAAI,YAAY,EAAE,CAAA;QACvC,MAAM,kBAAkB,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;QAEjE,IAAI,CAAC,GAAG,CACN,QAAQ,CAAC,UAAU,CACjB,KAAK,CAAC,SAAS,CAAC;YACd,CAAC,CAAC,6BAA6B;YAC/B,CAAC,CAAC,uBAAuB,EAC3B,CAAC,kBAAkB,CAAC,aAAa,EAAE,kBAAkB,CAAC,iBAAiB,CAAC,CACzE,CACF,CAAA;QAED,MAAM,kBAAkB,GAAG,IAAI,kBAAkB,CAAC,UAAU,CAAC,CAAA;QAC7D,MAAM,kBAAkB,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAA;QAErD,MAAM,sBAAsB,GAAG,IAAI,sBAAsB,CACvD,IAAI,CAAC,QAAQ,EACb,IAAI,CAAC,OAAO,EACZ,UAAU,EACV,kBAAkB,EAClB,QAAQ,CACT,CAAA;QACD,MAAM,cAAc,GAAG,MAAM,sBAAsB,CAAC,OAAO,EAAE,CAAA;QAE7D,MAAM,YAAY,GAAG,IAAI,wBAAwB,EAAE,CAAA;QACnD,MAAM,YAAY,CAAC,cAAc,CAC/B,cAAc,EACd,kBAAkB,CAAC,SAAS,CAC7B,CAAA;QACD,IAAI,CAAC,GAAG,CACN,QAAQ,CAAC,UAAU,CAAC,sBAAsB,EAAE;YAC1C,kBAAkB,CAAC,SAAS;SAC7B,CAAC,CACH,CAAA;QAED,MAAM,KAAK,GAAG,KAAK,CAAC,SAAS,CAAC;YAC5B,CAAC,CAAC,IAAI;YACN,CAAC,CAAC,sBAAsB,CAAC,cAAc,CAAC,cAAc,CAAC,CAAA;QAEzD,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACnB,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,qBAAqB,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;QAC/D,CAAC;QAED,IAAI,KAAK,KAAK,IAAI,IAAI,kBAAkB,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;YACjE,IAAI,KAAK,GAAG,kBAAkB,CAAC,SAAS,EAAE,CAAC;gBACzC,MAAM,QAAQ,CAAC,WAAW,CAAC,uBAAuB,EAAE;oBAClD,MAAM,CAAC,KAAK,CAAC;oBACb,MAAM,CAAC,kBAAkB,CAAC,SAAS,CAAC;iBACrC,CAAC,CAAA;YACJ,CAAC;QACH,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,2BAA2B,CAAC,CAAC,CAAA;QAC3D,OAAO,EAAE,KAAK,EAAE,CAAA;IAClB,CAAC"}
@@ -4,4 +4,11 @@ export declare class ExperimentalSwitchMutator extends BaseListener {
4
4
  enterSwitchStatement(ctx: ParserRuleContext): void;
5
5
  private isElseCase;
6
6
  private createSwapAdjacentValuesMutations;
7
+ /**
8
+ * Swap-span mutation spans two when-clauses. The MutationListener only
9
+ * verifies the switch-statement start line is covered; this method asserts
10
+ * coverage for at least one line inside each when-clause so we never emit
11
+ * a mutation whose replacement body is wholly uncovered.
12
+ */
13
+ private isSpanCovered;
7
14
  }
@@ -47,11 +47,28 @@ export class ExperimentalSwitchMutator extends BaseListener {
47
47
  // with swapped values (keeping blocks in original positions)
48
48
  const originalText = currentCase.text + nextCase.text;
49
49
  const swappedText = `when ${nextValue.text} ${currentBlock.text}when ${currentValue.text} ${nextBlock.text}`;
50
- if (currentCase.start && nextCase.stop) {
50
+ if (currentCase.start &&
51
+ nextCase.stop &&
52
+ this.isSpanCovered(currentCase.start.line, nextCase.stop.line)) {
51
53
  this.createMutation(currentCase.start, nextCase.stop, originalText, swappedText);
52
54
  }
53
55
  }
54
56
  }
55
57
  }
58
+ /**
59
+ * Swap-span mutation spans two when-clauses. The MutationListener only
60
+ * verifies the switch-statement start line is covered; this method asserts
61
+ * coverage for at least one line inside each when-clause so we never emit
62
+ * a mutation whose replacement body is wholly uncovered.
63
+ */
64
+ isSpanCovered(startLine, endLine) {
65
+ if (!this._coveredLines)
66
+ return true;
67
+ for (let line = startLine; line <= endLine; line++) {
68
+ if (this._coveredLines.has(line))
69
+ return true;
70
+ }
71
+ return false;
72
+ }
56
73
  }
57
74
  //# sourceMappingURL=experimentalSwitchMutator.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"experimentalSwitchMutator.js","sourceRoot":"","sources":["../../src/mutator/experimentalSwitchMutator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"experimentalSwitchMutator.js","sourceRoot":"","sources":["../../src/mutator/experimentalSwitchMutator.ts"],"names":[],"mappings":"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"}
@@ -8,8 +8,10 @@ export declare class MutationListener implements ApexParserListener {
8
8
  protected readonly allowedLines: Set<number> | undefined;
9
9
  protected readonly sourceLines: string[];
10
10
  private listeners;
11
+ private readonly dispatchCache;
11
12
  _mutations: ApexMutation[];
12
13
  getMutations(): ApexMutation[];
13
14
  constructor(listeners: BaseListener[], coveredLines: Set<number>, skipPatterns?: RE2Instance[], allowedLines?: Set<number> | undefined, sourceLines?: string[]);
15
+ private resolveSubscribers;
14
16
  private isLineEligible;
15
17
  }
@@ -5,6 +5,10 @@ export class MutationListener {
5
5
  allowedLines;
6
6
  sourceLines;
7
7
  listeners;
8
+ // Memoised dispatch table: method name → listeners that implement it.
9
+ // Populated lazily per method on first invocation so Proxy traps for
10
+ // unknown ANTLR hooks do not re-scan every listener on every AST node.
11
+ dispatchCache = new Map();
8
12
  _mutations = [];
9
13
  getMutations() {
10
14
  return this._mutations;
@@ -25,29 +29,37 @@ export class MutationListener {
25
29
  ;
26
30
  listener._mutations = this._mutations;
27
31
  });
28
- // Create a proxy that automatically forwards all method calls to listeners
32
+ // Create a proxy that automatically forwards all method calls to listeners.
33
+ // Per-trap cost is now O(K) where K = listeners implementing the hook
34
+ // (typically 1-2), not O(N) over all 25 mutators.
29
35
  return new Proxy(this, {
30
36
  get: (target, prop) => {
31
37
  if (prop in target) {
32
38
  return target[prop];
33
39
  }
34
- // Return a function that calls the method on all listeners that have it
35
40
  return (...args) => {
36
41
  if (Array.isArray(args) && args.length > 0) {
37
42
  const ctx = args[0];
38
43
  if (this.isLineEligible(ctx?.start?.line)) {
39
- this.listeners.forEach(listener => {
40
- if (prop in listener && typeof listener[prop] === 'function') {
41
- ;
42
- listener[prop].apply(listener, args);
43
- }
44
- });
44
+ const subscribers = this.resolveSubscribers(prop);
45
+ for (const listener of subscribers) {
46
+ ;
47
+ listener[prop].apply(listener, args);
48
+ }
45
49
  }
46
50
  }
47
51
  };
48
52
  },
49
53
  });
50
54
  }
55
+ resolveSubscribers(prop) {
56
+ const cached = this.dispatchCache.get(prop);
57
+ if (cached !== undefined)
58
+ return cached;
59
+ const subs = this.listeners.filter(listener => prop in listener && typeof listener[prop] === 'function');
60
+ this.dispatchCache.set(prop, subs);
61
+ return subs;
62
+ }
51
63
  isLineEligible(line) {
52
64
  if (!line) {
53
65
  return false;
@@ -1 +1 @@
1
- {"version":3,"file":"mutationListener.js","sourceRoot":"","sources":["../../src/mutator/mutationListener.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mutationListener.js","sourceRoot":"","sources":["../../src/mutator/mutationListener.ts"],"names":[],"mappings":"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"}
@@ -1,16 +1,35 @@
1
- import { writeFile } from 'node:fs/promises';
1
+ import { readFile, realpath, writeFile } from 'node:fs/promises';
2
+ import { createRequire } from 'node:module';
2
3
  import * as path from 'path';
4
+ const requireFromHere = createRequire(import.meta.url);
5
+ const MUTATION_TEST_ELEMENTS_PATH = requireFromHere.resolve('mutation-testing-elements/dist/mutation-test-elements.js');
6
+ async function loadMutationTestElements() {
7
+ const content = await readFile(MUTATION_TEST_ELEMENTS_PATH, 'utf8');
8
+ return content;
9
+ }
3
10
  export class ApexMutationHTMLReporter {
4
11
  async generateReport(apexMutationTestResult, outputDir = 'reports') {
12
+ // The caller (run.ts) validates that `outputDir` exists via the oclif
13
+ // `Flags.directory({ exists: true })` guard. We deliberately do NOT
14
+ // create the directory here: the plugin may be installed under a more
15
+ // privileged user than the one running the command, and auto-creating
16
+ // paths under that higher privilege would let a crafted `-r` flag write
17
+ // into locations the invoking user should not be able to touch.
18
+ //
19
+ // Two-stage path check:
20
+ // 1. string-level resolve rejects `../` traversal;
21
+ // 2. realpath rejects an existing symlink whose target is outside cwd.
22
+ const resolvedDir = resolveSafeOutputDir(outputDir);
23
+ await assertRealPathWithinCwd(resolvedDir, outputDir);
5
24
  const reportData = this.transformApexResults(apexMutationTestResult);
6
- // Generate and write the HTML file with the report data embedded
7
- const htmlContent = createReportHtml(reportData);
8
- await writeFile(path.join(outputDir, 'index.html'), htmlContent);
25
+ const bundle = await loadMutationTestElements();
26
+ const htmlContent = createReportHtml(reportData, bundle);
27
+ await writeFile(path.join(resolvedDir, 'index.html'), htmlContent);
9
28
  }
10
29
  transformApexResults(apexMutationTestResult) {
11
30
  const mutationTestResult = {
12
31
  schemaVersion: '2.0.0',
13
- config: {}, // You can add your configuration here
32
+ config: {},
14
33
  thresholds: {
15
34
  high: 80,
16
35
  low: 60,
@@ -52,31 +71,68 @@ export class ApexMutationHTMLReporter {
52
71
  return mutationTestResult;
53
72
  }
54
73
  }
55
- const createReportHtml = report => {
74
+ function resolveSafeOutputDir(outputDir) {
75
+ const resolved = path.resolve(outputDir);
76
+ const cwd = path.resolve(process.cwd());
77
+ if (resolved !== cwd && !resolved.startsWith(cwd + path.sep)) {
78
+ throw new Error(`Report directory '${outputDir}' resolves outside the current working directory (${cwd}). Refusing to write reports outside the project root.`);
79
+ }
80
+ return resolved;
81
+ }
82
+ /**
83
+ * Resolve symbolic links in the target directory and verify the dereferenced
84
+ * path still lives inside cwd. Defeats attacks where a symlink `reports` → `/etc`
85
+ * is present at cwd and the string-level check in resolveSafeOutputDir is satisfied.
86
+ */
87
+ async function assertRealPathWithinCwd(resolvedDir, originalInput) {
88
+ const realDir = await realpath(resolvedDir);
89
+ const realCwd = await realpath(process.cwd());
90
+ if (realDir !== realCwd && !realDir.startsWith(realCwd + path.sep)) {
91
+ throw new Error(`Report directory '${originalInput}' dereferences to '${realDir}', outside the current working directory (${realCwd}). Refusing to follow symlinks out of the project root.`);
92
+ }
93
+ }
94
+ const createReportHtml = (report, elementsBundle) => {
95
+ const safeJson = serializeReportForScript(report);
96
+ const safeBundle = neutraliseScriptContent(elementsBundle);
56
97
  return `<!DOCTYPE html>
57
98
  <html>
58
99
  <head>
59
100
  <meta charset="utf-8">
60
101
  <title>Mutation Testing Report</title>
61
- <script src="https://cdn.jsdelivr.net/npm/mutation-testing-elements@3.5.1/dist/mutation-test-elements.min.js"></script>
102
+ <script>${safeBundle}</script>
62
103
  </head>
63
104
  <body>
64
105
  <mutation-test-report-app titlePostfix="apex-mutation-testing">
65
106
  Your browser doesn't support <a href="https://caniuse.com/#search=custom%20elements">custom elements</a>.
66
107
  Please use a latest version of an evergreen browser (Firefox, Chrome, Safari, Opera, Edge, etc).
67
108
  </mutation-test-report-app>
109
+ <script id="mutation-report-data" type="application/json">${safeJson}</script>
68
110
  <script>
69
111
  const app = document.querySelector('mutation-test-report-app');
70
- app.report = ${escapeHtmlTags(JSON.stringify(report))};
112
+ app.report = JSON.parse(document.getElementById('mutation-report-data').textContent);
71
113
  </script>
72
114
  </body>
73
115
  </html>`;
74
116
  };
75
117
  /**
76
- * Escapes the HTML tags inside strings in a JSON input by breaking them apart.
118
+ * Neutralise `</script` so a vendored bundle cannot prematurely close the host <script> tag.
119
+ * The bundle is trusted (our own node_modules), but defensive escaping costs nothing.
120
+ */
121
+ function neutraliseScriptContent(content) {
122
+ return content.replace(/<\/script/gi, '<\\/script');
123
+ }
124
+ /**
125
+ * Serialise report data for safe embedding inside a <script type="application/json"> block.
126
+ * Neutralises every character sequence a browser parser treats specially inside script content:
127
+ * `</` (script-end sentinel), `<!--` (HTML comment open), `-->` (close), `<script`, and U+2028/2029.
77
128
  */
78
- function escapeHtmlTags(json) {
79
- const j = json.replace(/</g, '<"+"');
80
- return j;
129
+ function serializeReportForScript(report) {
130
+ return JSON.stringify(report)
131
+ .replace(/<\//g, '<\\/')
132
+ .replace(/<!--/g, '<\\!--')
133
+ .replace(/-->/g, '--\\>')
134
+ .replace(/<script/gi, '<\\script')
135
+ .replace(/\u2028/g, '\\u2028')
136
+ .replace(/\u2029/g, '\\u2029');
81
137
  }
82
138
  //# sourceMappingURL=HTMLReporter.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"HTMLReporter.js","sourceRoot":"","sources":["../../src/reporter/HTMLReporter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAC5C,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAG5B,MAAM,OAAO,wBAAwB;IACnC,KAAK,CAAC,cAAc,CAClB,sBAA8C,EAC9C,YAAoB,SAAS;QAE7B,MAAM,UAAU,GAAG,IAAI,CAAC,oBAAoB,CAAC,sBAAsB,CAAC,CAAA;QACpE,iEAAiE;QACjE,MAAM,WAAW,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAA;QAChD,MAAM,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,EAAE,WAAW,CAAC,CAAA;IAClE,CAAC;IAEO,oBAAoB,CAAC,sBAA8C;QACzE,MAAM,kBAAkB,GAAG;YACzB,aAAa,EAAE,OAAO;YACtB,MAAM,EAAE,EAAE,EAAE,sCAAsC;YAClD,UAAU,EAAE;gBACV,IAAI,EAAE,EAAE;gBACR,GAAG,EAAE,EAAE;aACR;YACD,KAAK,EAAE,EAAE;SACV,CAAA;QAED,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC;YAC/B,cAAc;YACd,cAAc;YACd,SAAS;SACV,CAAC,CAAA;QAEF,MAAM,UAAU,GAAG;YACjB,QAAQ,EAAE,MAAM;YAChB,MAAM,EAAE,sBAAsB,CAAC,iBAAiB;YAChD,OAAO,EAAE,sBAAsB,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBACrD,EAAE,EAAE,MAAM,CAAC,EAAE;gBACb,WAAW,EAAE,MAAM,CAAC,WAAW;gBAC/B,WAAW,EAAE,MAAM,CAAC,WAAW;gBAC/B,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,YAAY,EAAE,MAAM,CAAC,YAAY;gBACjC,MAAM,EAAE,KAAK;gBACb,SAAS,EAAE,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;gBAClE,QAAQ,EAAE,MAAM,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS;gBACxD,cAAc,EAAE,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC3D,QAAQ,EAAE;oBACR,KAAK,EAAE;wBACL,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI;wBAChC,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM;qBACrC;oBACD,GAAG,EAAE;wBACH,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI;wBAC9B,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM;qBACnC;iBACF;aACF,CAAC,CAAC;SACJ,CAAA;QAED,kBAAkB,CAAC,KAAK,CAAC,GAAG,sBAAsB,CAAC,UAAU,MAAM,CAAC;YAClE,UAAU,CAAA;QAEZ,OAAO,kBAAkB,CAAA;IAC3B,CAAC;CACF;AAED,MAAM,gBAAgB,GAAG,MAAM,CAAC,EAAE;IAChC,OAAO;;;;;;;;;;;;;;qBAcY,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;;;UAGjD,CAAA;AACV,CAAC,CAAA;AAED;;GAEG;AACH,SAAS,cAAc,CAAC,IAAY;IAClC,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IACpC,OAAO,CAAC,CAAA;AACV,CAAC"}
1
+ {"version":3,"file":"HTMLReporter.js","sourceRoot":"","sources":["../../src/reporter/HTMLReporter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAC3C,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAG5B,MAAM,eAAe,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AACtD,MAAM,2BAA2B,GAAG,eAAe,CAAC,OAAO,CACzD,0DAA0D,CAC3D,CAAA;AAED,KAAK,UAAU,wBAAwB;IACrC,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,2BAA2B,EAAE,MAAM,CAAC,CAAA;IACnE,OAAO,OAAO,CAAA;AAChB,CAAC;AAED,MAAM,OAAO,wBAAwB;IACnC,KAAK,CAAC,cAAc,CAClB,sBAA8C,EAC9C,YAAoB,SAAS;QAE7B,sEAAsE;QACtE,oEAAoE;QACpE,sEAAsE;QACtE,sEAAsE;QACtE,wEAAwE;QACxE,gEAAgE;QAChE,EAAE;QACF,wBAAwB;QACxB,qDAAqD;QACrD,yEAAyE;QACzE,MAAM,WAAW,GAAG,oBAAoB,CAAC,SAAS,CAAC,CAAA;QACnD,MAAM,uBAAuB,CAAC,WAAW,EAAE,SAAS,CAAC,CAAA;QACrD,MAAM,UAAU,GAAG,IAAI,CAAC,oBAAoB,CAAC,sBAAsB,CAAC,CAAA;QACpE,MAAM,MAAM,GAAG,MAAM,wBAAwB,EAAE,CAAA;QAC/C,MAAM,WAAW,GAAG,gBAAgB,CAAC,UAAU,EAAE,MAAM,CAAC,CAAA;QACxD,MAAM,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,EAAE,WAAW,CAAC,CAAA;IACpE,CAAC;IAEO,oBAAoB,CAAC,sBAA8C;QACzE,MAAM,kBAAkB,GAAG;YACzB,aAAa,EAAE,OAAO;YACtB,MAAM,EAAE,EAAE;YACV,UAAU,EAAE;gBACV,IAAI,EAAE,EAAE;gBACR,GAAG,EAAE,EAAE;aACR;YACD,KAAK,EAAE,EAAE;SACV,CAAA;QAED,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC;YAC/B,cAAc;YACd,cAAc;YACd,SAAS;SACV,CAAC,CAAA;QAEF,MAAM,UAAU,GAAG;YACjB,QAAQ,EAAE,MAAM;YAChB,MAAM,EAAE,sBAAsB,CAAC,iBAAiB;YAChD,OAAO,EAAE,sBAAsB,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBACrD,EAAE,EAAE,MAAM,CAAC,EAAE;gBACb,WAAW,EAAE,MAAM,CAAC,WAAW;gBAC/B,WAAW,EAAE,MAAM,CAAC,WAAW;gBAC/B,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,YAAY,EAAE,MAAM,CAAC,YAAY;gBACjC,MAAM,EAAE,KAAK;gBACb,SAAS,EAAE,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;gBAClE,QAAQ,EAAE,MAAM,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS;gBACxD,cAAc,EAAE,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAC3D,QAAQ,EAAE;oBACR,KAAK,EAAE;wBACL,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI;wBAChC,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM;qBACrC;oBACD,GAAG,EAAE;wBACH,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI;wBAC9B,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM;qBACnC;iBACF;aACF,CAAC,CAAC;SACJ,CAAA;QAED,kBAAkB,CAAC,KAAK,CAAC,GAAG,sBAAsB,CAAC,UAAU,MAAM,CAAC;YAClE,UAAU,CAAA;QAEZ,OAAO,kBAAkB,CAAA;IAC3B,CAAC;CACF;AAED,SAAS,oBAAoB,CAAC,SAAiB;IAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;IACxC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAA;IACvC,IAAI,QAAQ,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QAC7D,MAAM,IAAI,KAAK,CACb,qBAAqB,SAAS,qDAAqD,GAAG,wDAAwD,CAC/I,CAAA;IACH,CAAC;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,uBAAuB,CACpC,WAAmB,EACnB,aAAqB;IAErB,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,WAAW,CAAC,CAAA;IAC3C,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAA;IAC7C,IAAI,OAAO,KAAK,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACnE,MAAM,IAAI,KAAK,CACb,qBAAqB,aAAa,sBAAsB,OAAO,6CAA6C,OAAO,yDAAyD,CAC7K,CAAA;IACH,CAAC;AACH,CAAC;AAED,MAAM,gBAAgB,GAAG,CAAC,MAAe,EAAE,cAAsB,EAAU,EAAE;IAC3E,MAAM,QAAQ,GAAG,wBAAwB,CAAC,MAAM,CAAC,CAAA;IACjD,MAAM,UAAU,GAAG,uBAAuB,CAAC,cAAc,CAAC,CAAA;IAC1D,OAAO;;;;;cAKK,UAAU;;;;;;;gEAOwC,QAAQ;;;;;;UAM9D,CAAA;AACV,CAAC,CAAA;AAED;;;GAGG;AACH,SAAS,uBAAuB,CAAC,OAAe;IAC9C,OAAO,OAAO,CAAC,OAAO,CAAC,aAAa,EAAE,YAAY,CAAC,CAAA;AACrD,CAAC;AAED;;;;GAIG;AACH,SAAS,wBAAwB,CAAC,MAAe;IAC/C,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;SAC1B,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC;SACvB,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC;SAC1B,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC;SACxB,OAAO,CAAC,WAAW,EAAE,WAAW,CAAC;SACjC,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC;SAC7B,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,CAAA;AAClC,CAAC"}