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.
- package/CHANGELOG.md +12 -0
- package/README.md +669 -600
- package/node_modules/@fastscript/core-private/src/fs-error-codes.mjs +2 -2
- package/node_modules/@fastscript/core-private/src/fs-normalize.mjs +125 -91
- package/node_modules/@fastscript/core-private/src/fs-parser.mjs +197 -57
- package/node_modules/@fastscript/core-private/src/typecheck.mjs +1466 -1462
- package/package.json +41 -5
- package/src/benchmark-discipline.mjs +39 -0
- package/src/cli.mjs +37 -2
- package/src/compatibility-governance.mjs +257 -0
- package/src/conversion-manifest.mjs +101 -0
- package/src/diagnostics.mjs +100 -0
- package/src/fs-error-codes.mjs +2 -2
- package/src/fs-normalize.mjs +39 -7
- package/src/generated/compatibility-registry-report.mjs +815 -0
- package/src/generated/docs-search-index.mjs +1137 -275
- package/src/migrate-rollback.mjs +144 -0
- package/src/migrate.mjs +1275 -47
- package/src/migration-wizard.mjs +37 -11
- package/src/module-loader.mjs +13 -1
- package/src/permissions-cli.mjs +112 -0
- package/src/profile.mjs +95 -0
- package/src/regression-guard.mjs +245 -0
- package/src/runtime-permissions.mjs +299 -0
- package/src/trace.mjs +95 -0
- package/src/validate.mjs +10 -0
|
@@ -16,8 +16,8 @@ export const FS_ERROR_CODES = Object.freeze({
|
|
|
16
16
|
},
|
|
17
17
|
FS1004: {
|
|
18
18
|
severity: "error",
|
|
19
|
-
message: "
|
|
20
|
-
hint: "
|
|
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
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
next = next.replace(
|
|
84
|
-
next = next.replace(/\)\s
|
|
85
|
-
next = next.replace(/\
|
|
86
|
-
next = next.replace(
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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 {
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
873
|
-
const sourceOffset = mapGeneratedOffsetToSourceOffset(
|
|
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,
|
|
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:
|
|
893
|
-
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:
|
|
1056
|
+
transformedCode: finalGeneratedCode,
|
|
917
1057
|
sourceMap,
|
|
918
|
-
mapGeneratedToSource:
|
|
1058
|
+
mapGeneratedToSource: finalMapGeneratedToSource,
|
|
919
1059
|
rewrites: transformed.rewrites,
|
|
920
1060
|
source: text,
|
|
921
1061
|
};
|