@systemfsoftware/stryker-js-instrumenter 6.0.1 → 7.1.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.
- package/CHANGELOG.md +29 -0
- package/README.md +1 -1
- package/dist/Mutant-BYxuyyRL.d.mts +163 -0
- package/dist/Mutant-DnhV_fpo.mjs +128 -0
- package/dist/index.d.mts +195 -28
- package/dist/index.mjs +471 -716
- package/dist/mutants.d.mts +2 -0
- package/dist/mutants.mjs +2 -0
- package/package.json +31 -22
package/dist/index.mjs
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as isErrnoException, c as Mutant, d as MutantStatusSchema, f as RunOptionsFields, h as PositionSchema, i as errorToString, l as MutantActivationSchema, m as OpenEndLocationSchema, n as INSTRUMENTER_CONSTANTS, o as isMutant, p as LocationSchema, r as causeText, s as normalizeFileName, t as ERROR_CODES, u as MutantRunOptionsSchema } from "./Mutant-DnhV_fpo.mjs";
|
|
2
2
|
import * as Effect from "effect/Effect";
|
|
3
3
|
import * as Predicate from "effect/Predicate";
|
|
4
4
|
import * as S from "effect/Schema";
|
|
5
5
|
import * as Arr from "effect/Array";
|
|
6
6
|
import * as Match from "effect/Match";
|
|
7
7
|
import * as Option from "effect/Option";
|
|
8
|
-
import
|
|
9
|
-
import
|
|
8
|
+
import { walk } from "oxc-walker";
|
|
9
|
+
import { Schema } from "effect";
|
|
10
10
|
import { RegExpParser, visitRegExpAST } from "@eslint-community/regexpp";
|
|
11
11
|
//#region src/Instrument.schema.ts
|
|
12
|
-
var InstrumentError = class extends S.TaggedError("@systemfsoftware/stryker-js-instrumenter/InstrumentError")("InstrumentError", {
|
|
12
|
+
var InstrumentError = class extends S.TaggedError("@systemfsoftware/stryker-js-instrumenter/Instrument.schema/InstrumentError")("InstrumentError", {
|
|
13
13
|
message: S.String,
|
|
14
14
|
cause: S.Defect()
|
|
15
15
|
}) {
|
|
@@ -18,13 +18,13 @@ var InstrumentError = class extends S.TaggedError("@systemfsoftware/stryker-js-i
|
|
|
18
18
|
return this.message;
|
|
19
19
|
}
|
|
20
20
|
};
|
|
21
|
-
const PositionSchema = S.Struct({
|
|
21
|
+
const PositionSchema$1 = S.Struct({
|
|
22
22
|
line: S.Finite,
|
|
23
23
|
column: S.Finite
|
|
24
24
|
});
|
|
25
25
|
const RangeSchema = S.Struct({
|
|
26
|
-
start: PositionSchema,
|
|
27
|
-
end: PositionSchema
|
|
26
|
+
start: PositionSchema$1,
|
|
27
|
+
end: PositionSchema$1
|
|
28
28
|
});
|
|
29
29
|
const MutateDescriptionSchema = S.Union([S.Boolean, S.Array(RangeSchema)]);
|
|
30
30
|
const FileSchema = S.Struct({
|
|
@@ -33,27 +33,11 @@ const FileSchema = S.Struct({
|
|
|
33
33
|
mutate: MutateDescriptionSchema
|
|
34
34
|
});
|
|
35
35
|
const IgnorerSchema = S.Unknown;
|
|
36
|
-
const AstSchema = S.Unknown;
|
|
37
36
|
const InstrumenterOptionsSchema = S.Struct({
|
|
38
37
|
excludedMutations: S.Array(S.String),
|
|
39
38
|
ignorers: S.Array(IgnorerSchema),
|
|
40
39
|
noHeader: S.optional(S.Boolean)
|
|
41
40
|
});
|
|
42
|
-
var InstrumentCommand = class extends S.TaggedClass()("InstrumentCommand", {
|
|
43
|
-
files: S.Array(FileSchema),
|
|
44
|
-
options: InstrumenterOptionsSchema
|
|
45
|
-
}) {};
|
|
46
|
-
var InstrumentDecoded = class extends S.TaggedClass()("InstrumentDecoded", {
|
|
47
|
-
files: S.Array(FileSchema),
|
|
48
|
-
options: InstrumenterOptionsSchema,
|
|
49
|
-
asts: S.Array(AstSchema),
|
|
50
|
-
mutants: S.Array(Mutant)
|
|
51
|
-
}) {};
|
|
52
|
-
var InstrumentDecision = class extends S.TaggedClass()("InstrumentDecision", {
|
|
53
|
-
files: S.Array(FileSchema),
|
|
54
|
-
mutants: S.Array(Mutant),
|
|
55
|
-
asts: S.Array(AstSchema)
|
|
56
|
-
}) {};
|
|
57
41
|
var InstrumentResult = class extends S.TaggedClass()("InstrumentResult", {
|
|
58
42
|
files: S.Array(FileSchema),
|
|
59
43
|
mutants: S.Array(Mutant)
|
|
@@ -68,6 +52,9 @@ S.Literals([
|
|
|
68
52
|
//#endregion
|
|
69
53
|
//#region src/Syntax.ts
|
|
70
54
|
/**
|
|
55
|
+
* Syntax — the instrumenter's AST shapes, location helpers and syntax utilities.
|
|
56
|
+
*/
|
|
57
|
+
/**
|
|
71
58
|
* Determines if a location (needle) is included in an other location (haystack)
|
|
72
59
|
* @param haystack The range to look in
|
|
73
60
|
* @param needle the range to search for
|
|
@@ -122,13 +109,10 @@ function requireMidpoint(midValue) {
|
|
|
122
109
|
return midValue;
|
|
123
110
|
}
|
|
124
111
|
//#endregion
|
|
125
|
-
//#region src/
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
* back standard ESTree, so the instrumenter owns the traversal instead of
|
|
130
|
-
* without pulling scope machinery along.
|
|
131
|
-
*/
|
|
112
|
+
//#region src/Traversal.schema.ts
|
|
113
|
+
var TraversalStopped = class extends Schema.TaggedError()("TraversalStopped", {}) {};
|
|
114
|
+
//#endregion
|
|
115
|
+
//#region src/Ast.ts
|
|
132
116
|
const EXPRESSION_KINDS = /* @__PURE__ */ new Set([
|
|
133
117
|
"ArrayExpression",
|
|
134
118
|
"ArrowFunctionExpression",
|
|
@@ -194,10 +178,6 @@ const STATEMENT_KINDS = /* @__PURE__ */ new Set([
|
|
|
194
178
|
"WhileStatement",
|
|
195
179
|
"WithStatement"
|
|
196
180
|
]);
|
|
197
|
-
/**
|
|
198
|
-
* The node's [start, end) offsets. oxc is invoked with `range: true`, so every
|
|
199
|
-
* parsed node carries one; synthesized builders omit it.
|
|
200
|
-
*/
|
|
201
181
|
function spanOf(node) {
|
|
202
182
|
const range = node.range;
|
|
203
183
|
if (range === void 0) return void 0;
|
|
@@ -206,10 +186,6 @@ function spanOf(node) {
|
|
|
206
186
|
end: range[1]
|
|
207
187
|
};
|
|
208
188
|
}
|
|
209
|
-
/**
|
|
210
|
-
* The node's `type` tag, for checks against kinds outside the @types/estree
|
|
211
|
-
* union (TS and JSX extensions oxc emits).
|
|
212
|
-
*/
|
|
213
189
|
function nodeType(node) {
|
|
214
190
|
if (!isAstNode(node)) return void 0;
|
|
215
191
|
return node.type;
|
|
@@ -238,19 +214,22 @@ function identifier(name, loc) {
|
|
|
238
214
|
function stringLiteral(value, loc) {
|
|
239
215
|
return mark({
|
|
240
216
|
type: "Literal",
|
|
241
|
-
value
|
|
217
|
+
value,
|
|
218
|
+
raw: null
|
|
242
219
|
}, loc);
|
|
243
220
|
}
|
|
244
221
|
function booleanLiteral(value, loc) {
|
|
245
222
|
return mark({
|
|
246
223
|
type: "Literal",
|
|
247
|
-
value
|
|
224
|
+
value,
|
|
225
|
+
raw: null
|
|
248
226
|
}, loc);
|
|
249
227
|
}
|
|
250
228
|
function regExpLiteral(pattern, flags, loc) {
|
|
251
229
|
return mark({
|
|
252
230
|
type: "Literal",
|
|
253
231
|
value: null,
|
|
232
|
+
raw: null,
|
|
254
233
|
regex: {
|
|
255
234
|
pattern,
|
|
256
235
|
flags
|
|
@@ -278,12 +257,12 @@ function newExpression(callee, args = [], loc) {
|
|
|
278
257
|
arguments: [...args]
|
|
279
258
|
}, loc);
|
|
280
259
|
}
|
|
281
|
-
function memberExpression(object, property,
|
|
260
|
+
function memberExpression(object, property, optional, loc) {
|
|
282
261
|
return mark({
|
|
283
262
|
type: "MemberExpression",
|
|
284
263
|
object,
|
|
285
264
|
property,
|
|
286
|
-
computed,
|
|
265
|
+
computed: false,
|
|
287
266
|
optional
|
|
288
267
|
}, loc);
|
|
289
268
|
}
|
|
@@ -291,6 +270,8 @@ function arrowFunctionExpression(params, body, loc) {
|
|
|
291
270
|
const fnBody = body;
|
|
292
271
|
return mark({
|
|
293
272
|
type: "ArrowFunctionExpression",
|
|
273
|
+
id: null,
|
|
274
|
+
generator: false,
|
|
294
275
|
params: [...params],
|
|
295
276
|
body: fnBody,
|
|
296
277
|
async: false,
|
|
@@ -391,20 +372,9 @@ function switchCase(test, consequent, loc) {
|
|
|
391
372
|
consequent: [...consequent]
|
|
392
373
|
}, loc);
|
|
393
374
|
}
|
|
394
|
-
/**
|
|
395
|
-
* Deep clone of a plain ESTree node. oxc nodes are JSON-shaped, so
|
|
396
|
-
* Deep clone over plain nodes: no prototypes to preserve.
|
|
397
|
-
*/
|
|
398
375
|
function cloneNode(node) {
|
|
399
376
|
return structuredClone(node);
|
|
400
377
|
}
|
|
401
|
-
/**
|
|
402
|
-
* Attaches every comment to the node it precedes (`leadingComments`) or, when
|
|
403
|
-
* no node follows it, to the node it trails (`trailingComments`). oxc ships
|
|
404
|
-
* comments flat, and the Stryker directive pass reads `node.leadingComments`,
|
|
405
|
-
* so the flat list is folded into the tree once per transform with the file's
|
|
406
|
-
* line table in hand.
|
|
407
|
-
*/
|
|
408
378
|
function attachComments(root, comments, lineTable) {
|
|
409
379
|
if (comments.length === 0) return;
|
|
410
380
|
const nodes = collectNodes(root).filter((entry) => entry.node !== root);
|
|
@@ -421,13 +391,6 @@ function groupComments(nodes, comments) {
|
|
|
421
391
|
for (const comment of comments) hostComment(nodes, comment, groups);
|
|
422
392
|
return groups;
|
|
423
393
|
}
|
|
424
|
-
/**
|
|
425
|
-
* The map a comment is hosted in. A comment attaches to the node it precedes;
|
|
426
|
-
* one that precedes nothing — a same-line trailing comment — attaches to the
|
|
427
|
-
* nearest statement before it, because the statement printer is the only
|
|
428
|
-
* emitter of trailing comments and an expression host would never reach the
|
|
429
|
-
* output.
|
|
430
|
-
*/
|
|
431
394
|
function hostComment(nodes, comment, groups) {
|
|
432
395
|
const host = [{
|
|
433
396
|
field: "leading",
|
|
@@ -465,32 +428,27 @@ function pushComment(map, node, comment) {
|
|
|
465
428
|
if (list === void 0) map.set(node, [comment]);
|
|
466
429
|
else list.push(comment);
|
|
467
430
|
}
|
|
468
|
-
/** oxc emits a node's children as a plain array the walker reads and replaces into. */
|
|
469
431
|
const isNodeList = (value) => Array.isArray(value);
|
|
470
|
-
|
|
432
|
+
const walker = (root, visitors) => {
|
|
433
|
+
const ancestors = [];
|
|
434
|
+
walk(root, {
|
|
435
|
+
enter(node) {
|
|
436
|
+
visitors.enter?.(node, [...ancestors]);
|
|
437
|
+
ancestors.push(node);
|
|
438
|
+
},
|
|
439
|
+
leave(node) {
|
|
440
|
+
ancestors.pop();
|
|
441
|
+
visitors.leave?.(node, [...ancestors]);
|
|
442
|
+
}
|
|
443
|
+
});
|
|
444
|
+
};
|
|
445
|
+
function collectNodes(root) {
|
|
471
446
|
const out = [];
|
|
472
|
-
|
|
447
|
+
walker(root, { enter(node) {
|
|
448
|
+
appendEntry(node, out);
|
|
449
|
+
} });
|
|
473
450
|
return out;
|
|
474
451
|
}
|
|
475
|
-
function collect$1(node, out) {
|
|
476
|
-
if (isNodeList(node)) return collectList(node, out);
|
|
477
|
-
collectAstNode(node, out);
|
|
478
|
-
}
|
|
479
|
-
function collectList(items, out) {
|
|
480
|
-
for (const item of items) collect$1(item, out);
|
|
481
|
-
}
|
|
482
|
-
function collectAstNode(value, out) {
|
|
483
|
-
if (!isAstNode(value)) return;
|
|
484
|
-
appendEntry(value, out);
|
|
485
|
-
collectChildren(value, out);
|
|
486
|
-
}
|
|
487
|
-
function collectChildren(node, out) {
|
|
488
|
-
for (const key of Object.keys(node)) collectChild(node, key, out);
|
|
489
|
-
}
|
|
490
|
-
function collectChild(node, key, out) {
|
|
491
|
-
if (SKIP_KEYS.has(key)) return;
|
|
492
|
-
collect$1(node[key], out);
|
|
493
|
-
}
|
|
494
452
|
function appendEntry(node, out) {
|
|
495
453
|
const span = spanOf(node);
|
|
496
454
|
if (span === void 0) return;
|
|
@@ -510,80 +468,59 @@ function positionFromLineTable(offset, lineTable) {
|
|
|
510
468
|
const zeroBased = positionFromOffset(lineTable, offset);
|
|
511
469
|
return {
|
|
512
470
|
line: zeroBased.line + 1,
|
|
513
|
-
column: zeroBased.column
|
|
471
|
+
column: zeroBased.column + 1
|
|
514
472
|
};
|
|
515
473
|
}
|
|
516
|
-
const
|
|
517
|
-
|
|
518
|
-
"
|
|
519
|
-
"end",
|
|
520
|
-
"range",
|
|
521
|
-
"loc",
|
|
522
|
-
"leadingComments",
|
|
523
|
-
"trailingComments"
|
|
524
|
-
]);
|
|
525
|
-
function traverse(root, visitors) {
|
|
526
|
-
visit(root, null, "root", void 0, visitors, {
|
|
527
|
-
skipped: /* @__PURE__ */ new Set(),
|
|
528
|
-
stopped: false
|
|
529
|
-
});
|
|
474
|
+
const COMMENT_KEYS = /* @__PURE__ */ new Set(["leadingComments", "trailingComments"]);
|
|
475
|
+
function isCommentKey(key) {
|
|
476
|
+
return typeof key === "string" && COMMENT_KEYS.has(key);
|
|
530
477
|
}
|
|
531
|
-
function
|
|
532
|
-
|
|
533
|
-
|
|
478
|
+
function traverse(root, visitors) {
|
|
479
|
+
const stack = [];
|
|
480
|
+
try {
|
|
481
|
+
walk(root, {
|
|
482
|
+
enter(node, _parent, context) {
|
|
483
|
+
readPath(stack, node, this, context, visitors);
|
|
484
|
+
},
|
|
485
|
+
leave(_node, _parent, context) {
|
|
486
|
+
closePath(stack, context, visitors);
|
|
487
|
+
}
|
|
488
|
+
});
|
|
489
|
+
} catch (error) {
|
|
490
|
+
rethrowUnlessStopped(error);
|
|
491
|
+
}
|
|
534
492
|
}
|
|
535
|
-
|
|
536
|
-
if (!
|
|
537
|
-
|
|
493
|
+
const rethrowUnlessStopped = (error) => {
|
|
494
|
+
if (!S.is(TraversalStopped)(error)) throw error;
|
|
495
|
+
};
|
|
496
|
+
const readPath = (stack, node, controls, context, visitors) => {
|
|
497
|
+
if (isCommentKey(context.key)) return;
|
|
498
|
+
const path = createPath(node, parentOf(stack), controls, context);
|
|
499
|
+
stack.push(path);
|
|
538
500
|
notify(visitors.enter, path);
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
if (context.skipped.has(node)) return;
|
|
546
|
-
visitChildren(node, path, visitors, context);
|
|
547
|
-
notifyExit(visitors.exit, path, context);
|
|
548
|
-
}
|
|
549
|
-
function notifyExit(visitor, path, context) {
|
|
550
|
-
if (context.stopped) return;
|
|
551
|
-
notify(visitor, path);
|
|
552
|
-
}
|
|
501
|
+
};
|
|
502
|
+
const closePath = (stack, context, visitors) => {
|
|
503
|
+
if (isCommentKey(context.key)) return;
|
|
504
|
+
notify(visitors.exit, stack.pop());
|
|
505
|
+
};
|
|
506
|
+
const parentOf = (stack) => Option.getOrNull(Arr.last(stack));
|
|
553
507
|
function notify(visitor, path) {
|
|
554
508
|
if (visitor === void 0) return;
|
|
555
|
-
visitor
|
|
509
|
+
relay(visitor, path);
|
|
556
510
|
}
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
}
|
|
560
|
-
function
|
|
561
|
-
|
|
562
|
-
return keepVisitingChild(node[key], path, key, visitors, context);
|
|
563
|
-
}
|
|
564
|
-
function keepVisitingChild(child, path, key, visitors, context) {
|
|
565
|
-
if (isNodeList(child)) return keepVisitingList(child, path, key, visitors, context);
|
|
566
|
-
return keepVisitingValue(child, path, key, void 0, visitors, context);
|
|
567
|
-
}
|
|
568
|
-
function keepVisitingList(items, path, key, visitors, context) {
|
|
569
|
-
return items.every((item, index) => keepVisitingValue(item, path, key, String(index), visitors, context));
|
|
570
|
-
}
|
|
571
|
-
function keepVisitingValue(value, path, key, listKey, visitors, context) {
|
|
572
|
-
visit(value, path, key, listKey, visitors, context);
|
|
573
|
-
return !context.stopped;
|
|
574
|
-
}
|
|
575
|
-
function createPath(node, parentPath, key, listKey, context) {
|
|
511
|
+
const relay = (visitor, path) => {
|
|
512
|
+
if (path !== void 0) visitor(path);
|
|
513
|
+
};
|
|
514
|
+
function createPath(node, parentPath, controls, context) {
|
|
515
|
+
const key = typeof context.key === "string" ? context.key : void 0;
|
|
576
516
|
const path = {
|
|
577
517
|
node,
|
|
578
518
|
parentPath,
|
|
579
|
-
parent: parentPath?.node,
|
|
580
|
-
key,
|
|
581
|
-
listKey,
|
|
582
519
|
skip() {
|
|
583
|
-
|
|
520
|
+
controls.skip();
|
|
584
521
|
},
|
|
585
522
|
stop() {
|
|
586
|
-
|
|
523
|
+
throw TraversalStopped.make({});
|
|
587
524
|
},
|
|
588
525
|
find(predicate) {
|
|
589
526
|
return nearest(path, predicate);
|
|
@@ -592,10 +529,7 @@ function createPath(node, parentPath, key, listKey, context) {
|
|
|
592
529
|
return nearest(parentPath, (ancestor) => isStatementKind(ancestor.node));
|
|
593
530
|
},
|
|
594
531
|
replaceWith(replacement) {
|
|
595
|
-
|
|
596
|
-
},
|
|
597
|
-
is(kind) {
|
|
598
|
-
return node.type === kind;
|
|
532
|
+
replaceInSlot(parentPath, key, context.index, replacement);
|
|
599
533
|
},
|
|
600
534
|
isExpression() {
|
|
601
535
|
return isExpressionKind(node);
|
|
@@ -614,39 +548,36 @@ function takeOrAscend(path, predicate) {
|
|
|
614
548
|
if (predicate(path)) return path;
|
|
615
549
|
return nearest(path.parentPath, predicate);
|
|
616
550
|
}
|
|
617
|
-
function
|
|
551
|
+
function replaceInSlot(parentPath, key, index, replacement) {
|
|
618
552
|
if (parentPath === null) return;
|
|
619
|
-
|
|
553
|
+
writeInto(parentPath.node, key, index, replacement);
|
|
620
554
|
}
|
|
621
|
-
function
|
|
555
|
+
function writeInto(parent, key, index, replacement) {
|
|
622
556
|
if (!isAstNode(parent)) return;
|
|
623
|
-
|
|
624
|
-
}
|
|
625
|
-
function assignChild(parent, key, listKey, replacement) {
|
|
626
|
-
if (listKey === void 0) {
|
|
627
|
-
parent[key] = replacement;
|
|
628
|
-
return;
|
|
629
|
-
}
|
|
630
|
-
assignIndexed(parent, key, listKey, replacement);
|
|
557
|
+
writeAtKey(parent, key, index, replacement);
|
|
631
558
|
}
|
|
632
|
-
function
|
|
633
|
-
|
|
634
|
-
const container = parent[key];
|
|
635
|
-
if (isIndexedList(container, index)) container[index] = replacement;
|
|
559
|
+
function writeAtKey(parent, key, index, replacement) {
|
|
560
|
+
Match.value(key).pipe(Match.when(Predicate.isString, (slot) => writeAtSlot(parent, slot, index, replacement)), Match.orElse(() => void 0));
|
|
636
561
|
}
|
|
637
|
-
function
|
|
638
|
-
|
|
562
|
+
function writeAtSlot(parent, key, index, replacement) {
|
|
563
|
+
Match.value(index).pipe(Match.when(Match.null, () => overwrite(parent, key, replacement)), Match.orElse((position) => writeElement(parent[key], position, replacement)));
|
|
639
564
|
}
|
|
565
|
+
const overwrite = (parent, key, replacement) => {
|
|
566
|
+
parent[key] = replacement;
|
|
567
|
+
};
|
|
568
|
+
const writeElement = (container, index, replacement) => {
|
|
569
|
+
if (isNodeList(container)) container[index] = replacement;
|
|
570
|
+
};
|
|
640
571
|
//#endregion
|
|
641
572
|
//#region src/Oxc.ts
|
|
642
573
|
let oxc;
|
|
643
|
-
const loadOxc =
|
|
644
|
-
if (oxc === void 0) oxc =
|
|
574
|
+
const loadOxc = Effect.gen(function* () {
|
|
575
|
+
if (oxc === void 0) oxc = yield* Effect.promise(() => import("oxc-parser"));
|
|
645
576
|
return oxc;
|
|
646
|
-
};
|
|
577
|
+
});
|
|
647
578
|
//#endregion
|
|
648
579
|
//#region src/Parser.schema.ts
|
|
649
|
-
var ParseFailed = class extends S.TaggedError("@systemfsoftware/stryker-js-instrumenter/ParseFailed")("ParseFailed", {
|
|
580
|
+
var ParseFailed = class extends S.TaggedError("@systemfsoftware/stryker-js-instrumenter/Parser.schema/ParseFailed")("ParseFailed", {
|
|
650
581
|
fileName: S.String,
|
|
651
582
|
message: S.String,
|
|
652
583
|
location: S.Struct({
|
|
@@ -659,7 +590,7 @@ var ParseFailed = class extends S.TaggedError("@systemfsoftware/stryker-js-instr
|
|
|
659
590
|
return `Failed to parse ${this.fileName} at ${this.location.line}:${this.location.column}: ${this.message}`;
|
|
660
591
|
}
|
|
661
592
|
};
|
|
662
|
-
var ParserNotFound = class extends S.TaggedError("@systemfsoftware/stryker-js-instrumenter/ParserNotFound")("ParserNotFound", {
|
|
593
|
+
var ParserNotFound = class extends S.TaggedError("@systemfsoftware/stryker-js-instrumenter/Parser.schema/ParserNotFound")("ParserNotFound", {
|
|
663
594
|
fileName: S.String,
|
|
664
595
|
extension: S.String,
|
|
665
596
|
cause: S.Defect()
|
|
@@ -668,7 +599,7 @@ var ParserNotFound = class extends S.TaggedError("@systemfsoftware/stryker-js-in
|
|
|
668
599
|
return `No parser registered for ${this.fileName} (extension "${this.extension}")`;
|
|
669
600
|
}
|
|
670
601
|
};
|
|
671
|
-
var SvelteVersionNotSupported = class extends S.TaggedError("@systemfsoftware/stryker-js-instrumenter/SvelteVersionNotSupported")("SvelteVersionNotSupported", {
|
|
602
|
+
var SvelteVersionNotSupported = class extends S.TaggedError("@systemfsoftware/stryker-js-instrumenter/Parser.schema/SvelteVersionNotSupported")("SvelteVersionNotSupported", {
|
|
672
603
|
version: S.String,
|
|
673
604
|
fileName: S.String,
|
|
674
605
|
cause: S.Defect()
|
|
@@ -677,7 +608,7 @@ var SvelteVersionNotSupported = class extends S.TaggedError("@systemfsoftware/st
|
|
|
677
608
|
return `Svelte version ${this.version} is not supported for ${this.fileName} (expected >=3.30)`;
|
|
678
609
|
}
|
|
679
610
|
};
|
|
680
|
-
var SvelteWalkerNotFound = class extends S.TaggedError("@systemfsoftware/stryker-js-instrumenter/SvelteWalkerNotFound")("SvelteWalkerNotFound", {
|
|
611
|
+
var SvelteWalkerNotFound = class extends S.TaggedError("@systemfsoftware/stryker-js-instrumenter/Parser.schema/SvelteWalkerNotFound")("SvelteWalkerNotFound", {
|
|
681
612
|
fileName: S.String,
|
|
682
613
|
cause: S.Defect()
|
|
683
614
|
}) {
|
|
@@ -685,7 +616,7 @@ var SvelteWalkerNotFound = class extends S.TaggedError("@systemfsoftware/stryker
|
|
|
685
616
|
return `Svelte walker not found for ${this.fileName}`;
|
|
686
617
|
}
|
|
687
618
|
};
|
|
688
|
-
S.TaggedError("@systemfsoftware/stryker-js-instrumenter/SvelteParseFailed")("SvelteParseFailed", {
|
|
619
|
+
S.TaggedError("@systemfsoftware/stryker-js-instrumenter/Parser.schema/SvelteParseFailed")("SvelteParseFailed", {
|
|
689
620
|
fileName: S.String,
|
|
690
621
|
cause: S.Defect()
|
|
691
622
|
});
|
|
@@ -727,23 +658,23 @@ function fieldOf(value, key) {
|
|
|
727
658
|
function appendIfDefined(values, value) {
|
|
728
659
|
if (value !== void 0) values.push(value);
|
|
729
660
|
}
|
|
730
|
-
|
|
731
|
-
const { parseSync } =
|
|
661
|
+
const parseWithOxc = (text, fileName, lang) => Effect.gen(function* () {
|
|
662
|
+
const { parseSync } = yield* loadOxc;
|
|
732
663
|
const result = parseSync(fileName, text, {
|
|
733
664
|
lang,
|
|
734
665
|
range: true
|
|
735
666
|
});
|
|
736
667
|
const failure = oxcParseFailure(result.errors, text, fileName);
|
|
737
|
-
if (failure !== void 0)
|
|
668
|
+
if (failure !== void 0) return yield* failure;
|
|
738
669
|
return {
|
|
739
670
|
root: result.program,
|
|
740
671
|
comments: result.comments
|
|
741
672
|
};
|
|
742
|
-
}
|
|
673
|
+
});
|
|
743
674
|
function oxcParseFailure(errors, text, fileName) {
|
|
744
675
|
const first = errors.at(0);
|
|
745
676
|
if (first === void 0) return;
|
|
746
|
-
return
|
|
677
|
+
return ParseFailed.make({
|
|
747
678
|
fileName,
|
|
748
679
|
message: first.message,
|
|
749
680
|
location: positionFromLineTable(oxcErrorLabelStart(first), buildLineTable(text)),
|
|
@@ -770,13 +701,16 @@ function shiftScriptOffsets(ast, offset) {
|
|
|
770
701
|
}
|
|
771
702
|
function createParser() {
|
|
772
703
|
const jsParse = createJSParser();
|
|
773
|
-
|
|
704
|
+
function parse(code, fileName, formatOverride) {
|
|
774
705
|
const format = getFormat(fileName, formatOverride);
|
|
775
|
-
if (!format)
|
|
776
|
-
fileName
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
706
|
+
if (!format) {
|
|
707
|
+
const ext = extensionOf(fileName);
|
|
708
|
+
return Effect.fail(ParserNotFound.make({
|
|
709
|
+
fileName,
|
|
710
|
+
extension: ext,
|
|
711
|
+
cause: void 0
|
|
712
|
+
}));
|
|
713
|
+
}
|
|
780
714
|
return Match.value(format).pipe(Match.when("js", () => jsParse(code, fileName)), Match.when("tsx", () => parseTsx(code, fileName)), Match.when("ts", () => parseTS(code, fileName)), Match.when("html", () => parseHtml(code, fileName, { parse })), Match.when("svelte", () => parseSvelte(code, fileName, { parse })), Match.exhaustive);
|
|
781
715
|
}
|
|
782
716
|
return parse;
|
|
@@ -796,40 +730,37 @@ const FORMAT_BY_EXTENSION = {
|
|
|
796
730
|
".svelte": "svelte"
|
|
797
731
|
};
|
|
798
732
|
function getFormat(fileName, override) {
|
|
799
|
-
return override ?? FORMAT_BY_EXTENSION[
|
|
733
|
+
return override ?? FORMAT_BY_EXTENSION[extensionOf(fileName)];
|
|
800
734
|
}
|
|
735
|
+
const dotBeforeSlash = (dot, slash) => dot >= 0 && dot > slash;
|
|
736
|
+
const extensionOf = (fileName) => {
|
|
737
|
+
const dot = fileName.lastIndexOf(".");
|
|
738
|
+
const slash = Math.max(fileName.lastIndexOf("/"), fileName.lastIndexOf("\\"));
|
|
739
|
+
return dotBeforeSlash(dot, slash) ? fileName.slice(dot).toLowerCase() : "";
|
|
740
|
+
};
|
|
801
741
|
function createJSParser() {
|
|
802
|
-
return
|
|
803
|
-
const { root, comments } = await parseWithOxc(text, fileName, "js");
|
|
804
|
-
return {
|
|
805
|
-
originFileName: fileName,
|
|
806
|
-
rawContent: text,
|
|
807
|
-
format: "js",
|
|
808
|
-
root,
|
|
809
|
-
comments
|
|
810
|
-
};
|
|
811
|
-
};
|
|
812
|
-
}
|
|
813
|
-
async function parseTS(text, fileName) {
|
|
814
|
-
const { root, comments } = await parseWithOxc(text, fileName, "ts");
|
|
815
|
-
return {
|
|
742
|
+
return (text, fileName) => Effect.map(parseWithOxc(text, fileName, "js"), ({ root, comments }) => ({
|
|
816
743
|
originFileName: fileName,
|
|
817
744
|
rawContent: text,
|
|
818
|
-
format: "
|
|
745
|
+
format: "js",
|
|
819
746
|
root,
|
|
820
747
|
comments
|
|
821
|
-
};
|
|
822
|
-
}
|
|
823
|
-
async function parseTsx(text, fileName) {
|
|
824
|
-
const { root, comments } = await parseWithOxc(text, fileName, "tsx");
|
|
825
|
-
return {
|
|
826
|
-
root,
|
|
827
|
-
comments,
|
|
828
|
-
format: "tsx",
|
|
829
|
-
originFileName: fileName,
|
|
830
|
-
rawContent: text
|
|
831
|
-
};
|
|
748
|
+
}));
|
|
832
749
|
}
|
|
750
|
+
const parseTS = (text, fileName) => Effect.map(parseWithOxc(text, fileName, "ts"), ({ root, comments }) => ({
|
|
751
|
+
originFileName: fileName,
|
|
752
|
+
rawContent: text,
|
|
753
|
+
format: "ts",
|
|
754
|
+
root,
|
|
755
|
+
comments
|
|
756
|
+
}));
|
|
757
|
+
const parseTsx = (text, fileName) => Effect.map(parseWithOxc(text, fileName, "tsx"), ({ root, comments }) => ({
|
|
758
|
+
root,
|
|
759
|
+
comments,
|
|
760
|
+
format: "tsx",
|
|
761
|
+
originFileName: fileName,
|
|
762
|
+
rawContent: text
|
|
763
|
+
}));
|
|
833
764
|
const SCRIPT_TYPE_FORMATS = {
|
|
834
765
|
tsx: "tsx",
|
|
835
766
|
"text/tsx": "tsx",
|
|
@@ -841,27 +772,25 @@ const SCRIPT_TYPE_FORMATS = {
|
|
|
841
772
|
javascript: "js",
|
|
842
773
|
module: "js"
|
|
843
774
|
};
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
async function ngHtmlParser(text, fileName, parserContext) {
|
|
853
|
-
const ngParser = await import("angular-html-parser");
|
|
775
|
+
const parseHtml = (text, originFileName, context) => Effect.map(ngHtmlParser(text, originFileName, context), (root) => ({
|
|
776
|
+
originFileName,
|
|
777
|
+
rawContent: text,
|
|
778
|
+
format: "html",
|
|
779
|
+
root
|
|
780
|
+
}));
|
|
781
|
+
const ngHtmlParser = (text, fileName, parserContext) => Effect.gen(function* () {
|
|
782
|
+
const ngParser = yield* Effect.promise(() => import("angular-html-parser"));
|
|
854
783
|
const { rootNodes, errors } = ngParser.parse(text, {
|
|
855
784
|
canSelfClose: true,
|
|
856
785
|
allowHtmComponentClosingTags: true,
|
|
857
786
|
isTagNameCaseSensitive: true
|
|
858
787
|
});
|
|
859
|
-
if (errors.length !== 0)
|
|
860
|
-
const
|
|
788
|
+
if (errors.length !== 0) return yield* htmlErrorFailure(errors, fileName);
|
|
789
|
+
const scriptEffects = [];
|
|
861
790
|
const scriptCollector = {
|
|
862
791
|
visitElement: (el, context) => {
|
|
863
792
|
const scriptFormat = getScriptType(el);
|
|
864
|
-
if (scriptFormat)
|
|
793
|
+
if (scriptFormat) scriptEffects.push(parseScript(el, scriptFormat));
|
|
865
794
|
ngParser.visitAll(scriptCollector, el.children, context);
|
|
866
795
|
},
|
|
867
796
|
visitAttribute: () => void 0,
|
|
@@ -878,10 +807,9 @@ async function ngHtmlParser(text, fileName, parserContext) {
|
|
|
878
807
|
visitDirective: () => void 0
|
|
879
808
|
};
|
|
880
809
|
ngParser.visitAll(scriptCollector, rootNodes);
|
|
881
|
-
return { scripts:
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
if (ast != null) {
|
|
810
|
+
return { scripts: yield* Effect.all(scriptEffects) };
|
|
811
|
+
function parseScript(el, scriptFormat) {
|
|
812
|
+
return Effect.map(parserContext.parse(elementScriptText(el, text), fileName, scriptFormat), (ast) => {
|
|
885
813
|
const offset = el.startSourceSpan.end;
|
|
886
814
|
shiftScriptOffsets(ast, offset.offset);
|
|
887
815
|
return {
|
|
@@ -891,13 +819,12 @@ async function ngHtmlParser(text, fileName, parserContext) {
|
|
|
891
819
|
line: offset.line
|
|
892
820
|
}
|
|
893
821
|
};
|
|
894
|
-
}
|
|
895
|
-
return ast;
|
|
822
|
+
});
|
|
896
823
|
}
|
|
897
|
-
}
|
|
824
|
+
});
|
|
898
825
|
function htmlErrorFailure(errors, fileName) {
|
|
899
826
|
const first = errors.at(0);
|
|
900
|
-
if (first === void 0) return
|
|
827
|
+
if (first === void 0) return ParseFailed.make({
|
|
901
828
|
fileName,
|
|
902
829
|
message: "HTML parser reported errors but first error is missing",
|
|
903
830
|
location: {
|
|
@@ -906,7 +833,7 @@ function htmlErrorFailure(errors, fileName) {
|
|
|
906
833
|
},
|
|
907
834
|
cause: errors
|
|
908
835
|
});
|
|
909
|
-
return
|
|
836
|
+
return ParseFailed.make({
|
|
910
837
|
fileName,
|
|
911
838
|
message: first.msg,
|
|
912
839
|
location: toSourceLocation(first.span.start),
|
|
@@ -948,7 +875,7 @@ const SVELTE_5 = {
|
|
|
948
875
|
major: 5,
|
|
949
876
|
minor: 0
|
|
950
877
|
};
|
|
951
|
-
const
|
|
878
|
+
const WALKER_MODULE_MISSING = "walker module without walk export";
|
|
952
879
|
const COMPILER_WALK_MISSING = "svelte/compiler module without walk export";
|
|
953
880
|
const INSTANCE_RANGE_MISSING = "Svelte instance script without a source range";
|
|
954
881
|
const MODULE_RANGE_MISSING = "Svelte module script without a source range";
|
|
@@ -1029,75 +956,68 @@ function rangedExpressionOf(payload) {
|
|
|
1029
956
|
* Due to the way Svelte 5 is structured, we can no longer use the typings from Svelte 4, even though
|
|
1030
957
|
* we use the legacy AST. The full Svelte 5 migration should update these typings to use the new AST.
|
|
1031
958
|
*/
|
|
1032
|
-
|
|
1033
|
-
return Match.value(isAtLeast(version, SVELTE_5)).pipe(Match.when(true, () => loadWalkerModule(import.meta.resolve("estree-walker"), fileName, ESTREE_WALKER_MISSING)), Match.orElse(() => loadWalkerModule("svelte/compiler", fileName, COMPILER_WALK_MISSING)));
|
|
1034
|
-
}
|
|
959
|
+
const loadWalker = (version, fileName) => Match.value(isAtLeast(version, SVELTE_5)).pipe(Match.when(true, () => loadWalkerModule(import.meta.resolve("oxc-walker"), fileName, WALKER_MODULE_MISSING)), Match.orElse(() => loadWalkerModule("svelte/compiler", fileName, COMPILER_WALK_MISSING)));
|
|
1035
960
|
/**
|
|
1036
961
|
* The specifier is chosen at run time and both modules are optional peers of
|
|
1037
962
|
* this package, so neither can be a static import.
|
|
1038
963
|
*/
|
|
1039
|
-
|
|
1040
|
-
const module =
|
|
964
|
+
const loadWalkerModule = (specifier, fileName, cause) => Effect.gen(function* () {
|
|
965
|
+
const module = yield* Effect.promise(() => import(specifier));
|
|
1041
966
|
const walk = Match.value(module).pipe(Match.when(isRecordWithWalk, (record) => record.walk), Match.orElse(() => void 0));
|
|
1042
|
-
if (walk === void 0)
|
|
967
|
+
if (walk === void 0) return yield* SvelteWalkerNotFound.make({
|
|
1043
968
|
fileName,
|
|
1044
969
|
cause
|
|
1045
970
|
});
|
|
1046
971
|
return walk;
|
|
1047
|
-
}
|
|
1048
|
-
|
|
1049
|
-
const { parse: svelteParse, preprocess, VERSION } =
|
|
1050
|
-
if (!isAtLeast(VERSION, MINIMUM_SVELTE_VERSION))
|
|
972
|
+
});
|
|
973
|
+
const parseSvelte = (text, fileName, context) => Effect.gen(function* () {
|
|
974
|
+
const { parse: svelteParse, preprocess, VERSION } = yield* Effect.promise(() => import("svelte/compiler"));
|
|
975
|
+
if (!isAtLeast(VERSION, MINIMUM_SVELTE_VERSION)) return yield* SvelteVersionNotSupported.make({
|
|
1051
976
|
version: VERSION,
|
|
1052
977
|
fileName,
|
|
1053
978
|
cause: `Expected >=3.30`
|
|
1054
979
|
});
|
|
1055
|
-
const walk =
|
|
980
|
+
const walk = yield* loadWalker(VERSION, fileName);
|
|
1056
981
|
const lineStarts = computeLineStarts(text);
|
|
1057
|
-
const { replacedCode, scriptMap } =
|
|
982
|
+
const { replacedCode, scriptMap } = yield* replaceScripts(text, preprocess);
|
|
1058
983
|
const svelteAst = svelteParse(replacedCode, { filename: fileName });
|
|
1059
984
|
const { remappedModuleScriptRange, remappedScriptRanges } = remapScriptLocations(replacedCode, scriptMap, getModuleScriptRange(svelteAst), getTemplateScriptRanges(svelteAst, walk));
|
|
1060
|
-
const [moduleScript, ...additionalScripts] = await Promise.all([parseTemplateScriptIfDefined(remappedModuleScriptRange), ...remappedScriptRanges.map(parseTemplateScript)]);
|
|
1061
985
|
return {
|
|
1062
986
|
originFileName: fileName,
|
|
1063
987
|
rawContent: text,
|
|
1064
988
|
format: "svelte",
|
|
1065
|
-
root: svelteRoot(
|
|
989
|
+
root: svelteRoot(yield* parseTemplateScriptIfDefined(remappedModuleScriptRange, context, text, fileName, lineStarts), yield* Effect.forEach(remappedScriptRanges, (range) => parseTemplateScript(range, context, text, fileName, lineStarts)))
|
|
1066
990
|
};
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
const map = /* @__PURE__ */ new Map();
|
|
1073
|
-
let scriptIndex = 0;
|
|
991
|
+
});
|
|
992
|
+
const replaceScripts = (code, preprocess) => {
|
|
993
|
+
const map = /* @__PURE__ */ new Map();
|
|
994
|
+
let scriptIndex = 0;
|
|
995
|
+
return Effect.gen(function* () {
|
|
1074
996
|
return {
|
|
1075
|
-
replacedCode: (
|
|
997
|
+
replacedCode: (yield* Effect.promise(() => preprocess(code, { script(script) {
|
|
1076
998
|
const scriptName = `script${scriptIndex++}`;
|
|
1077
999
|
map.set(scriptName, script);
|
|
1078
1000
|
return { code: scriptName };
|
|
1079
|
-
} })).code,
|
|
1001
|
+
} }))).code,
|
|
1080
1002
|
scriptMap: map
|
|
1081
1003
|
};
|
|
1082
|
-
}
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
}
|
|
1100
|
-
}
|
|
1004
|
+
});
|
|
1005
|
+
};
|
|
1006
|
+
const parseTemplateScriptIfDefined = (range, context, text, fileName, lineStarts) => Effect.gen(function* () {
|
|
1007
|
+
if (range === void 0) return;
|
|
1008
|
+
return yield* parseTemplateScript(range, context, text, fileName, lineStarts);
|
|
1009
|
+
});
|
|
1010
|
+
const parseTemplateScript = ({ start, end, isExpression, format }, context, text, fileName, lineStarts) => Effect.map(context.parse(text.slice(start, end), fileName, format), (parsed) => ({
|
|
1011
|
+
ast: {
|
|
1012
|
+
...parsed,
|
|
1013
|
+
offset: positionFromOffset(lineStarts, start)
|
|
1014
|
+
},
|
|
1015
|
+
range: {
|
|
1016
|
+
start,
|
|
1017
|
+
end
|
|
1018
|
+
},
|
|
1019
|
+
isExpression
|
|
1020
|
+
}));
|
|
1101
1021
|
function svelteRoot(moduleScript, additionalScripts) {
|
|
1102
1022
|
return Match.value(moduleScript).pipe(Match.when(void 0, () => ({ additionalScripts })), Match.orElse((script) => ({
|
|
1103
1023
|
moduleScript: script,
|
|
@@ -1723,15 +1643,15 @@ var PrintState = class {
|
|
|
1723
1643
|
case "accessor":
|
|
1724
1644
|
this.out += `${fields.kind} `;
|
|
1725
1645
|
this.out += this.propertyKeyText(fields.key, fields.computed === true, PREC.Assignment);
|
|
1726
|
-
this.
|
|
1646
|
+
this.printFunctionTail(fields.value);
|
|
1727
1647
|
break;
|
|
1728
1648
|
case "method":
|
|
1729
1649
|
this.out += `${flagText(fields.async, "async ")}${flagText(fields.generator, "*")}`;
|
|
1730
1650
|
this.out += this.propertyKeyText(fields.key, fields.computed === true, PREC.Assignment);
|
|
1731
|
-
this.
|
|
1651
|
+
this.printFunctionTail(fields.value);
|
|
1732
1652
|
break;
|
|
1733
1653
|
case "shorthand":
|
|
1734
|
-
this.out += identifierName
|
|
1654
|
+
this.out += identifierName(fields.key);
|
|
1735
1655
|
break;
|
|
1736
1656
|
case "shorthandDefault":
|
|
1737
1657
|
this.printShorthandDefaultProperty(fields);
|
|
@@ -1744,7 +1664,7 @@ var PrintState = class {
|
|
|
1744
1664
|
}
|
|
1745
1665
|
printShorthandDefaultProperty(fields) {
|
|
1746
1666
|
const right = this.assignmentNodeText(fields.value.right);
|
|
1747
|
-
this.out += `${identifierName
|
|
1667
|
+
this.out += `${identifierName(fields.key)} = ${right}`;
|
|
1748
1668
|
}
|
|
1749
1669
|
propertyKeyText(key, computed, computedPrec) {
|
|
1750
1670
|
switch (computed) {
|
|
@@ -1763,10 +1683,6 @@ var PrintState = class {
|
|
|
1763
1683
|
printPropertyKeyForClass(key, computed) {
|
|
1764
1684
|
this.out += this.propertyKeyText(key, computed, PREC.Sequence);
|
|
1765
1685
|
}
|
|
1766
|
-
printFunctionValue(fn) {
|
|
1767
|
-
if (!fn) return;
|
|
1768
|
-
this.printFunctionTail(fn);
|
|
1769
|
-
}
|
|
1770
1686
|
printFunctionTail(fn) {
|
|
1771
1687
|
this.out += this.typeParametersText(fn.typeParameters);
|
|
1772
1688
|
this.out += `(${this.paramsText(fn.params)})`;
|
|
@@ -2222,13 +2138,16 @@ var PrintState = class {
|
|
|
2222
2138
|
}
|
|
2223
2139
|
}
|
|
2224
2140
|
printExpressionStatement(node) {
|
|
2225
|
-
if (node.directive) {
|
|
2141
|
+
if (this.isDirective(node.directive)) {
|
|
2226
2142
|
this.out += JSON.stringify(node.directive) + ";";
|
|
2227
2143
|
return;
|
|
2228
2144
|
}
|
|
2229
2145
|
this.printNode(node.expression, PREC.Sequence);
|
|
2230
2146
|
this.out += ";";
|
|
2231
2147
|
}
|
|
2148
|
+
isDirective(directive) {
|
|
2149
|
+
return directive != null && directive !== "";
|
|
2150
|
+
}
|
|
2232
2151
|
printIfStatement(node) {
|
|
2233
2152
|
this.out += "if (";
|
|
2234
2153
|
this.printNode(node.test, PREC.Sequence);
|
|
@@ -3092,12 +3011,12 @@ function propertyForm(fields) {
|
|
|
3092
3011
|
}
|
|
3093
3012
|
}
|
|
3094
3013
|
function isShorthandMatch(fields) {
|
|
3095
|
-
return fields.shorthand === true && namesMatch(identifierName
|
|
3014
|
+
return fields.shorthand === true && namesMatch(identifierName(fields.key), identifierName(fields.value));
|
|
3096
3015
|
}
|
|
3097
3016
|
function isShorthandDefaultMatch(fields) {
|
|
3098
|
-
return fields.shorthand === true && namesMatch(identifierName
|
|
3017
|
+
return fields.shorthand === true && namesMatch(identifierName(fields.key), defaultTargetName(fields.value));
|
|
3099
3018
|
}
|
|
3100
|
-
function identifierName
|
|
3019
|
+
function identifierName(node) {
|
|
3101
3020
|
switch (nodeKind(node)) {
|
|
3102
3021
|
case "Identifier": return node.name;
|
|
3103
3022
|
default: return;
|
|
@@ -3105,7 +3024,7 @@ function identifierName$1(node) {
|
|
|
3105
3024
|
}
|
|
3106
3025
|
function defaultTargetName(node) {
|
|
3107
3026
|
switch (nodeKind(node)) {
|
|
3108
|
-
case "AssignmentPattern": return identifierName
|
|
3027
|
+
case "AssignmentPattern": return identifierName(node.left);
|
|
3109
3028
|
default: return;
|
|
3110
3029
|
}
|
|
3111
3030
|
}
|
|
@@ -3374,12 +3293,8 @@ const hashbangOf = (root) => {
|
|
|
3374
3293
|
if (!isHashbang(hashbang)) return null;
|
|
3375
3294
|
return hashbang;
|
|
3376
3295
|
};
|
|
3377
|
-
const jsPrint = (file) => {
|
|
3378
|
-
|
|
3379
|
-
};
|
|
3380
|
-
const tsPrint = (file) => {
|
|
3381
|
-
return printProgram(file.root, { hashbang: hashbangOf(file.root) });
|
|
3382
|
-
};
|
|
3296
|
+
const jsPrint = (file) => printProgram(file.root, { hashbang: hashbangOf(file.root) });
|
|
3297
|
+
const tsPrint = (file) => printProgram(file.root, { hashbang: hashbangOf(file.root) });
|
|
3383
3298
|
function getScriptStart$1(script) {
|
|
3384
3299
|
const span = spanOf(script.root);
|
|
3385
3300
|
if (span === void 0) throw new Error("Script AST root without start");
|
|
@@ -3437,7 +3352,7 @@ function appendStatement(state, script, rawContent, context) {
|
|
|
3437
3352
|
/**
|
|
3438
3353
|
* Node identity: same kind, same span. oxc nodes always carry a range
|
|
3439
3354
|
* (parsed with `range: true`), which is a stronger identity than the old
|
|
3440
|
-
*
|
|
3355
|
+
* line/column loc.
|
|
3441
3356
|
*/
|
|
3442
3357
|
function eqNode(a, b) {
|
|
3443
3358
|
const identity = nodeIdentity(a);
|
|
@@ -3738,7 +3653,13 @@ const arithmeticOperatorReplacements = Object.freeze({
|
|
|
3738
3653
|
const ARITHMETIC_OPERATOR_KEYS = Object.keys(arithmeticOperatorReplacements);
|
|
3739
3654
|
const arithmeticOperatorMutator = (node) => Match.value(node).pipe(Match.when(isArithmeticBinary, (binary) => [withOperator(binary, arithmeticOperatorReplacements[binary.operator])]), Match.orElse(() => NO_MUTANTS));
|
|
3740
3655
|
function isArithmeticBinary(node) {
|
|
3741
|
-
return node
|
|
3656
|
+
return isBinaryExpression(node) && isSupportedArithmeticOperator(node.operator, node);
|
|
3657
|
+
}
|
|
3658
|
+
function isBinaryExpression(node) {
|
|
3659
|
+
return node.type === "BinaryExpression" && !isPrivateInExpression(node);
|
|
3660
|
+
}
|
|
3661
|
+
function isPrivateInExpression(node) {
|
|
3662
|
+
return node.left.type === "PrivateIdentifier";
|
|
3742
3663
|
}
|
|
3743
3664
|
function isSupportedArithmeticOperator(operator, node) {
|
|
3744
3665
|
return ARITHMETIC_OPERATOR_KEYS.includes(operator) && !isStringConcatenation(node);
|
|
@@ -4085,7 +4006,7 @@ function methodExpressionReplacement(mutation) {
|
|
|
4085
4006
|
return Match.value(mutation.newName).pipe(Match.when(null, () => callExpression(cloneNode(mutation.callee.object), [], mutation.callee.optional === true)), Match.orElse((newName) => renamedMethodCall(mutation, newName)));
|
|
4086
4007
|
}
|
|
4087
4008
|
function renamedMethodCall(mutation, newName) {
|
|
4088
|
-
return callExpression(memberExpression(cloneNode(mutation.callee.object), identifier(newName),
|
|
4009
|
+
return callExpression(memberExpression(cloneNode(mutation.callee.object), identifier(newName), mutation.callee.optional === true), spreadFreeArguments(mutation.call.arguments), mutation.call.optional === true);
|
|
4089
4010
|
}
|
|
4090
4011
|
function spreadFreeArguments(args) {
|
|
4091
4012
|
return args.filter(isNotSpreadElement).map((argument) => cloneNode(argument));
|
|
@@ -4275,13 +4196,13 @@ const allMutators = Object.freeze({
|
|
|
4275
4196
|
UnaryOperator: unaryOperatorMutator,
|
|
4276
4197
|
UpdateOperator: updateOperatorMutator
|
|
4277
4198
|
});
|
|
4278
|
-
S.TaggedError("@systemfsoftware/stryker-js-instrumenter/PlacementFailed")("PlacementFailed", {
|
|
4199
|
+
S.TaggedError("@systemfsoftware/stryker-js-instrumenter/Transformer.schema/PlacementFailed")("PlacementFailed", {
|
|
4279
4200
|
fileName: S.String,
|
|
4280
4201
|
placerName: S.String,
|
|
4281
4202
|
mutantIds: S.Array(S.String),
|
|
4282
4203
|
cause: S.Defect()
|
|
4283
4204
|
});
|
|
4284
|
-
S.TaggedError("@systemfsoftware/stryker-js-instrumenter/TransformFailed")("TransformFailed", {
|
|
4205
|
+
S.TaggedError("@systemfsoftware/stryker-js-instrumenter/Transformer.schema/TransformFailed")("TransformFailed", {
|
|
4285
4206
|
fileName: S.String,
|
|
4286
4207
|
cause: S.Defect()
|
|
4287
4208
|
});
|
|
@@ -4390,32 +4311,10 @@ function mutatorWarning(directive, mutatorName, originFileName) {
|
|
|
4390
4311
|
onSome: (scope) => `${directive.type} ${scope}`
|
|
4391
4312
|
})}' directive. Mutator with name '${mutatorName}' not found. Directive found at: ${originFileName}:${loc.start.line}:${loc.start.column}.`;
|
|
4392
4313
|
}
|
|
4393
|
-
function
|
|
4394
|
-
|
|
4395
|
-
|
|
4396
|
-
|
|
4397
|
-
return {
|
|
4398
|
-
node: path.node,
|
|
4399
|
-
parentPath: parentResult,
|
|
4400
|
-
isObjectExpression() {
|
|
4401
|
-
return nodeType(node) === "ObjectExpression";
|
|
4402
|
-
},
|
|
4403
|
-
isCallExpression() {
|
|
4404
|
-
return nodeType(node) === "CallExpression";
|
|
4405
|
-
},
|
|
4406
|
-
isClassProperty() {
|
|
4407
|
-
return nodeType(node) === "PropertyDefinition";
|
|
4408
|
-
},
|
|
4409
|
-
isClassPrivateProperty() {
|
|
4410
|
-
return nodeType(node) === "PropertyDefinition" && nodeType(propertyKeyOf(node)) === "PrivateIdentifier";
|
|
4411
|
-
},
|
|
4412
|
-
isClassAccessorProperty() {
|
|
4413
|
-
return nodeType(node) === "AccessorProperty";
|
|
4414
|
-
}
|
|
4415
|
-
};
|
|
4416
|
-
}
|
|
4417
|
-
function propertyKeyOf(node) {
|
|
4418
|
-
return Option.getOrUndefined(Option.map(Option.filter(Option.some(node), Predicate.hasProperty("key")), (holder) => holder["key"]));
|
|
4314
|
+
function ancestorsOf(path) {
|
|
4315
|
+
const ancestors = [];
|
|
4316
|
+
for (let current = path.parentPath; current !== null; current = current.parentPath) ancestors.push(current.node);
|
|
4317
|
+
return ancestors;
|
|
4419
4318
|
}
|
|
4420
4319
|
function isTypeNode(path) {
|
|
4421
4320
|
return [
|
|
@@ -4475,27 +4374,35 @@ function nodeOfKind(mutant, node, isKind, kind) {
|
|
|
4475
4374
|
if (!isKind(node)) throw new Error(`Cannot place mutant ${mutant.id}: expected ${kind}, got ${node.type}`);
|
|
4476
4375
|
return node;
|
|
4477
4376
|
}
|
|
4478
|
-
function throwPlacementError(error, nodePath, placer, mutants, fileName, lineTable) {
|
|
4479
|
-
const message = `${placer.name} could not place mutants with type(s): "${
|
|
4480
|
-
const errorMessage = `${placementLocation(nodePath.node, fileName, lineTable)} ${message}. Either remove this file from the list of files to be mutated, or exclude the mutator (using
|
|
4377
|
+
function throwPlacementError(error, nodePath, placer, mutants, fileName, lineTable, basePath) {
|
|
4378
|
+
const message = `${placer.name} could not place mutants with type(s): "${placementListFormat.format(mutants.map((mutant) => mutant.mutatorName))}"`;
|
|
4379
|
+
const errorMessage = `${placementLocation(nodePath.node, fileName, lineTable, basePath)} ${message}. Either remove this file from the list of files to be mutated, or exclude the mutator (using \`mutator.excludedMutations\`). Original error: ${error.stack}`;
|
|
4481
4380
|
throw new Error(errorMessage);
|
|
4482
4381
|
}
|
|
4483
|
-
function placementLocation(node, fileName, lineTable) {
|
|
4484
|
-
const relativeFile =
|
|
4382
|
+
function placementLocation(node, fileName, lineTable, basePath) {
|
|
4383
|
+
const relativeFile = basePath === void 0 ? fileName : relativeTo(basePath, fileName);
|
|
4485
4384
|
const position = Option.map(Option.fromNullishOr(spanOf(node)), (span) => positionFromLineTable(span.start, lineTable));
|
|
4486
4385
|
return Option.match(position, {
|
|
4487
4386
|
onNone: () => `${relativeFile}:undefined:undefined`,
|
|
4488
4387
|
onSome: (at) => `${relativeFile}:${at.line}:${at.column}`
|
|
4489
4388
|
});
|
|
4490
4389
|
}
|
|
4390
|
+
const placementListFormat = new Intl.ListFormat("en");
|
|
4391
|
+
const normalizeSeparators = (value) => value.replace(/\\/g, "/");
|
|
4392
|
+
const withTrailingSlash = (basePath) => {
|
|
4393
|
+
const normalized = normalizeSeparators(basePath);
|
|
4394
|
+
return normalized.endsWith("/") ? normalized : `${normalized}/`;
|
|
4395
|
+
};
|
|
4396
|
+
const relativeTo = (basePath, fileName) => {
|
|
4397
|
+
const prefix = withTrailingSlash(basePath);
|
|
4398
|
+
const normalizedFile = normalizeSeparators(fileName);
|
|
4399
|
+
return normalizedFile.startsWith(prefix) ? normalizedFile.slice(prefix.length) : fileName;
|
|
4400
|
+
};
|
|
4491
4401
|
function classOrFunctionExpressionNamedIfNeeded(path) {
|
|
4492
4402
|
return Match.value(path.node).pipe(Match.when(isAnonymousFunctionOrClass, (node) => nameFromParent(path, node)), Match.orElse(() => void 0));
|
|
4493
4403
|
}
|
|
4494
4404
|
function nameFromParent(path, node) {
|
|
4495
|
-
return Match.value(path.parentPath?.node).pipe(Match.when({
|
|
4496
|
-
type: "VariableDeclarator",
|
|
4497
|
-
id: { type: "Identifier" }
|
|
4498
|
-
}, (declarator) => adoptIdentifier(node, declarator.id)), Match.when({
|
|
4405
|
+
return Match.value(path.parentPath?.node).pipe(Match.when(isVariableDeclarator, (declarator) => adoptDeclaredName(node, declarator)), Match.when({
|
|
4499
4406
|
type: "Property",
|
|
4500
4407
|
key: { type: "Identifier" }
|
|
4501
4408
|
}, () => namedPropertyValue(path, node)), Match.orElse(() => void 0));
|
|
@@ -4528,10 +4435,22 @@ function namedArrowExpression(node, identifier) {
|
|
|
4528
4435
|
return callExpression(arrowFunctionExpression([], blockStatement([variableDeclaration("const", [variableDeclarator(identifier, node)]), returnStatement(identifier)])), []);
|
|
4529
4436
|
}
|
|
4530
4437
|
function declaratorIdentifier(parentPath) {
|
|
4531
|
-
return Option.flatMap(Option.fromNullishOr(parentPath), (parent) => Match.value(parent.node).pipe(Match.when(
|
|
4532
|
-
|
|
4533
|
-
|
|
4534
|
-
|
|
4438
|
+
return Option.flatMap(Option.fromNullishOr(parentPath), (parent) => Match.value(parent.node).pipe(Match.when(isVariableDeclarator, (declarator) => declaredName(declarator)), Match.orElse(() => Option.none())));
|
|
4439
|
+
}
|
|
4440
|
+
function isVariableDeclarator(node) {
|
|
4441
|
+
return nodeType(node) === "VariableDeclarator";
|
|
4442
|
+
}
|
|
4443
|
+
function adoptDeclaredName(node, declarator) {
|
|
4444
|
+
return Option.match(declaredName(declarator), {
|
|
4445
|
+
onNone: () => void 0,
|
|
4446
|
+
onSome: (identifier) => adoptIdentifier(node, identifier)
|
|
4447
|
+
});
|
|
4448
|
+
}
|
|
4449
|
+
function declaredName(declarator) {
|
|
4450
|
+
return Match.value(declarator.id).pipe(Match.when(isIdentifierReference, (identifier) => Option.some(identifier)), Match.orElse(() => Option.none()));
|
|
4451
|
+
}
|
|
4452
|
+
function isIdentifierReference(node) {
|
|
4453
|
+
return nodeType(node) === "Identifier";
|
|
4535
4454
|
}
|
|
4536
4455
|
function nameIfAnonymous(path) {
|
|
4537
4456
|
return classOrFunctionExpressionNamedIfNeeded(path) ?? arrowNameOrNode(path);
|
|
@@ -4666,139 +4585,9 @@ const allMutantPlacers = Object.freeze([
|
|
|
4666
4585
|
}
|
|
4667
4586
|
}
|
|
4668
4587
|
]);
|
|
4669
|
-
|
|
4670
|
-
"input",
|
|
4671
|
-
"model",
|
|
4672
|
-
"output"
|
|
4673
|
-
]);
|
|
4674
|
-
const ANGULAR_SIGNAL_QUERY_FUNCTIONS = Object.freeze([
|
|
4675
|
-
"contentChild",
|
|
4676
|
-
"contentChildren",
|
|
4677
|
-
"viewChild",
|
|
4678
|
-
"viewChildren"
|
|
4679
|
-
]);
|
|
4680
|
-
const INPUT_MODEL_OUTPUT_CONFIG_MSG = "Angular signal based input, model and output functions configuration object cannot be mutated as that causes issues with the Angular compiler.";
|
|
4681
|
-
const SIGNAL_QUERY_OPTIONS_MSG = "Angular signal query options object cannot be mutated as that causes issues with the Angular compiler.";
|
|
4682
|
-
function shouldIgnore(path) {
|
|
4683
|
-
return Option.orElse(reasonAt(path), () => ancestorReason(path));
|
|
4684
|
-
}
|
|
4685
|
-
function reasonAt(path) {
|
|
4686
|
-
return Match.value(path).pipe(Match.when(isInputModelOrOutputConfigurationObject, () => Option.some(INPUT_MODEL_OUTPUT_CONFIG_MSG)), Match.when(isSignalQueryOptionsObject, () => Option.some(SIGNAL_QUERY_OPTIONS_MSG)), Match.orElse(() => Option.none()));
|
|
4687
|
-
}
|
|
4688
|
-
function ancestorReason(path) {
|
|
4689
|
-
return Option.flatMap(Option.fromNullishOr(path.parentPath), shouldIgnore);
|
|
4690
|
-
}
|
|
4691
|
-
const angularIgnorer = { shouldIgnore };
|
|
4692
|
-
function isClassFieldLike(path) {
|
|
4693
|
-
return CLASS_FIELD_KINDS.includes(nodeType(path.node) ?? "");
|
|
4694
|
-
}
|
|
4695
|
-
const CLASS_FIELD_KINDS = Object.freeze(["PropertyDefinition", "AccessorProperty"]);
|
|
4696
|
-
function isInputModelOrOutputConfigurationObject(path) {
|
|
4697
|
-
return Option.match(signalCallSiteOf(path, isPropertyDefinitionField), {
|
|
4698
|
-
onNone: () => false,
|
|
4699
|
-
onSome: (site) => isArgumentAt(site, signalIoArgumentIndex(site.callee))
|
|
4700
|
-
});
|
|
4701
|
-
}
|
|
4702
|
-
function isSignalQueryOptionsObject(path) {
|
|
4703
|
-
return Option.match(signalCallSiteOf(path, isClassFieldLike), {
|
|
4704
|
-
onNone: () => false,
|
|
4705
|
-
onSome: (site) => isSignalQueryCall(site.callee) && isArgumentAt(site, Option.some(1))
|
|
4706
|
-
});
|
|
4707
|
-
}
|
|
4708
|
-
function isPropertyDefinitionField(path) {
|
|
4709
|
-
return nodeType(path.node) === "PropertyDefinition";
|
|
4710
|
-
}
|
|
4711
|
-
/** The call that takes the object expression as an argument, when a field-like member owns it. */
|
|
4712
|
-
function signalCallSiteOf(path, ownsCallSite) {
|
|
4713
|
-
return Option.flatMap(ownedCallPath(path, ownsCallSite), (callPath) => Option.map(callArgumentsOf(callPath), (call) => ({
|
|
4714
|
-
...call,
|
|
4715
|
-
objectExpression: path
|
|
4716
|
-
})));
|
|
4717
|
-
}
|
|
4718
|
-
function ownedCallPath(path, ownsCallSite) {
|
|
4719
|
-
const argument = Option.filter(Option.some(path), (candidate) => isOwnedCallArgument(candidate, ownsCallSite));
|
|
4720
|
-
return Option.flatMap(argument, (candidate) => Option.fromNullishOr(candidate.parentPath));
|
|
4721
|
-
}
|
|
4722
|
-
function isOwnedCallArgument(path, ownsCallSite) {
|
|
4723
|
-
return isObjectArgumentOfCall(path) && ownsCallSiteOf(path, ownsCallSite);
|
|
4724
|
-
}
|
|
4725
|
-
function isObjectArgumentOfCall(path) {
|
|
4726
|
-
return nodeType(path.node) === "ObjectExpression" && parentIsCallExpression(path);
|
|
4727
|
-
}
|
|
4728
|
-
function parentIsCallExpression(path) {
|
|
4729
|
-
return nodeType(path.parentPath?.node) === "CallExpression";
|
|
4730
|
-
}
|
|
4731
|
-
function ownsCallSiteOf(path, ownsCallSite) {
|
|
4732
|
-
return Option.exists(Option.fromNullishOr(path.parentPath?.parentPath), ownsCallSite);
|
|
4733
|
-
}
|
|
4734
|
-
function callArgumentsOf(callPath) {
|
|
4735
|
-
return Option.flatMap(Option.filter(Option.some(callPath.node), hasCallShape), (call) => Option.map(argumentArrayOf(call["arguments"]), (args) => ({
|
|
4736
|
-
callee: call["callee"],
|
|
4737
|
-
args
|
|
4738
|
-
})));
|
|
4739
|
-
}
|
|
4740
|
-
function hasCallShape(callNode) {
|
|
4741
|
-
return Predicate.hasProperty(callNode, "callee") && Predicate.hasProperty(callNode, "arguments");
|
|
4742
|
-
}
|
|
4743
|
-
function argumentArrayOf(argument) {
|
|
4744
|
-
return Option.filter(Option.some(argument), isUnknownArray);
|
|
4745
|
-
}
|
|
4746
|
-
function isUnknownArray(value) {
|
|
4588
|
+
function isCommentArray(value) {
|
|
4747
4589
|
return Array.isArray(value);
|
|
4748
4590
|
}
|
|
4749
|
-
function signalIoArgumentIndex(callee) {
|
|
4750
|
-
return Match.value(callee).pipe(Match.when(isRequiredSignalIoCall, () => Option.some(0)), Match.when(isOutputCall, () => Option.some(0)), Match.when(isSignalIoCall, () => Option.some(1)), Match.orElse(() => Option.none()));
|
|
4751
|
-
}
|
|
4752
|
-
function isRequiredSignalIoCall(callee) {
|
|
4753
|
-
return isMemberExpressionWithIdentifier(callee, ANGULAR_SIGNAL_IO_FUNCTIONS, "required");
|
|
4754
|
-
}
|
|
4755
|
-
function isOutputCall(callee) {
|
|
4756
|
-
return isIdentifierWithName(callee, "output");
|
|
4757
|
-
}
|
|
4758
|
-
function isSignalIoCall(callee) {
|
|
4759
|
-
return isIdentifierIn(callee, ANGULAR_SIGNAL_IO_FUNCTIONS);
|
|
4760
|
-
}
|
|
4761
|
-
function isSignalQueryCall(callee) {
|
|
4762
|
-
return isIdentifierIn(callee, ANGULAR_SIGNAL_QUERY_FUNCTIONS) || isMemberExpressionWithIdentifier(callee, ANGULAR_SIGNAL_QUERY_FUNCTIONS, "required");
|
|
4763
|
-
}
|
|
4764
|
-
function isArgumentAt(site, index) {
|
|
4765
|
-
return Option.exists(index, (position) => site.args.length > position && site.args[position] === site.objectExpression.node);
|
|
4766
|
-
}
|
|
4767
|
-
function isIdentifierWithName(node, name) {
|
|
4768
|
-
return Option.contains(identifierName(node), name);
|
|
4769
|
-
}
|
|
4770
|
-
function isIdentifierIn(node, names) {
|
|
4771
|
-
return Option.exists(identifierName(node), (name) => names.includes(name));
|
|
4772
|
-
}
|
|
4773
|
-
function identifierName(node) {
|
|
4774
|
-
return Option.map(identifierNode(node), (identifier) => identifier.name);
|
|
4775
|
-
}
|
|
4776
|
-
function identifierNode(node) {
|
|
4777
|
-
return Option.filter(Option.some(node), isNamedIdentifier);
|
|
4778
|
-
}
|
|
4779
|
-
function isNamedIdentifier(node) {
|
|
4780
|
-
return hasNodeType(node, "Identifier") && isStringProperty(node, "name");
|
|
4781
|
-
}
|
|
4782
|
-
function hasNodeType(node, type) {
|
|
4783
|
-
return Predicate.hasProperty(node, "type") && node["type"] === type;
|
|
4784
|
-
}
|
|
4785
|
-
function isStringProperty(node, property) {
|
|
4786
|
-
return Predicate.hasProperty(node, property) && typeof node[property] === "string";
|
|
4787
|
-
}
|
|
4788
|
-
function isMemberExpressionWithIdentifier(node, objectNames, propertyName) {
|
|
4789
|
-
return Option.exists(memberPartsOf(node), (member) => isIdentifierIn(member.object, objectNames) && isIdentifierWithName(member.property, propertyName));
|
|
4790
|
-
}
|
|
4791
|
-
function memberPartsOf(node) {
|
|
4792
|
-
return Option.filter(Option.some(node), isMemberExpressionRecord);
|
|
4793
|
-
}
|
|
4794
|
-
function isMemberExpressionRecord(node) {
|
|
4795
|
-
return hasNodeType(node, "MemberExpression") && isPropertyBearing(node);
|
|
4796
|
-
}
|
|
4797
|
-
function isPropertyBearing(node) {
|
|
4798
|
-
return Predicate.hasProperty(node, "object") && Predicate.hasProperty(node, "property");
|
|
4799
|
-
}
|
|
4800
|
-
const strykerPlugins = [];
|
|
4801
|
-
const frameworkPluginsFileUrl = import.meta.url;
|
|
4802
4591
|
const INSTRUMENTATION_HEADER_SOURCE = `// @ts-nocheck
|
|
4803
4592
|
var ${STRYKER_NAMESPACE_HELPER} = function(){
|
|
4804
4593
|
var g = typeof globalThis === 'object' && globalThis && globalThis.Math === Math && globalThis || new Function("return this")();
|
|
@@ -4845,32 +4634,29 @@ var ${IS_MUTANT_ACTIVE_HELPER} = function(id) {
|
|
|
4845
4634
|
return isActive(id);
|
|
4846
4635
|
}`;
|
|
4847
4636
|
let instrumentationHeaderValue;
|
|
4848
|
-
const instrumentationHeader =
|
|
4637
|
+
const instrumentationHeader = Effect.gen(function* () {
|
|
4849
4638
|
if (instrumentationHeaderValue === void 0) {
|
|
4850
|
-
instrumentationHeaderValue = (
|
|
4639
|
+
instrumentationHeaderValue = (yield* parseWithOxc(INSTRUMENTATION_HEADER_SOURCE, "instrumenter-header.js", "js")).root.body;
|
|
4851
4640
|
deepFreeze(instrumentationHeaderValue);
|
|
4852
4641
|
}
|
|
4853
4642
|
return instrumentationHeaderValue;
|
|
4854
|
-
};
|
|
4855
|
-
|
|
4856
|
-
if (shouldPlaceHeader(mutantCollector, originFileName, options))
|
|
4857
|
-
}
|
|
4643
|
+
});
|
|
4644
|
+
const placeHeaderIfNeeded = (mutantCollector, originFileName, options, root) => Effect.gen(function* () {
|
|
4645
|
+
if (shouldPlaceHeader(mutantCollector, originFileName, options)) yield* placeHeader(root);
|
|
4646
|
+
});
|
|
4647
|
+
const placeHeader = (root) => Effect.map(headerFor(root), (header) => {
|
|
4648
|
+
root.body.unshift(...header);
|
|
4649
|
+
});
|
|
4858
4650
|
function shouldPlaceHeader(mutantCollector, originFileName, options) {
|
|
4859
4651
|
return hasPlacedMutants(mutantCollector, originFileName) && options.noHeader !== true;
|
|
4860
4652
|
}
|
|
4861
|
-
|
|
4862
|
-
|
|
4863
|
-
|
|
4864
|
-
|
|
4865
|
-
const header = await instrumentationHeader();
|
|
4866
|
-
return Option.match(leadingCommentsOf(root), {
|
|
4867
|
-
onNone: () => header,
|
|
4868
|
-
onSome: (leadingComments) => [commentedHeader(leadingComments, header), ...header.slice(1)]
|
|
4869
|
-
});
|
|
4870
|
-
}
|
|
4653
|
+
const headerFor = (root) => Effect.map(instrumentationHeader, (header) => Option.match(leadingCommentsOf(root), {
|
|
4654
|
+
onNone: () => header,
|
|
4655
|
+
onSome: (leadingComments) => [commentedHeader(leadingComments, header), ...header.slice(1)]
|
|
4656
|
+
}));
|
|
4871
4657
|
function leadingCommentsOf(root) {
|
|
4872
4658
|
const firstStatement = root.body[0];
|
|
4873
|
-
return Option.filter(Option.fromNullishOr(firstStatement?.leadingComments),
|
|
4659
|
+
return Option.filter(Option.fromNullishOr(firstStatement?.leadingComments), isCommentArray);
|
|
4874
4660
|
}
|
|
4875
4661
|
function commentedHeader(leadingComments, header) {
|
|
4876
4662
|
const cloned = cloneNode(Option.getOrThrowWith(Option.fromNullishOr(header[0]), () => /* @__PURE__ */ new Error("Instrumentation header is empty")));
|
|
@@ -4913,7 +4699,7 @@ function isMap(value) {
|
|
|
4913
4699
|
function isSet(value) {
|
|
4914
4700
|
return value instanceof Set;
|
|
4915
4701
|
}
|
|
4916
|
-
|
|
4702
|
+
const transform = (ast, mutantCollector, transformerContext) => {
|
|
4917
4703
|
const context = {
|
|
4918
4704
|
...transformerContext,
|
|
4919
4705
|
transform
|
|
@@ -4925,32 +4711,27 @@ async function transform(ast, mutantCollector, transformerContext) {
|
|
|
4925
4711
|
case "tsx": return transformScript(ast, mutantCollector, context);
|
|
4926
4712
|
case "svelte": return transformSvelte(ast, mutantCollector, context);
|
|
4927
4713
|
}
|
|
4928
|
-
}
|
|
4929
|
-
const transformHtml = async ({ root }, mutantCollector, context) => {
|
|
4930
|
-
const warnings = [];
|
|
4931
|
-
for (const script of root.scripts) warnings.push(...await context.transform(script, mutantCollector, context));
|
|
4932
|
-
return warnings;
|
|
4933
4714
|
};
|
|
4715
|
+
const transformHtml = ({ root }, mutantCollector, context) => Effect.map(Effect.forEach(root.scripts, (script) => context.transform(script, mutantCollector, context)), (perScript) => perScript.flat());
|
|
4934
4716
|
const moduleScript = `<script context="module">
|
|
4935
4717
|
\n<\/script>\n`;
|
|
4936
|
-
const transformSvelte =
|
|
4937
|
-
const warnings = [];
|
|
4718
|
+
const transformSvelte = (svelte, mutantCollector, context) => Effect.gen(function* () {
|
|
4938
4719
|
const { root } = svelte;
|
|
4939
4720
|
const scripts = [root.moduleScript, ...root.additionalScripts].filter(Predicate.isNotNullish);
|
|
4940
|
-
|
|
4721
|
+
const warnings = (yield* Effect.forEach(scripts, (script) => context.transform(script.ast, mutantCollector, {
|
|
4941
4722
|
...context,
|
|
4942
4723
|
options: {
|
|
4943
4724
|
...context.options,
|
|
4944
4725
|
noHeader: true
|
|
4945
4726
|
}
|
|
4946
|
-
}));
|
|
4947
|
-
|
|
4727
|
+
}))).flat();
|
|
4728
|
+
yield* placeModuleHeaderIfNeeded(svelte, mutantCollector);
|
|
4948
4729
|
return warnings;
|
|
4949
|
-
};
|
|
4950
|
-
|
|
4951
|
-
if (hasPlacedMutants(mutantCollector, svelte.originFileName))
|
|
4952
|
-
}
|
|
4953
|
-
|
|
4730
|
+
});
|
|
4731
|
+
const placeModuleHeaderIfNeeded = (svelte, mutantCollector) => Effect.gen(function* () {
|
|
4732
|
+
if (hasPlacedMutants(mutantCollector, svelte.originFileName)) yield* placeModuleHeader(svelte);
|
|
4733
|
+
});
|
|
4734
|
+
const placeModuleHeader = (svelte) => Effect.gen(function* () {
|
|
4954
4735
|
const { root, originFileName } = svelte;
|
|
4955
4736
|
if (!root.moduleScript) {
|
|
4956
4737
|
root.moduleScript = {
|
|
@@ -4973,162 +4754,161 @@ async function placeModuleHeader(svelte) {
|
|
|
4973
4754
|
script.range.end += moduleScript.length;
|
|
4974
4755
|
});
|
|
4975
4756
|
}
|
|
4976
|
-
|
|
4977
|
-
}
|
|
4757
|
+
yield* placeHeader(root.moduleScript.ast.root);
|
|
4758
|
+
});
|
|
4978
4759
|
function emptyProgram() {
|
|
4979
4760
|
return {
|
|
4980
4761
|
type: "Program",
|
|
4981
4762
|
sourceType: "module",
|
|
4982
|
-
body: []
|
|
4763
|
+
body: [],
|
|
4764
|
+
hashbang: null
|
|
4983
4765
|
};
|
|
4984
4766
|
}
|
|
4767
|
+
const emptyAppliedMutants = () => /* @__PURE__ */ new Map();
|
|
4985
4768
|
function isMutateRangeList(value) {
|
|
4986
4769
|
return Array.isArray(value);
|
|
4987
4770
|
}
|
|
4988
|
-
const transformScript =
|
|
4989
|
-
const lineTable = buildLineTable(rawContent);
|
|
4990
|
-
attachComments(root, comments, lineTable);
|
|
4771
|
+
const transformScript = ({ root, originFileName, rawContent, offset, comments }, mutantCollector, { options, mutateDescription, basePath }, mutators, mutantPlacers) => {
|
|
4991
4772
|
const placementMap = /* @__PURE__ */ new Map();
|
|
4992
|
-
|
|
4993
|
-
|
|
4994
|
-
|
|
4995
|
-
|
|
4996
|
-
|
|
4997
|
-
|
|
4998
|
-
|
|
4999
|
-
|
|
5000
|
-
|
|
5001
|
-
|
|
5002
|
-
|
|
5003
|
-
|
|
5004
|
-
|
|
5005
|
-
|
|
5006
|
-
|
|
4773
|
+
return Effect.gen(function* () {
|
|
4774
|
+
const lineTable = buildLineTable(rawContent);
|
|
4775
|
+
attachComments(root, comments, lineTable);
|
|
4776
|
+
let directiveRule = rootRule;
|
|
4777
|
+
const mutatorEntries = Object.entries(Option.getOrElse(Option.fromNullishOr(mutators), () => allMutators));
|
|
4778
|
+
const placers = Option.getOrElse(Option.fromNullishOr(mutantPlacers), () => allMutantPlacers);
|
|
4779
|
+
const allMutatorNames = mutatorEntries.map(([name]) => name.toLowerCase());
|
|
4780
|
+
const warnings = [];
|
|
4781
|
+
traverse(root, {
|
|
4782
|
+
enter(path) {
|
|
4783
|
+
const result = processStrykerDirectives(directiveRule, path.node, allMutatorNames, originFileName);
|
|
4784
|
+
directiveRule = result.rule;
|
|
4785
|
+
warnings.push(...result.warnings);
|
|
4786
|
+
visitNode(path);
|
|
4787
|
+
},
|
|
4788
|
+
exit(path) {
|
|
4789
|
+
const placement = placementMap.get(path.node);
|
|
4790
|
+
if (hasAppliedMutants(placement)) applyPlacement(path, placement);
|
|
4791
|
+
}
|
|
4792
|
+
});
|
|
4793
|
+
yield* placeHeaderIfNeeded(mutantCollector, originFileName, options, root);
|
|
4794
|
+
return warnings;
|
|
4795
|
+
function visitNode(path) {
|
|
4796
|
+
if (shouldSkip(path)) {
|
|
4797
|
+
path.skip();
|
|
4798
|
+
return;
|
|
4799
|
+
}
|
|
4800
|
+
addToPlacementMapIfPossible(path);
|
|
4801
|
+
placeCollectedMutantsIfMutating(path);
|
|
5007
4802
|
}
|
|
5008
|
-
|
|
5009
|
-
|
|
5010
|
-
|
|
5011
|
-
|
|
5012
|
-
|
|
5013
|
-
|
|
5014
|
-
return;
|
|
4803
|
+
function addToPlacementMapIfPossible(path) {
|
|
4804
|
+
const placer = placers.find((candidate) => candidate.canPlace(path));
|
|
4805
|
+
if (placer !== void 0) placementMap.set(path.node, {
|
|
4806
|
+
appliedMutants: emptyAppliedMutants(),
|
|
4807
|
+
placer
|
|
4808
|
+
});
|
|
5015
4809
|
}
|
|
5016
|
-
|
|
5017
|
-
|
|
5018
|
-
}
|
|
5019
|
-
function addToPlacementMapIfPossible(path) {
|
|
5020
|
-
const placer = placers.find((candidate) => candidate.canPlace(path));
|
|
5021
|
-
if (placer !== void 0) placementMap.set(path.node, {
|
|
5022
|
-
appliedMutants: /* @__PURE__ */ new Map(),
|
|
5023
|
-
placer
|
|
5024
|
-
});
|
|
5025
|
-
}
|
|
5026
|
-
function hasAppliedMutants(placement) {
|
|
5027
|
-
return placement !== void 0 && placement.appliedMutants.size > 0;
|
|
5028
|
-
}
|
|
5029
|
-
function applyPlacement(path, placement) {
|
|
5030
|
-
try {
|
|
5031
|
-
placement.placer.place(path, placement.appliedMutants);
|
|
5032
|
-
path.skip();
|
|
5033
|
-
} catch (error) {
|
|
5034
|
-
throwPlacementError(toError(error), path, placement.placer, [...placement.appliedMutants.keys()], originFileName, lineTable);
|
|
4810
|
+
function hasAppliedMutants(placement) {
|
|
4811
|
+
return placement !== void 0 && placement.appliedMutants.size > 0;
|
|
5035
4812
|
}
|
|
5036
|
-
|
|
5037
|
-
|
|
5038
|
-
|
|
5039
|
-
|
|
5040
|
-
|
|
5041
|
-
|
|
5042
|
-
|
|
5043
|
-
|
|
5044
|
-
|
|
5045
|
-
|
|
5046
|
-
|
|
5047
|
-
|
|
5048
|
-
|
|
5049
|
-
|
|
5050
|
-
|
|
5051
|
-
|
|
5052
|
-
|
|
5053
|
-
|
|
5054
|
-
|
|
5055
|
-
|
|
5056
|
-
|
|
5057
|
-
|
|
5058
|
-
|
|
5059
|
-
|
|
5060
|
-
|
|
5061
|
-
|
|
5062
|
-
|
|
5063
|
-
|
|
5064
|
-
|
|
5065
|
-
|
|
5066
|
-
|
|
5067
|
-
|
|
5068
|
-
|
|
5069
|
-
|
|
5070
|
-
|
|
5071
|
-
|
|
5072
|
-
|
|
5073
|
-
|
|
5074
|
-
|
|
5075
|
-
|
|
5076
|
-
|
|
5077
|
-
|
|
5078
|
-
|
|
5079
|
-
|
|
5080
|
-
|
|
5081
|
-
|
|
5082
|
-
|
|
5083
|
-
|
|
5084
|
-
|
|
5085
|
-
}
|
|
5086
|
-
|
|
5087
|
-
|
|
5088
|
-
|
|
5089
|
-
|
|
5090
|
-
|
|
5091
|
-
|
|
5092
|
-
|
|
5093
|
-
|
|
5094
|
-
|
|
5095
|
-
|
|
5096
|
-
|
|
5097
|
-
|
|
5098
|
-
|
|
5099
|
-
|
|
5100
|
-
|
|
5101
|
-
|
|
5102
|
-
|
|
5103
|
-
|
|
5104
|
-
|
|
5105
|
-
|
|
5106
|
-
|
|
5107
|
-
|
|
5108
|
-
|
|
5109
|
-
|
|
5110
|
-
|
|
5111
|
-
|
|
5112
|
-
|
|
5113
|
-
|
|
5114
|
-
|
|
5115
|
-
|
|
5116
|
-
|
|
5117
|
-
|
|
5118
|
-
|
|
5119
|
-
|
|
4813
|
+
function applyPlacement(path, placement) {
|
|
4814
|
+
try {
|
|
4815
|
+
placement.placer.place(path, placement.appliedMutants);
|
|
4816
|
+
path.skip();
|
|
4817
|
+
} catch (error) {
|
|
4818
|
+
throwPlacementError(toError(error), path, placement.placer, [...placement.appliedMutants.keys()], originFileName, lineTable, basePath);
|
|
4819
|
+
}
|
|
4820
|
+
}
|
|
4821
|
+
function placeCollectedMutantsIfMutating(path) {
|
|
4822
|
+
if (shouldMutate(path)) placeCollectedMutants(path);
|
|
4823
|
+
}
|
|
4824
|
+
function placeCollectedMutants(path) {
|
|
4825
|
+
const mutantsToPlace = collectMutants(path);
|
|
4826
|
+
if (mutantsToPlace.length === 0) return;
|
|
4827
|
+
const placementPath = requiredPlacementPath(path, mutantsToPlace);
|
|
4828
|
+
const placement = requiredPlacement(placementPath.node);
|
|
4829
|
+
mutantsToPlace.forEach((mutant) => {
|
|
4830
|
+
placement.appliedMutants.set(mutant, applyMutant(mutant, placementPath.node));
|
|
4831
|
+
});
|
|
4832
|
+
}
|
|
4833
|
+
function requiredPlacementPath(path, mutantsToPlace) {
|
|
4834
|
+
return Option.getOrThrowWith(Option.fromNullishOr(path.find((ancestor) => placementMap.has(ancestor.node))), () => unplacedMutantsError(mutantsToPlace));
|
|
4835
|
+
}
|
|
4836
|
+
function unplacedMutantsError(mutantsToPlace) {
|
|
4837
|
+
return /* @__PURE__ */ new Error(`Mutants cannot be placed. This shouldn't happen! Unplaced mutants: ${JSON.stringify(mutantsToPlace, null, 2)}`);
|
|
4838
|
+
}
|
|
4839
|
+
function requiredPlacement(node) {
|
|
4840
|
+
return Option.getOrThrowWith(Option.fromNullishOr(placementMap.get(node)), () => /* @__PURE__ */ new Error("Placement not found for node"));
|
|
4841
|
+
}
|
|
4842
|
+
function shouldSkip(path) {
|
|
4843
|
+
return [
|
|
4844
|
+
isTypeNode(path),
|
|
4845
|
+
isImportDeclaration(path),
|
|
4846
|
+
nodeType(path.node) === "Decorator",
|
|
4847
|
+
mutateDescription === false,
|
|
4848
|
+
isOutsideMutateRanges(path)
|
|
4849
|
+
].some((skip) => skip);
|
|
4850
|
+
}
|
|
4851
|
+
function mutateRanges() {
|
|
4852
|
+
return Option.filter(Option.some(mutateDescription), isMutateRangeList);
|
|
4853
|
+
}
|
|
4854
|
+
function isOutsideMutateRanges(path) {
|
|
4855
|
+
return Option.exists(mutateRanges(), (ranges) => ranges.every((range) => !locationOverlaps(range, getNodeLocation(path.node))));
|
|
4856
|
+
}
|
|
4857
|
+
function shouldMutate(path) {
|
|
4858
|
+
return mutateDescription === true || isInsideMutateRanges(path);
|
|
4859
|
+
}
|
|
4860
|
+
function isInsideMutateRanges(path) {
|
|
4861
|
+
return Option.exists(mutateRanges(), (ranges) => ranges.some((range) => locationIncluded(range, getNodeLocation(path.node))));
|
|
4862
|
+
}
|
|
4863
|
+
function getNodeLocation(node) {
|
|
4864
|
+
const span = spanOf(node);
|
|
4865
|
+
if (span === void 0) throw new Error("Node without a span");
|
|
4866
|
+
return {
|
|
4867
|
+
start: positionFromLineTable(span.start, lineTable),
|
|
4868
|
+
end: positionFromLineTable(span.end, lineTable)
|
|
4869
|
+
};
|
|
4870
|
+
}
|
|
4871
|
+
function ignoreMessageFor(node, ancestors) {
|
|
4872
|
+
return ignorerReason(node, ancestors);
|
|
4873
|
+
}
|
|
4874
|
+
function ignorerReason(node, ancestors) {
|
|
4875
|
+
return options.ignorers.map((ignorer) => ignorer.shouldIgnore(node, ancestors)).find((reason) => reason !== void 0);
|
|
4876
|
+
}
|
|
4877
|
+
function collectMutants(path) {
|
|
4878
|
+
return mutablesFor(path).map((mutable) => collect(mutantCollector, originFileName, path.node, mutable, offset, lineTable)).filter((mutant) => mutant.ignoreReason === void 0);
|
|
4879
|
+
}
|
|
4880
|
+
function mutablesFor(path) {
|
|
4881
|
+
const ancestors = ancestorsOf(path);
|
|
4882
|
+
const context = toMutatorContext(ancestors);
|
|
4883
|
+
const line = getNodeLocation(path.node).start.line;
|
|
4884
|
+
return mutatorEntries.flatMap(([mutatorName, mutate]) => [...mutate(path.node, context)].map((replacement) => mutableFor(path.node, ancestors, mutatorName, replacement, line)));
|
|
4885
|
+
}
|
|
4886
|
+
function mutableFor(node, ancestors, mutatorName, replacement, line) {
|
|
4887
|
+
const mutableEntry = {
|
|
4888
|
+
replacement,
|
|
4889
|
+
mutatorName
|
|
4890
|
+
};
|
|
4891
|
+
const ignoreReason = ignoreReasonFor(node, ancestors, mutatorName, line);
|
|
4892
|
+
if (ignoreReason !== void 0) mutableEntry.ignoreReason = ignoreReason;
|
|
4893
|
+
return mutableEntry;
|
|
4894
|
+
}
|
|
4895
|
+
function ignoreReasonFor(node, ancestors, mutatorName, line) {
|
|
4896
|
+
return directiveOrExclusion(mutatorName, line) ?? ignoreMessageFor(node, ancestors);
|
|
4897
|
+
}
|
|
4898
|
+
function directiveOrExclusion(mutatorName, line) {
|
|
4899
|
+
return findIgnoreReason(directiveRule, mutatorName, line) ?? findExcludedMutatorIgnoreReason(mutatorName);
|
|
4900
|
+
}
|
|
4901
|
+
function findExcludedMutatorIgnoreReason(mutatorName) {
|
|
4902
|
+
if (options.excludedMutations.includes(mutatorName)) return `Ignored because of excluded mutation "${mutatorName}"`;
|
|
4903
|
+
else return;
|
|
4904
|
+
}
|
|
4905
|
+
});
|
|
5120
4906
|
};
|
|
5121
|
-
function toMutatorContext(
|
|
5122
|
-
const ancestors = [];
|
|
5123
|
-
let current = path.parentPath;
|
|
5124
|
-
while (current !== null) {
|
|
5125
|
-
ancestors.push(current.node);
|
|
5126
|
-
current = current.parentPath;
|
|
5127
|
-
}
|
|
4907
|
+
function toMutatorContext(ancestors) {
|
|
5128
4908
|
return {
|
|
5129
4909
|
parent: ancestors[0],
|
|
5130
4910
|
grandParent: ancestors[1],
|
|
5131
|
-
ancestors
|
|
4911
|
+
ancestors: [...ancestors]
|
|
5132
4912
|
};
|
|
5133
4913
|
}
|
|
5134
4914
|
function toError(value) {
|
|
@@ -5140,18 +4920,22 @@ function toError(value) {
|
|
|
5140
4920
|
const commentDirectiveRegEx = /^(\s*)@(ts-[a-z-]+).*$/;
|
|
5141
4921
|
const tsDirectiveLikeRegEx = /@(ts-[a-z-]+)/;
|
|
5142
4922
|
const STARTING_COMMENT = /^\s*\/\*[\s\S]*?\*\//;
|
|
5143
|
-
|
|
4923
|
+
const disableTypeChecks = (file) => {
|
|
5144
4924
|
const format = getFormat(file.name);
|
|
5145
|
-
if (format === void 0) return file;
|
|
4925
|
+
if (format === void 0) return Effect.succeed(file);
|
|
5146
4926
|
return disableTypeChecksFor(file, format);
|
|
5147
|
-
}
|
|
5148
|
-
|
|
5149
|
-
if (isJSFileWithoutTSDirectives(file, format)) return {
|
|
4927
|
+
};
|
|
4928
|
+
const disableTypeChecksFor = (file, format) => {
|
|
4929
|
+
if (isJSFileWithoutTSDirectives(file, format)) return Effect.succeed({
|
|
5150
4930
|
...file,
|
|
5151
4931
|
content: prefixWithNoCheck(file.content)
|
|
5152
|
-
};
|
|
5153
|
-
|
|
5154
|
-
|
|
4932
|
+
});
|
|
4933
|
+
const parse = createParser();
|
|
4934
|
+
return Effect.map(parse(file.content, file.name).pipe(Effect.mapError((cause) => InstrumentError.make({
|
|
4935
|
+
message: `Failed to parse ${file.name}`,
|
|
4936
|
+
cause
|
|
4937
|
+
}))), (ast) => withDisabledTypeChecking(file, ast));
|
|
4938
|
+
};
|
|
5155
4939
|
function withDisabledTypeChecking(file, ast) {
|
|
5156
4940
|
switch (ast.format) {
|
|
5157
4941
|
case "js":
|
|
@@ -5276,13 +5060,13 @@ function toOneBasedLineNumber(range) {
|
|
|
5276
5060
|
}
|
|
5277
5061
|
}));
|
|
5278
5062
|
}
|
|
5279
|
-
function
|
|
5063
|
+
function isIgnorer(value) {
|
|
5280
5064
|
return Predicate.isObject(value) && typeof value["shouldIgnore"] === "function";
|
|
5281
5065
|
}
|
|
5282
5066
|
function toTransformerOptions(options) {
|
|
5283
5067
|
const base = {
|
|
5284
5068
|
excludedMutations: [...options.excludedMutations],
|
|
5285
|
-
ignorers: options.ignorers.filter(
|
|
5069
|
+
ignorers: options.ignorers.filter(isIgnorer)
|
|
5286
5070
|
};
|
|
5287
5071
|
if (options.noHeader !== void 0) return {
|
|
5288
5072
|
...base,
|
|
@@ -5294,54 +5078,6 @@ const AST_SHAPE = ["format", "root"];
|
|
|
5294
5078
|
function isAst(value) {
|
|
5295
5079
|
return Predicate.isObject(value) && AST_SHAPE.every((key) => key in value);
|
|
5296
5080
|
}
|
|
5297
|
-
const readCollected = (command) => Effect.gen(function* () {
|
|
5298
|
-
const { files, options } = command;
|
|
5299
|
-
const parse = createParser();
|
|
5300
|
-
const parsed = yield* Effect.forEach(files, (file) => Effect.map(Effect.tryPromise({
|
|
5301
|
-
try: () => parse(file.content, file.name),
|
|
5302
|
-
catch: (cause) => new InstrumentError({
|
|
5303
|
-
message: `Failed to parse ${file.name}`,
|
|
5304
|
-
cause
|
|
5305
|
-
})
|
|
5306
|
-
}), (ast) => ({
|
|
5307
|
-
file,
|
|
5308
|
-
ast
|
|
5309
|
-
})));
|
|
5310
|
-
const collector = createMutantCollector();
|
|
5311
|
-
yield* Effect.forEach(parsed, ({ file, ast }) => Effect.tryPromise({
|
|
5312
|
-
try: () => transform(ast, collector, {
|
|
5313
|
-
options: toTransformerOptions(options),
|
|
5314
|
-
mutateDescription: toOneBasedLineNumber(file.mutate)
|
|
5315
|
-
}),
|
|
5316
|
-
catch: (cause) => new InstrumentError({
|
|
5317
|
-
message: `Failed to transform ${file.name}`,
|
|
5318
|
-
cause
|
|
5319
|
-
})
|
|
5320
|
-
}));
|
|
5321
|
-
const mutants = yield* Effect.try({
|
|
5322
|
-
try: () => collector.map(toApiMutant),
|
|
5323
|
-
catch: (cause) => new InstrumentError({
|
|
5324
|
-
message: "Failed to instrument",
|
|
5325
|
-
cause
|
|
5326
|
-
})
|
|
5327
|
-
});
|
|
5328
|
-
return {
|
|
5329
|
-
files,
|
|
5330
|
-
options,
|
|
5331
|
-
asts: parsed.map(({ ast }) => ast),
|
|
5332
|
-
mutants
|
|
5333
|
-
};
|
|
5334
|
-
});
|
|
5335
|
-
const printDecision = (decision) => Effect.try({
|
|
5336
|
-
try: () => InstrumentResult.make({
|
|
5337
|
-
files: decision.files.flatMap((file, index) => printedFile(file, decision.asts[index])),
|
|
5338
|
-
mutants: decision.mutants
|
|
5339
|
-
}),
|
|
5340
|
-
catch: (cause) => new InstrumentError({
|
|
5341
|
-
message: "Failed to print",
|
|
5342
|
-
cause
|
|
5343
|
-
})
|
|
5344
|
-
});
|
|
5345
5081
|
function printedFile(file, ast) {
|
|
5346
5082
|
if (!isAst(ast)) return [];
|
|
5347
5083
|
return [{
|
|
@@ -5350,28 +5086,47 @@ function printedFile(file, ast) {
|
|
|
5350
5086
|
content: print(ast)
|
|
5351
5087
|
}];
|
|
5352
5088
|
}
|
|
5353
|
-
const
|
|
5354
|
-
files: decoded.files,
|
|
5355
|
-
mutants: decoded.mutants,
|
|
5356
|
-
asts: decoded.asts
|
|
5357
|
-
});
|
|
5358
|
-
const instrument = (files, options) => Effect.gen(function* () {
|
|
5089
|
+
const instrument = (files, options, basePath) => Effect.gen(function* () {
|
|
5359
5090
|
const schemaFiles = files.map((file) => ({
|
|
5360
5091
|
name: file.name,
|
|
5361
5092
|
content: file.content,
|
|
5362
5093
|
mutate: file.mutate
|
|
5363
5094
|
}));
|
|
5364
|
-
const
|
|
5365
|
-
|
|
5366
|
-
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
|
|
5371
|
-
|
|
5372
|
-
|
|
5373
|
-
})
|
|
5374
|
-
|
|
5095
|
+
const parse = createParser();
|
|
5096
|
+
const parsed = yield* Effect.forEach(schemaFiles, (file) => Effect.map(parse(file.content, file.name).pipe(Effect.mapError((cause) => InstrumentError.make({
|
|
5097
|
+
message: `Failed to parse ${file.name}`,
|
|
5098
|
+
cause
|
|
5099
|
+
}))), (ast) => ({
|
|
5100
|
+
file,
|
|
5101
|
+
ast
|
|
5102
|
+
})));
|
|
5103
|
+
const collector = createMutantCollector();
|
|
5104
|
+
yield* Effect.forEach(parsed, ({ file, ast }) => transform(ast, collector, {
|
|
5105
|
+
options: toTransformerOptions(options),
|
|
5106
|
+
mutateDescription: toOneBasedLineNumber(file.mutate),
|
|
5107
|
+
basePath
|
|
5108
|
+
}).pipe(Effect.mapError((cause) => InstrumentError.make({
|
|
5109
|
+
message: `Failed to transform ${file.name}`,
|
|
5110
|
+
cause
|
|
5111
|
+
}))));
|
|
5112
|
+
const mutants = yield* Effect.try({
|
|
5113
|
+
try: () => collector.map(toApiMutant),
|
|
5114
|
+
catch: (cause) => InstrumentError.make({
|
|
5115
|
+
message: "Failed to instrument",
|
|
5116
|
+
cause
|
|
5117
|
+
})
|
|
5118
|
+
});
|
|
5119
|
+
const printed = yield* Effect.try({
|
|
5120
|
+
try: () => parsed.flatMap(({ file, ast }) => printedFile(file, ast)),
|
|
5121
|
+
catch: (cause) => InstrumentError.make({
|
|
5122
|
+
message: "Failed to print",
|
|
5123
|
+
cause
|
|
5124
|
+
})
|
|
5125
|
+
});
|
|
5126
|
+
return InstrumentResult.make({
|
|
5127
|
+
files: printed,
|
|
5128
|
+
mutants
|
|
5129
|
+
});
|
|
5375
5130
|
});
|
|
5376
5131
|
//#endregion
|
|
5377
|
-
export {
|
|
5132
|
+
export { ERROR_CODES, INSTRUMENTER_CONSTANTS, InstrumenterOptionsSchema, LocationSchema, Mutant, MutantActivationSchema, MutantRunOptionsSchema, MutantStatusSchema, OpenEndLocationSchema, PositionSchema, RunOptionsFields, causeText, disableTypeChecks, errorToString, instrument, isErrnoException, isMutant, normalizeFileName };
|