fastscript 2.0.0 → 3.0.1

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.
@@ -16,8 +16,8 @@ export const FS_ERROR_CODES = Object.freeze({
16
16
  },
17
17
  FS1004: {
18
18
  severity: "error",
19
- message: "Type declarations are not valid runtime FastScript syntax.",
20
- hint: "Move `type`, `interface`, and `enum` definitions to `.d.ts` files or remove them from `.fs` files.",
19
+ message: "Legacy compatibility frontend conflict.",
20
+ hint: "Ordinary TS type-only syntax in `.fs` should parse. If this appears, treat it as a FastScript compatibility bug.",
21
21
  },
22
22
  FS1005: {
23
23
  severity: "error",
@@ -1,91 +1,125 @@
1
- import { compileFastScript } from "./fs-parser.mjs";
2
-
3
- export function normalizeFastScript(source, options = {}) {
4
- const { code } = compileFastScript(source, {
5
- file: options.file || "",
6
- mode: options.mode || "lenient",
7
- recover: options.recover !== false,
8
- inlineSourceMap: options.sourceMap === "inline",
9
- });
10
- return code;
11
- }
12
-
13
- export function normalizeFastScriptWithMetadata(source, options = {}) {
14
- return compileFastScript(source, {
15
- file: options.file || "",
16
- mode: options.mode || "lenient",
17
- recover: options.recover !== false,
18
- inlineSourceMap: options.sourceMap === "inline",
19
- });
20
- }
21
-
22
- export function stripTypeScriptHints(source) {
23
- const lines = source.split(/\r?\n/);
24
- const out = [];
25
- let skippingBlock = false;
26
- let blockDepth = 0;
27
-
28
- for (let i = 0; i < lines.length; i += 1) {
29
- const line = lines[i];
30
- let next = line;
31
-
32
- if (skippingBlock) {
33
- const opens = (next.match(/{/g) || []).length;
34
- const closes = (next.match(/}/g) || []).length;
35
- blockDepth += opens - closes;
36
- if (blockDepth <= 0) {
37
- skippingBlock = false;
38
- blockDepth = 0;
39
- }
40
- continue;
41
- }
42
-
43
- if (/^\s*interface\s+[A-Za-z_$][\w$]*\s*[{]/.test(next) || /^\s*enum\s+[A-Za-z_$][\w$]*\s*[{]/.test(next)) {
44
- out.push(`// ${next.trim()} (removed by fastscript migrate)`);
45
- skippingBlock = true;
46
- const opens = (next.match(/{/g) || []).length;
47
- const closes = (next.match(/}/g) || []).length;
48
- blockDepth = Math.max(1, opens - closes);
49
- continue;
50
- }
51
-
52
- if (/^\s*type\s+[A-Za-z_$][\w$]*\s*=/.test(next)) {
53
- out.push(`// ${next.trim()} (removed by fastscript migrate)`);
54
- if (!next.includes(";") && next.includes("{")) {
55
- skippingBlock = true;
56
- const opens = (next.match(/{/g) || []).length;
57
- const closes = (next.match(/}/g) || []).length;
58
- blockDepth = Math.max(1, opens - closes);
59
- }
60
- continue;
61
- }
62
-
63
- next = next.replace(/\bimport\s+type\b/g, "import");
64
- next = next.replace(/\bexport\s+type\b/g, "export");
65
-
66
- next = next.replace(
67
- /^(\s*)(const|let|var)\s+([A-Za-z_$][\w$]*)\s*:\s*([^=;]+)([=;].*)$/,
68
- "$1$2 $3 $5",
69
- );
70
-
71
- if (/\bfunction\b/.test(next) || /\)\s*=>/.test(next)) {
72
- next = next.replace(/\(([^)]*)\)/, (_, params) => {
73
- const cleaned = params.replace(
74
- /([A-Za-z_$][\w$]*)\s*:\s*([A-Za-z_$][\w$<>\[\]\|&, ?.]*)/g,
75
- "$1",
76
- );
77
- return `(${cleaned})`;
78
- });
79
- next = next.replace(/\)\s*:\s*([A-Za-z_$][\w$<>\[\]\|&, ?.]*)\s*\{/g, ") {");
80
- next = next.replace(/\bfunction\s+([A-Za-z_$][\w$]*)\s*<[^>]+>\s*\(/g, "function $1(");
81
- }
82
-
83
- next = next.replace(/^\s*<([A-Za-z_$][\w$,\s]*)>\s*\(/, "(");
84
- next = next.replace(/\)\s*=>\s*<[A-Za-z_$][\w$<>\[\]\|&, ?.]*>/g, ") =>");
85
- next = next.replace(/\sas\s+const\b/g, "");
86
- next = next.replace(/\s+satisfies\s+[A-Za-z_$][\w$<>\[\]\|&, ?.]*/g, "");
87
- out.push(next);
88
- }
89
-
90
- return out.join("\n");
91
- }
1
+ import { compileFastScript } from "./fs-parser.mjs";
2
+
3
+ export function normalizeFastScript(source, options = {}) {
4
+ const prepared = stripTypeScriptHints(String(source ?? ""));
5
+ const { code } = compileFastScript(prepared, {
6
+ file: options.file || "",
7
+ mode: options.mode || "lenient",
8
+ recover: options.recover !== false,
9
+ inlineSourceMap: options.sourceMap === "inline",
10
+ });
11
+ return code;
12
+ }
13
+
14
+ export function normalizeFastScriptWithMetadata(source, options = {}) {
15
+ const prepared = stripTypeScriptHints(String(source ?? ""));
16
+ return compileFastScript(prepared, {
17
+ file: options.file || "",
18
+ mode: options.mode || "lenient",
19
+ recover: options.recover !== false,
20
+ inlineSourceMap: options.sourceMap === "inline",
21
+ });
22
+ }
23
+
24
+ export function stripTypeScriptHints(source) {
25
+ const lines = source.split(/\r?\n/);
26
+ const out = [];
27
+ let skippingBlock = false;
28
+ let blockDepth = 0;
29
+
30
+ for (let i = 0; i < lines.length; i += 1) {
31
+ const line = lines[i];
32
+ let next = line;
33
+
34
+ if (skippingBlock) {
35
+ const opens = (next.match(/{/g) || []).length;
36
+ const closes = (next.match(/}/g) || []).length;
37
+ blockDepth += opens - closes;
38
+ if (blockDepth <= 0) {
39
+ skippingBlock = false;
40
+ blockDepth = 0;
41
+ }
42
+ continue;
43
+ }
44
+
45
+ if (/^\\s*interface\\s+[A-Za-z_$][\\w$]*(?:\\s*<[^>]+>)?\\s*[{]/.test(next) || /^\s*enum\s+[A-Za-z_$][\w$]*\s*[{]/.test(next)) {
46
+ out.push(`// ${next.trim()} (removed by fastscript migrate)`);
47
+ skippingBlock = true;
48
+ const opens = (next.match(/{/g) || []).length;
49
+ const closes = (next.match(/}/g) || []).length;
50
+ blockDepth = Math.max(1, opens - closes);
51
+ continue;
52
+ }
53
+
54
+ if (/^\\s*type\\s+[A-Za-z_$][\\w$]*(?:\\s*<[^>]+>)?\\s*=/.test(next)) {
55
+ out.push(`// ${next.trim()} (removed by fastscript migrate)`);
56
+ if (!next.includes(";") && next.includes("{")) {
57
+ skippingBlock = true;
58
+ const opens = (next.match(/{/g) || []).length;
59
+ const closes = (next.match(/}/g) || []).length;
60
+ blockDepth = Math.max(1, opens - closes);
61
+ }
62
+ continue;
63
+ }
64
+
65
+ if (/^\s*declare\s+(global|module|namespace)\b/.test(next)) {
66
+ out.push(`// ${next.trim()} (removed by fastscript migrate)`);
67
+ if (next.includes("{")) {
68
+ skippingBlock = true;
69
+ const opens = (next.match(/{/g) || []).length;
70
+ const closes = (next.match(/}/g) || []).length;
71
+ blockDepth = Math.max(1, opens - closes);
72
+ }
73
+ continue;
74
+ }
75
+
76
+ if (/^\s*declare\s+/.test(next)) {
77
+ out.push(`// ${next.trim()} (removed by fastscript migrate)`);
78
+ continue;
79
+ }
80
+
81
+ next = next.replace(/\bimport\s+type\b/g, "import");
82
+ next = next.replace(/\bexport\s+type\b/g, "export");
83
+ next = next.replace(/\btype\s+([A-Za-z_$][\w$]*)\s+as\s+/g, "$1 as ");
84
+ next = next.replace(/\b(?:public|private|protected|readonly|declare|override|abstract)\s+/g, "");
85
+ next = next.replace(/\s+implements\s+[A-Za-z_$][\w$<>\[\]\|&, ?.]+/g, "");
86
+ next = next.replace(/([A-Za-z_$][\w$]*)!([?:;=,\)])/g, "$1$2");
87
+
88
+ next = next.replace(
89
+ /^(\s*)(const|let|var)\s+([A-Za-z_$][\w$]*)\s*:\s*([^=;]+)([=;].*)$/,
90
+ "$1$2 $3 $5",
91
+ );
92
+ next = next.replace(
93
+ /^(\s*)(const|let|var)\s+([A-Za-z_$][\w$]*)\s*<[^>]+>\s*=\s*/,
94
+ "$1$2 $3 = ",
95
+ );
96
+
97
+ if (/\bfunction\b/.test(next) || /\bfn\b/.test(next) || /\)\s*=>/.test(next)) {
98
+ next = next.replace(/\(([^)]*)\)/, (_, params) => {
99
+ const cleaned = params.replace(
100
+ /([A-Za-z_$][\w$]*)(\?)?\s*:\s*([A-Za-z_$][\w$<>\[\]\|&, ?.:{}=]*)/g,
101
+ "$1",
102
+ );
103
+ return `(${cleaned})`;
104
+ });
105
+ next = next.replace(/\)\s*:\s*([A-Za-z_$][\w$<>\[\]\|&, ?.:{}=]*)\s*\{/g, ") {");
106
+ next = next.replace(/\)\s*:\s*([A-Za-z_$][\w$<>\[\]\|&, ?.:{}=]*)\s*=>/g, ") =>");
107
+ next = next.replace(/\bfunction\s+([A-Za-z_$][\w$]*)\s*<[^>]+>\s*\(/g, "function $1(");
108
+ next = next.replace(/\bfn\s+([A-Za-z_$][\w$]*)\s*<[^>]+>\s*\(/g, "fn $1(");
109
+ next = next.replace(/=\s*async\s*<[^>]+>\s*\(/g, "= async (");
110
+ next = next.replace(/=\s*<[^>]+>\s*\(/g, "= (");
111
+ }
112
+
113
+ next = next.replace(/^\s*<([A-Za-z_$][\w$,\s]*)>\s*\(/, "(");
114
+ next = next.replace(/\)\s*=>\s*<[A-Za-z_$][\w$<>\[\]\|&, ?.]*>/g, ") =>");
115
+ next = next.replace(/\s+as\s+const\b/g, "");
116
+ next = next.replace(/\s+as\s+[A-Za-z_$][\w$<>\[\]\|&, ?.:{}=]*/g, "");
117
+ next = next.replace(/\sas\s+const\b/g, "");
118
+ next = next.replace(/\s+satisfies\s+[A-Za-z_$][\w$<>\[\]\|&, ?.]*/g, "");
119
+ out.push(next);
120
+ }
121
+
122
+ return out.join("\n");
123
+ }
124
+
125
+
@@ -1,10 +1,12 @@
1
1
  import { parse as acornParse, tokenizer as acornTokenizer } from "acorn";
2
+ import * as esbuild from "esbuild";
2
3
  import { resolveErrorMeta } from "./fs-error-codes.mjs";
3
4
 
4
5
  export const FASTSCRIPT_AST_VERSION = "1.0.0";
5
6
 
6
7
  const STATEMENT_BOUNDARY_TOKENS = new Set([";", "{", "}"]);
7
- const TYPE_DECLARATION_KEYWORDS = new Set(["type", "interface", "enum"]);
8
+ const BASE64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
9
+ const BASE64_LOOKUP = new Map(Array.from(BASE64).map((char, index) => [char, index]));
8
10
 
9
11
  function createLineStarts(source) {
10
12
  const text = String(source ?? "");
@@ -436,9 +438,23 @@ function collectRewriteOperations(source, { file = "", lineStarts, significant }
436
438
 
437
439
  if (token.value === "fn" && token.type === "identifier") {
438
440
  const prev = previousSignificant(significant, idx);
441
+ const asyncToken = prev?.value === "async" ? prev : null;
442
+ const asyncIndex = asyncToken ? idx - 1 : -1;
443
+ const beforeAsync = asyncToken ? previousSignificant(significant, asyncIndex) : null;
439
444
  const startsStatement = isStatementStart(significant, idx);
440
445
  const followsExport = prev?.value === "export" && prev.end.line === token.start.line;
441
- if (startsStatement || followsExport) {
446
+ const followsDefaultExport =
447
+ prev?.value === "default" &&
448
+ previousSignificant(significant, idx - 1)?.value === "export" &&
449
+ previousSignificant(significant, idx - 1)?.end.line === token.start.line;
450
+ const followsAsync =
451
+ asyncToken &&
452
+ (
453
+ isStatementStart(significant, asyncIndex) ||
454
+ beforeAsync?.value === "export" ||
455
+ beforeAsync?.value === "default"
456
+ );
457
+ if (startsStatement || followsExport || followsDefaultExport || followsAsync) {
442
458
  const nameToken = nextSignificant(significant, idx, 1);
443
459
  const openParenToken = nextSignificant(significant, idx, 2);
444
460
  if (isIdentifierToken(nameToken) && openParenToken?.value === "(") {
@@ -465,40 +481,6 @@ function collectRewriteOperations(source, { file = "", lineStarts, significant }
465
481
  continue;
466
482
  }
467
483
 
468
- if (TYPE_DECLARATION_KEYWORDS.has(token.value) && token.type === "identifier" && isStatementStart(significant, idx)) {
469
- const nextToken = nextSignificant(significant, idx, 1);
470
- if (!isIdentifierToken(nextToken)) continue;
471
- const shouldHandleType = token.value === "type" && nextSignificant(significant, idx, 2)?.value === "=";
472
- const shouldHandleBlock = (token.value === "interface" || token.value === "enum") && nextSignificant(significant, idx, 2);
473
- if (!shouldHandleType && !shouldHandleBlock) continue;
474
-
475
- const span = declarationSpanFromKeyword(source, lineStarts, sourceLength, significant, idx);
476
- const snippet = source.slice(span.start, span.end).trim();
477
- diagnostics.push(
478
- createDiagnostic({
479
- source,
480
- lineStarts,
481
- file,
482
- code: "FS1004",
483
- span,
484
- fixes: [
485
- {
486
- message: "Remove declaration from runtime source.",
487
- span,
488
- text: "",
489
- },
490
- ],
491
- }),
492
- );
493
- ops.push(
494
- operation(
495
- span.start,
496
- span.end,
497
- `/* ${snippet || token.value} (removed by fastscript compiler) */`,
498
- "erase-type",
499
- ),
500
- );
501
- }
502
484
  }
503
485
 
504
486
  const lexicalTodoPattern = /\bTODO_ERROR\b/g;
@@ -589,7 +571,104 @@ function applyRewriteOperations(source, ops) {
589
571
  return { code, mapGeneratedToSource, rewrites };
590
572
  }
591
573
 
592
- const BASE64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
574
+ function decodeVlqValue(mapping, startIndex) {
575
+ let result = 0;
576
+ let shift = 0;
577
+ let index = startIndex;
578
+
579
+ while (index < mapping.length) {
580
+ const value = BASE64_LOOKUP.get(mapping[index]);
581
+ if (value == null) break;
582
+ index += 1;
583
+ const continuation = (value & 32) !== 0;
584
+ result |= (value & 31) << shift;
585
+ shift += 5;
586
+ if (!continuation) {
587
+ const signed = (result & 1) ? -(result >> 1) : result >> 1;
588
+ return { value: signed, next: index };
589
+ }
590
+ }
591
+
592
+ return { value: 0, next: index };
593
+ }
594
+
595
+ function decodeSourceMapMappings(mappings) {
596
+ const lines = [];
597
+ let sourceIndex = 0;
598
+ let sourceLine = 0;
599
+ let sourceColumn = 0;
600
+ let generatedLine = 0;
601
+ let generatedColumn = 0;
602
+
603
+ for (const line of String(mappings || "").split(";")) {
604
+ const segments = [];
605
+ generatedColumn = 0;
606
+ if (line) {
607
+ for (const rawSegment of line.split(",")) {
608
+ if (!rawSegment) continue;
609
+ let cursor = 0;
610
+ const values = [];
611
+ while (cursor < rawSegment.length) {
612
+ const decoded = decodeVlqValue(rawSegment, cursor);
613
+ values.push(decoded.value);
614
+ cursor = decoded.next;
615
+ }
616
+ if (!values.length) continue;
617
+ generatedColumn += values[0];
618
+ if (values.length >= 4) {
619
+ sourceIndex += values[1];
620
+ sourceLine += values[2];
621
+ sourceColumn += values[3];
622
+ segments.push({ generatedLine, generatedColumn, sourceIndex, sourceLine, sourceColumn });
623
+ }
624
+ }
625
+ }
626
+ lines.push(segments);
627
+ generatedLine += 1;
628
+ }
629
+
630
+ return lines;
631
+ }
632
+
633
+ function buildGeneratedOffsetMapFromSourceMap({ generated, mapText, sourceLength }) {
634
+ const parsed = JSON.parse(String(mapText || "{}"));
635
+ const lineStarts = createLineStarts(generated);
636
+ const sourceLineStarts = createLineStarts(parsed?.sourcesContent?.[0] || "");
637
+ const decoded = decodeSourceMapMappings(parsed.mappings || "");
638
+ const out = [];
639
+
640
+ for (let lineIndex = 0; lineIndex < lineStarts.length; lineIndex += 1) {
641
+ const lineStart = lineStarts[lineIndex];
642
+ const lineEnd = lineStarts[lineIndex + 1] ?? generated.length;
643
+ const segments = decoded[lineIndex] || [];
644
+ let active = segments[0] || null;
645
+ let segmentIndex = 0;
646
+
647
+ for (let offset = lineStart; offset < lineEnd; offset += 1) {
648
+ const column = offset - lineStart;
649
+ while (segmentIndex + 1 < segments.length && segments[segmentIndex + 1].generatedColumn <= column) {
650
+ segmentIndex += 1;
651
+ active = segments[segmentIndex];
652
+ }
653
+
654
+ if (!active) {
655
+ out.push(clamp(offset, 0, sourceLength));
656
+ continue;
657
+ }
658
+
659
+ const delta = Math.max(0, column - active.generatedColumn);
660
+ const mappedBase = sourceLineStarts[active.sourceLine] ?? 0;
661
+ out.push(clamp(mappedBase + active.sourceColumn + delta, 0, sourceLength));
662
+ }
663
+ }
664
+
665
+ out.push(sourceLength);
666
+ return out;
667
+ }
668
+
669
+ function composeOffsetMaps(finalToIntermediate, intermediateToSource, sourceLength) {
670
+ return finalToIntermediate.map((offset) => mapGeneratedOffsetToSourceOffset(intermediateToSource, offset, sourceLength));
671
+ }
593
672
 
594
673
  function encodeVlq(value) {
595
674
  let num = value < 0 ? ((-value) << 1) + 1 : value << 1;
@@ -796,9 +875,66 @@ function parseGeneratedJavaScript(generated, { file = "" } = {}) {
796
875
  onToken: parseTokens,
797
876
  onComment: parseComments,
798
877
  });
799
- return { estree, parseTokens, parseComments, error: null };
878
+ return {
879
+ estree,
880
+ parseTokens,
881
+ parseComments,
882
+ error: null,
883
+ frontend: {
884
+ usedCompatibilityFrontend: false,
885
+ mapGeneratedToInput: null,
886
+ generatedCode: generated,
887
+ },
888
+ };
800
889
  } catch (error) {
801
- return { estree: null, parseTokens, parseComments, error };
890
+ try {
891
+ const transformed = esbuild.transformSync(generated, {
892
+ loader: "tsx",
893
+ format: "esm",
894
+ target: "esnext",
895
+ sourcefile: file || "<memory>",
896
+ sourcemap: "external",
897
+ jsx: "transform",
898
+ });
899
+ const compatTokens = [];
900
+ const compatComments = [];
901
+ const estree = acornParse(transformed.code, {
902
+ ecmaVersion: "latest",
903
+ sourceType: "module",
904
+ allowHashBang: true,
905
+ locations: true,
906
+ ranges: true,
907
+ onToken: compatTokens,
908
+ onComment: compatComments,
909
+ });
910
+ return {
911
+ estree,
912
+ parseTokens: compatTokens,
913
+ parseComments: compatComments,
914
+ error: null,
915
+ frontend: {
916
+ usedCompatibilityFrontend: true,
917
+ mapGeneratedToInput: buildGeneratedOffsetMapFromSourceMap({
918
+ generated: transformed.code,
919
+ mapText: transformed.map,
920
+ sourceLength: generated.length,
921
+ }),
922
+ generatedCode: transformed.code,
923
+ },
924
+ };
925
+ } catch {
926
+ return {
927
+ estree: null,
928
+ parseTokens,
929
+ parseComments,
930
+ error,
931
+ frontend: {
932
+ usedCompatibilityFrontend: false,
933
+ mapGeneratedToInput: null,
934
+ generatedCode: generated,
935
+ },
936
+ };
937
+ }
802
938
  }
803
939
  }
804
940
 
@@ -842,7 +978,21 @@ export function parseFastScript(source, { file = "", mode = "lenient", recover =
842
978
 
843
979
  const diagnostics = [];
844
980
 
845
- if (tokenization.lexicalError) {
981
+ const rewrites = collectRewriteOperations(text, {
982
+ file,
983
+ lineStarts,
984
+ significant: tokenization.significant,
985
+ });
986
+ diagnostics.push(...rewrites.diagnostics);
987
+
988
+ const transformed = applyRewriteOperations(text, rewrites.ops);
989
+ const parsedGenerated = parseGeneratedJavaScript(transformed.code, { file });
990
+ const finalGeneratedCode = parsedGenerated.frontend?.generatedCode || transformed.code;
991
+ const finalMapGeneratedToSource = parsedGenerated.frontend?.mapGeneratedToInput
992
+ ? composeOffsetMaps(parsedGenerated.frontend.mapGeneratedToInput, transformed.mapGeneratedToSource, text.length)
993
+ : transformed.mapGeneratedToSource;
994
+
995
+ if (tokenization.lexicalError && !parsedGenerated.frontend?.usedCompatibilityFrontend) {
846
996
  const loc = tokenization.lexicalError.loc || { line: 1, column: 0 };
847
997
  const lineStart = lineStarts[clamp((loc.line || 1) - 1, 0, lineStarts.length - 1)] ?? 0;
848
998
  const offset = clamp(lineStart + (loc.column || 0), 0, text.length);
@@ -858,19 +1008,9 @@ export function parseFastScript(source, { file = "", mode = "lenient", recover =
858
1008
  );
859
1009
  }
860
1010
 
861
- const rewrites = collectRewriteOperations(text, {
862
- file,
863
- lineStarts,
864
- significant: tokenization.significant,
865
- });
866
- diagnostics.push(...rewrites.diagnostics);
867
-
868
- const transformed = applyRewriteOperations(text, rewrites.ops);
869
- const parsedGenerated = parseGeneratedJavaScript(transformed.code, { file });
870
-
871
1011
  if (parsedGenerated.error) {
872
- const parseOffset = clamp(parsedGenerated.error.pos ?? 0, 0, transformed.code.length);
873
- const sourceOffset = mapGeneratedOffsetToSourceOffset(transformed.mapGeneratedToSource, parseOffset, text.length);
1012
+ const parseOffset = clamp(parsedGenerated.error.pos ?? 0, 0, finalGeneratedCode.length);
1013
+ const sourceOffset = mapGeneratedOffsetToSourceOffset(finalMapGeneratedToSource, parseOffset, text.length);
874
1014
  diagnostics.push(
875
1015
  createDiagnostic({
876
1016
  source: text,
@@ -884,13 +1024,13 @@ export function parseFastScript(source, { file = "", mode = "lenient", recover =
884
1024
  }
885
1025
 
886
1026
  const estree = ensureProgramShape(parsedGenerated.estree);
887
- remapAstNodeLocations(estree, text, lineStarts, transformed.mapGeneratedToSource);
1027
+ remapAstNodeLocations(estree, text, lineStarts, finalMapGeneratedToSource);
888
1028
 
889
1029
  const cst = buildCst({ source: text, file, lineStarts, tokens, estree });
890
1030
  const sourceMap = buildSourceMap({
891
1031
  source: text,
892
- generated: transformed.code,
893
- mapGeneratedToSource: transformed.mapGeneratedToSource,
1032
+ generated: finalGeneratedCode,
1033
+ mapGeneratedToSource: finalMapGeneratedToSource,
894
1034
  file,
895
1035
  });
896
1036
 
@@ -913,9 +1053,9 @@ export function parseFastScript(source, { file = "", mode = "lenient", recover =
913
1053
  cst,
914
1054
  tokens,
915
1055
  diagnostics: normalizedDiagnostics,
916
- transformedCode: transformed.code,
1056
+ transformedCode: finalGeneratedCode,
917
1057
  sourceMap,
918
- mapGeneratedToSource: transformed.mapGeneratedToSource,
1058
+ mapGeneratedToSource: finalMapGeneratedToSource,
919
1059
  rewrites: transformed.rewrites,
920
1060
  source: text,
921
1061
  };