@systemfsoftware/stryker-js-instrumenter 2.0.1 → 3.0.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/dist/index.mjs CHANGED
@@ -1,5 +1,3 @@
1
- import babel, { File } from "@babel/core";
2
- import generator from "@babel/generator";
3
1
  import { Cell, Wire, Workflow } from "@systemfsoftware/effect-cell-types";
4
2
  import { INSTRUMENTER_CONSTANTS, Mutant } from "@systemfsoftware/stryker-js/Mutant";
5
3
  import * as Effect from "effect/Effect";
@@ -7,7 +5,7 @@ import { pipe } from "effect/Function";
7
5
  import * as Predicate from "effect/Predicate";
8
6
  import * as Result from "effect/Result";
9
7
  import * as S from "effect/Schema";
10
- import { createRequire } from "module";
8
+ import { parseSync } from "oxc-parser";
11
9
  import path from "path";
12
10
  import "@systemfsoftware/stryker-js/Ignorer";
13
11
  import { propertyPath, strykerReportBugUrl } from "@systemfsoftware/stryker-js/Schema";
@@ -18,7 +16,7 @@ import { RegExpParser, visitRegExpAST } from "@eslint-community/regexpp";
18
16
  /**
19
17
  * Instrument.workflow — pure decision for the instrument capability.
20
18
  *
21
- * The heavy lifting (Babel traversal, mutant collection, code generation)
19
+ * The heavy lifting (AST traversal, mutant collection, code generation)
22
20
  * happens in `Instrument.ts`'s read phase, which is allowed to be stateful.
23
21
  * This decision receives the already-collected mutants as data and wraps them
24
22
  * into the decision type. All helpers and schemas live in this file so the
@@ -48,11 +46,9 @@ const FileSchema = S.Struct({
48
46
  content: S.String,
49
47
  mutate: MutateDescriptionSchema
50
48
  });
51
- const PluginSchema = Wire.mint(S.Unknown);
52
49
  const IgnorerSchema = Wire.mint(S.Unknown);
53
50
  const AstSchema = Wire.mint(S.Unknown);
54
51
  const InstrumenterOptionsSchema = Wire.wire({
55
- plugins: Wire.mint(S.NullOr(Wire.mint(S.Array(PluginSchema)))),
56
52
  excludedMutations: Wire.mint(S.Array(Wire.mint(S.String))),
57
53
  ignorers: Wire.mint(S.Array(IgnorerSchema)),
58
54
  noHeader: Wire.mint(S.optional(Wire.mint(S.Boolean)))
@@ -81,47 +77,6 @@ const instrumentWorkflow = Workflow.make(InstrumentDecoded, (decoded) => Result.
81
77
  mutants: decoded.mutants,
82
78
  asts: decoded.asts
83
79
  })));
84
- //#endregion
85
- //#region src/Parser.schema.ts
86
- var ParseFailed = class extends S.TaggedError("@systemfsoftware/stryker-js-instrumenter/ParseFailed")("ParseFailed", {
87
- fileName: S.String,
88
- message: S.String,
89
- location: S.Struct({
90
- line: S.Finite,
91
- column: S.Finite
92
- }),
93
- cause: S.Defect()
94
- }) {
95
- get message() {
96
- return `Failed to parse ${this.fileName} at ${this.location.line}:${this.location.column}: ${this.message}`;
97
- }
98
- };
99
- S.TaggedError("@systemfsoftware/stryker-js-instrumenter/ParserNotFound")("ParserNotFound", {
100
- fileName: S.String,
101
- extension: S.String,
102
- cause: S.Defect()
103
- });
104
- var SvelteVersionNotSupported = class extends S.TaggedError("@systemfsoftware/stryker-js-instrumenter/SvelteVersionNotSupported")("SvelteVersionNotSupported", {
105
- version: S.String,
106
- fileName: S.String,
107
- cause: S.Defect()
108
- }) {
109
- get message() {
110
- return `Svelte version ${this.version} is not supported for ${this.fileName} (expected >=3.30)`;
111
- }
112
- };
113
- var SvelteWalkerNotFound = class extends S.TaggedError("@systemfsoftware/stryker-js-instrumenter/SvelteWalkerNotFound")("SvelteWalkerNotFound", {
114
- fileName: S.String,
115
- cause: S.Defect()
116
- }) {
117
- get message() {
118
- return `Svelte walker not found for ${this.fileName}`;
119
- }
120
- };
121
- S.TaggedError("@systemfsoftware/stryker-js-instrumenter/SvelteParseFailed")("SvelteParseFailed", {
122
- fileName: S.String,
123
- cause: S.Defect()
124
- });
125
80
  S.Literals([
126
81
  "html",
127
82
  "js",
@@ -226,20 +181,538 @@ function isLineBreak(ch) {
226
181
  return ch === CharacterCodes.lineFeed || ch === CharacterCodes.carriageReturn || ch === CharacterCodes.lineSeparator || ch === CharacterCodes.paragraphSeparator;
227
182
  }
228
183
  //#endregion
184
+ //#region src/estree.ts
185
+ const EXPRESSION_KINDS = /* @__PURE__ */ new Set([
186
+ "ArrayExpression",
187
+ "ArrowFunctionExpression",
188
+ "AwaitExpression",
189
+ "BinaryExpression",
190
+ "CallExpression",
191
+ "ChainExpression",
192
+ "ClassExpression",
193
+ "ConditionalExpression",
194
+ "FunctionExpression",
195
+ "Identifier",
196
+ "Import",
197
+ "ImportExpression",
198
+ "JSXElement",
199
+ "JSXFragment",
200
+ "Literal",
201
+ "LogicalExpression",
202
+ "MetaProperty",
203
+ "NewExpression",
204
+ "ObjectExpression",
205
+ "PrivateIdentifier",
206
+ "SequenceExpression",
207
+ "Super",
208
+ "TaggedTemplateExpression",
209
+ "TemplateLiteral",
210
+ "ThisExpression",
211
+ "TSAsExpression",
212
+ "TSInstantiationExpression",
213
+ "TSNonNullExpression",
214
+ "TSSatisfiesExpression",
215
+ "TSTypeAssertion",
216
+ "UnaryExpression",
217
+ "UpdateExpression",
218
+ "YieldExpression"
219
+ ]);
220
+ const STATEMENT_KINDS = /* @__PURE__ */ new Set([
221
+ "BlockStatement",
222
+ "BreakStatement",
223
+ "ClassDeclaration",
224
+ "ContinueStatement",
225
+ "DebuggerStatement",
226
+ "DoWhileStatement",
227
+ "ExportAllDeclaration",
228
+ "ExportDefaultDeclaration",
229
+ "ExportNamedDeclaration",
230
+ "ExpressionStatement",
231
+ "ForInStatement",
232
+ "ForOfStatement",
233
+ "ForStatement",
234
+ "FunctionDeclaration",
235
+ "IfStatement",
236
+ "ImportDeclaration",
237
+ "LabeledStatement",
238
+ "ReturnStatement",
239
+ "SwitchStatement",
240
+ "ThrowStatement",
241
+ "TSExportAssignment",
242
+ "TSImportEqualsDeclaration",
243
+ "TSInterfaceDeclaration",
244
+ "TSModuleDeclaration",
245
+ "TSTypeAliasDeclaration",
246
+ "VariableDeclaration",
247
+ "WhileStatement",
248
+ "WithStatement"
249
+ ]);
250
+ /**
251
+ * The node's [start, end) offsets. oxc is invoked with `range: true`, so every
252
+ * parsed node carries one; synthesized builders omit it.
253
+ */
254
+ function spanOf(node) {
255
+ const range = node.range;
256
+ if (range === void 0) return void 0;
257
+ return {
258
+ start: range[0],
259
+ end: range[1]
260
+ };
261
+ }
262
+ /**
263
+ * The node's `type` tag, for checks against kinds outside the @types/estree
264
+ * union (TS and JSX extensions oxc emits).
265
+ */
266
+ function nodeType(node) {
267
+ return isAstNode(node) ? node.type : void 0;
268
+ }
269
+ function isExpressionKind(node) {
270
+ return node !== void 0 && node !== null && EXPRESSION_KINDS.has(node.type);
271
+ }
272
+ function isStatementKind(node) {
273
+ return node !== void 0 && node !== null && STATEMENT_KINDS.has(node.type);
274
+ }
275
+ function mark(node, loc) {
276
+ if (loc !== void 0) return Object.assign(node, {
277
+ start: loc.start,
278
+ end: loc.end
279
+ });
280
+ return node;
281
+ }
282
+ function identifier(name, loc) {
283
+ return mark({
284
+ type: "Identifier",
285
+ name
286
+ }, loc);
287
+ }
288
+ function stringLiteral(value, loc) {
289
+ return mark({
290
+ type: "Literal",
291
+ value
292
+ }, loc);
293
+ }
294
+ function booleanLiteral(value, loc) {
295
+ return mark({
296
+ type: "Literal",
297
+ value
298
+ }, loc);
299
+ }
300
+ function regExpLiteral(pattern, flags, loc) {
301
+ return mark({
302
+ type: "Literal",
303
+ value: null,
304
+ regex: {
305
+ pattern,
306
+ flags
307
+ }
308
+ }, loc);
309
+ }
310
+ function arrayExpression(elements = [], loc) {
311
+ const elementList = [];
312
+ for (const element of elements) if (element !== null) elementList.push(element);
313
+ return mark({
314
+ type: "ArrayExpression",
315
+ elements: elementList
316
+ }, loc);
317
+ }
318
+ function callExpression(callee, args = [], optional = false, loc) {
319
+ return mark({
320
+ type: "CallExpression",
321
+ callee,
322
+ arguments: [...args],
323
+ optional
324
+ }, loc);
325
+ }
326
+ function newExpression(callee, args = [], loc) {
327
+ return mark({
328
+ type: "NewExpression",
329
+ callee,
330
+ arguments: [...args]
331
+ }, loc);
332
+ }
333
+ function memberExpression(object, property, computed = false, optional = false, loc) {
334
+ return mark({
335
+ type: "MemberExpression",
336
+ object,
337
+ property,
338
+ computed,
339
+ optional
340
+ }, loc);
341
+ }
342
+ function arrowFunctionExpression(params, body, loc) {
343
+ const fnBody = body;
344
+ return mark({
345
+ type: "ArrowFunctionExpression",
346
+ params: [...params],
347
+ body: fnBody,
348
+ async: false,
349
+ expression: fnBody.type !== "BlockStatement"
350
+ }, loc);
351
+ }
352
+ function blockStatement(body, loc) {
353
+ return mark({
354
+ type: "BlockStatement",
355
+ body: [...body]
356
+ }, loc);
357
+ }
358
+ function expressionStatement(expression, loc) {
359
+ return mark({
360
+ type: "ExpressionStatement",
361
+ expression
362
+ }, loc);
363
+ }
364
+ function ifStatement(test, consequent, alternate, loc) {
365
+ return mark({
366
+ type: "IfStatement",
367
+ test,
368
+ consequent,
369
+ alternate: alternate ?? null
370
+ }, loc);
371
+ }
372
+ function variableDeclarator(id, init, loc) {
373
+ return mark({
374
+ type: "VariableDeclarator",
375
+ id,
376
+ init
377
+ }, loc);
378
+ }
379
+ function variableDeclaration(kind, declarations, loc) {
380
+ return mark({
381
+ type: "VariableDeclaration",
382
+ kind,
383
+ declarations: [...declarations]
384
+ }, loc);
385
+ }
386
+ function returnStatement(argument, loc) {
387
+ return mark({
388
+ type: "ReturnStatement",
389
+ argument
390
+ }, loc);
391
+ }
392
+ function sequenceExpression(expressions, loc) {
393
+ return mark({
394
+ type: "SequenceExpression",
395
+ expressions: [...expressions]
396
+ }, loc);
397
+ }
398
+ function conditionalExpression(test, consequent, alternate, loc) {
399
+ return mark({
400
+ type: "ConditionalExpression",
401
+ test,
402
+ consequent,
403
+ alternate
404
+ }, loc);
405
+ }
406
+ function unaryExpression(operator, argument, loc) {
407
+ return mark({
408
+ type: "UnaryExpression",
409
+ operator,
410
+ argument,
411
+ prefix: true
412
+ }, loc);
413
+ }
414
+ function updateExpression(operator, argument, prefix, loc) {
415
+ return mark({
416
+ type: "UpdateExpression",
417
+ operator,
418
+ argument,
419
+ prefix
420
+ }, loc);
421
+ }
422
+ function templateElement(raw, loc) {
423
+ return mark({
424
+ type: "TemplateElement",
425
+ value: {
426
+ raw,
427
+ cooked: raw
428
+ },
429
+ tail: true
430
+ }, loc);
431
+ }
432
+ function templateLiteral(quasis, expressions, loc) {
433
+ return mark({
434
+ type: "TemplateLiteral",
435
+ quasis: [...quasis],
436
+ expressions: [...expressions]
437
+ }, loc);
438
+ }
439
+ function switchCase(test, consequent, loc) {
440
+ return mark({
441
+ type: "SwitchCase",
442
+ test,
443
+ consequent: [...consequent]
444
+ }, loc);
445
+ }
446
+ /**
447
+ * Deep clone of a plain ESTree node. oxc nodes are JSON-shaped, so
448
+ * Deep clone over plain nodes: no prototypes to preserve.
449
+ */
450
+ function cloneNode(node) {
451
+ return structuredClone(node);
452
+ }
453
+ /**
454
+ * Attaches every comment to the node it precedes (`leadingComments`) or, when
455
+ * no node follows it, to the node it trails (`trailingComments`). oxc ships
456
+ * comments flat, and the Stryker directive pass reads `node.leadingComments`,
457
+ * so the flat list is folded into the tree once per transform with the file's
458
+ * line table in hand.
459
+ */
460
+ function attachComments(root, comments, lineTable) {
461
+ if (comments.length === 0) return;
462
+ const nodes = collectNodes(root).filter((entry) => entry.node !== root);
463
+ nodes.sort((a, b) => a.start - b.start);
464
+ const leading = /* @__PURE__ */ new Map();
465
+ const trailing = /* @__PURE__ */ new Map();
466
+ for (const comment of comments) {
467
+ const next = nodes.find((entry) => entry.start >= comment.end);
468
+ if (next !== void 0) pushComment(leading, next.node, comment);
469
+ else {
470
+ const previous = nodes.findLast((entry) => entry.end <= comment.start && isStatementKind(entry.node));
471
+ if (previous !== void 0) pushComment(trailing, previous.node, comment);
472
+ }
473
+ }
474
+ assignComments(leading, lineTable, "leadingComments");
475
+ assignComments(trailing, lineTable, "trailingComments");
476
+ }
477
+ function assignComments(map, lineTable, field) {
478
+ for (const [node, list] of map) {
479
+ const located = list.map((comment) => ({
480
+ ...comment,
481
+ loc: {
482
+ start: positionFromLineTable(comment.start, lineTable),
483
+ end: positionFromLineTable(comment.end, lineTable)
484
+ }
485
+ }));
486
+ Object.assign(node, { [field]: located });
487
+ }
488
+ }
489
+ function pushComment(map, node, comment) {
490
+ const list = map.get(node);
491
+ if (list === void 0) map.set(node, [comment]);
492
+ else list.push(comment);
493
+ }
494
+ function collectNodes(node) {
495
+ const out = [];
496
+ collect$1(node, out);
497
+ return out;
498
+ }
499
+ function collect$1(node, out) {
500
+ if (Array.isArray(node)) {
501
+ for (const item of node) collect$1(item, out);
502
+ return;
503
+ }
504
+ if (!isAstNode(node)) return;
505
+ const startOffset = node["start"];
506
+ const endOffset = node["end"];
507
+ if (typeof startOffset === "number" && typeof endOffset === "number") out.push({
508
+ node,
509
+ start: startOffset,
510
+ end: endOffset
511
+ });
512
+ for (const key of Object.keys(node)) {
513
+ if (key === "leadingComments" || key === "trailingComments") continue;
514
+ collect$1(node[key], out);
515
+ }
516
+ }
517
+ function isAstNode(value) {
518
+ return typeof value === "object" && value !== null && "type" in value && typeof value.type === "string";
519
+ }
520
+ function buildLineTable(content) {
521
+ return computeLineStarts(content);
522
+ }
523
+ function positionFromLineTable(offset, lineTable) {
524
+ const zeroBased = positionFromOffset(lineTable, offset);
525
+ return {
526
+ line: zeroBased.line + 1,
527
+ column: zeroBased.column
528
+ };
529
+ }
530
+ const SKIP_KEYS = /* @__PURE__ */ new Set([
531
+ "type",
532
+ "start",
533
+ "end",
534
+ "range",
535
+ "loc",
536
+ "leadingComments",
537
+ "trailingComments"
538
+ ]);
539
+ function traverse(root, visitors) {
540
+ visit(root, null, "root", void 0, visitors, {
541
+ skipped: /* @__PURE__ */ new Set(),
542
+ stopped: false
543
+ });
544
+ }
545
+ function visit(node, parentPath, key, listKey, visitors, context) {
546
+ if (context.stopped) return;
547
+ if (!isAstNode(node) || context.skipped.has(node)) return;
548
+ const path = createPath(node, parentPath, key, listKey, context);
549
+ visitors.enter?.(path);
550
+ if (context.stopped || context.skipped.has(node)) return;
551
+ visitChildren(node, path, visitors, context);
552
+ if (context.stopped) return;
553
+ visitors.exit?.(path);
554
+ }
555
+ function visitChildren(node, path, visitors, context) {
556
+ for (const childKey of Object.keys(node)) {
557
+ if (SKIP_KEYS.has(childKey)) continue;
558
+ visitChild(node[childKey], path, childKey, visitors, context);
559
+ if (context.stopped) return;
560
+ }
561
+ }
562
+ function visitChild(child, path, key, visitors, context) {
563
+ if (Array.isArray(child)) {
564
+ for (let i = 0; i < child.length; i++) {
565
+ visit(child[i], path, key, String(i), visitors, context);
566
+ if (context.stopped) return;
567
+ }
568
+ return;
569
+ }
570
+ if (isAstNode(child)) visit(child, path, key, void 0, visitors, context);
571
+ }
572
+ function createPath(node, parentPath, key, listKey, context) {
573
+ const path = {
574
+ node,
575
+ parentPath,
576
+ parent: parentPath?.node,
577
+ key,
578
+ listKey,
579
+ skip() {
580
+ context.skipped.add(node);
581
+ },
582
+ stop() {
583
+ context.stopped = true;
584
+ },
585
+ find(predicate) {
586
+ let current = path;
587
+ while (current !== null) {
588
+ if (predicate(current)) return current;
589
+ current = current.parentPath;
590
+ }
591
+ },
592
+ getStatementParent() {
593
+ let current = parentPath;
594
+ while (current !== null) {
595
+ if (isStatementKind(current.node)) return current;
596
+ current = current.parentPath;
597
+ }
598
+ },
599
+ replaceWith(replacement) {
600
+ replaceInParent(parentPath, key, listKey, replacement);
601
+ },
602
+ is(kind) {
603
+ return node.type === kind;
604
+ },
605
+ isExpression() {
606
+ return isExpressionKind(node);
607
+ },
608
+ isStatement() {
609
+ return isStatementKind(node);
610
+ }
611
+ };
612
+ return path;
613
+ }
614
+ function replaceInParent(parentPath, key, listKey, replacement) {
615
+ if (parentPath === null) return;
616
+ const parent = parentPath.node;
617
+ if (!isAstNode(parent)) return;
618
+ if (listKey === void 0) {
619
+ parent[key] = replacement;
620
+ return;
621
+ }
622
+ const index = Number(listKey);
623
+ const container = parent[key];
624
+ if (Array.isArray(container) && Number.isInteger(index)) container[index] = replacement;
625
+ }
626
+ //#endregion
627
+ //#region src/Parser.schema.ts
628
+ var ParseFailed = class extends S.TaggedError("@systemfsoftware/stryker-js-instrumenter/ParseFailed")("ParseFailed", {
629
+ fileName: S.String,
630
+ message: S.String,
631
+ location: S.Struct({
632
+ line: S.Finite,
633
+ column: S.Finite
634
+ }),
635
+ cause: S.Defect()
636
+ }) {
637
+ get message() {
638
+ return `Failed to parse ${this.fileName} at ${this.location.line}:${this.location.column}: ${this.message}`;
639
+ }
640
+ };
641
+ var ParserNotFound = class extends S.TaggedError("@systemfsoftware/stryker-js-instrumenter/ParserNotFound")("ParserNotFound", {
642
+ fileName: S.String,
643
+ extension: S.String,
644
+ cause: S.Defect()
645
+ }) {
646
+ get message() {
647
+ return `No parser registered for ${this.fileName} (extension "${this.extension}")`;
648
+ }
649
+ };
650
+ var SvelteVersionNotSupported = class extends S.TaggedError("@systemfsoftware/stryker-js-instrumenter/SvelteVersionNotSupported")("SvelteVersionNotSupported", {
651
+ version: S.String,
652
+ fileName: S.String,
653
+ cause: S.Defect()
654
+ }) {
655
+ get message() {
656
+ return `Svelte version ${this.version} is not supported for ${this.fileName} (expected >=3.30)`;
657
+ }
658
+ };
659
+ var SvelteWalkerNotFound = class extends S.TaggedError("@systemfsoftware/stryker-js-instrumenter/SvelteWalkerNotFound")("SvelteWalkerNotFound", {
660
+ fileName: S.String,
661
+ cause: S.Defect()
662
+ }) {
663
+ get message() {
664
+ return `Svelte walker not found for ${this.fileName}`;
665
+ }
666
+ };
667
+ S.TaggedError("@systemfsoftware/stryker-js-instrumenter/SvelteParseFailed")("SvelteParseFailed", {
668
+ fileName: S.String,
669
+ cause: S.Defect()
670
+ });
671
+ //#endregion
229
672
  //#region src/Parser.ts
673
+ function parseWithOxc(text, fileName, lang) {
674
+ const result = parseSync(fileName, text, {
675
+ lang,
676
+ range: true
677
+ });
678
+ if (result.errors.length > 0) {
679
+ const first = result.errors[0];
680
+ const label = first?.labels[0];
681
+ const position = positionFromLineTable(label?.start ?? 0, buildLineTable(text));
682
+ throw new ParseFailed({
683
+ fileName,
684
+ message: first?.message ?? "unknown parse error",
685
+ location: position,
686
+ cause: result.errors.map((error) => error.message)
687
+ });
688
+ }
689
+ return {
690
+ root: result.program,
691
+ comments: result.comments
692
+ };
693
+ }
230
694
  /**
231
- * Parser — all parsers that turn source text into the instrumenter's ASTs.
695
+ * Shifts a parsed script's root span by the offset of the script tag inside
696
+ * the embedding document (html/svelte), so range math against the raw
697
+ * document stays consistent. Child nodes keep their script-relative offsets —
698
+ * mutant positions are re-mapped through the AST's `offset` field.
232
699
  */
233
- const { types: types$1, parseAsync } = babel;
234
- const require = createRequire(import.meta.url);
235
- function createParser(parserOptions) {
236
- const jsParse = createJSParser(parserOptions);
700
+ function shiftScriptOffsets(ast, offset) {
701
+ const root = ast.root;
702
+ if (typeof root === "object" && root !== null && "start" in root && "end" in root && typeof root.start === "number" && typeof root.end === "number") {
703
+ root.start += offset;
704
+ root.end += offset;
705
+ }
706
+ }
707
+ function createParser() {
708
+ const jsParse = createJSParser();
237
709
  async function parse(code, fileName, formatOverride) {
238
710
  const format = getFormat(fileName, formatOverride);
239
- if (!format) {
240
- const ext = path.extname(fileName).toLowerCase();
241
- throw new Error(`Unable to parse ${fileName}. No parser registered for ${ext}!`);
242
- }
711
+ if (!format) throw new ParserNotFound({
712
+ fileName,
713
+ extension: path.extname(fileName).toLowerCase(),
714
+ cause: void 0
715
+ });
243
716
  switch (format) {
244
717
  case "js": return jsParse(code, fileName);
245
718
  case "tsx": return parseTsx(code, fileName);
@@ -269,97 +742,38 @@ function getFormat(fileName, override) {
269
742
  default: return;
270
743
  }
271
744
  }
272
- function isParserPlugin(value) {
273
- return typeof value === "string" || Array.isArray(value);
274
- }
275
- function isParserPluginArray(value) {
276
- return value.every(isParserPlugin);
277
- }
278
- function getParserPlugins(override) {
279
- if (override === null) return defaultPlugins;
280
- if (isParserPluginArray(override)) return override;
281
- throw new Error("Invalid parser plugins: expected ParserPlugin[]");
282
- }
283
- const defaultPlugins = [
284
- "doExpressions",
285
- "objectRestSpread",
286
- "classProperties",
287
- "exportDefaultFrom",
288
- "exportNamespaceFrom",
289
- "asyncGenerators",
290
- "functionBind",
291
- "functionSent",
292
- "dynamicImport",
293
- "numericSeparator",
294
- "importMeta",
295
- "optionalCatchBinding",
296
- "optionalChaining",
297
- "classPrivateProperties",
298
- ["pipelineOperator", { proposal: "minimal" }],
299
- "nullishCoalescingOperator",
300
- "bigInt",
301
- "throwExpressions",
302
- "logicalAssignment",
303
- "classPrivateMethods",
304
- "v8intrinsic",
305
- "partialApplication",
306
- ["decorators", { decoratorsBeforeExport: false }],
307
- "jsx"
308
- ];
309
- function createJSParser({ plugins: pluginsOverride }) {
745
+ function createJSParser() {
310
746
  return async function parse(text, fileName) {
311
- const plugins = getParserPlugins(pluginsOverride);
312
- const ast = await parseAsync(text, {
313
- parserOpts: { plugins: [...plugins] },
314
- filename: fileName,
315
- sourceType: "module"
316
- });
317
- if (ast === null) throw new Error(`Expected ${fileName} to contain a babel.types.file, but it yielded null`);
747
+ const { root, comments } = parseWithOxc(text, fileName, "js");
318
748
  return {
319
749
  originFileName: fileName,
320
750
  rawContent: text,
321
751
  format: "js",
322
- root: ast
752
+ root,
753
+ comments
323
754
  };
324
755
  };
325
756
  }
326
- /**
327
- * See https://babeljs.io/docs/en/babel-preset-typescript
328
- * @param text The text to parse
329
- * @param fileName The name of the file
330
- */
331
757
  async function parseTS(text, fileName) {
758
+ const { root, comments } = parseWithOxc(text, fileName, "ts");
332
759
  return {
333
760
  originFileName: fileName,
334
761
  rawContent: text,
335
762
  format: "ts",
336
- root: await parseTSInternal(text, fileName, false)
763
+ root,
764
+ comments
337
765
  };
338
766
  }
339
767
  async function parseTsx(text, fileName) {
768
+ const { root, comments } = parseWithOxc(text, fileName, "tsx");
340
769
  return {
341
- root: await parseTSInternal(text, fileName, true),
770
+ root,
771
+ comments,
342
772
  format: "tsx",
343
773
  originFileName: fileName,
344
774
  rawContent: text
345
775
  };
346
776
  }
347
- async function parseTSInternal(text, fileName, isTSX) {
348
- const ast = await parseAsync(text, {
349
- filename: fileName,
350
- parserOpts: { ranges: true },
351
- configFile: false,
352
- babelrc: false,
353
- presets: [[require.resolve("@babel/preset-typescript"), {
354
- isTSX,
355
- allExtensions: true
356
- }]],
357
- plugins: [[require.resolve("@babel/plugin-proposal-decorators"), { legacy: true }], [require.resolve("@babel/plugin-transform-explicit-resource-management")]]
358
- });
359
- if (ast === null) throw new Error(`Expected ${fileName} to contain a babel.types.file, but it yielded null`);
360
- if (types$1.isProgram(ast)) throw new Error(`Expected ${fileName} to contain a babel.types.file, but was a program`);
361
- return ast;
362
- }
363
777
  const TSX_SCRIPT_TYPES = Object.freeze(["tsx", "text/tsx"]);
364
778
  const TS_SCRIPT_TYPES = Object.freeze([
365
779
  "ts",
@@ -434,12 +848,7 @@ async function ngHtmlParser(text, fileName, parserContext) {
434
848
  const ast = await parserContext.parse(content, fileName, scriptFormat);
435
849
  if (ast !== null && ast !== void 0) {
436
850
  const offset = el.startSourceSpan.end;
437
- const rootStart = ast.root.start;
438
- if (rootStart == null) throw new Error("Babel File node without a start offset");
439
- const rootEnd = ast.root.end;
440
- if (rootEnd == null) throw new Error("Babel File node without an end offset");
441
- ast.root.start = rootStart + offset.offset;
442
- ast.root.end = rootEnd + offset.offset;
851
+ shiftScriptOffsets(ast, offset.offset);
443
852
  return {
444
853
  ...ast,
445
854
  offset: {
@@ -544,162 +953,2171 @@ async function parseSvelte(text, fileName, context) {
544
953
  });
545
954
  walk = svelteCompilerModule["walk"];
546
955
  }
547
- const lineStarts = computeLineStarts(text);
548
- const { replacedCode, scriptMap } = await replaceScripts(text);
549
- const svelteAst = svelteParse(replacedCode, { filename: fileName });
550
- const { remappedModuleScriptRange, remappedScriptRanges } = remapScriptLocations(replacedCode, scriptMap, getModuleScriptRange(svelteAst), getTemplateScriptRanges(svelteAst, walk));
551
- const [moduleScript, ...additionalScripts] = await Promise.all([parseTemplateScriptIfDefined(remappedModuleScriptRange), ...remappedScriptRanges.map(parseTemplateScript)]);
552
- let root;
553
- if (moduleScript === void 0) root = { additionalScripts };
554
- else root = {
555
- moduleScript,
556
- additionalScripts
557
- };
558
- return {
559
- originFileName: fileName,
560
- rawContent: text,
561
- format: "svelte",
562
- root
563
- };
564
- /**
565
- * Replaces script tags with placeholders.
566
- * This is needed, because svelte's `parse` doesn't support `lang="ts"`.
567
- */
568
- async function replaceScripts(code) {
569
- const map = /* @__PURE__ */ new Map();
570
- let scriptIndex = 0;
571
- return {
572
- replacedCode: (await preprocess(code, { script(script) {
573
- const scriptName = `script${scriptIndex++}`;
574
- map.set(scriptName, script);
575
- return { code: scriptName };
576
- } })).code,
577
- scriptMap: map
578
- };
956
+ const lineStarts = computeLineStarts(text);
957
+ const { replacedCode, scriptMap } = await replaceScripts(text);
958
+ const svelteAst = svelteParse(replacedCode, { filename: fileName });
959
+ const { remappedModuleScriptRange, remappedScriptRanges } = remapScriptLocations(replacedCode, scriptMap, getModuleScriptRange(svelteAst), getTemplateScriptRanges(svelteAst, walk));
960
+ const [moduleScript, ...additionalScripts] = await Promise.all([parseTemplateScriptIfDefined(remappedModuleScriptRange), ...remappedScriptRanges.map(parseTemplateScript)]);
961
+ let root;
962
+ if (moduleScript === void 0) root = { additionalScripts };
963
+ else root = {
964
+ moduleScript,
965
+ additionalScripts
966
+ };
967
+ return {
968
+ originFileName: fileName,
969
+ rawContent: text,
970
+ format: "svelte",
971
+ root
972
+ };
973
+ /**
974
+ * Replaces script tags with placeholders.
975
+ * This is needed, because svelte's `parse` doesn't support `lang="ts"`.
976
+ */
977
+ async function replaceScripts(code) {
978
+ const map = /* @__PURE__ */ new Map();
979
+ let scriptIndex = 0;
980
+ return {
981
+ replacedCode: (await preprocess(code, { script(script) {
982
+ const scriptName = `script${scriptIndex++}`;
983
+ map.set(scriptName, script);
984
+ return { code: scriptName };
985
+ } })).code,
986
+ scriptMap: map
987
+ };
988
+ }
989
+ function getTemplateScriptRanges(ast, walker) {
990
+ const ranges = [];
991
+ if (isPlainRecord(ast) && ast["instance"] !== null && ast["instance"] !== void 0) {
992
+ const instance = ast["instance"];
993
+ if (isPlainRecord(instance) && "content" in instance) {
994
+ const content = instance["content"];
995
+ if (isRangedProgram(content)) ranges.push({
996
+ start: content.start,
997
+ end: content.end,
998
+ isExpression: false
999
+ });
1000
+ else throw new Error("Svelte instance script without a source range");
1001
+ }
1002
+ }
1003
+ if (!isPlainRecord(ast) || !("html" in ast)) throw new Error("Svelte AST without html");
1004
+ const html = ast["html"];
1005
+ walker(html, { enter(node) {
1006
+ const scriptRange = tryGetScriptRangeFromElement(node);
1007
+ if (scriptRange) ranges.push(scriptRange);
1008
+ const templateExpression = collectTemplateExpression(node);
1009
+ if (templateExpression) {
1010
+ const { start, end } = templateExpression;
1011
+ ranges.push({
1012
+ start,
1013
+ end,
1014
+ isExpression: true
1015
+ });
1016
+ }
1017
+ } });
1018
+ return ranges;
1019
+ }
1020
+ async function parseTemplateScriptIfDefined(range) {
1021
+ if (range) return parseTemplateScript(range);
1022
+ }
1023
+ async function parseTemplateScript({ start, end, isExpression, format }) {
1024
+ const scriptText = text.slice(start, end);
1025
+ return {
1026
+ ast: {
1027
+ ...await context.parse(scriptText, fileName, format),
1028
+ offset: positionFromOffset(lineStarts, start)
1029
+ },
1030
+ range: {
1031
+ start,
1032
+ end
1033
+ },
1034
+ isExpression
1035
+ };
1036
+ }
1037
+ }
1038
+ function getModuleScriptRange(svelteAst) {
1039
+ if (!isPlainRecord(svelteAst) || !("module" in svelteAst) || svelteAst["module"] === null || svelteAst["module"] === void 0) return;
1040
+ const mod = svelteAst["module"];
1041
+ if (!isPlainRecord(mod) || !("content" in mod)) throw new Error("Svelte module script without a source range");
1042
+ const content = mod["content"];
1043
+ if (!isRangedProgram(content)) throw new Error("Svelte module script without a source range");
1044
+ return {
1045
+ start: content.start,
1046
+ end: content.end,
1047
+ isExpression: false
1048
+ };
1049
+ }
1050
+ /**
1051
+ * Remaps script locations back to the original places using the script map
1052
+ */
1053
+ function remapScriptLocations(code, scriptMap, moduleScriptRange, templateRanges) {
1054
+ const scriptRanges = [moduleScriptRange, ...templateRanges].filter(Predicate.isNotNullish).sort((a, b) => a.start - b.start);
1055
+ let offset = 0;
1056
+ let newModuleScriptRange;
1057
+ const newScriptRanges = scriptRanges.map((range) => {
1058
+ const script = code.substring(range.start, range.end);
1059
+ const actualScript = scriptMap.get(script);
1060
+ const start = range.start + offset;
1061
+ if (actualScript) {
1062
+ let langFormat = "js";
1063
+ if (actualScript.attributes["lang"] === "ts") langFormat = "ts";
1064
+ const scriptRange = {
1065
+ start,
1066
+ end: start + actualScript.content.length,
1067
+ isExpression: range.isExpression,
1068
+ format: langFormat
1069
+ };
1070
+ offset += actualScript.content.length - script.length;
1071
+ if (range === moduleScriptRange) newModuleScriptRange = scriptRange;
1072
+ return scriptRange;
1073
+ } else return {
1074
+ start,
1075
+ end: start + script.length,
1076
+ isExpression: range.isExpression,
1077
+ format: "js"
1078
+ };
1079
+ });
1080
+ return {
1081
+ remappedModuleScriptRange: newModuleScriptRange,
1082
+ remappedScriptRanges: newScriptRanges.filter((range) => range !== newModuleScriptRange)
1083
+ };
1084
+ }
1085
+ function collectTemplateExpression(node) {
1086
+ if (!isPlainRecord(node) || typeof node["type"] !== "string") return;
1087
+ if (!isTemplateExpressionType(node["type"])) return;
1088
+ if (!("expression" in node)) return;
1089
+ const expression = node["expression"];
1090
+ if (isRangedBaseNode(expression)) return expression;
1091
+ }
1092
+ //#endregion
1093
+ //#region src/print/index.ts
1094
+ function printProgram(program, opts = {}) {
1095
+ return new PrintState(opts).printProgram(program);
1096
+ }
1097
+ function printNode(node, opts = {}) {
1098
+ return new PrintState(opts).printAnyNode(node);
1099
+ }
1100
+ const PREC = {
1101
+ Sequence: 0,
1102
+ Assignment: 1,
1103
+ Conditional: 2,
1104
+ NullishCoalescing: 3,
1105
+ LogicalOR: 4,
1106
+ LogicalAND: 5,
1107
+ BitwiseOR: 6,
1108
+ BitwiseXOR: 7,
1109
+ BitwiseAND: 8,
1110
+ Equality: 9,
1111
+ Relational: 10,
1112
+ Shift: 11,
1113
+ Additive: 12,
1114
+ Multiplicative: 13,
1115
+ Exponential: 14,
1116
+ Unary: 15,
1117
+ Update: 16,
1118
+ Call: 17,
1119
+ Member: 18,
1120
+ Primary: 19
1121
+ };
1122
+ function binaryPrec(op) {
1123
+ switch (op) {
1124
+ case "||": return PREC.LogicalOR;
1125
+ case "&&": return PREC.LogicalAND;
1126
+ case "??": return PREC.NullishCoalescing;
1127
+ case "|": return PREC.BitwiseOR;
1128
+ case "^": return PREC.BitwiseXOR;
1129
+ case "&": return PREC.BitwiseAND;
1130
+ case "==":
1131
+ case "!=":
1132
+ case "===":
1133
+ case "!==": return PREC.Equality;
1134
+ case "<":
1135
+ case ">":
1136
+ case "<=":
1137
+ case ">=":
1138
+ case "in":
1139
+ case "instanceof": return PREC.Relational;
1140
+ case "<<":
1141
+ case ">>":
1142
+ case ">>>": return PREC.Shift;
1143
+ case "+":
1144
+ case "-": return PREC.Additive;
1145
+ case "*":
1146
+ case "/":
1147
+ case "%": return PREC.Multiplicative;
1148
+ case "**": return PREC.Exponential;
1149
+ default: return PREC.Additive;
1150
+ }
1151
+ }
1152
+ function logicalPrec(op) {
1153
+ if (op === "??") return PREC.NullishCoalescing;
1154
+ if (op === "||") return PREC.LogicalOR;
1155
+ return PREC.LogicalAND;
1156
+ }
1157
+ var PrintState = class {
1158
+ out = "";
1159
+ indentLevel = 0;
1160
+ comments;
1161
+ hashbang;
1162
+ commentIdx = 0;
1163
+ sortedComments;
1164
+ constructor(opts) {
1165
+ this.comments = opts.comments ?? [];
1166
+ this.hashbang = opts.hashbang ?? null;
1167
+ const filtered = this.hashbang ? this.comments.filter((c) => !(c.type === "Line" && c.start === this.hashbang.start)) : this.comments;
1168
+ this.sortedComments = [...filtered].sort((a, b) => a.start - b.start);
1169
+ }
1170
+ printProgram(program) {
1171
+ this.out = "";
1172
+ this.indentLevel = 0;
1173
+ this.commentIdx = 0;
1174
+ if (this.hashbang) this.out += `#!${this.hashbang.value}\n`;
1175
+ this.emitCommentsBefore(this.firstStatementStart(program));
1176
+ for (let i = 0; i < program.body.length; i++) {
1177
+ const stmt = program.body[i];
1178
+ this.emitCommentsBefore(stmt.start ?? -1);
1179
+ this.printStatement(stmt);
1180
+ if (i < program.body.length - 1) this.out += "\n";
1181
+ else this.out += "\n";
1182
+ }
1183
+ this.emitRemainingComments();
1184
+ return this.out;
1185
+ }
1186
+ printAnyNode(node) {
1187
+ this.out = "";
1188
+ this.indentLevel = 0;
1189
+ this.printNode(node, PREC.Sequence);
1190
+ return this.out;
1191
+ }
1192
+ firstStatementStart(program) {
1193
+ if (program.body.length === 0) return Number.POSITIVE_INFINITY;
1194
+ return program.body[0].start ?? Number.POSITIVE_INFINITY;
1195
+ }
1196
+ emitCommentsBefore(pos) {
1197
+ if (pos < 0 || !Number.isFinite(pos)) return;
1198
+ while (this.commentIdx < this.sortedComments.length) {
1199
+ const c = this.sortedComments[this.commentIdx];
1200
+ if (c.start >= pos) break;
1201
+ this.emitComment(c);
1202
+ this.commentIdx++;
1203
+ }
1204
+ }
1205
+ emitRemainingComments() {
1206
+ while (this.commentIdx < this.sortedComments.length) {
1207
+ const c = this.sortedComments[this.commentIdx];
1208
+ this.emitComment(c);
1209
+ this.commentIdx++;
1210
+ }
1211
+ }
1212
+ emitComment(c) {
1213
+ if (c.type === "Line") this.out += `//${c.value}\n`;
1214
+ else this.out += `/*${c.value}*/\n`;
1215
+ }
1216
+ indent() {
1217
+ return " ".repeat(this.indentLevel);
1218
+ }
1219
+ nl() {
1220
+ this.out += "\n";
1221
+ }
1222
+ needsParens(childPrec, parentPrec, isRight, op) {
1223
+ if (childPrec < parentPrec) return true;
1224
+ if (childPrec > parentPrec) return false;
1225
+ if (op === "**") return !isRight;
1226
+ return isRight;
1227
+ }
1228
+ wrapIfNeeded(node, prec, parentPrec, isRight, op) {
1229
+ const inner = this.printExpressionToString(node, prec);
1230
+ if (this.needsParens(prec, parentPrec, isRight, op)) return `(${inner})`;
1231
+ return inner;
1232
+ }
1233
+ printExpressionToString(node, prec) {
1234
+ const saved = this.out;
1235
+ this.out = "";
1236
+ this.printNode(node, prec);
1237
+ const result = this.out;
1238
+ this.out = saved;
1239
+ return result;
1240
+ }
1241
+ printNode(node, prec) {
1242
+ if (!node) return;
1243
+ const t = node.type;
1244
+ if (t === "Literal") {
1245
+ this.printLiteral(node);
1246
+ return;
1247
+ }
1248
+ switch (t) {
1249
+ case "Identifier":
1250
+ this.printIdentifier(node);
1251
+ break;
1252
+ case "PrivateIdentifier":
1253
+ this.out += `#${node.name}`;
1254
+ break;
1255
+ case "ThisExpression":
1256
+ this.out += "this";
1257
+ break;
1258
+ case "Super":
1259
+ this.out += "super";
1260
+ break;
1261
+ case "ArrayExpression":
1262
+ this.printArrayExpression(node);
1263
+ break;
1264
+ case "ObjectExpression":
1265
+ this.printObjectExpression(node);
1266
+ break;
1267
+ case "Property":
1268
+ this.printProperty(node);
1269
+ break;
1270
+ case "TemplateLiteral":
1271
+ this.printTemplateLiteral(node);
1272
+ break;
1273
+ case "TemplateElement":
1274
+ this.out += node.value.raw;
1275
+ break;
1276
+ case "TaggedTemplateExpression":
1277
+ this.printTaggedTemplate(node);
1278
+ break;
1279
+ case "MemberExpression":
1280
+ this.printMemberExpression(node);
1281
+ break;
1282
+ case "CallExpression":
1283
+ this.printCallExpression(node, prec);
1284
+ break;
1285
+ case "NewExpression":
1286
+ this.printNewExpression(node, prec);
1287
+ break;
1288
+ case "MetaProperty":
1289
+ this.printMetaProperty(node);
1290
+ break;
1291
+ case "SpreadElement":
1292
+ this.out += "...";
1293
+ this.printNode(node.argument, PREC.Assignment);
1294
+ break;
1295
+ case "RestElement":
1296
+ this.out += "...";
1297
+ this.printNode(node.argument, PREC.Assignment);
1298
+ break;
1299
+ case "UpdateExpression":
1300
+ this.printUpdateExpression(node, prec);
1301
+ break;
1302
+ case "UnaryExpression":
1303
+ this.printUnaryExpression(node, prec);
1304
+ break;
1305
+ case "BinaryExpression":
1306
+ this.printBinaryExpression(node, prec);
1307
+ break;
1308
+ case "LogicalExpression":
1309
+ this.printLogicalExpression(node, prec);
1310
+ break;
1311
+ case "ConditionalExpression":
1312
+ this.printConditionalExpression(node, prec);
1313
+ break;
1314
+ case "AssignmentExpression":
1315
+ this.printAssignmentExpression(node, prec);
1316
+ break;
1317
+ case "AssignmentPattern":
1318
+ this.printAssignmentPattern(node, prec);
1319
+ break;
1320
+ case "ObjectPattern":
1321
+ this.printObjectPattern(node);
1322
+ break;
1323
+ case "ArrayPattern":
1324
+ this.printArrayPattern(node);
1325
+ break;
1326
+ case "SequenceExpression":
1327
+ this.printSequenceExpression(node, prec);
1328
+ break;
1329
+ case "AwaitExpression":
1330
+ this.out += "await ";
1331
+ this.printNode(node.argument, PREC.Unary);
1332
+ if (node.argument === null) {}
1333
+ break;
1334
+ case "YieldExpression":
1335
+ this.printYieldExpression(node, prec);
1336
+ break;
1337
+ case "ChainExpression":
1338
+ this.printNode(node.expression, prec);
1339
+ break;
1340
+ case "ParenthesizedExpression":
1341
+ this.out += "(";
1342
+ this.printNode(node.expression, PREC.Sequence);
1343
+ this.out += ")";
1344
+ break;
1345
+ case "ImportExpression":
1346
+ this.printImportExpression(node);
1347
+ break;
1348
+ case "V8IntrinsicExpression":
1349
+ this.printV8Intrinsic(node);
1350
+ break;
1351
+ case "ArrowFunctionExpression":
1352
+ this.printArrowFunction(node, prec);
1353
+ break;
1354
+ case "FunctionExpression":
1355
+ case "FunctionDeclaration":
1356
+ case "TSDeclareFunction":
1357
+ case "TSEmptyBodyFunctionExpression":
1358
+ this.printFunction(node, prec);
1359
+ break;
1360
+ case "ClassDeclaration":
1361
+ case "ClassExpression":
1362
+ this.printClass(node, prec);
1363
+ break;
1364
+ case "JSXElement":
1365
+ this.printJSXElement(node);
1366
+ break;
1367
+ case "JSXFragment":
1368
+ this.printJSXFragment(node);
1369
+ break;
1370
+ case "JSXOpeningElement":
1371
+ this.printJSXOpeningElement(node);
1372
+ break;
1373
+ case "JSXClosingElement": break;
1374
+ case "JSXIdentifier":
1375
+ this.out += node.name;
1376
+ break;
1377
+ case "JSXNamespacedName":
1378
+ this.out += `${node.namespace.name}:${node.name.name}`;
1379
+ break;
1380
+ case "JSXMemberExpression":
1381
+ this.printJSXMemberExpression(node);
1382
+ break;
1383
+ case "JSXAttribute":
1384
+ this.printJSXAttribute(node);
1385
+ break;
1386
+ case "JSXSpreadAttribute":
1387
+ this.out += "{...";
1388
+ this.printNode(node.argument, PREC.Assignment);
1389
+ this.out += "}";
1390
+ break;
1391
+ case "JSXExpressionContainer":
1392
+ this.out += "{";
1393
+ this.printNode(node.expression, PREC.Sequence);
1394
+ this.out += "}";
1395
+ break;
1396
+ case "JSXEmptyExpression": break;
1397
+ case "JSXText":
1398
+ this.out += node.value;
1399
+ break;
1400
+ case "JSXSpreadChild":
1401
+ this.out += "{...";
1402
+ this.printNode(node.expression, PREC.Assignment);
1403
+ this.out += "}";
1404
+ break;
1405
+ case "TSAsExpression":
1406
+ this.printTSAsExpression(node, prec);
1407
+ break;
1408
+ case "TSSatisfiesExpression":
1409
+ this.printTSSatisfiesExpression(node, prec);
1410
+ break;
1411
+ case "TSTypeAssertion":
1412
+ this.printTSTypeAssertion(node, prec);
1413
+ break;
1414
+ case "TSNonNullExpression":
1415
+ this.printNode(node.expression, PREC.Member);
1416
+ this.out += "!";
1417
+ break;
1418
+ case "TSInstantiationExpression":
1419
+ this.printTSInstantiationExpression(node, prec);
1420
+ break;
1421
+ case "BlockStatement":
1422
+ this.printBlockStatement(node);
1423
+ break;
1424
+ case "EmptyStatement":
1425
+ this.out += ";";
1426
+ break;
1427
+ case "ExpressionStatement":
1428
+ this.printExpressionStatement(node);
1429
+ break;
1430
+ case "IfStatement":
1431
+ this.printIfStatement(node);
1432
+ break;
1433
+ case "DoWhileStatement":
1434
+ this.printDoWhileStatement(node);
1435
+ break;
1436
+ case "WhileStatement":
1437
+ this.printWhileStatement(node);
1438
+ break;
1439
+ case "ForStatement":
1440
+ this.printForStatement(node);
1441
+ break;
1442
+ case "ForInStatement":
1443
+ this.printForInStatement(node);
1444
+ break;
1445
+ case "ForOfStatement":
1446
+ this.printForOfStatement(node);
1447
+ break;
1448
+ case "ContinueStatement":
1449
+ this.out += "continue";
1450
+ if (node.label) this.out += ` ${node.label.name}`;
1451
+ this.out += ";";
1452
+ break;
1453
+ case "BreakStatement":
1454
+ this.out += "break";
1455
+ if (node.label) this.out += ` ${node.label.name}`;
1456
+ this.out += ";";
1457
+ break;
1458
+ case "ReturnStatement":
1459
+ this.printReturnStatement(node);
1460
+ break;
1461
+ case "WithStatement":
1462
+ this.printWithStatement(node);
1463
+ break;
1464
+ case "SwitchStatement":
1465
+ this.printSwitchStatement(node);
1466
+ break;
1467
+ case "SwitchCase": break;
1468
+ case "LabeledStatement":
1469
+ this.printLabeledStatement(node);
1470
+ break;
1471
+ case "ThrowStatement":
1472
+ this.out += "throw ";
1473
+ this.printNode(node.argument, PREC.Sequence);
1474
+ this.out += ";";
1475
+ break;
1476
+ case "TryStatement":
1477
+ this.printTryStatement(node);
1478
+ break;
1479
+ case "CatchClause": break;
1480
+ case "DebuggerStatement":
1481
+ this.out += "debugger;";
1482
+ break;
1483
+ case "VariableDeclaration":
1484
+ this.printVariableDeclaration(node);
1485
+ break;
1486
+ case "VariableDeclarator":
1487
+ this.printVariableDeclarator(node);
1488
+ break;
1489
+ case "ClassBody":
1490
+ this.printClassBody(node);
1491
+ break;
1492
+ case "MethodDefinition":
1493
+ case "TSAbstractMethodDefinition":
1494
+ this.printMethodDefinition(node);
1495
+ break;
1496
+ case "PropertyDefinition":
1497
+ case "TSAbstractPropertyDefinition":
1498
+ this.printPropertyDefinition(node);
1499
+ break;
1500
+ case "AccessorProperty":
1501
+ case "TSAbstractAccessorProperty":
1502
+ this.printAccessorProperty(node);
1503
+ break;
1504
+ case "StaticBlock":
1505
+ this.printStaticBlock(node);
1506
+ break;
1507
+ case "ImportDeclaration":
1508
+ this.printImportDeclaration(node);
1509
+ break;
1510
+ case "ExportNamedDeclaration":
1511
+ this.printExportNamedDeclaration(node);
1512
+ break;
1513
+ case "ExportDefaultDeclaration":
1514
+ this.printExportDefaultDeclaration(node);
1515
+ break;
1516
+ case "ExportAllDeclaration":
1517
+ this.printExportAllDeclaration(node);
1518
+ break;
1519
+ case "Decorator":
1520
+ this.out += "@";
1521
+ this.printNode(node.expression, PREC.Member);
1522
+ break;
1523
+ case "TSTypeAliasDeclaration":
1524
+ this.printTSTypeAliasDeclaration(node);
1525
+ break;
1526
+ case "TSInterfaceDeclaration":
1527
+ this.printTSInterfaceDeclaration(node);
1528
+ break;
1529
+ case "TSEnumDeclaration":
1530
+ this.printTSEnumDeclaration(node);
1531
+ break;
1532
+ case "TSModuleDeclaration":
1533
+ this.printTSModuleDeclaration(node);
1534
+ break;
1535
+ case "TSImportEqualsDeclaration":
1536
+ this.printTSImportEqualsDeclaration(node);
1537
+ break;
1538
+ case "TSExportAssignment":
1539
+ this.out += `export = `;
1540
+ this.printNode(node.expression, PREC.Sequence);
1541
+ this.out += ";";
1542
+ break;
1543
+ case "TSNamespaceExportDeclaration":
1544
+ this.out += `export as namespace ${node.id.name};`;
1545
+ break;
1546
+ default: if (isTSTypeNode(t)) this.printTSType(node);
1547
+ else if (t === "TSTypeAnnotation") {
1548
+ this.out += ": ";
1549
+ this.printTSType(node.typeAnnotation);
1550
+ } else if (t === "TSTypeParameterDeclaration") this.printTSTypeParameterDeclaration(node);
1551
+ else if (t === "TSTypeParameterInstantiation") this.printTSTypeParameterInstantiation(node);
1552
+ else if (t === "TSTypeParameter") this.printTSTypeParameter(node);
1553
+ else this.out += `/* unknown:${t} */`;
1554
+ }
1555
+ }
1556
+ printLiteral(node) {
1557
+ if (node.raw != null) {
1558
+ this.out += node.raw;
1559
+ return;
1560
+ }
1561
+ if (node.regex) {
1562
+ this.out += `/${node.regex.pattern}/${node.regex.flags}`;
1563
+ return;
1564
+ }
1565
+ if (node.bigint != null) {
1566
+ this.out += node.bigint;
1567
+ return;
1568
+ }
1569
+ const v = node.value;
1570
+ if (v === null) this.out += "null";
1571
+ else if (typeof v === "string") this.out += JSON.stringify(v);
1572
+ else if (typeof v === "number") this.out += String(v);
1573
+ else if (typeof v === "boolean") this.out += v ? "true" : "false";
1574
+ else if (typeof v === "bigint") this.out += `${v}n`;
1575
+ else this.out += "null";
1576
+ }
1577
+ printIdentifier(node) {
1578
+ this.out += node.name;
1579
+ }
1580
+ printArrayExpression(node) {
1581
+ this.out += "[";
1582
+ for (let i = 0; i < node.elements.length; i++) {
1583
+ if (i > 0) this.out += ", ";
1584
+ const el = node.elements[i];
1585
+ if (el === null) continue;
1586
+ this.printNode(el, PREC.Assignment);
1587
+ }
1588
+ this.out += "]";
1589
+ }
1590
+ printObjectExpression(node) {
1591
+ if (node.properties.length === 0) {
1592
+ this.out += "{}";
1593
+ return;
1594
+ }
1595
+ this.out += "{ ";
1596
+ for (let i = 0; i < node.properties.length; i++) {
1597
+ if (i > 0) this.out += ", ";
1598
+ this.printNode(node.properties[i], PREC.Sequence);
1599
+ }
1600
+ this.out += " }";
1601
+ }
1602
+ printProperty(node) {
1603
+ const n = node;
1604
+ const kind = n["kind"];
1605
+ const method = n["method"];
1606
+ const shorthand = n["shorthand"];
1607
+ const computed = n["computed"];
1608
+ const key = n["key"];
1609
+ const value = n["value"];
1610
+ if (kind === "get" || kind === "set") {
1611
+ this.out += `${kind} `;
1612
+ this.printPropertyKey(key, !!computed);
1613
+ this.printFunctionValue(value);
1614
+ return;
1615
+ }
1616
+ if (method) {
1617
+ if (n["async"]) this.out += "async ";
1618
+ if (n["generator"]) this.out += "*";
1619
+ this.printPropertyKey(key, !!computed);
1620
+ this.printFunctionValue(value);
1621
+ return;
1622
+ }
1623
+ if (shorthand && key.type === "Identifier" && value && value.type === "Identifier") {
1624
+ const kName = key.name;
1625
+ if (kName === value.name) {
1626
+ this.out += kName;
1627
+ return;
1628
+ }
1629
+ }
1630
+ const defaultPattern = value;
1631
+ if (shorthand && key.type === "Identifier" && defaultPattern && defaultPattern.type === "AssignmentPattern" && defaultPattern.left.type === "Identifier" && defaultPattern.left.name === key.name) {
1632
+ const kName = key.name;
1633
+ const savedOut = this.out;
1634
+ this.out = "";
1635
+ this.printNode(defaultPattern.right, PREC.Assignment);
1636
+ const rightStr = this.out;
1637
+ this.out = savedOut;
1638
+ this.out += `${kName} = ${rightStr}`;
1639
+ return;
1640
+ }
1641
+ this.printPropertyKey(key, !!computed);
1642
+ this.out += ": ";
1643
+ if (value) this.printNode(value, PREC.Assignment);
1644
+ }
1645
+ printPropertyKey(key, computed) {
1646
+ if (computed) {
1647
+ this.out += "[";
1648
+ this.printNode(key, PREC.Assignment);
1649
+ this.out += "]";
1650
+ } else if (key.type === "Identifier") this.out += key.name;
1651
+ else if (key.type === "PrivateIdentifier") this.out += `#${key.name}`;
1652
+ else if (key.type === "Literal") this.printLiteral(key);
1653
+ else this.printNode(key, PREC.Assignment);
1654
+ }
1655
+ printFunctionValue(fn) {
1656
+ if (!fn) return;
1657
+ if (fn.typeParameters) this.printTSTypeParameterDeclaration(fn.typeParameters);
1658
+ this.out += "(";
1659
+ this.printParams(fn.params);
1660
+ this.out += ")";
1661
+ if (fn.returnType) this.printTSTypeAnnotation(fn.returnType);
1662
+ if (fn.body) {
1663
+ this.out += " ";
1664
+ this.printBlockStatement(fn.body);
1665
+ } else this.out += ";";
1666
+ }
1667
+ printTemplateLiteral(node) {
1668
+ this.out += "`";
1669
+ for (let i = 0; i < node.quasis.length; i++) {
1670
+ const q = node.quasis[i];
1671
+ this.out += q.value.raw;
1672
+ if (!q.tail) {
1673
+ this.out += "${";
1674
+ this.printNode(node.expressions[i], PREC.Sequence);
1675
+ this.out += "}";
1676
+ }
1677
+ }
1678
+ this.out += "`";
1679
+ }
1680
+ printTaggedTemplate(node) {
1681
+ this.printNode(node.tag, PREC.Member);
1682
+ if (node.typeArguments) this.printTSTypeParameterInstantiation(node.typeArguments);
1683
+ this.printTemplateLiteral(node.quasi);
1684
+ }
1685
+ printMemberExpression(node, prec = PREC.Member) {
1686
+ const n = node;
1687
+ const computed = n["computed"];
1688
+ const optional = n["optional"];
1689
+ const object = n["object"];
1690
+ const property = n["property"];
1691
+ const objStr = this.printExpressionToString(object, PREC.Member);
1692
+ const objOut = needsParensForMemberObject(object) ? `(${objStr})` : objStr;
1693
+ if (optional) {
1694
+ if (computed) {
1695
+ this.out += `${objOut}?.[`;
1696
+ this.printNode(property, PREC.Sequence);
1697
+ this.out += "]";
1698
+ } else {
1699
+ const propName = property.type === "Identifier" ? property.name : property.type === "PrivateIdentifier" ? `#${property.name}` : "";
1700
+ if (propName) this.out += `${objOut}?.${propName}`;
1701
+ else {
1702
+ this.out += `${objOut}?.`;
1703
+ this.printNode(property, PREC.Sequence);
1704
+ }
1705
+ }
1706
+ } else if (computed) {
1707
+ this.out += `${objOut}[`;
1708
+ this.printNode(property, PREC.Sequence);
1709
+ this.out += "]";
1710
+ } else {
1711
+ const propName = property.type === "Identifier" ? property.name : property.type === "PrivateIdentifier" ? `#${property.name}` : "";
1712
+ if (propName) this.out += `${objOut}.${propName}`;
1713
+ else {
1714
+ this.out += `${objOut}.`;
1715
+ this.printNode(property, PREC.Sequence);
1716
+ }
1717
+ }
1718
+ }
1719
+ printCallExpression(node, prec) {
1720
+ const calleePrec = PREC.Member;
1721
+ const calleeStr = this.printExpressionToString(node.callee, calleePrec);
1722
+ const calleeNeedsParen = node.callee.type === "SequenceExpression" || node.callee.type === "ConditionalExpression";
1723
+ this.out += calleeNeedsParen ? `(${calleeStr})` : calleeStr;
1724
+ if (node.optional) this.out += "?.";
1725
+ if (node.typeArguments) this.printTSTypeParameterInstantiation(node.typeArguments);
1726
+ this.out += "(";
1727
+ for (let i = 0; i < node.arguments.length; i++) {
1728
+ if (i > 0) this.out += ", ";
1729
+ this.printNode(node.arguments[i], PREC.Assignment);
1730
+ }
1731
+ this.out += ")";
1732
+ }
1733
+ printNewExpression(node, prec) {
1734
+ this.out += "new ";
1735
+ const calleeStr = this.printExpressionToString(node.callee, PREC.Member);
1736
+ this.out += calleeStr;
1737
+ if (node.typeArguments) this.printTSTypeParameterInstantiation(node.typeArguments);
1738
+ this.out += "(";
1739
+ for (let i = 0; i < node.arguments.length; i++) {
1740
+ if (i > 0) this.out += ", ";
1741
+ this.printNode(node.arguments[i], PREC.Assignment);
1742
+ }
1743
+ this.out += ")";
1744
+ }
1745
+ printMetaProperty(node) {
1746
+ this.out += `${node.meta.name}.${node.property.name}`;
1747
+ }
1748
+ printV8Intrinsic(node) {
1749
+ this.out += `%${node.name.name}(`;
1750
+ for (let i = 0; i < node.arguments.length; i++) {
1751
+ if (i > 0) this.out += ", ";
1752
+ this.printNode(node.arguments[i], PREC.Assignment);
1753
+ }
1754
+ this.out += ")";
1755
+ }
1756
+ printImportExpression(node) {
1757
+ this.out += "import";
1758
+ if (node.phase) this.out += `.${node.phase}`;
1759
+ this.out += "(";
1760
+ this.printNode(node.source, PREC.Assignment);
1761
+ if (node.options) {
1762
+ this.out += ", ";
1763
+ this.printNode(node.options, PREC.Assignment);
1764
+ }
1765
+ this.out += ")";
1766
+ }
1767
+ printUpdateExpression(node, prec) {
1768
+ const myPrec = PREC.Update;
1769
+ if (node.prefix) {
1770
+ this.out += node.operator;
1771
+ const argStr = this.printExpressionToString(node.argument, myPrec);
1772
+ const needsParen = needsParensForMemberObject(node.argument);
1773
+ this.out += needsParen ? `(${argStr})` : argStr;
1774
+ } else {
1775
+ const argStr = this.printExpressionToString(node.argument, myPrec);
1776
+ const needsParen = needsParensForMemberObject(node.argument);
1777
+ this.out += needsParen ? `(${argStr})` : argStr;
1778
+ this.out += node.operator;
1779
+ }
1780
+ }
1781
+ printUnaryExpression(node, prec) {
1782
+ const myPrec = PREC.Unary;
1783
+ const op = node.operator;
1784
+ const needsSpace = op === "typeof" || op === "void" || op === "delete";
1785
+ this.out += op + (needsSpace ? " " : "");
1786
+ const argStr = this.printExpressionToString(node.argument, myPrec);
1787
+ const argNeedsParen = node.argument.type === "BinaryExpression" || node.argument.type === "LogicalExpression" || node.argument.type === "ConditionalExpression" || node.argument.type === "SequenceExpression";
1788
+ this.out += argNeedsParen ? `(${argStr})` : argStr;
1789
+ }
1790
+ printBinaryExpression(node, prec) {
1791
+ const myPrec = binaryPrec(node.operator);
1792
+ const leftStr = this.wrapIfNeeded(node.left, precOf(node.left), myPrec, false, node.operator);
1793
+ const rightStr = this.wrapIfNeeded(node.right, precOf(node.right), myPrec, true, node.operator);
1794
+ const whole = `${leftStr} ${node.operator} ${rightStr}`;
1795
+ if (myPrec < prec) this.out += `(${whole})`;
1796
+ else this.out += whole;
1797
+ }
1798
+ printLogicalExpression(node, prec) {
1799
+ const myPrec = logicalPrec(node.operator);
1800
+ const leftStr = this.wrapIfNeeded(node.left, precOf(node.left), myPrec, false, node.operator);
1801
+ const rightStr = this.wrapIfNeeded(node.right, precOf(node.right), myPrec, true, node.operator);
1802
+ const whole = `${leftStr} ${node.operator} ${rightStr}`;
1803
+ if (myPrec < prec) this.out += `(${whole})`;
1804
+ else this.out += whole;
1805
+ }
1806
+ printConditionalExpression(node, prec) {
1807
+ const myPrec = PREC.Conditional;
1808
+ const whole = `${this.wrapIfNeeded(node.test, precOf(node.test), myPrec, false)} ? ${this.printExpressionToString(node.consequent, PREC.Assignment)} : ${this.printExpressionToString(node.alternate, PREC.Assignment)}`;
1809
+ if (myPrec < prec) this.out += `(${whole})`;
1810
+ else this.out += whole;
1811
+ }
1812
+ printAssignmentExpression(node, prec) {
1813
+ const myPrec = PREC.Assignment;
1814
+ const leftStr = this.printExpressionToString(node.left, myPrec);
1815
+ const rightStr = this.printExpressionToString(node.right, myPrec - .1);
1816
+ const whole = `${leftStr} ${node.operator} ${rightStr}`;
1817
+ if (myPrec < prec) this.out += `(${whole})`;
1818
+ else this.out += whole;
1819
+ }
1820
+ printAssignmentPattern(node, prec) {
1821
+ const leftStr = this.printExpressionToString(node.left, PREC.Assignment);
1822
+ const annotation = node.left.typeAnnotation;
1823
+ const rightStr = this.printExpressionToString(node.right, PREC.Assignment);
1824
+ let whole = leftStr;
1825
+ if (annotation) {
1826
+ const saved = this.out;
1827
+ this.out = "";
1828
+ this.printTSTypeAnnotation(annotation);
1829
+ whole += this.out;
1830
+ this.out = saved;
1831
+ }
1832
+ whole += ` = ${rightStr}`;
1833
+ if (PREC.Assignment < prec) this.out += `(${whole})`;
1834
+ else this.out += whole;
1835
+ }
1836
+ printObjectPattern(node) {
1837
+ if (node.properties.length === 0) {
1838
+ this.out += "{}";
1839
+ return;
1840
+ }
1841
+ this.out += "{ ";
1842
+ for (let i = 0; i < node.properties.length; i++) {
1843
+ if (i > 0) this.out += ", ";
1844
+ this.printNode(node.properties[i], PREC.Sequence);
1845
+ }
1846
+ this.out += " }";
1847
+ }
1848
+ printArrayPattern(node) {
1849
+ this.out += "[";
1850
+ for (let i = 0; i < node.elements.length; i++) {
1851
+ if (i > 0) this.out += ", ";
1852
+ const el = node.elements[i];
1853
+ if (el === null) continue;
1854
+ this.printNode(el, PREC.Assignment);
1855
+ }
1856
+ this.out += "]";
1857
+ }
1858
+ printSequenceExpression(node, prec) {
1859
+ const myPrec = PREC.Sequence;
1860
+ const parts = [];
1861
+ for (const expr of node.expressions) parts.push(this.printExpressionToString(expr, myPrec));
1862
+ const whole = parts.join(", ");
1863
+ if (myPrec < prec) this.out += `(${whole})`;
1864
+ else this.out += whole;
1865
+ }
1866
+ printYieldExpression(node, prec) {
1867
+ PREC.Unary;
1868
+ if (node.delegate) this.out += "yield*";
1869
+ else this.out += "yield";
1870
+ if (node.argument) {
1871
+ this.out += " ";
1872
+ this.printNode(node.argument, PREC.Assignment);
1873
+ }
1874
+ }
1875
+ printArrowFunction(node, prec) {
1876
+ const myPrec = PREC.Assignment;
1877
+ let arrow = "";
1878
+ if (node.async) arrow += "async ";
1879
+ if (node.typeParameters) {
1880
+ const saved = this.out;
1881
+ this.out = "";
1882
+ this.printTSTypeParameterDeclaration(node.typeParameters);
1883
+ const tp = this.out;
1884
+ this.out = saved;
1885
+ arrow += tp;
1886
+ }
1887
+ const singleParam = node.params[0];
1888
+ if (node.params.length === 1 && singleParam?.type === "Identifier" && !singleParam.typeAnnotation && !node.returnType) arrow += singleParam.name;
1889
+ else {
1890
+ arrow += "(";
1891
+ const saved = this.out;
1892
+ this.out = "";
1893
+ this.printParams(node.params);
1894
+ const p = this.out;
1895
+ this.out = saved;
1896
+ arrow += p + ")";
1897
+ }
1898
+ if (node.returnType) {
1899
+ const saved = this.out;
1900
+ this.out = "";
1901
+ this.printTSTypeAnnotation(node.returnType);
1902
+ const rt = this.out;
1903
+ this.out = saved;
1904
+ arrow += rt;
1905
+ }
1906
+ arrow += " => ";
1907
+ if (typeof node.body === "object" && node.body !== null && node.body.type === "BlockStatement") {
1908
+ const saved = this.out;
1909
+ this.out = "";
1910
+ this.printBlockStatement(node.body);
1911
+ const b = this.out;
1912
+ this.out = saved;
1913
+ arrow += b;
1914
+ } else {
1915
+ const saved = this.out;
1916
+ this.out = "";
1917
+ this.printNode(node.body, PREC.Assignment);
1918
+ const b = this.out;
1919
+ this.out = saved;
1920
+ arrow += b;
1921
+ }
1922
+ if (myPrec < prec) this.out += `(${arrow})`;
1923
+ else this.out += arrow;
1924
+ }
1925
+ printFunction(node, _prec) {
1926
+ if (node.declare) this.out += "declare ";
1927
+ if (node.async) this.out += "async ";
1928
+ this.out += "function";
1929
+ if (node.generator) this.out += "*";
1930
+ if (node.id) this.out += ` ${node.id.name}`;
1931
+ if (node.typeParameters) this.printTSTypeParameterDeclaration(node.typeParameters);
1932
+ this.out += "(";
1933
+ this.printParams(node.params);
1934
+ this.out += ")";
1935
+ if (node.returnType) this.printTSTypeAnnotation(node.returnType);
1936
+ if (node.body) {
1937
+ this.out += " ";
1938
+ this.printBlockStatement(node.body);
1939
+ } else this.out += ";";
1940
+ }
1941
+ printClass(node, _prec) {
1942
+ this.printDecorators(node.decorators);
1943
+ if (node.declare) this.out += "declare ";
1944
+ if (node.abstract) this.out += "abstract ";
1945
+ this.out += "class";
1946
+ if (node.id) this.out += ` ${node.id.name}`;
1947
+ if (node.typeParameters) this.printTSTypeParameterDeclaration(node.typeParameters);
1948
+ if (node.superClass) {
1949
+ this.out += " extends ";
1950
+ this.printNode(node.superClass, PREC.Assignment);
1951
+ if (node.superTypeArguments) this.printTSTypeParameterInstantiation(node.superTypeArguments);
1952
+ }
1953
+ if (node.implements && node.implements.length > 0) {
1954
+ this.out += " implements ";
1955
+ for (let i = 0; i < node.implements.length; i++) {
1956
+ if (i > 0) this.out += ", ";
1957
+ const impl = node.implements[i];
1958
+ this.printNode(impl.expression, PREC.Assignment);
1959
+ if (impl.typeArguments) this.printTSTypeParameterInstantiation(impl.typeArguments);
1960
+ }
1961
+ }
1962
+ this.out += " ";
1963
+ this.printClassBody(node.body);
1964
+ }
1965
+ printDecorators(decorators) {
1966
+ if (!decorators || decorators.length === 0) return;
1967
+ for (const d of decorators) {
1968
+ this.out += "@";
1969
+ this.printNode(d.expression, PREC.Member);
1970
+ this.out += " ";
1971
+ }
1972
+ }
1973
+ printJSXElement(node) {
1974
+ this.printJSXOpeningElement(node.openingElement);
1975
+ for (const child of node.children) this.printJSXChild(child);
1976
+ if (node.closingElement) {
1977
+ this.out += `</`;
1978
+ this.printJSXElementName(node.closingElement.name);
1979
+ this.out += ">";
1980
+ }
1981
+ }
1982
+ printJSXFragment(node) {
1983
+ this.out += "<>";
1984
+ for (const child of node.children) this.printJSXChild(child);
1985
+ this.out += "</>";
1986
+ }
1987
+ printJSXOpeningElement(node) {
1988
+ this.out += "<";
1989
+ this.printJSXElementName(node.name);
1990
+ if (node.typeArguments) this.printTSTypeParameterInstantiation(node.typeArguments);
1991
+ for (const attr of node.attributes) {
1992
+ this.out += " ";
1993
+ this.printNode(attr, PREC.Sequence);
1994
+ }
1995
+ this.out += node.selfClosing ? " />" : ">";
1996
+ }
1997
+ printJSXElementName(name) {
1998
+ if (name.type === "JSXIdentifier") this.out += name.name;
1999
+ else if (name.type === "JSXNamespacedName") this.out += `${name.namespace.name}:${name.name.name}`;
2000
+ else this.printJSXMemberExpression(name);
2001
+ }
2002
+ printJSXMemberExpression(node) {
2003
+ const obj = node.object;
2004
+ if (obj.type === "JSXIdentifier") this.out += `${obj.name}.${node.property.name}`;
2005
+ else {
2006
+ this.printJSXMemberExpression(obj);
2007
+ this.out += `.${node.property.name}`;
2008
+ }
2009
+ }
2010
+ printJSXAttribute(node) {
2011
+ const n = node.name;
2012
+ if (n.type === "JSXIdentifier") this.out += n.name;
2013
+ else this.out += `${n.namespace.name}:${n.name.name}`;
2014
+ if (node.value) {
2015
+ this.out += "=";
2016
+ if (node.value.type === "Literal") this.printLiteral(node.value);
2017
+ else if (node.value.type === "JSXExpressionContainer") {
2018
+ this.out += "{";
2019
+ this.printNode(node.value.expression, PREC.Sequence);
2020
+ this.out += "}";
2021
+ } else this.printNode(node.value, PREC.Sequence);
2022
+ }
2023
+ }
2024
+ printJSXChild(child) {
2025
+ switch (child.type) {
2026
+ case "JSXText":
2027
+ this.out += child.value;
2028
+ break;
2029
+ case "JSXElement":
2030
+ this.printJSXElement(child);
2031
+ break;
2032
+ case "JSXFragment":
2033
+ this.printJSXFragment(child);
2034
+ break;
2035
+ case "JSXExpressionContainer":
2036
+ this.out += "{";
2037
+ this.printNode(child.expression, PREC.Sequence);
2038
+ this.out += "}";
2039
+ break;
2040
+ case "JSXSpreadChild":
2041
+ this.out += "{...";
2042
+ this.printNode(child.expression, PREC.Assignment);
2043
+ this.out += "}";
2044
+ break;
2045
+ default: this.printNode(child, PREC.Sequence);
2046
+ }
2047
+ }
2048
+ printTSAsExpression(node, prec) {
2049
+ const myPrec = PREC.Relational;
2050
+ const whole = `${this.printExpressionToString(node.expression, myPrec)} as ${this.printTSTypeToString(node.typeAnnotation)}`;
2051
+ if (myPrec < prec) this.out += `(${whole})`;
2052
+ else this.out += whole;
2053
+ }
2054
+ printTSSatisfiesExpression(node, prec) {
2055
+ const myPrec = PREC.Relational;
2056
+ const whole = `${this.printExpressionToString(node.expression, myPrec)} satisfies ${this.printTSTypeToString(node.typeAnnotation)}`;
2057
+ if (myPrec < prec) this.out += `(${whole})`;
2058
+ else this.out += whole;
2059
+ }
2060
+ printTSTypeAssertion(node, _prec) {
2061
+ this.out += `<${this.printTSTypeToString(node.typeAnnotation)}>`;
2062
+ this.printNode(node.expression, PREC.Unary);
2063
+ }
2064
+ printTSInstantiationExpression(node, _prec) {
2065
+ this.printNode(node.expression, PREC.Member);
2066
+ this.printTSTypeParameterInstantiation(node.typeArguments);
2067
+ }
2068
+ printStatement(node) {
2069
+ const n = node;
2070
+ this.printAttachedComments(n, "leadingComments");
2071
+ switch (n.type) {
2072
+ case "BlockStatement":
2073
+ this.printBlockStatement(n);
2074
+ break;
2075
+ case "VariableDeclaration":
2076
+ this.printVariableDeclaration(n);
2077
+ this.out += ";";
2078
+ break;
2079
+ case "FunctionDeclaration":
2080
+ case "TSDeclareFunction":
2081
+ this.printFunction(n, PREC.Sequence);
2082
+ break;
2083
+ case "ClassDeclaration":
2084
+ this.printClass(n, PREC.Sequence);
2085
+ break;
2086
+ case "ExpressionStatement":
2087
+ this.printExpressionStatement(n);
2088
+ break;
2089
+ case "IfStatement":
2090
+ this.printIfStatement(n);
2091
+ break;
2092
+ case "ForStatement":
2093
+ this.printForStatement(n);
2094
+ break;
2095
+ case "ForInStatement":
2096
+ this.printForInStatement(n);
2097
+ break;
2098
+ case "ForOfStatement":
2099
+ this.printForOfStatement(n);
2100
+ break;
2101
+ case "WhileStatement":
2102
+ this.printWhileStatement(n);
2103
+ break;
2104
+ case "DoWhileStatement":
2105
+ this.printDoWhileStatement(n);
2106
+ break;
2107
+ case "ReturnStatement":
2108
+ this.printReturnStatement(n);
2109
+ break;
2110
+ case "ThrowStatement":
2111
+ this.out += "throw ";
2112
+ this.printNode(n.argument, PREC.Sequence);
2113
+ this.out += ";";
2114
+ break;
2115
+ case "TryStatement":
2116
+ this.printTryStatement(n);
2117
+ break;
2118
+ case "SwitchStatement":
2119
+ this.printSwitchStatement(n);
2120
+ break;
2121
+ case "LabeledStatement":
2122
+ this.printLabeledStatement(n);
2123
+ break;
2124
+ case "BreakStatement":
2125
+ case "ContinueStatement":
2126
+ case "DebuggerStatement":
2127
+ case "EmptyStatement":
2128
+ this.printNode(n, PREC.Sequence);
2129
+ break;
2130
+ case "WithStatement":
2131
+ this.printWithStatement(n);
2132
+ break;
2133
+ case "ImportDeclaration":
2134
+ this.printImportDeclaration(n);
2135
+ break;
2136
+ case "ExportNamedDeclaration":
2137
+ this.printExportNamedDeclaration(n);
2138
+ break;
2139
+ case "ExportDefaultDeclaration":
2140
+ this.printExportDefaultDeclaration(n);
2141
+ break;
2142
+ case "ExportAllDeclaration":
2143
+ this.printExportAllDeclaration(n);
2144
+ break;
2145
+ case "TSTypeAliasDeclaration":
2146
+ this.printTSTypeAliasDeclaration(n);
2147
+ break;
2148
+ case "TSInterfaceDeclaration":
2149
+ this.printTSInterfaceDeclaration(n);
2150
+ break;
2151
+ case "TSEnumDeclaration":
2152
+ this.printTSEnumDeclaration(n);
2153
+ break;
2154
+ case "TSModuleDeclaration":
2155
+ this.printTSModuleDeclaration(n);
2156
+ break;
2157
+ case "TSImportEqualsDeclaration":
2158
+ this.printTSImportEqualsDeclaration(n);
2159
+ break;
2160
+ case "TSExportAssignment":
2161
+ case "TSNamespaceExportDeclaration":
2162
+ this.printNode(n, PREC.Sequence);
2163
+ break;
2164
+ default: if (isTSTypeNode(n.type)) {
2165
+ this.printTSType(n);
2166
+ this.out += ";";
2167
+ } else throw new Error(`Printer: unhandled statement kind ${n.type}`);
2168
+ }
2169
+ this.printAttachedComments(n, "trailingComments");
2170
+ }
2171
+ /**
2172
+ * Emits the comments `attachComments` folded into the tree
2173
+ * (`leadingComments` before the statement, `trailingComments` on the
2174
+ * statement's last line). The flat `opts.comments` path only serves direct
2175
+ * `printProgram` calls on freshly parsed trees; instrumented trees carry
2176
+ * their comments attached to nodes.
2177
+ */
2178
+ printAttachedComments(node, field) {
2179
+ const comments = node[field];
2180
+ if (!Array.isArray(comments)) return;
2181
+ for (const comment of comments) {
2182
+ if (field === "leadingComments") this.out += this.indent();
2183
+ if (comment.type === "Block") this.out += `/*${comment.value}*/`;
2184
+ else this.out += `//${comment.value}`;
2185
+ this.out += field === "leadingComments" ? "\n" : " ";
2186
+ }
2187
+ }
2188
+ printBlockStatement(node) {
2189
+ if (node.body.length === 0) {
2190
+ this.out += "{}";
2191
+ return;
2192
+ }
2193
+ this.out += "{\n";
2194
+ this.indentLevel++;
2195
+ for (const stmt of node.body) {
2196
+ this.out += this.indent();
2197
+ this.printStatement(stmt);
2198
+ this.out += "\n";
2199
+ }
2200
+ this.indentLevel--;
2201
+ this.out += `${this.indent()}}`;
2202
+ }
2203
+ printExpressionStatement(node) {
2204
+ if (node.directive) {
2205
+ this.out += JSON.stringify(node.directive) + ";";
2206
+ return;
2207
+ }
2208
+ this.printNode(node.expression, PREC.Sequence);
2209
+ this.out += ";";
2210
+ }
2211
+ printIfStatement(node) {
2212
+ this.out += "if (";
2213
+ this.printNode(node.test, PREC.Sequence);
2214
+ this.out += ") ";
2215
+ this.printStatementOrBlock(node.consequent);
2216
+ if (node.alternate) {
2217
+ this.out += " else ";
2218
+ this.printStatementOrBlock(node.alternate);
2219
+ }
2220
+ }
2221
+ printStatementOrBlock(node) {
2222
+ if (node.type === "BlockStatement") this.printBlockStatement(node);
2223
+ else this.printStatement(node);
2224
+ }
2225
+ printWhileStatement(node) {
2226
+ this.out += "while (";
2227
+ this.printNode(node.test, PREC.Sequence);
2228
+ this.out += ") ";
2229
+ this.printStatementOrBlock(node.body);
2230
+ }
2231
+ printDoWhileStatement(node) {
2232
+ this.out += "do ";
2233
+ this.printStatementOrBlock(node.body);
2234
+ this.out += " while (";
2235
+ this.printNode(node.test, PREC.Sequence);
2236
+ this.out += ");";
2237
+ }
2238
+ printForStatement(node) {
2239
+ this.out += "for (";
2240
+ if (node.init) {
2241
+ if (node.init.type === "VariableDeclaration") this.printVariableDeclaration(node.init);
2242
+ else this.printNode(node.init, PREC.Sequence);
2243
+ }
2244
+ this.out += "; ";
2245
+ if (node.test) this.printNode(node.test, PREC.Sequence);
2246
+ this.out += "; ";
2247
+ if (node.update) this.printNode(node.update, PREC.Sequence);
2248
+ this.out += ") ";
2249
+ this.printStatementOrBlock(node.body);
2250
+ }
2251
+ printForInStatement(node) {
2252
+ this.out += "for (";
2253
+ if (node.left.type === "VariableDeclaration") this.printVariableDeclaration(node.left);
2254
+ else this.printNode(node.left, PREC.Sequence);
2255
+ this.out += " in ";
2256
+ this.printNode(node.right, PREC.Sequence);
2257
+ this.out += ") ";
2258
+ this.printStatementOrBlock(node.body);
2259
+ }
2260
+ printForOfStatement(node) {
2261
+ this.out += node.await ? "for await (" : "for (";
2262
+ if (node.left.type === "VariableDeclaration") this.printVariableDeclaration(node.left);
2263
+ else this.printNode(node.left, PREC.Sequence);
2264
+ this.out += " of ";
2265
+ this.printNode(node.right, PREC.Sequence);
2266
+ this.out += ") ";
2267
+ this.printStatementOrBlock(node.body);
2268
+ }
2269
+ printReturnStatement(node) {
2270
+ if (node.argument) {
2271
+ this.out += "return ";
2272
+ this.printNode(node.argument, PREC.Sequence);
2273
+ this.out += ";";
2274
+ } else this.out += "return;";
2275
+ }
2276
+ printWithStatement(node) {
2277
+ this.out += "with (";
2278
+ this.printNode(node.object, PREC.Sequence);
2279
+ this.out += ") ";
2280
+ this.printStatementOrBlock(node.body);
2281
+ }
2282
+ printSwitchStatement(node) {
2283
+ this.out += "switch (";
2284
+ this.printNode(node.discriminant, PREC.Sequence);
2285
+ this.out += ") {\n";
2286
+ this.indentLevel++;
2287
+ for (const c of node.cases) {
2288
+ this.out += this.indent();
2289
+ if (c.test) {
2290
+ this.out += "case ";
2291
+ this.printNode(c.test, PREC.Sequence);
2292
+ this.out += ":\n";
2293
+ } else this.out += "default:\n";
2294
+ this.indentLevel++;
2295
+ for (const stmt of c.consequent) {
2296
+ this.out += this.indent();
2297
+ this.printStatement(stmt);
2298
+ this.out += "\n";
2299
+ }
2300
+ this.indentLevel--;
2301
+ }
2302
+ this.indentLevel--;
2303
+ this.out += `${this.indent()}}`;
2304
+ }
2305
+ printLabeledStatement(node) {
2306
+ this.out += `${node.label.name}: `;
2307
+ this.printStatement(node.body);
2308
+ }
2309
+ printTryStatement(node) {
2310
+ this.out += "try ";
2311
+ this.printBlockStatement(node.block);
2312
+ if (node.handler) {
2313
+ this.out += " catch";
2314
+ if (node.handler.param) {
2315
+ this.out += " (";
2316
+ if (node.handler.param.type === "Identifier") this.printIdentifierWithOptional(node.handler.param);
2317
+ else this.printNode(node.handler.param, PREC.Sequence);
2318
+ this.out += ")";
2319
+ }
2320
+ this.out += " ";
2321
+ this.printBlockStatement(node.handler.body);
2322
+ }
2323
+ if (node.finalizer) {
2324
+ this.out += " finally ";
2325
+ this.printBlockStatement(node.finalizer);
2326
+ }
2327
+ }
2328
+ printVariableDeclaration(node) {
2329
+ if (node.declare) this.out += "declare ";
2330
+ this.out += `${node.kind} `;
2331
+ for (let i = 0; i < node.declarations.length; i++) {
2332
+ if (i > 0) this.out += ", ";
2333
+ this.printVariableDeclarator(node.declarations[i]);
2334
+ }
2335
+ }
2336
+ printVariableDeclarator(node) {
2337
+ const idWithType = node.id;
2338
+ if (idWithType.type === "Identifier" && idWithType.name) {
2339
+ this.out += idWithType.name;
2340
+ if (idWithType.optional) this.out += "?";
2341
+ if (node["definite"]) this.out += "!";
2342
+ if (idWithType.typeAnnotation) this.printTSTypeAnnotation(idWithType.typeAnnotation);
2343
+ } else if (idWithType.type === "Identifier" && idWithType.optional) {
2344
+ this.out += "?";
2345
+ if (node["definite"]) this.out += "!";
2346
+ if (idWithType.typeAnnotation) this.printTSTypeAnnotation(idWithType.typeAnnotation);
2347
+ } else {
2348
+ this.printNode(node.id, PREC.Sequence);
2349
+ if (node["definite"]) this.out += "!";
2350
+ if (idWithType.typeAnnotation) this.printTSTypeAnnotation(idWithType.typeAnnotation);
2351
+ }
2352
+ if (node.init) {
2353
+ this.out += " = ";
2354
+ this.printNode(node.init, PREC.Assignment);
2355
+ }
2356
+ }
2357
+ printParams(params) {
2358
+ for (let i = 0; i < params.length; i++) {
2359
+ if (i > 0) this.out += ", ";
2360
+ const p = params[i];
2361
+ if (p["type"] === "RestElement") {
2362
+ this.out += "...";
2363
+ this.printNode(p["argument"], PREC.Assignment);
2364
+ if (p["typeAnnotation"]) this.printTSTypeAnnotation(p["typeAnnotation"]);
2365
+ } else if (p["type"] === "TSParameterProperty") {
2366
+ const pp = p;
2367
+ this.printDecorators(pp.decorators);
2368
+ if (pp.accessibility) this.out += `${pp.accessibility} `;
2369
+ if (pp.readonly) this.out += "readonly ";
2370
+ if (pp.override) this.out += "override ";
2371
+ if (pp.static) this.out += "static ";
2372
+ const inner = pp.parameter;
2373
+ if (inner["type"] === "Identifier") this.printIdentifierWithOptional(inner);
2374
+ else this.printNode(inner, PREC.Sequence);
2375
+ } else {
2376
+ const fp = p;
2377
+ if (fp["decorators"] && fp["decorators"].length > 0) this.printDecorators(fp["decorators"]);
2378
+ if (fp["type"] === "Identifier") this.printIdentifierWithOptional(fp);
2379
+ else {
2380
+ this.printNode(fp, PREC.Assignment);
2381
+ if (fp["typeAnnotation"]) this.printTSTypeAnnotation(fp["typeAnnotation"]);
2382
+ }
2383
+ }
2384
+ }
2385
+ }
2386
+ printIdentifierWithOptional(node) {
2387
+ this.out += node.name;
2388
+ if (node.optional) this.out += "?";
2389
+ if (node.typeAnnotation) this.printTSTypeAnnotation(node.typeAnnotation);
2390
+ }
2391
+ printClassBody(node) {
2392
+ if (node.body.length === 0) {
2393
+ this.out += "{}";
2394
+ return;
2395
+ }
2396
+ this.out += "{\n";
2397
+ this.indentLevel++;
2398
+ for (const el of node.body) {
2399
+ this.out += this.indent();
2400
+ this.printNode(el, PREC.Sequence);
2401
+ this.out += "\n";
2402
+ }
2403
+ this.indentLevel--;
2404
+ this.out += `${this.indent()}}`;
2405
+ }
2406
+ printMethodDefinition(node) {
2407
+ this.printDecorators(node.decorators);
2408
+ if (node.accessibility) this.out += `${node.accessibility} `;
2409
+ if (node.static) this.out += "static ";
2410
+ if (node.override) this.out += "override ";
2411
+ const fn = node.value;
2412
+ if (fn.async) this.out += "async ";
2413
+ if (fn.generator) this.out += "*";
2414
+ const kind = node.kind;
2415
+ if (kind === "get" || kind === "set") this.out += `${kind} `;
2416
+ else if (kind === "constructor") {}
2417
+ if (node.computed) {
2418
+ this.out += "[";
2419
+ this.printNode(node.key, PREC.Sequence);
2420
+ this.out += "]";
2421
+ } else this.printPropertyKeyForClass(node.key);
2422
+ if (node.optional) this.out += "?";
2423
+ if (fn.typeParameters) this.printTSTypeParameterDeclaration(fn.typeParameters);
2424
+ this.out += "(";
2425
+ this.printParams(fn.params);
2426
+ this.out += ")";
2427
+ if (fn.returnType) this.printTSTypeAnnotation(fn.returnType);
2428
+ if (fn.body) {
2429
+ this.out += " ";
2430
+ this.printBlockStatement(fn.body);
2431
+ } else this.out += ";";
2432
+ }
2433
+ printPropertyDefinition(node) {
2434
+ this.printDecorators(node.decorators);
2435
+ if (node.declare) this.out += "declare ";
2436
+ if (node.accessibility) this.out += `${node.accessibility} `;
2437
+ if (node.static) this.out += "static ";
2438
+ if (node.readonly) this.out += "readonly ";
2439
+ if (node.override) this.out += "override ";
2440
+ if (node.computed) {
2441
+ this.out += "[";
2442
+ this.printNode(node.key, PREC.Sequence);
2443
+ this.out += "]";
2444
+ } else this.printPropertyKeyForClass(node.key);
2445
+ if (node.optional) this.out += "?";
2446
+ if (node.definite) this.out += "!";
2447
+ if (node.typeAnnotation) this.printTSTypeAnnotation(node.typeAnnotation);
2448
+ if (node.value) {
2449
+ this.out += " = ";
2450
+ this.printNode(node.value, PREC.Assignment);
2451
+ }
2452
+ this.out += ";";
2453
+ }
2454
+ printAccessorProperty(node) {
2455
+ this.printDecorators(node.decorators);
2456
+ if (node.accessibility) this.out += `${node.accessibility} `;
2457
+ if (node.static) this.out += "static ";
2458
+ if (node.override) this.out += "override ";
2459
+ this.out += "accessor ";
2460
+ if (node.computed) {
2461
+ this.out += "[";
2462
+ this.printNode(node.key, PREC.Sequence);
2463
+ this.out += "]";
2464
+ } else this.printPropertyKeyForClass(node.key);
2465
+ if (node.definite) this.out += "!";
2466
+ if (node.typeAnnotation) this.printTSTypeAnnotation(node.typeAnnotation);
2467
+ if (node.value) {
2468
+ this.out += " = ";
2469
+ this.printNode(node.value, PREC.Assignment);
2470
+ }
2471
+ this.out += ";";
2472
+ }
2473
+ printPropertyKeyForClass(key, computed = false) {
2474
+ if (computed) {
2475
+ this.out += "[";
2476
+ this.printNode(key, PREC.Sequence);
2477
+ this.out += "]";
2478
+ return;
2479
+ }
2480
+ if (key.type === "Identifier") this.out += key.name;
2481
+ else if (key.type === "PrivateIdentifier") this.out += `#${key.name}`;
2482
+ else if (key.type === "Literal") this.printLiteral(key);
2483
+ else this.printNode(key, PREC.Assignment);
2484
+ }
2485
+ printStaticBlock(node) {
2486
+ this.out += "static {\n";
2487
+ this.indentLevel++;
2488
+ for (const stmt of node.body) {
2489
+ this.out += this.indent();
2490
+ this.printStatement(stmt);
2491
+ this.out += "\n";
2492
+ }
2493
+ this.indentLevel--;
2494
+ this.out += `${this.indent()}}`;
2495
+ }
2496
+ printImportDeclaration(node) {
2497
+ const kind = node.importKind === "type" ? "type " : "";
2498
+ if (node.specifiers.length === 0) {
2499
+ this.out += `import ${kind}${this.printImportSource(node.source, node.attributes)};`;
2500
+ return;
2501
+ }
2502
+ const specs = node.specifiers;
2503
+ const defaultSpec = specs.find((s) => s.type === "ImportDefaultSpecifier");
2504
+ const namespaceSpec = specs.find((s) => s.type === "ImportNamespaceSpecifier");
2505
+ const namedSpecs = specs.filter((s) => s.type === "ImportSpecifier");
2506
+ this.out += `import ${kind}`;
2507
+ const parts = [];
2508
+ if (defaultSpec) parts.push(defaultSpec.local.name);
2509
+ if (namespaceSpec) parts.push(`* as ${namespaceSpec.local.name}`);
2510
+ if (namedSpecs.length > 0) {
2511
+ const named = namedSpecs.map((s) => {
2512
+ const imported = s.imported;
2513
+ const importedName = imported.type === "Identifier" ? imported.name : imported.value;
2514
+ const inlineType = s.importKind === "type" ? "type " : "";
2515
+ if (importedName === s.local.name) return `${inlineType}${importedName}`;
2516
+ return `${inlineType}${importedName} as ${s.local.name}`;
2517
+ }).join(", ");
2518
+ parts.push(`{ ${named} }`);
2519
+ }
2520
+ this.out += parts.join(", ");
2521
+ this.out += ` from ${this.printImportSource(node.source, node.attributes)};`;
2522
+ }
2523
+ printImportSource(source, attrs) {
2524
+ const raw = source.raw ?? JSON.stringify(source.value);
2525
+ if (attrs.length === 0) return raw;
2526
+ return `${raw} with { ${attrs.map((a) => `${this.printImportAttrKey(a.key)}: ${JSON.stringify(a.value.value)}`).join(", ")} }`;
2527
+ }
2528
+ printImportAttrKey(key) {
2529
+ if (key.type === "Identifier") return key.name;
2530
+ return JSON.stringify(key.value);
2531
+ }
2532
+ printExportNamedDeclaration(node) {
2533
+ if (node.declaration) {
2534
+ this.out += "export ";
2535
+ this.printStatement(node.declaration);
2536
+ return;
2537
+ }
2538
+ this.out += "export ";
2539
+ if (node.exportKind === "type") this.out += "type ";
2540
+ this.out += "{ ";
2541
+ for (let i = 0; i < node.specifiers.length; i++) {
2542
+ if (i > 0) this.out += ", ";
2543
+ const s = node.specifiers[i];
2544
+ const localName = exportNameToString(s.local);
2545
+ const exportedName = exportNameToString(s.exported);
2546
+ const inlineType = s.exportKind === "type" ? "type " : "";
2547
+ if (localName === exportedName) this.out += `${inlineType}${localName}`;
2548
+ else this.out += `${inlineType}${localName} as ${exportedName}`;
2549
+ }
2550
+ this.out += " }";
2551
+ if (node.source) {
2552
+ this.out += ` from ${JSON.stringify(node.source.value)}`;
2553
+ if (node.attributes.length > 0) {
2554
+ const attrStr = node.attributes.map((a) => `${this.printImportAttrKey(a.key)}: ${JSON.stringify(a.value.value)}`).join(", ");
2555
+ this.out += ` with { ${attrStr} }`;
2556
+ }
2557
+ }
2558
+ this.out += ";";
2559
+ }
2560
+ printExportDefaultDeclaration(node) {
2561
+ this.out += "export default ";
2562
+ const decl = node.declaration;
2563
+ if (decl.type === "FunctionDeclaration" || decl.type === "ClassDeclaration" || decl.type === "TSInterfaceDeclaration") this.printStatement(decl);
2564
+ else {
2565
+ this.printNode(decl, PREC.Assignment);
2566
+ this.out += ";";
2567
+ }
2568
+ }
2569
+ printExportAllDeclaration(node) {
2570
+ this.out += "export ";
2571
+ if (node.exportKind === "type") this.out += "type ";
2572
+ this.out += "*";
2573
+ if (node.exported) this.out += ` as ${exportNameToString(node.exported)}`;
2574
+ this.out += ` from ${JSON.stringify(node.source.value)}`;
2575
+ if (node.attributes.length > 0) {
2576
+ const attrStr = node.attributes.map((a) => `${this.printImportAttrKey(a.key)}: ${JSON.stringify(a.value.value)}`).join(", ");
2577
+ this.out += ` with { ${attrStr} }`;
2578
+ }
2579
+ this.out += ";";
2580
+ }
2581
+ printTSTypeAliasDeclaration(node) {
2582
+ if (node.declare) this.out += "declare ";
2583
+ this.out += `type ${node.id.name}`;
2584
+ if (node.typeParameters) this.printTSTypeParameterDeclaration(node.typeParameters);
2585
+ this.out += ` = ${this.printTSTypeToString(node.typeAnnotation)};`;
2586
+ }
2587
+ printTSInterfaceDeclaration(node) {
2588
+ if (node.declare) this.out += "declare ";
2589
+ this.out += `interface ${node.id.name}`;
2590
+ if (node.typeParameters) this.printTSTypeParameterDeclaration(node.typeParameters);
2591
+ if (node.extends.length > 0) {
2592
+ this.out += " extends ";
2593
+ for (let i = 0; i < node.extends.length; i++) {
2594
+ if (i > 0) this.out += ", ";
2595
+ const ex = node.extends[i];
2596
+ this.printNode(ex.expression, PREC.Assignment);
2597
+ if (ex.typeArguments) this.printTSTypeParameterInstantiation(ex.typeArguments);
2598
+ }
2599
+ }
2600
+ this.out += " ";
2601
+ this.printTSInterfaceBody(node.body);
2602
+ }
2603
+ printTSInterfaceBody(node) {
2604
+ if (node.body.length === 0) {
2605
+ this.out += "{}";
2606
+ return;
2607
+ }
2608
+ this.out += "{\n";
2609
+ this.indentLevel++;
2610
+ for (const m of node.body) {
2611
+ this.out += this.indent();
2612
+ this.printTSSignature(m);
2613
+ this.out += "\n";
2614
+ }
2615
+ this.indentLevel--;
2616
+ this.out += `${this.indent()}}`;
2617
+ }
2618
+ printTSSignature(sig) {
2619
+ switch (sig.type) {
2620
+ case "TSPropertySignature": {
2621
+ const n = sig;
2622
+ if (n.readonly) this.out += "readonly ";
2623
+ this.printPropertyKeyForClass(n.key, n.computed === true);
2624
+ if (n.optional) this.out += "?";
2625
+ if (n.typeAnnotation) this.printTSTypeAnnotation(n.typeAnnotation);
2626
+ this.out += ";";
2627
+ break;
2628
+ }
2629
+ case "TSIndexSignature": {
2630
+ const n = sig;
2631
+ if (n.readonly) this.out += "readonly ";
2632
+ if (n.static) this.out += "static ";
2633
+ this.out += "[";
2634
+ for (let i = 0; i < n.parameters.length; i++) {
2635
+ if (i > 0) this.out += ", ";
2636
+ const p = n.parameters[i];
2637
+ this.out += `${p.name}: `;
2638
+ this.printTSType(p.typeAnnotation.typeAnnotation);
2639
+ }
2640
+ this.out += "]";
2641
+ this.printTSTypeAnnotation(n.typeAnnotation);
2642
+ this.out += ";";
2643
+ break;
2644
+ }
2645
+ case "TSCallSignatureDeclaration": {
2646
+ const n = sig;
2647
+ if (n.typeParameters) this.printTSTypeParameterDeclaration(n.typeParameters);
2648
+ this.out += "(";
2649
+ this.printParams(n.params);
2650
+ this.out += ")";
2651
+ if (n.returnType) this.printTSTypeAnnotation(n.returnType);
2652
+ this.out += ";";
2653
+ break;
2654
+ }
2655
+ case "TSConstructSignatureDeclaration": {
2656
+ const n = sig;
2657
+ this.out += "new ";
2658
+ if (n.typeParameters) this.printTSTypeParameterDeclaration(n.typeParameters);
2659
+ this.out += "(";
2660
+ this.printParams(n.params);
2661
+ this.out += ")";
2662
+ if (n.returnType) this.printTSTypeAnnotation(n.returnType);
2663
+ this.out += ";";
2664
+ break;
2665
+ }
2666
+ case "TSMethodSignature": {
2667
+ const n = sig;
2668
+ if (n.kind === "get" || n.kind === "set") this.out += `${n.kind} `;
2669
+ this.printPropertyKeyForClass(n.key, n.computed === true);
2670
+ if (n.optional) this.out += "?";
2671
+ if (n.typeParameters) this.printTSTypeParameterDeclaration(n.typeParameters);
2672
+ this.out += "(";
2673
+ this.printParams(n.params);
2674
+ this.out += ")";
2675
+ if (n.returnType) this.printTSTypeAnnotation(n.returnType);
2676
+ this.out += ";";
2677
+ break;
2678
+ }
2679
+ default: this.out += `/* sig:${sig.type} */;`;
2680
+ }
2681
+ }
2682
+ printTSEnumDeclaration(node) {
2683
+ if (node.declare) this.out += "declare ";
2684
+ if (node.const) this.out += "const ";
2685
+ this.out += `enum ${node.id.name} `;
2686
+ this.out += "{\n";
2687
+ this.indentLevel++;
2688
+ for (const m of node.body.members) {
2689
+ this.out += this.indent();
2690
+ if (m.id.type === "Identifier") this.out += m.id.name;
2691
+ else if (m.id.type === "Literal") this.printLiteral(m.id);
2692
+ else this.printNode(m.id, PREC.Sequence);
2693
+ if (m.initializer) {
2694
+ this.out += " = ";
2695
+ this.printNode(m.initializer, PREC.Assignment);
2696
+ }
2697
+ this.out += ",\n";
2698
+ }
2699
+ this.indentLevel--;
2700
+ this.out += `${this.indent()}}`;
2701
+ }
2702
+ printTSModuleDeclaration(node) {
2703
+ if (node.declare) this.out += "declare ";
2704
+ if (node.global) this.out += "global ";
2705
+ else {
2706
+ const kind = node.kind;
2707
+ this.out += `${kind} `;
2708
+ const id = node.id;
2709
+ if (id.type === "Identifier") this.out += id.name;
2710
+ else if (id.type === "Literal") this.printLiteral(id);
2711
+ else this.printNode(id, PREC.Sequence);
2712
+ }
2713
+ if (node.body) {
2714
+ this.out += " ";
2715
+ this.printTSModuleBlock(node.body);
2716
+ } else this.out += ";";
2717
+ }
2718
+ printTSModuleBlock(node) {
2719
+ this.out += "{\n";
2720
+ this.indentLevel++;
2721
+ for (const stmt of node.body) {
2722
+ this.out += this.indent();
2723
+ this.printStatement(stmt);
2724
+ this.out += "\n";
2725
+ }
2726
+ this.indentLevel--;
2727
+ this.out += `${this.indent()}}`;
2728
+ }
2729
+ printTSImportEqualsDeclaration(node) {
2730
+ this.out += `import ${node.importKind === "type" ? "type " : ""}${node.id.name} = `;
2731
+ const ref = node.moduleReference;
2732
+ if (ref.type === "TSExternalModuleReference") this.out += `require(${ref.expression.value ? JSON.stringify(ref.expression.value) : "\"\""})`;
2733
+ else this.printNode(ref, PREC.Sequence);
2734
+ this.out += ";";
2735
+ }
2736
+ printTSType(node) {
2737
+ this.out += this.printTSTypeToString(node);
2738
+ }
2739
+ printTSTypeToString(node) {
2740
+ const saved = this.out;
2741
+ this.out = "";
2742
+ this.doPrintTSType(node);
2743
+ const result = this.out;
2744
+ this.out = saved;
2745
+ return result;
2746
+ }
2747
+ doPrintTSType(node) {
2748
+ switch (node.type) {
2749
+ case "TSAnyKeyword":
2750
+ this.out += "any";
2751
+ break;
2752
+ case "TSStringKeyword":
2753
+ this.out += "string";
2754
+ break;
2755
+ case "TSBooleanKeyword":
2756
+ this.out += "boolean";
2757
+ break;
2758
+ case "TSNumberKeyword":
2759
+ this.out += "number";
2760
+ break;
2761
+ case "TSBigIntKeyword":
2762
+ this.out += "bigint";
2763
+ break;
2764
+ case "TSSymbolKeyword":
2765
+ this.out += "symbol";
2766
+ break;
2767
+ case "TSVoidKeyword":
2768
+ this.out += "void";
2769
+ break;
2770
+ case "TSUndefinedKeyword":
2771
+ this.out += "undefined";
2772
+ break;
2773
+ case "TSNullKeyword":
2774
+ this.out += "null";
2775
+ break;
2776
+ case "TSNeverKeyword":
2777
+ this.out += "never";
2778
+ break;
2779
+ case "TSUnknownKeyword":
2780
+ this.out += "unknown";
2781
+ break;
2782
+ case "TSObjectKeyword":
2783
+ this.out += "object";
2784
+ break;
2785
+ case "TSIntrinsicKeyword":
2786
+ this.out += "intrinsic";
2787
+ break;
2788
+ case "TSThisType":
2789
+ this.out += "this";
2790
+ break;
2791
+ case "TSTypeReference": {
2792
+ const n = node;
2793
+ this.printTSTypeName(n.typeName);
2794
+ if (n.typeArguments) this.printTSTypeParameterInstantiation(n.typeArguments);
2795
+ break;
2796
+ }
2797
+ case "TSUnionType": {
2798
+ const n = node;
2799
+ for (let i = 0; i < n.types.length; i++) {
2800
+ if (i > 0) this.out += " | ";
2801
+ this.doPrintTSType(n.types[i]);
2802
+ }
2803
+ break;
2804
+ }
2805
+ case "TSIntersectionType": {
2806
+ const n = node;
2807
+ for (let i = 0; i < n.types.length; i++) {
2808
+ if (i > 0) this.out += " & ";
2809
+ this.doPrintTSType(n.types[i]);
2810
+ }
2811
+ break;
2812
+ }
2813
+ case "TSArrayType": {
2814
+ const n = node;
2815
+ const needsParens = n.elementType.type === "TSUnionType" || n.elementType.type === "TSIntersectionType";
2816
+ if (needsParens) this.out += "(";
2817
+ this.doPrintTSType(n.elementType);
2818
+ if (needsParens) this.out += ")";
2819
+ this.out += "[]";
2820
+ break;
2821
+ }
2822
+ case "TSTypeLiteral": {
2823
+ const n = node;
2824
+ if (n.members.length === 0) this.out += "{}";
2825
+ else {
2826
+ this.out += "{ ";
2827
+ for (let i = 0; i < n.members.length; i++) {
2828
+ if (i > 0) this.out += "; ";
2829
+ this.printTSSignature(n.members[i]);
2830
+ if (this.out.endsWith(";")) this.out = this.out.slice(0, -1);
2831
+ }
2832
+ this.out += " }";
2833
+ }
2834
+ break;
2835
+ }
2836
+ case "TSTupleType": {
2837
+ const n = node;
2838
+ this.out += "[";
2839
+ for (let i = 0; i < n.elementTypes.length; i++) {
2840
+ if (i > 0) this.out += ", ";
2841
+ const el = n.elementTypes[i];
2842
+ if (el.type === "TSRestType") {
2843
+ this.out += "...";
2844
+ this.doPrintTSType(el.typeAnnotation);
2845
+ } else if (el.type === "TSOptionalType") {
2846
+ this.doPrintTSType(el.typeAnnotation);
2847
+ this.out += "?";
2848
+ } else if (el.type === "TSNamedTupleMember") {
2849
+ const m = el;
2850
+ this.out += `${m.label.name}${m.optional ? "?" : ""}: `;
2851
+ const inner = m.elementType;
2852
+ if (inner.type === "TSRestType") {
2853
+ this.out += "...";
2854
+ this.doPrintTSType(inner.typeAnnotation);
2855
+ } else if (inner.type === "TSOptionalType") {
2856
+ this.doPrintTSType(inner.typeAnnotation);
2857
+ this.out += "?";
2858
+ } else this.doPrintTSType(inner);
2859
+ } else this.doPrintTSType(el);
2860
+ }
2861
+ this.out += "]";
2862
+ break;
2863
+ }
2864
+ case "TSConditionalType": {
2865
+ const n = node;
2866
+ this.doPrintTSType(n.checkType);
2867
+ this.out += " extends ";
2868
+ this.doPrintTSType(n.extendsType);
2869
+ this.out += " ? ";
2870
+ this.doPrintTSType(n.trueType);
2871
+ this.out += " : ";
2872
+ this.doPrintTSType(n.falseType);
2873
+ break;
2874
+ }
2875
+ case "TSInferType": {
2876
+ const n = node;
2877
+ this.out += `infer ${n.typeParameter.name.name}`;
2878
+ if (n.typeParameter.constraint) {
2879
+ this.out += " extends ";
2880
+ this.doPrintTSType(n.typeParameter.constraint);
2881
+ }
2882
+ break;
2883
+ }
2884
+ case "TSTypeQuery": {
2885
+ const n = node;
2886
+ this.out += "typeof ";
2887
+ if (n.exprName.type === "TSImportType") this.doPrintTSType(n.exprName);
2888
+ else this.printTSTypeName(n.exprName);
2889
+ if (n.typeArguments) this.printTSTypeParameterInstantiation(n.typeArguments);
2890
+ break;
2891
+ }
2892
+ case "TSImportType": {
2893
+ const n = node;
2894
+ if (n.options) {
2895
+ this.out += `import(${JSON.stringify(n.source.value)}, `;
2896
+ this.printNode(n.options, PREC.Assignment);
2897
+ this.out += ")";
2898
+ } else this.out += `import(${JSON.stringify(n.source.value)})`;
2899
+ if (n.qualifier) {
2900
+ this.out += ".";
2901
+ this.printTSImportTypeQualifier(n.qualifier);
2902
+ }
2903
+ if (n.typeArguments) this.printTSTypeParameterInstantiation(n.typeArguments);
2904
+ break;
2905
+ }
2906
+ case "TSTypeOperator": {
2907
+ const n = node;
2908
+ this.out += `${n.operator} `;
2909
+ this.doPrintTSType(n.typeAnnotation);
2910
+ break;
2911
+ }
2912
+ case "TSMappedType": {
2913
+ const n = node;
2914
+ this.out += "{ ";
2915
+ if (n.readonly) this.out += n.readonly === true ? "readonly " : `${n.readonly}readonly `;
2916
+ this.out += `[${n.key.name} in `;
2917
+ this.doPrintTSType(n.constraint);
2918
+ if (n.nameType) {
2919
+ this.out += " as ";
2920
+ this.doPrintTSType(n.nameType);
2921
+ }
2922
+ this.out += "]";
2923
+ if (n.optional) this.out += n.optional === true ? "?" : `${n.optional}?`;
2924
+ if (n.typeAnnotation) {
2925
+ this.out += ": ";
2926
+ this.doPrintTSType(n.typeAnnotation);
2927
+ }
2928
+ this.out += " }";
2929
+ break;
2930
+ }
2931
+ case "TSTemplateLiteralType": {
2932
+ const n = node;
2933
+ this.out += "`";
2934
+ for (let i = 0; i < n.quasis.length; i++) {
2935
+ this.out += n.quasis[i].value.raw;
2936
+ if (!n.quasis[i].tail) {
2937
+ this.out += "${";
2938
+ this.doPrintTSType(n.types[i]);
2939
+ this.out += "}";
2940
+ }
2941
+ }
2942
+ this.out += "`";
2943
+ break;
2944
+ }
2945
+ case "TSFunctionType": {
2946
+ const n = node;
2947
+ if (n.typeParameters) this.printTSTypeParameterDeclaration(n.typeParameters);
2948
+ this.out += "(";
2949
+ this.printParams(n.params);
2950
+ this.out += ") => ";
2951
+ this.doPrintTSType(n.returnType.typeAnnotation);
2952
+ break;
2953
+ }
2954
+ case "TSConstructorType": {
2955
+ const n = node;
2956
+ if (n.abstract) this.out += "abstract ";
2957
+ this.out += "new ";
2958
+ if (n.typeParameters) this.printTSTypeParameterDeclaration(n.typeParameters);
2959
+ this.out += "(";
2960
+ this.printParams(n.params);
2961
+ this.out += ") => ";
2962
+ this.doPrintTSType(n.returnType.typeAnnotation);
2963
+ break;
2964
+ }
2965
+ case "TSTypePredicate": {
2966
+ const n = node;
2967
+ if (n.asserts) this.out += "asserts ";
2968
+ if (n.parameterName.type === "TSThisType") this.out += "this";
2969
+ else this.out += n.parameterName.name;
2970
+ if (n.typeAnnotation) {
2971
+ this.out += " is ";
2972
+ this.doPrintTSType(n.typeAnnotation.typeAnnotation);
2973
+ }
2974
+ break;
2975
+ }
2976
+ case "TSIndexedAccessType": {
2977
+ const n = node;
2978
+ this.doPrintTSType(n.objectType);
2979
+ this.out += "[";
2980
+ this.doPrintTSType(n.indexType);
2981
+ this.out += "]";
2982
+ break;
2983
+ }
2984
+ case "TSLiteralType": {
2985
+ const lit = node.literal;
2986
+ if (lit.type === "Literal") this.printLiteral(lit);
2987
+ else if (lit.type === "TemplateLiteral") this.printTemplateLiteral(lit);
2988
+ else if (lit.type === "UnaryExpression") {
2989
+ const u = lit;
2990
+ this.out += u.operator;
2991
+ this.printLiteral(u.argument);
2992
+ } else this.printNode(lit, PREC.Sequence);
2993
+ break;
2994
+ }
2995
+ case "TSParenthesizedType": {
2996
+ const n = node;
2997
+ this.out += "(";
2998
+ this.doPrintTSType(n.typeAnnotation);
2999
+ this.out += ")";
3000
+ break;
3001
+ }
3002
+ case "TSJSDocNullableType": {
3003
+ const n = node;
3004
+ if (n.postfix) {
3005
+ this.doPrintTSType(n.typeAnnotation);
3006
+ this.out += "?";
3007
+ } else {
3008
+ this.out += "?";
3009
+ this.doPrintTSType(n.typeAnnotation);
3010
+ }
3011
+ break;
3012
+ }
3013
+ case "TSJSDocNonNullableType": {
3014
+ const n = node;
3015
+ if (n.postfix) {
3016
+ this.doPrintTSType(n.typeAnnotation);
3017
+ this.out += "!";
3018
+ } else {
3019
+ this.out += "!";
3020
+ this.doPrintTSType(n.typeAnnotation);
3021
+ }
3022
+ break;
3023
+ }
3024
+ case "TSJSDocUnknownType":
3025
+ this.out += "?";
3026
+ break;
3027
+ default: this.out += `/* type:${node.type} */`;
3028
+ }
3029
+ }
3030
+ printTSTypeName(name) {
3031
+ if (!name) return;
3032
+ if (name.type === "Identifier") this.out += name.name;
3033
+ else if (name.type === "TSQualifiedName") {
3034
+ this.printTSTypeName(name.left);
3035
+ this.out += ".";
3036
+ this.out += name.right.name;
3037
+ } else if (name.type === "ThisExpression") this.out += "this";
3038
+ else this.printNode(name, PREC.Sequence);
579
3039
  }
580
- function getTemplateScriptRanges(ast, walker) {
581
- const ranges = [];
582
- if (isPlainRecord(ast) && ast["instance"] !== null && ast["instance"] !== void 0) {
583
- const instance = ast["instance"];
584
- if (isPlainRecord(instance) && "content" in instance) {
585
- const content = instance["content"];
586
- if (isRangedProgram(content)) ranges.push({
587
- start: content.start,
588
- end: content.end,
589
- isExpression: false
590
- });
591
- else throw new Error("Svelte instance script without a source range");
592
- }
3040
+ printTSImportTypeQualifier(q) {
3041
+ if (!q) return;
3042
+ if (q.type === "Identifier") this.out += q.name;
3043
+ else {
3044
+ const qq = q;
3045
+ this.printTSImportTypeQualifier(qq.left);
3046
+ this.out += `.${qq.right.name}`;
593
3047
  }
594
- if (!isPlainRecord(ast) || !("html" in ast)) throw new Error("Svelte AST without html");
595
- const html = ast["html"];
596
- walker(html, { enter(node) {
597
- const scriptRange = tryGetScriptRangeFromElement(node);
598
- if (scriptRange) ranges.push(scriptRange);
599
- const templateExpression = collectTemplateExpression(node);
600
- if (templateExpression) {
601
- const { start, end } = templateExpression;
602
- ranges.push({
603
- start,
604
- end,
605
- isExpression: true
606
- });
607
- }
608
- } });
609
- return ranges;
610
3048
  }
611
- async function parseTemplateScriptIfDefined(range) {
612
- if (range) return parseTemplateScript(range);
3049
+ printTSTypeAnnotation(node) {
3050
+ this.out += ": ";
3051
+ this.doPrintTSType(node.typeAnnotation);
613
3052
  }
614
- async function parseTemplateScript({ start, end, isExpression, format }) {
615
- const scriptText = text.slice(start, end);
616
- return {
617
- ast: {
618
- ...await context.parse(scriptText, fileName, format),
619
- offset: positionFromOffset(lineStarts, start)
620
- },
621
- range: {
622
- start,
623
- end
624
- },
625
- isExpression
626
- };
3053
+ printTSTypeParameterDeclaration(node) {
3054
+ this.out += "<";
3055
+ for (let i = 0; i < node.params.length; i++) {
3056
+ if (i > 0) this.out += ", ";
3057
+ this.printTSTypeParameter(node.params[i]);
3058
+ }
3059
+ this.out += ">";
3060
+ }
3061
+ printTSTypeParameterInstantiation(node) {
3062
+ this.out += "<";
3063
+ for (let i = 0; i < node.params.length; i++) {
3064
+ if (i > 0) this.out += ", ";
3065
+ this.doPrintTSType(node.params[i]);
3066
+ }
3067
+ this.out += ">";
3068
+ }
3069
+ printTSTypeParameter(node) {
3070
+ if (node.in) this.out += "in ";
3071
+ if (node.out) this.out += "out ";
3072
+ if (node.const) this.out += "const ";
3073
+ this.out += node.name.name;
3074
+ if (node.constraint) {
3075
+ this.out += " extends ";
3076
+ this.doPrintTSType(node.constraint);
3077
+ }
3078
+ if (node.default) {
3079
+ this.out += " = ";
3080
+ this.doPrintTSType(node.default);
3081
+ }
3082
+ }
3083
+ };
3084
+ function exportNameToString(name) {
3085
+ if (name.type === "Identifier") return name.name;
3086
+ return name.value ?? "";
3087
+ }
3088
+ function isTSTypeNode(t) {
3089
+ return t === "TSAnyKeyword" || t === "TSStringKeyword" || t === "TSBooleanKeyword" || t === "TSNumberKeyword" || t === "TSBigIntKeyword" || t === "TSSymbolKeyword" || t === "TSVoidKeyword" || t === "TSUndefinedKeyword" || t === "TSNullKeyword" || t === "TSNeverKeyword" || t === "TSUnknownKeyword" || t === "TSObjectKeyword" || t === "TSIntrinsicKeyword" || t === "TSThisType" || t === "TSTypeReference" || t === "TSUnionType" || t === "TSIntersectionType" || t === "TSArrayType" || t === "TSTypeLiteral" || t === "TSTupleType" || t === "TSNamedTupleMember" || t === "TSOptionalType" || t === "TSRestType" || t === "TSConditionalType" || t === "TSInferType" || t === "TSTypeQuery" || t === "TSImportType" || t === "TSTypeOperator" || t === "TSMappedType" || t === "TSTemplateLiteralType" || t === "TSFunctionType" || t === "TSConstructorType" || t === "TSTypePredicate" || t === "TSIndexedAccessType" || t === "TSLiteralType" || t === "TSParenthesizedType" || t === "TSJSDocNullableType" || t === "TSJSDocNonNullableType" || t === "TSJSDocUnknownType";
3090
+ }
3091
+ function precOf(node) {
3092
+ switch (node.type) {
3093
+ case "SequenceExpression": return PREC.Sequence;
3094
+ case "AssignmentExpression": return PREC.Assignment;
3095
+ case "ConditionalExpression": return PREC.Conditional;
3096
+ case "LogicalExpression": return logicalPrec(node.operator);
3097
+ case "BinaryExpression": return binaryPrec(node.operator);
3098
+ case "UnaryExpression":
3099
+ case "AwaitExpression":
3100
+ case "YieldExpression": return PREC.Unary;
3101
+ case "UpdateExpression": return PREC.Update;
3102
+ case "CallExpression":
3103
+ case "NewExpression":
3104
+ case "TaggedTemplateExpression":
3105
+ case "ImportExpression": return PREC.Call;
3106
+ case "MemberExpression":
3107
+ case "ChainExpression": return PREC.Member;
3108
+ default: return PREC.Primary;
627
3109
  }
628
3110
  }
629
- function getModuleScriptRange(svelteAst) {
630
- if (!isPlainRecord(svelteAst) || !("module" in svelteAst) || svelteAst["module"] === null || svelteAst["module"] === void 0) return;
631
- const mod = svelteAst["module"];
632
- if (!isPlainRecord(mod) || !("content" in mod)) throw new Error("Svelte module script without a source range");
633
- const content = mod["content"];
634
- if (!isRangedProgram(content)) throw new Error("Svelte module script without a source range");
635
- return {
636
- start: content.start,
637
- end: content.end,
638
- isExpression: false
639
- };
640
- }
641
- /**
642
- * Remaps script locations back to the original places using the script map
643
- */
644
- function remapScriptLocations(code, scriptMap, moduleScriptRange, templateRanges) {
645
- const scriptRanges = [moduleScriptRange, ...templateRanges].filter(Predicate.isNotNullish).sort((a, b) => a.start - b.start);
646
- let offset = 0;
647
- let newModuleScriptRange;
648
- const newScriptRanges = scriptRanges.map((range) => {
649
- const script = code.substring(range.start, range.end);
650
- const actualScript = scriptMap.get(script);
651
- const start = range.start + offset;
652
- if (actualScript) {
653
- let langFormat = "js";
654
- if (actualScript.attributes["lang"] === "ts") langFormat = "ts";
655
- const scriptRange = {
656
- start,
657
- end: start + actualScript.content.length,
658
- isExpression: range.isExpression,
659
- format: langFormat
660
- };
661
- offset += actualScript.content.length - script.length;
662
- if (range === moduleScriptRange) newModuleScriptRange = scriptRange;
663
- return scriptRange;
664
- } else return {
665
- start,
666
- end: start + script.length,
667
- isExpression: range.isExpression,
668
- format: "js"
669
- };
670
- });
671
- return {
672
- remappedModuleScriptRange: newModuleScriptRange,
673
- remappedScriptRanges: newScriptRanges.filter((range) => range !== newModuleScriptRange)
674
- };
675
- }
676
- function collectTemplateExpression(node) {
677
- if (!isPlainRecord(node) || typeof node["type"] !== "string") return;
678
- if (!isTemplateExpressionType(node["type"])) return;
679
- if (!("expression" in node)) return;
680
- const expression = node["expression"];
681
- if (isRangedBaseNode(expression)) return expression;
3111
+ function needsParensForMemberObject(node) {
3112
+ return node.type === "SequenceExpression" || node.type === "AssignmentExpression" || node.type === "ConditionalExpression" || node.type === "LogicalExpression" || node.type === "BinaryExpression" || node.type === "UnaryExpression" || node.type === "UpdateExpression" || node.type === "AwaitExpression" || node.type === "YieldExpression";
682
3113
  }
683
3114
  //#endregion
684
3115
  //#region src/Printer.ts
685
3116
  /**
686
- * Printer — turns the instrumenter's ASTs back into source text.
687
- */
688
- /**
689
- * `@babel/generator` is CommonJS. Under Node's own ESM interop a default import
690
- * of it is the module's `exports` object, so the code generator sits behind
691
- * `.default` — the shape upstream reaches for, because upstream ships one
692
- * emitted file per source file. This package ships a bundle, where the default
693
- * import is already the function and `.default` is `undefined`, which fails at
694
- * the first mutant with `generator is not a function` rather than at build
695
- * time. Resolving both shapes once keeps the printers and the mutant's
696
- * replacement code identical under either layout.
3117
+ * Printer — turns the instrumenter's ASTs back into source text. The owned
3118
+ * ESTree printer (`./print/index.js`) renders; the script-root offsets that
3119
+ * html/svelte slicing needs come from the parsed `range`.
697
3120
  */
698
- function resolveGenerate$1() {
699
- if (typeof generator === "function") return generator;
700
- return generator.default;
701
- }
702
- const generate$2 = resolveGenerate$1();
703
3121
  function print(file) {
704
3122
  const context = { print };
705
3123
  switch (file.format) {
@@ -710,24 +3128,34 @@ function print(file) {
710
3128
  case "svelte": return sveltePrint(file, context);
711
3129
  }
712
3130
  }
3131
+ const hashbangOf = (root) => {
3132
+ if (!("hashbang" in root)) return null;
3133
+ const hashbang = root["hashbang"];
3134
+ if (typeof hashbang !== "object" || hashbang === null) return null;
3135
+ if (!("type" in hashbang && hashbang.type === "Hashbang")) return null;
3136
+ if (!("value" in hashbang && typeof hashbang.value === "string")) return null;
3137
+ if (!("start" in hashbang && typeof hashbang.start === "number")) return null;
3138
+ return {
3139
+ type: "Hashbang",
3140
+ value: hashbang.value,
3141
+ start: hashbang.start
3142
+ };
3143
+ };
713
3144
  const jsPrint = (file) => {
714
- return generate$2(file.root, { sourceMaps: false }).code;
3145
+ return printProgram(file.root, { hashbang: hashbangOf(file.root) });
715
3146
  };
716
3147
  const tsPrint = (file) => {
717
- return generate$2(file.root, {
718
- decoratorsBeforeExport: true,
719
- sourceMaps: false
720
- }).code;
3148
+ return printProgram(file.root, { hashbang: hashbangOf(file.root) });
721
3149
  };
722
3150
  function getScriptStart$1(script) {
723
- const start = script.root.start;
724
- if (start === void 0 || start === null) throw new Error("Script AST root without start");
725
- return start;
3151
+ const span = spanOf(script.root);
3152
+ if (span === void 0) throw new Error("Script AST root without start");
3153
+ return span.start;
726
3154
  }
727
3155
  function getScriptEnd$1(script) {
728
- const end = script.root.end;
729
- if (end === void 0 || end === null) throw new Error("Script AST root without end");
730
- return end;
3156
+ const span = spanOf(script.root);
3157
+ if (span === void 0) throw new Error("Script AST root without end");
3158
+ return span.end;
731
3159
  }
732
3160
  const htmlPrint = (ast, context) => {
733
3161
  const sortedScripts = [...ast.root.scripts].sort((a, b) => getScriptStart$1(a) - getScriptStart$1(b));
@@ -766,71 +3194,95 @@ const sveltePrint = ({ root, rawContent }, context) => {
766
3194
  /**
767
3195
  * Mutator — every mutation operator and its registry.
768
3196
  */
769
- const { traverse: babelTraverse, types: babelTypes$2 } = babel;
770
- const t$1 = babelTypes$2;
771
- function isGeneratorFn(value) {
772
- return typeof value === "function";
773
- }
774
- function hasDefault(value) {
775
- if (typeof value !== "object" || value === null) return false;
776
- if (!("default" in value)) return false;
777
- return typeof Reflect.get(value, "default") === "function";
778
- }
779
- let generateExport;
780
- const candidate = generator;
781
- if (isGeneratorFn(candidate)) generateExport = candidate;
782
- else if (hasDefault(candidate)) generateExport = candidate.default;
783
- else throw new Error("Missing generator");
784
- const generate$1 = generateExport;
785
- function deepCloneNode(node) {
786
- return babelTypes$2.cloneNode(node, true, false);
787
- }
788
- function eqPosition(a, b) {
789
- return a.line === b.line && a.column === b.column;
790
- }
791
- function eqLocation(a, b) {
792
- return eqPosition(a.start, b.start) && eqPosition(a.end, b.end);
793
- }
3197
+ /**
3198
+ * Node identity: same kind, same span. oxc nodes always carry a range
3199
+ * (parsed with `range: true`), which is a stronger identity than the old
3200
+ * estree line/column loc.
3201
+ */
794
3202
  function eqNode(a, b) {
795
- return a.type === b.type && !!a.loc && !!b.loc && eqLocation(a.loc, b.loc);
3203
+ const spanA = spanOf(a);
3204
+ const spanB = spanOf(b);
3205
+ return a.type === b.type && spanA !== void 0 && spanB !== void 0 && spanA.start === spanB.start && spanA.end === spanB.end;
796
3206
  }
797
3207
  function createMutant(id, fileName, original, specs, offset = {
798
3208
  column: 0,
799
3209
  line: 0
800
- }) {
3210
+ }, lineTable = buildLineTable("")) {
801
3211
  return {
802
3212
  id,
803
3213
  fileName,
804
3214
  original,
805
3215
  offset,
3216
+ lineTable,
806
3217
  replacement: specs.replacement,
807
3218
  mutatorName: specs.mutatorName,
808
3219
  ignoreReason: specs.ignoreReason,
809
- replacementCode: generate$1(specs.replacement, { sourceMaps: false }).code
3220
+ replacementCode: printNode(specs.replacement)
3221
+ };
3222
+ }
3223
+ function toApiMutant(mutant) {
3224
+ const start = nodeOffset(mutant, "start");
3225
+ const end = nodeOffset(mutant, "end");
3226
+ const baseFields = {
3227
+ fileName: mutant.fileName,
3228
+ id: mutant.id,
3229
+ location: toApiLocation(start, end, mutant.lineTable, mutant.offset),
3230
+ mutatorName: mutant.mutatorName,
3231
+ replacement: mutant.replacementCode
810
3232
  };
3233
+ if (mutant.ignoreReason !== void 0) return Mutant.make({
3234
+ ...baseFields,
3235
+ statusReason: mutant.ignoreReason,
3236
+ status: "Ignored"
3237
+ });
3238
+ return Mutant.make(baseFields);
3239
+ }
3240
+ function nodeOffset(mutant, edge) {
3241
+ const value = spanOf(mutant.original)?.[edge];
3242
+ if (typeof value !== "number") throw new Error(`Node without a ${edge} offset`);
3243
+ return value;
811
3244
  }
812
3245
  function applyMutant(mutant, originalTree) {
813
3246
  if (originalTree === mutant.original) return mutant.replacement;
814
- const mutatedAst = deepCloneNode(originalTree);
3247
+ const mutatedAst = cloneNode(originalTree);
815
3248
  const { original, replacement } = mutant;
816
3249
  if (hasReplaced(mutatedAst, original, replacement) === false) throw new Error(`Could not apply mutant ${JSON.stringify(replacement)}.`);
817
3250
  return mutatedAst;
818
3251
  }
819
3252
  function hasReplaced(root, original, replacement) {
820
3253
  let applied = false;
821
- babelTraverse(root, {
822
- noScope: true,
823
- enter(path) {
824
- if (eqNode(path.node, original)) {
825
- path.replaceWith(replacement);
826
- path.stop();
827
- applied = true;
828
- }
3254
+ traverse(root, { enter(path) {
3255
+ if (applied) {
3256
+ path.stop();
3257
+ return;
829
3258
  }
830
- });
3259
+ if (eqNode(path.node, original)) {
3260
+ path.replaceWith(replacement);
3261
+ applied = true;
3262
+ path.stop();
3263
+ }
3264
+ } });
831
3265
  return applied;
832
3266
  }
833
3267
  /**
3268
+ * Converts a node span to the API location: offsets become positions via the
3269
+ * file's line table, then the embedding-document offset (html/svelte) applies.
3270
+ */
3271
+ function toApiLocation(startOffset, endOffset, lineTable, offset) {
3272
+ return {
3273
+ start: toPosition(positionFromLineTable(startOffset, lineTable), offset),
3274
+ end: toPosition(positionFromLineTable(endOffset, lineTable), offset)
3275
+ };
3276
+ }
3277
+ function toPosition(source, offset) {
3278
+ let columnOffset = 0;
3279
+ if (source.line === 1) columnOffset = offset.column;
3280
+ return {
3281
+ column: source.column + columnOffset,
3282
+ line: source.line + offset.line - 1
3283
+ };
3284
+ }
3285
+ /**
834
3286
  * The mutations of a regular expression pattern.
835
3287
  *
836
3288
  * Pure: a pattern and its flags in, replacement patterns out. No I/O, no clock,
@@ -970,41 +3422,39 @@ const arithmeticOperatorReplacements = Object.freeze({
970
3422
  "%": "*"
971
3423
  });
972
3424
  const arithmeticOperatorMutator = function* (node, _context) {
973
- if (t$1.isBinaryExpression(node) && isSupportedArithmeticOperator(node.operator, node)) {
3425
+ if (node.type === "BinaryExpression" && isSupportedArithmeticOperator(node.operator, node)) {
974
3426
  const mutatedOperator = arithmeticOperatorReplacements[node.operator];
975
- const replacement = deepCloneNode(node);
3427
+ const replacement = cloneNode(node);
976
3428
  replacement.operator = mutatedOperator;
977
3429
  yield replacement;
978
3430
  }
979
3431
  };
980
3432
  function isSupportedArithmeticOperator(operator, node) {
981
3433
  if (!Object.keys(arithmeticOperatorReplacements).includes(operator)) return false;
982
- const stringTypes = ["StringLiteral", "TemplateLiteral"];
983
- let leftType;
984
- if (t$1.isBinaryExpression(node.left)) leftType = node.left.right.type;
985
- else leftType = node.left.type;
986
- if (stringTypes.includes(node.right.type) || stringTypes.includes(leftType)) return false;
3434
+ let leftOperand = node.left;
3435
+ if (node.left.type === "BinaryExpression") leftOperand = node.left.right;
3436
+ if (isStringLike(node.right) || isStringLike(leftOperand)) return false;
987
3437
  return true;
988
3438
  }
989
3439
  const arrayDeclarationMutator = function* (node, _context) {
990
- if (babelTypes$2.isArrayExpression(node)) {
3440
+ if (node.type === "ArrayExpression") {
991
3441
  let replacement;
992
- if (node.elements.length > 0) replacement = babelTypes$2.arrayExpression();
993
- else replacement = babelTypes$2.arrayExpression([babelTypes$2.stringLiteral("Stryker was here")]);
3442
+ if (node.elements.length > 0) replacement = arrayExpression();
3443
+ else replacement = arrayExpression([stringLiteral("Stryker was here")]);
994
3444
  yield replacement;
995
3445
  }
996
- if ((babelTypes$2.isCallExpression(node) || babelTypes$2.isNewExpression(node)) && babelTypes$2.isIdentifier(node.callee) && node.callee.name === "Array") {
3446
+ if ((node.type === "CallExpression" || node.type === "NewExpression") && node.callee.type === "Identifier" && node.callee.name === "Array") {
997
3447
  let mutatedCallArgs;
998
3448
  if (node.arguments.length > 0) mutatedCallArgs = [];
999
- else mutatedCallArgs = [babelTypes$2.arrayExpression()];
3449
+ else mutatedCallArgs = [arrayExpression()];
1000
3450
  let replacement;
1001
- if (babelTypes$2.isNewExpression(node)) replacement = babelTypes$2.newExpression(deepCloneNode(node.callee), mutatedCallArgs);
1002
- else replacement = babelTypes$2.callExpression(deepCloneNode(node.callee), mutatedCallArgs);
3451
+ if (node.type === "NewExpression") replacement = newExpression(cloneNode(node.callee), mutatedCallArgs);
3452
+ else replacement = callExpression(cloneNode(node.callee), mutatedCallArgs);
1003
3453
  yield replacement;
1004
3454
  }
1005
3455
  };
1006
3456
  const arrowFunctionMutator = function* (node, _context) {
1007
- if (babelTypes$2.isArrowFunctionExpression(node) && !babelTypes$2.isBlockStatement(node.body) && !(babelTypes$2.isIdentifier(node.body) && node.body.name === "undefined")) yield babelTypes$2.arrowFunctionExpression([], babelTypes$2.identifier("undefined"));
3457
+ if (node.type === "ArrowFunctionExpression" && node.body.type !== "BlockStatement" && !(node.body.type === "Identifier" && node.body.name === "undefined")) yield arrowFunctionExpression([], identifier("undefined"));
1008
3458
  };
1009
3459
  const assignmentOperatorReplacements = Object.freeze({
1010
3460
  "+=": "-=",
@@ -1020,16 +3470,20 @@ const assignmentOperatorReplacements = Object.freeze({
1020
3470
  "||=": "&&=",
1021
3471
  "??=": "&&="
1022
3472
  });
1023
- const stringTypes = Object.freeze(["StringLiteral", "TemplateLiteral"]);
3473
+ function isStringLike(node) {
3474
+ if (node === null || node === void 0) return false;
3475
+ if (nodeType(node) === "TemplateLiteral") return true;
3476
+ return nodeType(node) === "Literal" && typeof node.value === "string";
3477
+ }
1024
3478
  const stringAssignmentTypes = Object.freeze([
1025
3479
  "&&=",
1026
3480
  "||=",
1027
3481
  "??="
1028
3482
  ]);
1029
3483
  const assignmentOperatorMutator = function* (node, _context) {
1030
- if (babelTypes$2.isAssignmentExpression(node) && isSupportedAssignmentOperator(node.operator) && isSupportedAssignmentExpression(node)) {
3484
+ if (node.type === "AssignmentExpression" && isSupportedAssignmentOperator(node.operator) && isSupportedAssignmentExpression(node)) {
1031
3485
  const mutatedOperator = assignmentOperatorReplacements[node.operator];
1032
- const replacement = deepCloneNode(node);
3486
+ const replacement = cloneNode(node);
1033
3487
  replacement.operator = mutatedOperator;
1034
3488
  yield replacement;
1035
3489
  }
@@ -1038,11 +3492,11 @@ function isSupportedAssignmentOperator(operator) {
1038
3492
  return Object.keys(assignmentOperatorReplacements).includes(operator);
1039
3493
  }
1040
3494
  function isSupportedAssignmentExpression(node) {
1041
- if (stringTypes.includes(node.right.type) && !stringAssignmentTypes.includes(node.operator)) return false;
3495
+ if (isStringLike(node.right) && !stringAssignmentTypes.includes(node.operator)) return false;
1042
3496
  return true;
1043
3497
  }
1044
3498
  const blockStatementMutator = function* (node, context) {
1045
- if (babelTypes$2.isBlockStatement(node) && isValid(node, context)) yield babelTypes$2.blockStatement([]);
3499
+ if (node.type === "BlockStatement" && isValid(node, context)) yield blockStatement([]);
1046
3500
  };
1047
3501
  function isValid(node, context) {
1048
3502
  return !isEmpty(node) && !isInvalidConstructorBody(node, context);
@@ -1052,16 +3506,16 @@ function isEmpty(node) {
1052
3506
  }
1053
3507
  function isInvalidConstructorBody(node, context) {
1054
3508
  const parent = context.parent;
1055
- if (parent === void 0 || !babelTypes$2.isClassMethod(parent) || parent.kind !== "constructor") return false;
1056
- const hasParamProps = parent.params.some((param) => babelTypes$2.isTSParameterProperty(param));
3509
+ if (parent === void 0 || parent.type !== "MethodDefinition" || parent.kind !== "constructor") return false;
3510
+ const hasParamProps = parent.value.params.some((param) => param !== null && nodeType(param) === "TSParameterProperty");
1057
3511
  const hasInitProps = containsInitializedClassProperties(parent, context);
1058
3512
  const hasSuper = hasSuperExpression(node);
1059
3513
  return (hasParamProps || hasInitProps) && hasSuper;
1060
3514
  }
1061
3515
  function containsInitializedClassProperties(constructor, context) {
1062
3516
  const grandParent = context.grandParent;
1063
- if (grandParent === void 0 || !babelTypes$2.isClassBody(grandParent)) return false;
1064
- return grandParent.body.some((classMember) => babelTypes$2.isClassProperty(classMember) && classMember.value !== null && classMember.value !== void 0);
3517
+ if (grandParent === void 0 || grandParent.type !== "ClassBody") return false;
3518
+ return grandParent.body.some((classMember) => classMember.type === "PropertyDefinition" && classMember.value !== null && classMember.value !== void 0);
1065
3519
  }
1066
3520
  function hasSuperExpression(block) {
1067
3521
  return containsSuperCall(block);
@@ -1088,8 +3542,8 @@ function hasSuperInChildren(node) {
1088
3542
  return false;
1089
3543
  }
1090
3544
  const booleanLiteralMutator = function* (node, _context) {
1091
- if (babelTypes$2.isBooleanLiteral(node)) yield babelTypes$2.booleanLiteral(!node.value);
1092
- if (babelTypes$2.isUnaryExpression(node) && node.operator === "!" && node.prefix) yield deepCloneNode(node.argument);
3545
+ if (node.type === "Literal" && typeof node.value === "boolean") yield booleanLiteral(!node.value);
3546
+ if (node.type === "UnaryExpression" && node.operator === "!" && node.prefix) yield cloneNode(node.argument);
1093
3547
  };
1094
3548
  const booleanOperators = Object.freeze([
1095
3549
  "!=",
@@ -1104,50 +3558,50 @@ const booleanOperators = Object.freeze([
1104
3558
  "||"
1105
3559
  ]);
1106
3560
  const conditionalExpressionMutator = function* (node, context) {
1107
- if (isTestOfLoop(node, context)) yield babelTypes$2.booleanLiteral(false);
3561
+ if (isTestOfLoop(node, context)) yield booleanLiteral(false);
1108
3562
  else if (isTestOfCondition(node, context)) {
1109
- yield babelTypes$2.booleanLiteral(true);
1110
- yield babelTypes$2.booleanLiteral(false);
3563
+ yield booleanLiteral(true);
3564
+ yield booleanLiteral(false);
1111
3565
  } else if (isBooleanExpression(node)) {
1112
3566
  const parent = context.parent;
1113
- if (parent !== void 0 && babelTypes$2.isLogicalExpression(parent)) {
3567
+ if (parent !== void 0 && parent.type === "LogicalExpression") {
1114
3568
  if (parent.operator === "||") {
1115
- yield babelTypes$2.booleanLiteral(false);
3569
+ yield booleanLiteral(false);
1116
3570
  return;
1117
3571
  }
1118
3572
  if (parent.operator === "&&") {
1119
- yield babelTypes$2.booleanLiteral(true);
3573
+ yield booleanLiteral(true);
1120
3574
  return;
1121
3575
  }
1122
3576
  }
1123
- yield babelTypes$2.booleanLiteral(true);
1124
- yield babelTypes$2.booleanLiteral(false);
1125
- } else if (babelTypes$2.isForStatement(node) && node.test === null) {
1126
- const replacement = deepCloneNode(node);
1127
- replacement.test = babelTypes$2.booleanLiteral(false);
3577
+ yield booleanLiteral(true);
3578
+ yield booleanLiteral(false);
3579
+ } else if (node.type === "ForStatement" && node.test === null) {
3580
+ const replacement = cloneNode(node);
3581
+ if (replacement.type === "ForStatement") replacement.test = booleanLiteral(false);
1128
3582
  yield replacement;
1129
- } else if (babelTypes$2.isSwitchCase(node) && node.consequent.length > 0) {
1130
- const replacement = deepCloneNode(node);
1131
- replacement.consequent = [];
3583
+ } else if (node.type === "SwitchCase" && node.consequent.length > 0) {
3584
+ const replacement = cloneNode(node);
3585
+ if (replacement.type === "SwitchCase") replacement.consequent = [];
1132
3586
  yield replacement;
1133
3587
  }
1134
3588
  };
1135
3589
  function isTestOfLoop(node, context) {
1136
3590
  const parent = context.parent;
1137
3591
  if (parent === void 0) return false;
1138
- if (babelTypes$2.isForStatement(parent) && parent.test === node) return true;
1139
- if (babelTypes$2.isWhileStatement(parent) && parent.test === node) return true;
1140
- if (babelTypes$2.isDoWhileStatement(parent) && parent.test === node) return true;
3592
+ if (parent.type === "ForStatement" && parent.test === node) return true;
3593
+ if (parent.type === "WhileStatement" && parent.test === node) return true;
3594
+ if (parent.type === "DoWhileStatement" && parent.test === node) return true;
1141
3595
  return false;
1142
3596
  }
1143
3597
  function isTestOfCondition(node, context) {
1144
3598
  const parent = context.parent;
1145
3599
  if (parent === void 0) return false;
1146
- return babelTypes$2.isIfStatement(parent) && parent.test === node;
3600
+ return parent.type === "IfStatement" && parent.test === node;
1147
3601
  }
1148
3602
  function isBooleanExpression(node) {
1149
- if (babelTypes$2.isBinaryExpression(node)) return booleanOperators.includes(node.operator);
1150
- if (babelTypes$2.isLogicalExpression(node)) return booleanOperators.includes(node.operator);
3603
+ if (node.type === "BinaryExpression") return booleanOperators.includes(node.operator);
3604
+ if (node.type === "LogicalExpression") return booleanOperators.includes(node.operator);
1151
3605
  return false;
1152
3606
  }
1153
3607
  const operators = {
@@ -1164,8 +3618,8 @@ function isEqualityOperator(operator) {
1164
3618
  return Object.keys(operators).includes(operator);
1165
3619
  }
1166
3620
  const equalityOperatorMutator = function* (node, _context) {
1167
- if (t$1.isBinaryExpression(node) && isEqualityOperator(node.operator)) for (const mutableOperator of operators[node.operator]) {
1168
- const replacement = t$1.cloneNode(node, true);
3621
+ if (node.type === "BinaryExpression" && isEqualityOperator(node.operator)) for (const mutableOperator of operators[node.operator]) {
3622
+ const replacement = cloneNode(node);
1169
3623
  replacement.operator = mutableOperator;
1170
3624
  yield replacement;
1171
3625
  }
@@ -1176,9 +3630,9 @@ const logicalOperatorReplacements = Object.freeze({
1176
3630
  "??": "&&"
1177
3631
  });
1178
3632
  const logicalOperatorMutator = function* (node, _context) {
1179
- if (babelTypes$2.isLogicalExpression(node) && isSupportedLogicalOperator(node.operator)) {
3633
+ if (node.type === "LogicalExpression" && isSupportedLogicalOperator(node.operator)) {
1180
3634
  const mutatedOperator = logicalOperatorReplacements[node.operator];
1181
- const replacement = deepCloneNode(node);
3635
+ const replacement = cloneNode(node);
1182
3636
  replacement.operator = mutatedOperator;
1183
3637
  yield replacement;
1184
3638
  }
@@ -1214,62 +3668,71 @@ const noReverseReplacements = ["getUTCDate", "setUTCDate"];
1214
3668
  const replacements = new Map(Object.entries(baseReplacements));
1215
3669
  for (const [key, value] of Object.entries(baseReplacements)) if (value !== null && !noReverseReplacements.includes(key)) replacements.set(value, key);
1216
3670
  const methodExpressionMutator = function* (node, _context) {
1217
- if (!(babelTypes$2.isCallExpression(node) || babelTypes$2.isOptionalCallExpression(node))) return;
3671
+ if (node.type !== "CallExpression") return;
1218
3672
  const { callee } = node;
1219
- if (!(babelTypes$2.isMemberExpression(callee) || babelTypes$2.isOptionalMemberExpression(callee)) || !babelTypes$2.isIdentifier(callee.property)) return;
3673
+ if (callee.type !== "MemberExpression" || callee.property.type !== "Identifier") return;
1220
3674
  const newName = replacements.get(callee.property.name);
1221
3675
  if (newName === void 0) return;
3676
+ if (callee.object.type === "Super") return;
1222
3677
  if (newName === null) {
1223
- yield deepCloneNode(callee.object);
3678
+ yield callExpression(cloneNode(callee.object), [], callee.optional === true);
1224
3679
  return;
1225
3680
  }
1226
- const nodeArguments = node.arguments.map((argumentNode) => deepCloneNode(argumentNode));
1227
- let mutatedCallee;
1228
- if (babelTypes$2.isMemberExpression(callee)) mutatedCallee = babelTypes$2.memberExpression(deepCloneNode(callee.object), babelTypes$2.identifier(newName), false, callee.optional);
1229
- else mutatedCallee = babelTypes$2.optionalMemberExpression(deepCloneNode(callee.object), babelTypes$2.identifier(newName), false, callee.optional);
1230
- if (babelTypes$2.isCallExpression(node)) yield babelTypes$2.callExpression(mutatedCallee, nodeArguments);
1231
- else yield babelTypes$2.optionalCallExpression(mutatedCallee, nodeArguments, node.optional);
3681
+ const nodeArguments = [];
3682
+ for (const argumentNode of node.arguments) if (argumentNode.type !== "SpreadElement") nodeArguments.push(cloneNode(argumentNode));
3683
+ yield callExpression(memberExpression(cloneNode(callee.object), identifier(newName), false, callee.optional === true), nodeArguments, node.optional === true);
1232
3684
  };
1233
3685
  const objectLiteralMutator = function* (node, _context) {
1234
- if (babelTypes$2.isObjectExpression(node) && node.properties.length > 0) yield babelTypes$2.objectExpression([]);
3686
+ if (node.type === "ObjectExpression" && node.properties.length > 0) yield {
3687
+ type: "ObjectExpression",
3688
+ properties: []
3689
+ };
1235
3690
  };
1236
3691
  const optionalChainingMutator = function* (node, _context) {
1237
- if (t$1.isOptionalMemberExpression(node) && node.optional) yield t$1.optionalMemberExpression(t$1.cloneNode(node.object, true), t$1.cloneNode(node.property, true), node.computed, false);
1238
- if (t$1.isOptionalCallExpression(node) && node.optional) yield t$1.optionalCallExpression(t$1.cloneNode(node.callee, true), node.arguments.map((arg) => t$1.cloneNode(arg, true)), false);
3692
+ if (node.type === "MemberExpression" && node.optional) {
3693
+ const replacement = cloneNode(node);
3694
+ replacement.optional = false;
3695
+ yield replacement;
3696
+ }
3697
+ if (node.type === "CallExpression" && node.optional) {
3698
+ const replacement = cloneNode(node);
3699
+ replacement.optional = false;
3700
+ yield replacement;
3701
+ }
1239
3702
  };
1240
3703
  const regexMutator = function* (node, context) {
1241
- if (babelTypes$2.isRegExpLiteral(node)) for (const replacementPattern of mutateRegexPattern(node.pattern, node.flags)) yield babelTypes$2.regExpLiteral(replacementPattern, node.flags);
1242
- else if (babelTypes$2.isStringLiteral(node) && isObviousRegexString(node, context)) {
3704
+ if (nodeType(node) === "Literal" && "regex" in node && node.regex !== null && node.regex !== void 0) for (const replacementPattern of mutateRegexPattern(node.regex.pattern, node.regex.flags)) yield regExpLiteral(replacementPattern, node.regex.flags);
3705
+ else if (nodeType(node) === "Literal" && "value" in node && typeof node.value === "string" && isObviousRegexString(node, context)) {
1243
3706
  const parent = context.parent;
1244
- if (parent !== void 0 && babelTypes$2.isNewExpression(parent)) {
3707
+ if (parent !== void 0 && parent.type === "NewExpression") {
1245
3708
  const flags = getFlags(parent);
1246
- for (const replacementPattern of mutateRegexPattern(node.value, flags)) yield babelTypes$2.stringLiteral(replacementPattern);
3709
+ for (const replacementPattern of mutateRegexPattern(node.value, flags)) yield stringLiteral(replacementPattern);
1247
3710
  }
1248
3711
  }
1249
3712
  };
1250
3713
  function isObviousRegexString(node, context) {
1251
3714
  const parent = context.parent;
1252
- if (parent === void 0 || !babelTypes$2.isNewExpression(parent) || !babelTypes$2.isIdentifier(parent.callee) || parent.callee.name !== RegExp.name) return false;
3715
+ if (parent === void 0 || parent.type !== "NewExpression" || parent.callee.type !== "Identifier" || parent.callee.name !== RegExp.name) return false;
1253
3716
  return parent.arguments[0] === node;
1254
3717
  }
1255
3718
  function getFlags(node) {
1256
3719
  const secondArg = node.arguments[1];
1257
- if (secondArg !== void 0 && babelTypes$2.isStringLiteral(secondArg)) return secondArg.value;
3720
+ if (secondArg !== void 0 && secondArg.type === "Literal" && typeof secondArg.value === "string") return secondArg.value;
1258
3721
  }
1259
3722
  const stringLiteralMutator = function* (node, context) {
1260
- if (babelTypes$2.isTemplateLiteral(node)) {
3723
+ if (node.type === "TemplateLiteral") {
1261
3724
  const firstQuasi = node.quasis[0];
1262
3725
  if (firstQuasi === void 0) return;
1263
3726
  let replacement;
1264
3727
  if (node.quasis.length === 1 && firstQuasi.value.raw.length === 0) replacement = "Stryker was here!";
1265
3728
  else replacement = "";
1266
- yield babelTypes$2.templateLiteral([babelTypes$2.templateElement({ raw: replacement })], []);
3729
+ yield templateLiteral([templateElement(replacement)], []);
1267
3730
  }
1268
- if (babelTypes$2.isStringLiteral(node) && isValidParent(node, context)) {
3731
+ if (nodeType(node) === "Literal" && "value" in node && typeof node.value === "string" && isValidParent(node, context)) {
1269
3732
  let replacement;
1270
3733
  if (node.value.length === 0) replacement = "Stryker was here!";
1271
3734
  else replacement = "";
1272
- yield babelTypes$2.stringLiteral(replacement);
3735
+ yield stringLiteral(replacement);
1273
3736
  }
1274
3737
  };
1275
3738
  function isValidParent(child, context) {
@@ -1278,25 +3741,25 @@ function isValidParent(child, context) {
1278
3741
  return !isImportExportRelated(parent) && !isJsxOrExpressionRelated(parent) && !isObjectOrClassPropertyKey(parent, child) && !isDisallowedCallExpression(parent);
1279
3742
  }
1280
3743
  function isImportExportRelated(parent) {
1281
- return babelTypes$2.isImportDeclaration(parent) || babelTypes$2.isExportDeclaration(parent) || babelTypes$2.isImportOrExportDeclaration(parent) || babelTypes$2.isTSExternalModuleReference(parent);
3744
+ return nodeType(parent) === "ImportDeclaration" || nodeType(parent) === "ExportNamedDeclaration" || nodeType(parent) === "ExportDefaultDeclaration" || nodeType(parent) === "ExportAllDeclaration" || nodeType(parent) === "TSExternalModuleReference";
1282
3745
  }
1283
3746
  function isJsxOrExpressionRelated(parent) {
1284
- return babelTypes$2.isJSXAttribute(parent) || babelTypes$2.isExpressionStatement(parent) || babelTypes$2.isTSLiteralType(parent) || babelTypes$2.isObjectMethod(parent);
3747
+ return nodeType(parent) === "JSXAttribute" || nodeType(parent) === "ExpressionStatement" || nodeType(parent) === "TSLiteralType" || parent.type === "Property" && parent.method === true;
1285
3748
  }
1286
3749
  function isObjectOrClassPropertyKey(parent, child) {
1287
- return babelTypes$2.isObjectProperty(parent) && parent.key === child || babelTypes$2.isClassProperty(parent) && parent.key === child;
3750
+ return (parent.type === "Property" || parent.type === "PropertyDefinition") && nodeType(parent.key) !== void 0 && parent.key === child;
1288
3751
  }
1289
3752
  function isDisallowedCallExpression(parent) {
1290
3753
  return isRequireCall(parent) || isSymbolCall(parent) || isImportCall(parent);
1291
3754
  }
1292
3755
  function isRequireCall(parent) {
1293
- return babelTypes$2.isCallExpression(parent) && babelTypes$2.isIdentifier(parent.callee, { name: "require" });
3756
+ return parent.type === "CallExpression" && nodeType(parent.callee) === "Identifier" && "name" in parent.callee && parent.callee.name === "require";
1294
3757
  }
1295
3758
  function isSymbolCall(parent) {
1296
- return babelTypes$2.isCallExpression(parent) && babelTypes$2.isIdentifier(parent.callee, { name: "Symbol" });
3759
+ return parent.type === "CallExpression" && nodeType(parent.callee) === "Identifier" && "name" in parent.callee && parent.callee.name === "Symbol";
1297
3760
  }
1298
3761
  function isImportCall(parent) {
1299
- return babelTypes$2.isCallExpression(parent) && babelTypes$2.isImport(parent.callee);
3762
+ return parent.type === "CallExpression" && nodeType(parent.callee) === "Import";
1300
3763
  }
1301
3764
  const UnaryOperator = {
1302
3765
  "+": "-",
@@ -1304,11 +3767,11 @@ const UnaryOperator = {
1304
3767
  "~": ""
1305
3768
  };
1306
3769
  const unaryOperatorMutator = function* (node, _context) {
1307
- if (babelTypes$2.isUnaryExpression(node) && isSupportedUnaryOperator(node.operator) && node.prefix) {
3770
+ if (node.type === "UnaryExpression" && isSupportedUnaryOperator(node.operator) && node.prefix) {
1308
3771
  const mutatedOperator = UnaryOperator[node.operator];
1309
3772
  let replacement;
1310
- if (isPlusOrMinus(mutatedOperator)) replacement = babelTypes$2.unaryExpression(mutatedOperator, deepCloneNode(node.argument));
1311
- else replacement = deepCloneNode(node.argument);
3773
+ if (isPlusOrMinus(mutatedOperator)) replacement = unaryExpression(mutatedOperator, cloneNode(node.argument));
3774
+ else replacement = cloneNode(node.argument);
1312
3775
  yield replacement;
1313
3776
  }
1314
3777
  };
@@ -1323,7 +3786,7 @@ const UpdateOperators = {
1323
3786
  "--": "++"
1324
3787
  };
1325
3788
  const updateOperatorMutator = function* (node, _context) {
1326
- if (babelTypes$2.isUpdateExpression(node)) yield babelTypes$2.updateExpression(UpdateOperators[node.operator], deepCloneNode(node.argument), node.prefix);
3789
+ if (node.type === "UpdateExpression") yield updateExpression(UpdateOperators[node.operator], cloneNode(node.argument), node.prefix);
1327
3790
  };
1328
3791
  /**
1329
3792
  * Every mutator this instrumenter can apply, named explicitly.
@@ -1371,11 +3834,6 @@ S.TaggedError("@systemfsoftware/stryker-js-instrumenter/TransformFailed")("Trans
1371
3834
  });
1372
3835
  //#endregion
1373
3836
  //#region src/Transformer.ts
1374
- /**
1375
- * Transformer — traverses ASTs, asks mutators for mutants and placers to instrument them.
1376
- */
1377
- const { types: babelTypes$1 } = babel;
1378
- const t = babelTypes$1;
1379
3837
  const STRYKER_NAMESPACE_HELPER = "stryNS_9fa48";
1380
3838
  const COVER_MUTANT_HELPER = "stryCov_9fa48";
1381
3839
  const IS_MUTANT_ACTIVE_HELPER = "stryMutAct_9fa48";
@@ -1385,8 +3843,8 @@ function createMutantCollector() {
1385
3843
  function collect(collector, fileName, original, mutable, offset = {
1386
3844
  line: 0,
1387
3845
  column: 0
1388
- }) {
1389
- const mutant = createMutant(collector.length.toString(), fileName, original, mutable, offset);
3846
+ }, lineTable = buildLineTable("")) {
3847
+ const mutant = createMutant(collector.length.toString(), fileName, original, mutable, offset, lineTable);
1390
3848
  collector.push(mutant);
1391
3849
  return mutant;
1392
3850
  }
@@ -1448,7 +3906,7 @@ function processStrykerDirectives(rule, node, allMutatorNames, originFileName) {
1448
3906
  }
1449
3907
  mutatorNames = mutatorNames.map((mutator) => mutator.toLowerCase());
1450
3908
  const reason = (optionalReason ?? DEFAULT_REASON).trim();
1451
- current = applyDirective(current, directiveType, scope, mutatorNames, reason, node.loc);
3909
+ current = applyDirective(current, directiveType, scope, mutatorNames, reason, comment.loc);
1452
3910
  }
1453
3911
  return {
1454
3912
  rule: current,
@@ -1499,62 +3957,52 @@ function applyRestore(rule, scope, mutatorNames, loc) {
1499
3957
  }
1500
3958
  }
1501
3959
  function getLine(loc) {
1502
- if (loc == null) throw new Error("Babel node without location");
3960
+ if (loc == null) throw new Error("Comment without location");
1503
3961
  return loc.start.line;
1504
3962
  }
1505
3963
  function toIgnorerPath(path) {
1506
3964
  let parentResult = null;
1507
3965
  if (path.parentPath !== null) parentResult = toIgnorerPath(path.parentPath);
3966
+ const node = path.node;
1508
3967
  return {
1509
3968
  node: path.node,
1510
3969
  parentPath: parentResult,
1511
3970
  isObjectExpression() {
1512
- return path.isObjectExpression();
3971
+ return nodeType(node) === "ObjectExpression";
1513
3972
  },
1514
3973
  isCallExpression() {
1515
- return path.isCallExpression() || path.isOptionalCallExpression();
3974
+ return nodeType(node) === "CallExpression";
1516
3975
  },
1517
3976
  isClassProperty() {
1518
- return path.isClassProperty();
3977
+ return nodeType(node) === "PropertyDefinition";
1519
3978
  },
1520
3979
  isClassPrivateProperty() {
1521
- return path.isClassPrivateProperty();
3980
+ return nodeType(node) === "PropertyDefinition" && Predicate.hasProperty(node, "key") && nodeType(PredicateRecord.key(node)) === "PrivateIdentifier";
1522
3981
  },
1523
3982
  isClassAccessorProperty() {
1524
- return path.isClassAccessorProperty();
3983
+ return nodeType(node) === "AccessorProperty";
1525
3984
  }
1526
3985
  };
1527
3986
  }
1528
- /**
1529
- * Wraps a parsed AST the way Babel's own pipeline does, so
1530
- * `NodePath#buildCodeFrameError` can render a code frame
1531
- * (https://github.com/babel/babel/issues/11889). Without the wrapper a
1532
- * placement failure reports no source context.
1533
- */
1534
- function createBabelFile(filename, code, ast) {
1535
- return new File({ filename }, {
1536
- code,
1537
- ast
1538
- });
1539
- }
3987
+ const PredicateRecord = { key: (node) => Predicate.hasProperty(node, "key") ? node["key"] : void 0 };
1540
3988
  function isTypeNode(path) {
1541
- return path.isTypeAnnotation() || flowTypeAnnotationNodeTypes.includes(path.node.type) || tsTypeAnnotationNodeTypes.includes(path.node.type) || isDeclareVariableStatement(path) || isDeclareModule(path);
3989
+ return flowTypeAnnotationNodeTypes.includes(path.node.type) || tsTypeAnnotationNodeTypes.includes(path.node.type) || isDeclareVariableStatement(path.node) || isDeclareModule(path.node);
1542
3990
  }
1543
3991
  /**
1544
3992
  * Determines whether or not it is a declare variable statement node.
1545
3993
  * @example
1546
3994
  * declare const foo: 'foo';
1547
3995
  */
1548
- function isDeclareVariableStatement(path) {
1549
- return path.isVariableDeclaration() && path.node.declare === true;
3996
+ function isDeclareVariableStatement(node) {
3997
+ return nodeType(node) === "VariableDeclaration" && "declare" in node && node.declare === true;
1550
3998
  }
1551
3999
  /**
1552
4000
  * Determines whether or not a node is a string literal that is the name of a module.
1553
4001
  * @example
1554
4002
  * declare module "express" {};
1555
4003
  */
1556
- function isDeclareModule(path) {
1557
- return path.isTSModuleDeclaration() && (path.node.declare ?? false);
4004
+ function isDeclareModule(node) {
4005
+ return nodeType(node) === "TSModuleDeclaration" && "declare" in node && node.declare === true;
1558
4006
  }
1559
4007
  const tsTypeAnnotationNodeTypes = Object.freeze([
1560
4008
  "TSAsExpression",
@@ -1579,18 +4027,17 @@ const flowTypeAnnotationNodeTypes = Object.freeze([
1579
4027
  "DeclareExportAllDeclaration",
1580
4028
  "InterfaceDeclaration",
1581
4029
  "OpaqueType",
1582
- "TypeAlias",
1583
- "InterfaceDeclaration"
4030
+ "TypeAlias"
1584
4031
  ]);
1585
4032
  function isImportDeclaration(path) {
1586
- return babelTypes$1.isTSImportEqualsDeclaration(path.node) || path.isImportDeclaration();
4033
+ return nodeType(path.node) === "TSImportEqualsDeclaration" || path.node.type === "ImportDeclaration";
1587
4034
  }
1588
4035
  /**
1589
4036
  * returns syntax for `global.activeMutant === $mutantId`
1590
4037
  * @param mutantId The id of the mutant to switch
1591
4038
  */
1592
4039
  function mutantTestExpression(mutantId) {
1593
- return babelTypes$1.callExpression(babelTypes$1.identifier(IS_MUTANT_ACTIVE_HELPER), [babelTypes$1.stringLiteral(mutantId)]);
4040
+ return callExpression(identifier(IS_MUTANT_ACTIVE_HELPER), [stringLiteral(mutantId)]);
1594
4041
  }
1595
4042
  /**
1596
4043
  * Returns a sequence of mutation coverage counters with an optional last expression.
@@ -1600,30 +4047,26 @@ function mutantTestExpression(mutantId) {
1600
4047
  * @param targetExpression The original expression
1601
4048
  */
1602
4049
  function mutationCoverageSequenceExpression(mutants, targetExpression) {
1603
- const mutantIds = [...mutants].map((mutant) => babelTypes$1.stringLiteral(mutant.id));
1604
- const sequence = [babelTypes$1.callExpression(babelTypes$1.identifier(COVER_MUTANT_HELPER), mutantIds)];
4050
+ const mutantIds = [...mutants].map((mutant) => stringLiteral(mutant.id));
4051
+ const sequence = [callExpression(identifier(COVER_MUTANT_HELPER), mutantIds)];
1605
4052
  if (targetExpression) sequence.push(targetExpression);
1606
- return babelTypes$1.sequenceExpression(sequence);
4053
+ return sequenceExpression(sequence);
1607
4054
  }
1608
4055
  /**
1609
- * Narrows an applied mutant to the node kind a placer emits. `applied()` hands
1610
- * back a plain node — whether it fits this position is the placer's claim, and
1611
- * `canPlace` is what established it, so a mismatch here means the placer was
1612
- * handed a mutant it never accepted.
4056
+ * Verifies the placer's claim: `canPlace` established the node kind, so a
4057
+ * mismatch here means the placer was handed a mutant it never accepted.
1613
4058
  */
1614
4059
  function nodeOfKind(mutant, node, isKind, kind) {
1615
4060
  if (!isKind(node)) throw new Error(`Cannot place mutant ${mutant.id}: expected ${kind}, got ${node.type}`);
1616
4061
  return node;
1617
4062
  }
1618
- function throwPlacementError(error, nodePath, placer, mutants, fileName) {
1619
- const location = `${path$1.relative(process.cwd(), fileName)}:${nodePath.node.loc?.start.line}:${nodePath.node.loc?.start.column}`;
4063
+ function throwPlacementError(error, nodePath, placer, mutants, fileName, lineTable) {
4064
+ const span = spanOf(nodePath.node);
4065
+ const position = span !== void 0 ? positionFromLineTable(span.start, lineTable) : void 0;
4066
+ const location = `${path$1.relative(process.cwd(), fileName)}:${position?.line}:${position?.column}`;
1620
4067
  const message = `${placer.name} could not place mutants with type(s): "${new Intl.ListFormat("en").format(mutants.map((mutant) => mutant.mutatorName))}"`;
1621
4068
  const errorMessage = `${location} ${message}. Either remove this file from the list of files to be mutated, or exclude the mutator (using ${propertyPath()("mutator", "excludedMutations")}). Please report this issue at ${strykerReportBugUrl(message)}. Original error: ${error.stack}`;
1622
- let builtError = new Error(errorMessage);
1623
- try {
1624
- builtError = nodePath.buildCodeFrameError(errorMessage);
1625
- } catch {}
1626
- throw builtError;
4069
+ throw new Error(errorMessage);
1627
4070
  }
1628
4071
  /**
1629
4072
  * Will set the identifier of anonymous function expressions if is located in a variable declaration.
@@ -1634,11 +4077,15 @@ function throwPlacementError(error, nodePath, placer, mutants, fileName) {
1634
4077
  * const a = function a() {}
1635
4078
  */
1636
4079
  function classOrFunctionExpressionNamedIfNeeded(path) {
1637
- if ((path.isFunctionExpression() || path.isClassExpression()) && !path.node.id) {
1638
- if (path.parentPath.isVariableDeclarator() && babelTypes$1.isIdentifier(path.parentPath.node.id)) {
1639
- path.node.id = path.parentPath.node.id;
4080
+ const kind = nodeType(path.node);
4081
+ if ((kind === "FunctionExpression" || kind === "ClassExpression") && !("id" in path.node) === false && path.node["id"] !== null) {}
4082
+ if ((kind === "FunctionExpression" || kind === "ClassExpression") && "id" in path.node && path.node.id == null) {
4083
+ const parentPath = path.parentPath;
4084
+ if (parentPath !== null && parentPath.node.type === "VariableDeclarator" && parentPath.node.id.type === "Identifier") {
4085
+ path.node.id = parentPath.node.id;
1640
4086
  return path.node;
1641
- } else if (path.parentPath.isObjectProperty() && babelTypes$1.isIdentifier(path.parentPath.node.key) && path.getStatementParent()?.isVariableDeclaration() === true) return path.node;
4087
+ }
4088
+ if (parentPath !== null && parentPath.node.type === "Property" && parentPath.node.key.type === "Identifier" && path.getStatementParent()?.node.type === "VariableDeclaration") return path.node;
1642
4089
  }
1643
4090
  }
1644
4091
  /**
@@ -1650,26 +4097,32 @@ function classOrFunctionExpressionNamedIfNeeded(path) {
1650
4097
  * const a = (() => { const a = () => {}; return a; })()
1651
4098
  */
1652
4099
  function arrowFunctionExpressionNamedIfNeeded(path) {
1653
- if (path.isArrowFunctionExpression() && path.parentPath.isVariableDeclarator() && babelTypes$1.isIdentifier(path.parentPath.node.id)) return babelTypes$1.callExpression(babelTypes$1.arrowFunctionExpression([], babelTypes$1.blockStatement([babelTypes$1.variableDeclaration("const", [babelTypes$1.variableDeclarator(path.parentPath.node.id, path.node)]), babelTypes$1.returnStatement(path.parentPath.node.id)])), []);
4100
+ const parentPath = path.parentPath;
4101
+ if (path.node.type === "ArrowFunctionExpression" && parentPath !== null && parentPath.node.type === "VariableDeclarator" && parentPath.node.id.type === "Identifier") {
4102
+ const declaratorId = parentPath.node.id;
4103
+ return callExpression(arrowFunctionExpression([], blockStatement([variableDeclaration("const", [variableDeclarator(declaratorId, path.node)]), returnStatement(declaratorId)])), []);
4104
+ }
1654
4105
  }
1655
4106
  function nameIfAnonymous(path) {
1656
4107
  return classOrFunctionExpressionNamedIfNeeded(path) ?? arrowFunctionExpressionNamedIfNeeded(path) ?? path.node;
1657
4108
  }
1658
4109
  function isMemberOrCallOrNonNullExpression(path) {
1659
- return isCallExpression(path) || isMemberOrNonNullExpression(path);
4110
+ return isCallExpressionNode(path) || isMemberOrNonNullExpression(path);
1660
4111
  }
1661
4112
  function isMemberOrNonNullExpression(path) {
1662
- return isMemberExpression(path) || path.isTSNonNullExpression();
4113
+ return isMemberExpressionNode(path) || nodeType(path?.node) === "TSNonNullExpression";
1663
4114
  }
1664
- function isMemberExpression(path) {
1665
- return path.isMemberExpression() || path.isOptionalMemberExpression();
4115
+ function isMemberExpressionNode(path) {
4116
+ return nodeType(path?.node) === "MemberExpression";
1666
4117
  }
1667
- function isCallExpression(path) {
1668
- return path.isCallExpression() || path.isOptionalCallExpression();
4118
+ function isCallExpressionNode(path) {
4119
+ return nodeType(path?.node) === "CallExpression";
1669
4120
  }
1670
4121
  function isValidExpression(path) {
1671
4122
  const parent = path.parentPath;
1672
- return !isObjectPropertyKey() && !isPartOfChain() && !parent.isTaggedTemplateExpression() && !isPartOfDeleteExpression() && !isPartOfAssignmentExpression();
4123
+ if (parent === null) return true;
4124
+ const parentNode = parent.node;
4125
+ return !isObjectPropertyKey() && !isPartOfChain() && !(parentNode.type === "TaggedTemplateExpression") && !isPartOfDeleteExpression() && !isPartOfAssignmentExpression();
1673
4126
  /**
1674
4127
  * Determines if the expression is property of an object.
1675
4128
  * @example
@@ -1678,7 +4131,7 @@ function isValidExpression(path) {
1678
4131
  * };
1679
4132
  */
1680
4133
  function isObjectPropertyKey() {
1681
- return parent.isObjectProperty() && parent.node.key === path.node;
4134
+ return parentNode.type === "Property" && parentNode.key === path.node;
1682
4135
  }
1683
4136
  /**
1684
4137
  * Determines if the expression is part of a call/member chain.
@@ -1694,7 +4147,7 @@ function isValidExpression(path) {
1694
4147
  * bar?.baz[0]
1695
4148
  */
1696
4149
  function isPartOfChain() {
1697
- return isMemberOrCallOrNonNullExpression(path) && (isMemberExpression(parent) && !(parent.node.computed && parent.node.property === path.node) || parent.isTSNonNullExpression() || isCallExpression(parent) && parent.node.callee === path.node);
4150
+ return isMemberOrCallOrNonNullExpression(path) && (isMemberExpressionNode(parent) && !(parentNode.type === "MemberExpression" && parentNode.computed && parentNode.property === path.node) || nodeType(parentNode) === "TSNonNullExpression" || isCallExpressionNode(parent) && parentNode.type === "CallExpression" && parentNode.callee === path.node);
1698
4151
  }
1699
4152
  /**
1700
4153
  * Determines if the expression is part of a delete expression.
@@ -1703,7 +4156,7 @@ function isValidExpression(path) {
1703
4156
  * delete foo.bar;
1704
4157
  */
1705
4158
  function isPartOfDeleteExpression() {
1706
- return parent.isUnaryExpression() && parent.node.operator === "delete";
4159
+ return parentNode.type === "UnaryExpression" && parentNode.operator === "delete";
1707
4160
  }
1708
4161
  /**
1709
4162
  * Determines if the expression is part of an assignment expression.
@@ -1713,7 +4166,7 @@ function isValidExpression(path) {
1713
4166
  * initialNodes.filter((n) => n.id === 'tiptilt')[0].className = tiptiltState;
1714
4167
  */
1715
4168
  function isPartOfAssignmentExpression() {
1716
- return parent.isAssignmentExpression() && parent.node.left === path.node;
4169
+ return parentNode.type === "AssignmentExpression" && parentNode.left === path.node;
1717
4170
  }
1718
4171
  }
1719
4172
  const allMutantPlacers = Object.freeze([
@@ -1725,7 +4178,7 @@ const allMutantPlacers = Object.freeze([
1725
4178
  place(path, appliedMutants) {
1726
4179
  let expression = nameIfAnonymous(path);
1727
4180
  expression = mutationCoverageSequenceExpression(appliedMutants.keys(), expression);
1728
- for (const [mutant, appliedMutant] of appliedMutants) expression = babelTypes$1.conditionalExpression(mutantTestExpression(mutant.id), nodeOfKind(mutant, appliedMutant, babelTypes$1.isExpression, "an expression"), expression);
4181
+ for (const [mutant, appliedMutant] of appliedMutants) expression = conditionalExpression(mutantTestExpression(mutant.id), nodeOfKind(mutant, appliedMutant, isExpressionKind, "an expression"), expression);
1729
4182
  path.replaceWith(expression);
1730
4183
  }
1731
4184
  },
@@ -1735,27 +4188,28 @@ const allMutantPlacers = Object.freeze([
1735
4188
  return path.isStatement();
1736
4189
  },
1737
4190
  place(path, appliedMutants) {
1738
- const bodyStatements = [t.expressionStatement(mutationCoverageSequenceExpression(appliedMutants.keys()))];
1739
- if (path.isBlockStatement()) bodyStatements.push(...path.node.body);
4191
+ const bodyStatements = [expressionStatement(mutationCoverageSequenceExpression(appliedMutants.keys()))];
4192
+ if (path.node.type === "BlockStatement") bodyStatements.push(...path.node.body);
1740
4193
  else bodyStatements.push(path.node);
1741
- let statement = t.blockStatement(bodyStatements);
1742
- for (const [mutant, appliedMutant] of appliedMutants) statement = t.ifStatement(mutantTestExpression(mutant.id), t.blockStatement([nodeOfKind(mutant, appliedMutant, t.isStatement, "a statement")]), statement);
1743
- if (path.isBlockStatement()) path.replaceWith(t.blockStatement([statement]));
4194
+ let statement = blockStatement(bodyStatements);
4195
+ for (const [mutant, appliedMutant] of appliedMutants) statement = ifStatement(mutantTestExpression(mutant.id), blockStatement([nodeOfKind(mutant, appliedMutant, isStatementKind, "a statement")]), statement);
4196
+ if (path.node.type === "BlockStatement") path.replaceWith(blockStatement([statement]));
1744
4197
  else path.replaceWith(statement);
1745
4198
  }
1746
4199
  },
1747
4200
  {
1748
4201
  name: "switchCaseMutantPlacer",
1749
4202
  canPlace(path) {
1750
- return path.isSwitchCase();
4203
+ return nodeType(path.node) === "SwitchCase";
1751
4204
  },
1752
4205
  place(path, appliedMutants) {
1753
- let consequence = babel.types.blockStatement([babel.types.expressionStatement(mutationCoverageSequenceExpression(appliedMutants.keys())), ...path.node.consequent]);
4206
+ const currentCase = path.node;
4207
+ let consequence = blockStatement([expressionStatement(mutationCoverageSequenceExpression(appliedMutants.keys())), ...currentCase.consequent]);
1754
4208
  for (const [mutant, appliedMutant] of appliedMutants) {
1755
- const switchCase = nodeOfKind(mutant, appliedMutant, babel.types.isSwitchCase, "a switch case");
1756
- consequence = babel.types.ifStatement(mutantTestExpression(mutant.id), babel.types.blockStatement(switchCase.consequent), consequence);
4209
+ const appliedCase = nodeOfKind(mutant, appliedMutant, (candidate) => nodeType(candidate) === "SwitchCase", "a switch case");
4210
+ consequence = ifStatement(mutantTestExpression(mutant.id), blockStatement(appliedCase.consequent), consequence);
1757
4211
  }
1758
- path.replaceWith(babel.types.switchCase(path.node.test, [consequence]));
4212
+ path.replaceWith(switchCase(currentCase.test, [consequence]));
1759
4213
  }
1760
4214
  }
1761
4215
  ]);
@@ -1781,15 +4235,17 @@ function shouldIgnore(path) {
1781
4235
  }
1782
4236
  const angularIgnorer = { shouldIgnore };
1783
4237
  function isClassFieldLike(path) {
1784
- return path.isClassProperty() || path.isClassPrivateProperty() || path.isClassAccessorProperty();
4238
+ const kind = nodeType(path.node);
4239
+ if (kind === "PropertyDefinition" || kind === "AccessorProperty") return true;
4240
+ return kind === "PropertyDefinition" && Predicate.hasProperty(path.node, "key") && nodeType(path.node["key"]) === "PrivateIdentifier";
1785
4241
  }
1786
4242
  function isInputModelOrOutputConfigurationObject(path) {
1787
4243
  const parent = path.parentPath;
1788
4244
  const grandParent = parent?.parentPath;
1789
- if (!path.isObjectExpression() || parent === null || parent === void 0 || !parent.isCallExpression() || grandParent === null || grandParent === void 0 || !grandParent.isClassProperty()) return false;
1790
- const callExpression = parent;
1791
- const objectExpression = path;
1792
- const callNode = callExpression.node;
4245
+ if (nodeType(path.node) !== "ObjectExpression" || parent === null || parent === void 0 || nodeType(parent.node) !== "CallExpression" || grandParent === null || grandParent === void 0 || nodeType(grandParent.node) !== "PropertyDefinition") return false;
4246
+ const callExpressionPath = parent;
4247
+ const objectExpressionPath = path;
4248
+ const callNode = callExpressionPath.node;
1793
4249
  if (!Predicate.hasProperty(callNode, "callee") || !Predicate.hasProperty(callNode, "arguments")) return false;
1794
4250
  const callee = callNode["callee"];
1795
4251
  const args = callNode["arguments"];
@@ -1797,17 +4253,17 @@ function isInputModelOrOutputConfigurationObject(path) {
1797
4253
  const isRequiredSignalIOFunction = isMemberExpressionWithIdentifier(callee, ANGULAR_SIGNAL_IO_FUNCTIONS, "required");
1798
4254
  const isSignalIOFunction = isIdentifierIn(callee, ANGULAR_SIGNAL_IO_FUNCTIONS);
1799
4255
  const isOutput = isIdentifierWithName(callee, "output");
1800
- if (isRequiredSignalIOFunction || isOutput) return args.length >= 1 && args[0] === objectExpression.node;
1801
- if (isSignalIOFunction) return args.length >= 2 && args[1] === objectExpression.node;
4256
+ if (isRequiredSignalIOFunction || isOutput) return args.length >= 1 && args[0] === objectExpressionPath.node;
4257
+ if (isSignalIOFunction) return args.length >= 2 && args[1] === objectExpressionPath.node;
1802
4258
  return false;
1803
4259
  }
1804
4260
  function isSignalQueryOptionsObject(path) {
1805
4261
  const parent = path.parentPath;
1806
4262
  const grandParent = parent?.parentPath;
1807
- if (!path.isObjectExpression() || parent === null || parent === void 0 || !parent.isCallExpression() || grandParent === null || grandParent === void 0 || !isClassFieldLike(grandParent)) return false;
1808
- const callExpression = parent;
1809
- const objectExpression = path;
1810
- const callNode = callExpression.node;
4263
+ if (nodeType(path.node) !== "ObjectExpression" || parent === null || parent === void 0 || nodeType(parent.node) !== "CallExpression" || grandParent === null || grandParent === void 0 || !isClassFieldLike(grandParent)) return false;
4264
+ const callExpressionPath = parent;
4265
+ const objectExpressionPath = path;
4266
+ const callNode = callExpressionPath.node;
1811
4267
  if (!Predicate.hasProperty(callNode, "callee") || !Predicate.hasProperty(callNode, "arguments")) return false;
1812
4268
  const callee = callNode["callee"];
1813
4269
  const args = callNode["arguments"];
@@ -1815,7 +4271,7 @@ function isSignalQueryOptionsObject(path) {
1815
4271
  const isQueryFn = isIdentifierIn(callee, ANGULAR_SIGNAL_QUERY_FUNCTIONS);
1816
4272
  const isRequiredQueryFn = isMemberExpressionWithIdentifier(callee, ANGULAR_SIGNAL_QUERY_FUNCTIONS, "required");
1817
4273
  if (!isQueryFn && !isRequiredQueryFn) return false;
1818
- return args.length >= 2 && args[1] === objectExpression.node;
4274
+ return args.length >= 2 && args[1] === objectExpressionPath.node;
1819
4275
  }
1820
4276
  function isIdentifierWithName(node, name) {
1821
4277
  return Predicate.hasProperty(node, "type") && node["type"] === "Identifier" && Predicate.hasProperty(node, "name") && node["name"] === name;
@@ -1829,9 +4285,11 @@ function isMemberExpressionWithIdentifier(node, objectNames, propertyName) {
1829
4285
  const strykerPlugins = [];
1830
4286
  const frameworkPluginsFileUrl = import.meta.url;
1831
4287
  /**
1832
- * Returns syntax for the header if JS/TS files
4288
+ * The instrumentation header: parsed once with oxc, frozen, shared. The
4289
+ * `globalThis` implementation is based on core-js's — see
4290
+ * https://github.com/stryker-mutator/stryker-js/issues/4035
1833
4291
  */
1834
- const parsedInstrumentationHeader = babel.parse(`// @ts-nocheck
4292
+ const parsedInstrumentationHeader = parseSync("instrumenter-header.js", `// @ts-nocheck
1835
4293
  var ${STRYKER_NAMESPACE_HELPER} = function(){
1836
4294
  var g = typeof globalThis === 'object' && globalThis && globalThis.Math === Math && globalThis || new Function("return this")();
1837
4295
  var ns = g.${INSTRUMENTER_CONSTANTS.NAMESPACE} || (g.${INSTRUMENTER_CONSTANTS.NAMESPACE} = {});
@@ -1876,27 +4334,26 @@ var ${IS_MUTANT_ACTIVE_HELPER} = function(id) {
1876
4334
  ${IS_MUTANT_ACTIVE_HELPER} = isActive;
1877
4335
  return isActive(id);
1878
4336
  }`, {
1879
- configFile: false,
1880
- browserslistConfigFile: false,
1881
- env: { targets: {} }
4337
+ lang: "js",
4338
+ range: true
1882
4339
  });
1883
- if (!babelTypes$1.isFile(parsedInstrumentationHeader)) throw new Error("Instrumentation header parsed as non-File");
1884
- const instrumentationBabelHeader = parsedInstrumentationHeader.program.body;
1885
- deepFreeze(instrumentationBabelHeader);
4340
+ if (parsedInstrumentationHeader.errors.length > 0) throw new Error("Instrumentation header failed to parse");
4341
+ const instrumentationHeader = parsedInstrumentationHeader.program.body;
4342
+ deepFreeze(instrumentationHeader);
1886
4343
  function placeHeaderIfNeeded(mutantCollector, originFileName, options, root) {
1887
4344
  if (hasPlacedMutants(mutantCollector, originFileName) && options.noHeader !== true) placeHeader(root);
1888
4345
  }
1889
4346
  function placeHeader(root) {
1890
- let header = instrumentationBabelHeader;
1891
- const leadingComments = root.program.body[0]?.leadingComments;
4347
+ let header = instrumentationHeader;
4348
+ const leadingComments = root.body[0]?.leadingComments;
1892
4349
  if (Array.isArray(leadingComments)) {
1893
- const firstHeader = instrumentationBabelHeader[0];
4350
+ const firstHeader = instrumentationHeader[0];
1894
4351
  if (firstHeader === void 0) throw new Error("Instrumentation header is empty");
1895
- const cloned = babelTypes$1.cloneNode(firstHeader, true, false);
4352
+ const cloned = cloneNode(firstHeader);
1896
4353
  cloned.leadingComments = leadingComments;
1897
- header = [cloned, ...instrumentationBabelHeader.slice(1)];
4354
+ header = [cloned, ...instrumentationHeader.slice(1)];
1898
4355
  }
1899
- root.program.body.unshift(...header);
4356
+ root.body.unshift(...header);
1900
4357
  }
1901
4358
  function deepFreeze(value) {
1902
4359
  if (value !== null && typeof value === "object") {
@@ -1930,7 +4387,7 @@ function transform(ast, mutantCollector, transformerContext) {
1930
4387
  case "html": return transformHtml(ast, mutantCollector, context);
1931
4388
  case "js":
1932
4389
  case "ts":
1933
- case "tsx": return transformBabel(ast, mutantCollector, context);
4390
+ case "tsx": return transformScript(ast, mutantCollector, context);
1934
4391
  case "svelte": return transformSvelte(ast, mutantCollector, context);
1935
4392
  }
1936
4393
  }
@@ -1960,7 +4417,8 @@ const transformSvelte = (svelte, mutantCollector, context) => {
1960
4417
  root.moduleScript = {
1961
4418
  ast: {
1962
4419
  format: "js",
1963
- root: babelTypes$1.file(babelTypes$1.program([])),
4420
+ root: emptyProgram(),
4421
+ comments: [],
1964
4422
  rawContent: "",
1965
4423
  originFileName
1966
4424
  },
@@ -1980,15 +4438,22 @@ const transformSvelte = (svelte, mutantCollector, context) => {
1980
4438
  }
1981
4439
  return warnings;
1982
4440
  };
1983
- const { traverse: traverse$1 } = babel;
1984
- const transformBabel = ({ root, originFileName, rawContent, offset }, mutantCollector, { options, mutateDescription }, mutators = allMutators, mutantPlacers = allMutantPlacers) => {
1985
- const file = createBabelFile(originFileName, rawContent, root);
4441
+ function emptyProgram() {
4442
+ return {
4443
+ type: "Program",
4444
+ sourceType: "module",
4445
+ body: []
4446
+ };
4447
+ }
4448
+ const transformScript = ({ root, originFileName, rawContent, offset, comments }, mutantCollector, { options, mutateDescription }, mutators = allMutators, mutantPlacers = allMutantPlacers) => {
4449
+ const lineTable = buildLineTable(rawContent);
4450
+ attachComments(root, comments, lineTable);
1986
4451
  const placementMap = /* @__PURE__ */ new Map();
1987
4452
  let directiveRule = rootRule;
1988
4453
  const mutatorEntries = Object.entries(mutators);
1989
4454
  const allMutatorNames = mutatorEntries.map(([name]) => name.toLowerCase());
1990
4455
  const warnings = [];
1991
- traverse$1(file.ast, {
4456
+ traverse(root, {
1992
4457
  enter(path) {
1993
4458
  const result = processStrykerDirectives(directiveRule, path.node, allMutatorNames, originFileName);
1994
4459
  directiveRule = result.rule;
@@ -2024,7 +4489,7 @@ const transformBabel = ({ root, originFileName, rawContent, offset }, mutantColl
2024
4489
  });
2025
4490
  }
2026
4491
  function shouldSkip(path) {
2027
- return isTypeNode(path) || isImportDeclaration(path) || path.isDecorator() || mutateDescription === false || Array.isArray(mutateDescription) && mutateDescription.every((range) => {
4492
+ return isTypeNode(path) || isImportDeclaration(path) || nodeType(path.node) === "Decorator" || mutateDescription === false || Array.isArray(mutateDescription) && mutateDescription.every((range) => {
2028
4493
  return !locationOverlaps(range, getNodeLocation(path.node));
2029
4494
  });
2030
4495
  }
@@ -2033,13 +4498,21 @@ const transformBabel = ({ root, originFileName, rawContent, offset }, mutantColl
2033
4498
  return locationIncluded(range, getNodeLocation(path.node));
2034
4499
  });
2035
4500
  }
4501
+ function getNodeLocation(node) {
4502
+ const span = spanOf(node);
4503
+ if (span === void 0) throw new Error("Node without a span");
4504
+ return {
4505
+ start: positionFromLineTable(span.start, lineTable),
4506
+ end: positionFromLineTable(span.end, lineTable)
4507
+ };
4508
+ }
2036
4509
  function placeMutantsIfNeeded(path) {
2037
4510
  const mutantsPlacement = placementMap.get(path.node);
2038
4511
  if (mutantsPlacement !== void 0 && mutantsPlacement.appliedMutants.size > 0) try {
2039
4512
  mutantsPlacement.placer.place(path, mutantsPlacement.appliedMutants);
2040
4513
  path.skip();
2041
4514
  } catch (error) {
2042
- throwPlacementError(toError(error), path, mutantsPlacement.placer, [...mutantsPlacement.appliedMutants.keys()], originFileName);
4515
+ throwPlacementError(toError(error), path, mutantsPlacement.placer, [...mutantsPlacement.appliedMutants.keys()], originFileName, lineTable);
2043
4516
  }
2044
4517
  }
2045
4518
  function ignoreMessageFor(path) {
@@ -2050,7 +4523,7 @@ const transformBabel = ({ root, originFileName, rawContent, offset }, mutantColl
2050
4523
  }
2051
4524
  }
2052
4525
  function collectMutants(path) {
2053
- return [...mutate(path)].map((mutable) => collect(mutantCollector, originFileName, path.node, mutable, offset)).filter((mutant) => mutant.ignoreReason === void 0);
4526
+ return [...mutate(path)].map((mutable) => collect(mutantCollector, originFileName, path.node, mutable, offset, lineTable)).filter((mutant) => mutant.ignoreReason === void 0);
2054
4527
  }
2055
4528
  function* mutate(path) {
2056
4529
  const context = toMutatorContext(path);
@@ -2082,20 +4555,6 @@ function toMutatorContext(path) {
2082
4555
  ancestors
2083
4556
  };
2084
4557
  }
2085
- function getNodeLocation(node) {
2086
- const loc = node.loc;
2087
- if (loc == null) throw new Error("Babel node without location");
2088
- return {
2089
- start: {
2090
- line: loc.start.line,
2091
- column: loc.start.column
2092
- },
2093
- end: {
2094
- line: loc.end.line,
2095
- column: loc.end.column
2096
- }
2097
- };
2098
- }
2099
4558
  function toError(value) {
2100
4559
  if (value instanceof Error) return value;
2101
4560
  return new Error("Unexpected error", { cause: value });
@@ -2105,60 +4564,23 @@ function toError(value) {
2105
4564
  /**
2106
4565
  * Instrument — the instrument capability: Cell description, file/mutant types and the instrument entry point.
2107
4566
  */
2108
- const { traverse, types: babelTypes } = babel;
2109
- function resolveGenerate() {
2110
- if (typeof generator === "function") return generator;
2111
- return generator.default;
2112
- }
2113
- resolveGenerate();
2114
- function toApiMutant(mutant) {
2115
- const loc = mutant.original.loc;
2116
- if (loc === void 0 || loc === null) throw new Error("Babel node without a source location");
2117
- const base = {
2118
- fileName: mutant.fileName,
2119
- id: mutant.id,
2120
- location: toApiLocation(loc, mutant.offset),
2121
- mutatorName: mutant.mutatorName,
2122
- replacement: mutant.replacementCode
2123
- };
2124
- if (mutant.ignoreReason === void 0) return Mutant.make(base);
2125
- return Mutant.make({
2126
- ...base,
2127
- statusReason: mutant.ignoreReason,
2128
- status: "Ignored"
2129
- });
2130
- }
2131
- function toApiLocation(source, offset) {
2132
- return {
2133
- start: toPosition(source.start, offset),
2134
- end: toPosition(source.end, offset)
2135
- };
2136
- }
2137
- function toPosition(source, offset) {
2138
- let columnOffset = 0;
2139
- if (source.line === 1) columnOffset = offset.column;
2140
- return {
2141
- column: source.column + columnOffset,
2142
- line: source.line + offset.line - 1
2143
- };
2144
- }
2145
4567
  const commentDirectiveRegEx = /^(\s*)@(ts-[a-z-]+).*$/;
2146
4568
  const tsDirectiveLikeRegEx = /@(ts-[a-z-]+)/;
2147
4569
  const startingCommentRegex = /(^\s*\/\*.*?\*\/)/gs;
2148
- async function disableTypeChecks(file, options) {
4570
+ async function disableTypeChecks(file) {
2149
4571
  const format = getFormat(file.name);
2150
4572
  if (!format) return file;
2151
4573
  if (isJSFileWithoutTSDirectives(file, format)) return {
2152
4574
  ...file,
2153
4575
  content: prefixWithNoCheck(file.content)
2154
4576
  };
2155
- const ast = await createParser(options)(file.content, file.name);
4577
+ const ast = await createParser()(file.content, file.name);
2156
4578
  switch (ast.format) {
2157
4579
  case "js":
2158
4580
  case "ts":
2159
4581
  case "tsx": return {
2160
4582
  ...file,
2161
- content: disableTypeCheckingInBabelAst(ast)
4583
+ content: disableTypeCheckingInScript(ast)
2162
4584
  };
2163
4585
  case "html": return {
2164
4586
  ...file,
@@ -2173,8 +4595,8 @@ async function disableTypeChecks(file, options) {
2173
4595
  function isJSFileWithoutTSDirectives(file, format) {
2174
4596
  return (format === "ts" || format === "js") && !tsDirectiveLikeRegEx.test(file.content);
2175
4597
  }
2176
- function disableTypeCheckingInBabelAst(ast) {
2177
- return prefixWithNoCheck(removeTSDirectives(ast.rawContent, ast.root.comments));
4598
+ function disableTypeCheckingInScript(ast) {
4599
+ return prefixWithNoCheck(removeTSDirectives(ast.rawContent, ast.comments));
2178
4600
  }
2179
4601
  function prefixWithNoCheck(code) {
2180
4602
  if (code.startsWith("#")) {
@@ -2189,14 +4611,14 @@ function prefixWithNoCheck(code) {
2189
4611
  }
2190
4612
  }
2191
4613
  function getScriptStart(script) {
2192
- const start = script.root.start;
2193
- if (start === void 0 || start === null) throw new Error("Script AST root without start");
2194
- return start;
4614
+ const span = spanOf(script.root);
4615
+ if (span === void 0) throw new Error("Script AST root without start");
4616
+ return span.start;
2195
4617
  }
2196
4618
  function getScriptEnd(script) {
2197
- const end = script.root.end;
2198
- if (end === void 0 || end === null) throw new Error("Script AST root without end");
2199
- return end;
4619
+ const span = spanOf(script.root);
4620
+ if (span === void 0) throw new Error("Script AST root without end");
4621
+ return span.end;
2200
4622
  }
2201
4623
  function disableTypeCheckingInHtml(ast) {
2202
4624
  const sortedScripts = [...ast.root.scripts].sort((a, b) => getScriptStart(a) - getScriptStart(b));
@@ -2205,7 +4627,7 @@ function disableTypeCheckingInHtml(ast) {
2205
4627
  for (const script of sortedScripts) {
2206
4628
  html += ast.rawContent.substring(currentIndex, getScriptStart(script));
2207
4629
  html += "\n";
2208
- html += prefixWithNoCheck(removeTSDirectives(script.rawContent, script.root.comments));
4630
+ html += prefixWithNoCheck(removeTSDirectives(script.rawContent, script.comments));
2209
4631
  html += "\n";
2210
4632
  currentIndex = getScriptEnd(script);
2211
4633
  }
@@ -2219,7 +4641,7 @@ function disableTypeCheckingInSvelte(ast) {
2219
4641
  for (const script of sortedScripts) {
2220
4642
  html += ast.rawContent.substring(currentIndex, script.range.start);
2221
4643
  html += "\n";
2222
- html += prefixWithNoCheck(removeTSDirectives(script.ast.rawContent, script.ast.root.comments));
4644
+ html += prefixWithNoCheck(removeTSDirectives(script.ast.rawContent, script.ast.comments));
2223
4645
  html += "\n";
2224
4646
  currentIndex = script.range.end;
2225
4647
  }
@@ -2243,7 +4665,7 @@ function tryParseTSDirective(comment) {
2243
4665
  const match = commentDirectiveRegEx.exec(comment.value);
2244
4666
  if (match !== null) {
2245
4667
  const start = comment.start;
2246
- if (start == null) throw new Error("Comment without start");
4668
+ if (start === void 0) throw new Error("Comment without start");
2247
4669
  const directivePrefix = match[1];
2248
4670
  if (directivePrefix === void 0) throw new Error("TS directive match without prefix");
2249
4671
  const directiveName = match[2];
@@ -2255,7 +4677,7 @@ function tryParseTSDirective(comment) {
2255
4677
  };
2256
4678
  }
2257
4679
  }
2258
- function toBabelLineNumber(range) {
4680
+ function toOneBasedLineNumber(range) {
2259
4681
  if (typeof range === "boolean") return range;
2260
4682
  return range.map(({ start, end }) => ({
2261
4683
  start: {
@@ -2288,7 +4710,7 @@ function isAst(value) {
2288
4710
  const instrumentDescription = pipe(Cell.read((command) => Effect.gen(function* () {
2289
4711
  const files = command.files;
2290
4712
  const options = command.options;
2291
- const parse = createParser(options);
4713
+ const parse = createParser();
2292
4714
  const asts = [];
2293
4715
  for (const { name, content } of files) {
2294
4716
  const ast = yield* Effect.tryPromise({
@@ -2309,7 +4731,7 @@ const instrumentDescription = pipe(Cell.read((command) => Effect.gen(function* (
2309
4731
  yield* Effect.try({
2310
4732
  try: () => transform(ast, collector, {
2311
4733
  options: toTransformerOptions(options),
2312
- mutateDescription: toBabelLineNumber(file.mutate)
4734
+ mutateDescription: toOneBasedLineNumber(file.mutate)
2313
4735
  }),
2314
4736
  catch: (cause) => new InstrumentError({
2315
4737
  message: `Failed to transform ${file.name}`,