ttsc 0.4.3 → 0.4.4
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/lib/api.d.ts +1 -0
- package/lib/api.js +508 -7
- package/lib/api.js.map +1 -1
- package/lib/plugin.d.ts +34 -0
- package/lib/plugin.js +96 -0
- package/lib/plugin.js.map +1 -1
- package/lib/project.d.ts +1 -1
- package/lib/project.js +7 -1
- package/lib/project.js.map +1 -1
- package/package.json +8 -8
- package/src/api.ts +629 -8
- package/src/plugin.ts +155 -0
- package/src/project.ts +10 -3
package/lib/api.d.ts
CHANGED
|
@@ -66,6 +66,7 @@ export type CheckOptions = Omit<BuildOptions, "emit">;
|
|
|
66
66
|
export declare function transform(options: TransformOptions): string;
|
|
67
67
|
/** Result of `build()`. Non-zero `status` means the build failed. */
|
|
68
68
|
export interface BuildResult {
|
|
69
|
+
emittedFiles?: string[];
|
|
69
70
|
status: number;
|
|
70
71
|
stdout: string;
|
|
71
72
|
stderr: string;
|
package/lib/api.js
CHANGED
|
@@ -122,6 +122,9 @@ function transform(options) {
|
|
|
122
122
|
const sourceFile = realpathIfExists(path.isAbsolute(options.file)
|
|
123
123
|
? options.file
|
|
124
124
|
: path.resolve(options.cwd ?? process.cwd(), options.file));
|
|
125
|
+
if (execution.sourcePlugins.length > 0) {
|
|
126
|
+
return transformWithSourceTransforms(options, execution, sourceFile);
|
|
127
|
+
}
|
|
125
128
|
if (execution.nativeBinary) {
|
|
126
129
|
return transformWithNativeBinary(options, execution, sourceFile);
|
|
127
130
|
}
|
|
@@ -147,8 +150,9 @@ function transform(options) {
|
|
|
147
150
|
if (!emitted) {
|
|
148
151
|
throw new Error(`ttsc.transform: no output produced for ${sourceFile}`);
|
|
149
152
|
}
|
|
150
|
-
const transformed = finalizeTransformText(execution.
|
|
153
|
+
const transformed = finalizeTransformText(execution.outputPlugins, {
|
|
151
154
|
command: "transform",
|
|
155
|
+
compilerOptions: execution.compilerOptions,
|
|
152
156
|
cwd: execution.cwd,
|
|
153
157
|
projectRoot: execution.projectRoot,
|
|
154
158
|
sourceFile,
|
|
@@ -185,8 +189,9 @@ function transformWithNativeBinary(options, execution, sourceFile) {
|
|
|
185
189
|
if (res.status !== 0) {
|
|
186
190
|
throw new Error("ttsc.transform exited " + res.status + "\n" + (res.stderr || ""));
|
|
187
191
|
}
|
|
188
|
-
const transformed = finalizeTransformText(execution.
|
|
192
|
+
const transformed = finalizeTransformText(execution.outputPlugins, {
|
|
189
193
|
command: "transform",
|
|
194
|
+
compilerOptions: execution.compilerOptions,
|
|
190
195
|
cwd: execution.cwd,
|
|
191
196
|
projectRoot: execution.projectRoot,
|
|
192
197
|
sourceFile,
|
|
@@ -198,6 +203,58 @@ function transformWithNativeBinary(options, execution, sourceFile) {
|
|
|
198
203
|
}
|
|
199
204
|
return transformed;
|
|
200
205
|
}
|
|
206
|
+
function transformWithSourceTransforms(options, execution, sourceFile) {
|
|
207
|
+
if (execution.nativeBinary || execution.nativeMode !== "none") {
|
|
208
|
+
throw new Error("ttsc.transform: transformSource cannot be combined with native rewrite mode yet");
|
|
209
|
+
}
|
|
210
|
+
const materialized = materializeSourceTransformedProject(execution, "transform", sourceFile);
|
|
211
|
+
const tempOutDir = path.join(materialized.root, ".ttsc-transform-out");
|
|
212
|
+
try {
|
|
213
|
+
const tempSourceFile = toMaterializedPath(sourceFile, materialized);
|
|
214
|
+
const result = build({
|
|
215
|
+
...options,
|
|
216
|
+
cwd: materialized.root,
|
|
217
|
+
emit: true,
|
|
218
|
+
forceListEmittedFiles: true,
|
|
219
|
+
outDir: tempOutDir,
|
|
220
|
+
plugins: false,
|
|
221
|
+
tsconfig: materialized.tsconfig,
|
|
222
|
+
});
|
|
223
|
+
if (result.status !== 0) {
|
|
224
|
+
throw new Error("ttsc.transform exited " +
|
|
225
|
+
result.status +
|
|
226
|
+
"\n" +
|
|
227
|
+
(result.stderr || result.stdout));
|
|
228
|
+
}
|
|
229
|
+
const emitted = findEmittedFile(tempOutDir, materialized.root, tempSourceFile);
|
|
230
|
+
if (!emitted) {
|
|
231
|
+
throw new Error(`ttsc.transform: no output produced for ${sourceFile}`);
|
|
232
|
+
}
|
|
233
|
+
let transformed = finalizeTransformText(execution.outputPlugins, {
|
|
234
|
+
command: "transform",
|
|
235
|
+
compilerOptions: execution.compilerOptions,
|
|
236
|
+
cwd: execution.cwd,
|
|
237
|
+
projectRoot: execution.projectRoot,
|
|
238
|
+
sourceFile,
|
|
239
|
+
tsconfig: execution.tsconfig,
|
|
240
|
+
}, fs.readFileSync(emitted, "utf8"));
|
|
241
|
+
if (options.out) {
|
|
242
|
+
const mapFile = `${emitted}.map`;
|
|
243
|
+
if (fs.existsSync(mapFile)) {
|
|
244
|
+
const outMap = `${options.out}.map`;
|
|
245
|
+
fs.mkdirSync(path.dirname(outMap), { recursive: true });
|
|
246
|
+
fs.writeFileSync(outMap, patchSourceMapText(fs.readFileSync(mapFile, "utf8"), materialized, outMap, mapFile), "utf8");
|
|
247
|
+
transformed = rewriteSourceMapReference(transformed, path.basename(outMap));
|
|
248
|
+
}
|
|
249
|
+
fs.mkdirSync(path.dirname(options.out), { recursive: true });
|
|
250
|
+
fs.writeFileSync(options.out, transformed, "utf8");
|
|
251
|
+
}
|
|
252
|
+
return transformed;
|
|
253
|
+
}
|
|
254
|
+
finally {
|
|
255
|
+
fs.rmSync(materialized.root, { recursive: true, force: true });
|
|
256
|
+
}
|
|
257
|
+
}
|
|
201
258
|
function realpathIfExists(file) {
|
|
202
259
|
try {
|
|
203
260
|
return fs.realpathSync(file);
|
|
@@ -213,6 +270,9 @@ function realpathIfExists(file) {
|
|
|
213
270
|
*/
|
|
214
271
|
function build(options = {}) {
|
|
215
272
|
const execution = resolveExecutionContext(options);
|
|
273
|
+
if (execution.sourcePlugins.length > 0) {
|
|
274
|
+
return buildWithSourceTransforms(options, execution);
|
|
275
|
+
}
|
|
216
276
|
if (execution.nativeBinary) {
|
|
217
277
|
return buildWithNativeBinary(options, execution);
|
|
218
278
|
}
|
|
@@ -231,7 +291,8 @@ function build(options = {}) {
|
|
|
231
291
|
}
|
|
232
292
|
}
|
|
233
293
|
const args = createTsgoBuildArgs(execution, options, {
|
|
234
|
-
listEmittedFiles: options.emit !== false &&
|
|
294
|
+
listEmittedFiles: options.emit !== false &&
|
|
295
|
+
(execution.outputPlugins.length > 0 || options.forceListEmittedFiles === true),
|
|
235
296
|
});
|
|
236
297
|
const res = spawnBinary(execution.tsgo.binary, args, {
|
|
237
298
|
cwd: execution.projectRoot,
|
|
@@ -253,10 +314,10 @@ function build(options = {}) {
|
|
|
253
314
|
if (emittedFiles.length !== 0) {
|
|
254
315
|
result.stdout = stripEmittedFileLines(result.stdout);
|
|
255
316
|
}
|
|
256
|
-
if (result.status === 0 && options.emit !== false && execution.
|
|
257
|
-
applyBuildPlugins(execution.
|
|
317
|
+
if (result.status === 0 && options.emit !== false && execution.outputPlugins.length > 0) {
|
|
318
|
+
applyBuildPlugins(execution.outputPlugins, execution, emittedFiles);
|
|
258
319
|
}
|
|
259
|
-
return normalizeFailedDiagnostics(result);
|
|
320
|
+
return normalizeFailedDiagnostics({ ...result, emittedFiles });
|
|
260
321
|
}
|
|
261
322
|
function buildWithNativeBinary(options, execution) {
|
|
262
323
|
const args = createNativeBuildArgs(execution, options);
|
|
@@ -277,6 +338,38 @@ function buildWithNativeBinary(options, execution) {
|
|
|
277
338
|
stderr: outputText(res.stderr),
|
|
278
339
|
});
|
|
279
340
|
}
|
|
341
|
+
function buildWithSourceTransforms(options, execution) {
|
|
342
|
+
if (execution.nativeBinary || execution.nativeMode !== "none") {
|
|
343
|
+
return {
|
|
344
|
+
status: 2,
|
|
345
|
+
stdout: "",
|
|
346
|
+
stderr: "ttsc.build: transformSource cannot be combined with native rewrite mode yet\n",
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
const materialized = materializeSourceTransformedProject(execution, "build");
|
|
350
|
+
try {
|
|
351
|
+
const outDir = mapOutDirToMaterializedProject(options.outDir, execution, materialized);
|
|
352
|
+
const result = build({
|
|
353
|
+
...options,
|
|
354
|
+
cwd: materialized.root,
|
|
355
|
+
forceListEmittedFiles: true,
|
|
356
|
+
outDir,
|
|
357
|
+
plugins: false,
|
|
358
|
+
tsconfig: materialized.tsconfig,
|
|
359
|
+
});
|
|
360
|
+
if (result.status === 0 && options.emit !== false) {
|
|
361
|
+
const copied = copyMaterializedEmittedFiles(materialized, result.emittedFiles ?? []);
|
|
362
|
+
result.emittedFiles = copied;
|
|
363
|
+
if (execution.outputPlugins.length > 0) {
|
|
364
|
+
applyBuildPlugins(execution.outputPlugins, execution, copied);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
return result;
|
|
368
|
+
}
|
|
369
|
+
finally {
|
|
370
|
+
fs.rmSync(materialized.root, { recursive: true, force: true });
|
|
371
|
+
}
|
|
372
|
+
}
|
|
280
373
|
/**
|
|
281
374
|
* Run `ttsc check` (build without emit) — CI gate / pre-commit hook use.
|
|
282
375
|
* Resolves with an exit-code record; does not throw.
|
|
@@ -374,11 +467,13 @@ function resolveExecutionContext(options) {
|
|
|
374
467
|
tsconfig,
|
|
375
468
|
});
|
|
376
469
|
return {
|
|
470
|
+
compilerOptions: loaded.project.compilerOptions,
|
|
377
471
|
cwd,
|
|
378
472
|
nativeBinary: loaded.nativeBinary ?? null,
|
|
379
473
|
nativeMode: options.rewriteMode ?? loaded.nativeMode,
|
|
380
|
-
|
|
474
|
+
outputPlugins: loaded.plugins.filter((plugin) => plugin.transformOutput),
|
|
381
475
|
projectRoot,
|
|
476
|
+
sourcePlugins: loaded.plugins.filter((plugin) => plugin.transformSource),
|
|
382
477
|
tsgo,
|
|
383
478
|
tsconfig,
|
|
384
479
|
};
|
|
@@ -404,6 +499,7 @@ function applyBuildPlugins(plugins, execution, emittedFiles) {
|
|
|
404
499
|
const next = (0, plugin_1.applyPluginTransforms)(plugins, {
|
|
405
500
|
code: current,
|
|
406
501
|
command: "build",
|
|
502
|
+
compilerOptions: execution.compilerOptions,
|
|
407
503
|
cwd: execution.cwd,
|
|
408
504
|
outputFile: file,
|
|
409
505
|
projectRoot: execution.projectRoot,
|
|
@@ -442,6 +538,7 @@ function normalizeFailedDiagnostics(result) {
|
|
|
442
538
|
return result;
|
|
443
539
|
}
|
|
444
540
|
return {
|
|
541
|
+
emittedFiles: result.emittedFiles,
|
|
445
542
|
status: result.status,
|
|
446
543
|
stdout: "",
|
|
447
544
|
stderr: result.stdout,
|
|
@@ -514,4 +611,408 @@ function readOwnPackageVersion() {
|
|
|
514
611
|
return "0.0.0";
|
|
515
612
|
}
|
|
516
613
|
}
|
|
614
|
+
function materializeSourceTransformedProject(execution, command, onlySourceFile) {
|
|
615
|
+
const root = fs.mkdtempSync(path.join(os.tmpdir(), "ttsc-source-"));
|
|
616
|
+
const materialized = {
|
|
617
|
+
mappers: new Map(),
|
|
618
|
+
originalRoot: execution.projectRoot,
|
|
619
|
+
root,
|
|
620
|
+
tsconfig: path.join(root, path.relative(execution.projectRoot, execution.tsconfig)),
|
|
621
|
+
};
|
|
622
|
+
copyProjectForSourceTransforms(execution.projectRoot, root, execution.compilerOptions);
|
|
623
|
+
const files = onlySourceFile
|
|
624
|
+
? [toMaterializedPath(onlySourceFile, materialized)]
|
|
625
|
+
: listSourceTransformFiles(root);
|
|
626
|
+
for (const tempFile of files) {
|
|
627
|
+
if (!fs.existsSync(tempFile) || !fs.statSync(tempFile).isFile()) {
|
|
628
|
+
continue;
|
|
629
|
+
}
|
|
630
|
+
const originalFile = fromMaterializedPath(tempFile, materialized);
|
|
631
|
+
const current = fs.readFileSync(tempFile, "utf8");
|
|
632
|
+
const transformed = (0, plugin_1.applyPluginSourceTransformsWithMap)(execution.sourcePlugins, {
|
|
633
|
+
code: current,
|
|
634
|
+
command,
|
|
635
|
+
compilerOptions: execution.compilerOptions,
|
|
636
|
+
cwd: execution.cwd,
|
|
637
|
+
projectRoot: execution.projectRoot,
|
|
638
|
+
sourceFile: originalFile,
|
|
639
|
+
tsconfig: execution.tsconfig,
|
|
640
|
+
});
|
|
641
|
+
const next = transformed.code;
|
|
642
|
+
if (next !== current) {
|
|
643
|
+
fs.writeFileSync(tempFile, next, "utf8");
|
|
644
|
+
}
|
|
645
|
+
if (transformed.stages.length > 0) {
|
|
646
|
+
materialized.mappers.set(filepathKey(tempFile), {
|
|
647
|
+
finalCode: next,
|
|
648
|
+
originalCode: current,
|
|
649
|
+
stages: transformed.stages,
|
|
650
|
+
});
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
return materialized;
|
|
654
|
+
}
|
|
655
|
+
function copyProjectForSourceTransforms(source, target, compilerOptions) {
|
|
656
|
+
const excluded = new Set([".git", "node_modules"]);
|
|
657
|
+
const outDir = typeof compilerOptions.outDir === "string" ? compilerOptions.outDir : "";
|
|
658
|
+
const resolvedOutDir = outDir ? path.resolve(outDir) : "";
|
|
659
|
+
copyDirectoryFiltered(source, target, (entry) => {
|
|
660
|
+
if (excluded.has(path.basename(entry))) {
|
|
661
|
+
return false;
|
|
662
|
+
}
|
|
663
|
+
if (resolvedOutDir && isPathInside(entry, resolvedOutDir)) {
|
|
664
|
+
return false;
|
|
665
|
+
}
|
|
666
|
+
return true;
|
|
667
|
+
});
|
|
668
|
+
const nodeModules = path.join(source, "node_modules");
|
|
669
|
+
if (fs.existsSync(nodeModules)) {
|
|
670
|
+
const targetNodeModules = path.join(target, "node_modules");
|
|
671
|
+
try {
|
|
672
|
+
fs.symlinkSync(nodeModules, targetNodeModules, "junction");
|
|
673
|
+
}
|
|
674
|
+
catch {
|
|
675
|
+
copyDirectoryFiltered(nodeModules, targetNodeModules, () => true);
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
function copyDirectoryFiltered(source, target, shouldCopy) {
|
|
680
|
+
if (!shouldCopy(source)) {
|
|
681
|
+
return;
|
|
682
|
+
}
|
|
683
|
+
const stat = fs.lstatSync(source);
|
|
684
|
+
if (stat.isSymbolicLink()) {
|
|
685
|
+
const link = fs.readlinkSync(source);
|
|
686
|
+
fs.symlinkSync(link, target);
|
|
687
|
+
return;
|
|
688
|
+
}
|
|
689
|
+
if (stat.isDirectory()) {
|
|
690
|
+
fs.mkdirSync(target, { recursive: true });
|
|
691
|
+
for (const entry of fs.readdirSync(source)) {
|
|
692
|
+
copyDirectoryFiltered(path.join(source, entry), path.join(target, entry), shouldCopy);
|
|
693
|
+
}
|
|
694
|
+
return;
|
|
695
|
+
}
|
|
696
|
+
if (stat.isFile()) {
|
|
697
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
698
|
+
fs.copyFileSync(source, target);
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
function listSourceTransformFiles(root) {
|
|
702
|
+
const out = [];
|
|
703
|
+
const stack = [root];
|
|
704
|
+
while (stack.length !== 0) {
|
|
705
|
+
const current = stack.pop();
|
|
706
|
+
for (const entry of fs.readdirSync(current, { withFileTypes: true })) {
|
|
707
|
+
if (entry.name === "node_modules" || entry.name === ".git") {
|
|
708
|
+
continue;
|
|
709
|
+
}
|
|
710
|
+
const next = path.join(current, entry.name);
|
|
711
|
+
if (entry.isDirectory()) {
|
|
712
|
+
stack.push(next);
|
|
713
|
+
}
|
|
714
|
+
else if (entry.isFile() && isTransformableSource(next)) {
|
|
715
|
+
out.push(next);
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
return out;
|
|
720
|
+
}
|
|
721
|
+
function isTransformableSource(file) {
|
|
722
|
+
return /\.(?:[cm]?tsx?)$/i.test(file) && !/\.d\.[cm]?ts$/i.test(file);
|
|
723
|
+
}
|
|
724
|
+
function mapOutDirToMaterializedProject(outDir, execution, materialized) {
|
|
725
|
+
if (!outDir) {
|
|
726
|
+
return undefined;
|
|
727
|
+
}
|
|
728
|
+
const resolved = path.resolve(execution.cwd, outDir);
|
|
729
|
+
if (isPathInside(resolved, execution.projectRoot)) {
|
|
730
|
+
return toMaterializedPath(resolved, materialized);
|
|
731
|
+
}
|
|
732
|
+
return path.join(materialized.root, ".ttsc-out");
|
|
733
|
+
}
|
|
734
|
+
function copyMaterializedEmittedFiles(materialized, emittedFiles) {
|
|
735
|
+
const copied = [];
|
|
736
|
+
for (const emitted of emittedFiles) {
|
|
737
|
+
if (!isPathInside(emitted, materialized.root)) {
|
|
738
|
+
continue;
|
|
739
|
+
}
|
|
740
|
+
const target = fromMaterializedPath(emitted, materialized);
|
|
741
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
742
|
+
if (/\.map$/i.test(emitted)) {
|
|
743
|
+
fs.writeFileSync(target, patchSourceMapText(fs.readFileSync(emitted, "utf8"), materialized, target), "utf8");
|
|
744
|
+
}
|
|
745
|
+
else {
|
|
746
|
+
fs.copyFileSync(emitted, target);
|
|
747
|
+
}
|
|
748
|
+
copied.push(target);
|
|
749
|
+
}
|
|
750
|
+
return copied;
|
|
751
|
+
}
|
|
752
|
+
function toMaterializedPath(file, materialized) {
|
|
753
|
+
const relative = path.relative(materialized.originalRoot, file);
|
|
754
|
+
if (relative.startsWith("..") || path.isAbsolute(relative)) {
|
|
755
|
+
return file;
|
|
756
|
+
}
|
|
757
|
+
return path.join(materialized.root, relative);
|
|
758
|
+
}
|
|
759
|
+
function fromMaterializedPath(file, materialized) {
|
|
760
|
+
const relative = path.relative(materialized.root, file);
|
|
761
|
+
if (relative.startsWith("..") || path.isAbsolute(relative)) {
|
|
762
|
+
return file;
|
|
763
|
+
}
|
|
764
|
+
return path.join(materialized.originalRoot, relative);
|
|
765
|
+
}
|
|
766
|
+
function isPathInside(file, parent) {
|
|
767
|
+
const relative = path.relative(parent, file);
|
|
768
|
+
return relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative));
|
|
769
|
+
}
|
|
770
|
+
function filepathKey(file) {
|
|
771
|
+
return path.resolve(file).replace(/\\/g, "/");
|
|
772
|
+
}
|
|
773
|
+
function patchSourceMapText(text, materialized, outputFile, tempOutputFile = toMaterializedPath(outputFile, materialized)) {
|
|
774
|
+
let map;
|
|
775
|
+
try {
|
|
776
|
+
map = JSON.parse(text);
|
|
777
|
+
}
|
|
778
|
+
catch {
|
|
779
|
+
return text;
|
|
780
|
+
}
|
|
781
|
+
if (!Array.isArray(map.sources)) {
|
|
782
|
+
return text;
|
|
783
|
+
}
|
|
784
|
+
const tempMapDir = path.dirname(tempOutputFile);
|
|
785
|
+
const originalMapDir = path.dirname(outputFile);
|
|
786
|
+
const nextSources = [];
|
|
787
|
+
const nextSourcesContent = Array.isArray(map.sourcesContent)
|
|
788
|
+
? [...map.sourcesContent]
|
|
789
|
+
: undefined;
|
|
790
|
+
const sourceMappings = new Map();
|
|
791
|
+
map.sources.forEach((source, index) => {
|
|
792
|
+
const tempSource = path.isAbsolute(source)
|
|
793
|
+
? source
|
|
794
|
+
: path.resolve(tempMapDir, source);
|
|
795
|
+
if (isPathInside(tempSource, materialized.root)) {
|
|
796
|
+
const originalSource = fromMaterializedPath(tempSource, materialized);
|
|
797
|
+
const mapper = materialized.mappers.get(filepathKey(tempSource));
|
|
798
|
+
if (mapper) {
|
|
799
|
+
sourceMappings.set(index, mapper);
|
|
800
|
+
}
|
|
801
|
+
nextSources.push(relativeSourceMapPath(originalMapDir, originalSource));
|
|
802
|
+
if (nextSourcesContent) {
|
|
803
|
+
try {
|
|
804
|
+
nextSourcesContent[index] = fs.readFileSync(originalSource, "utf8");
|
|
805
|
+
}
|
|
806
|
+
catch {
|
|
807
|
+
/* keep emitted sourcesContent */
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
else {
|
|
812
|
+
nextSources.push(source);
|
|
813
|
+
}
|
|
814
|
+
});
|
|
815
|
+
if (sourceMappings.size > 0 && typeof map.mappings === "string") {
|
|
816
|
+
map.mappings = remapSourceMapMappings(map.mappings, sourceMappings);
|
|
817
|
+
}
|
|
818
|
+
map.sources = nextSources;
|
|
819
|
+
if (nextSourcesContent) {
|
|
820
|
+
map.sourcesContent = nextSourcesContent;
|
|
821
|
+
}
|
|
822
|
+
delete map.sourceRoot;
|
|
823
|
+
return JSON.stringify(map);
|
|
824
|
+
}
|
|
825
|
+
function relativeSourceMapPath(fromDir, file) {
|
|
826
|
+
const relative = path.relative(fromDir, file).replace(/\\/g, "/");
|
|
827
|
+
return relative.startsWith(".") ? relative : `./${relative}`;
|
|
828
|
+
}
|
|
829
|
+
function rewriteSourceMapReference(code, mapFileName) {
|
|
830
|
+
const reference = `//# sourceMappingURL=${mapFileName}`;
|
|
831
|
+
if (/\/\/# sourceMappingURL=.*(?:\r?\n)?$/m.test(code)) {
|
|
832
|
+
return code.replace(/\/\/# sourceMappingURL=.*(?:\r?\n)?$/m, `${reference}\n`);
|
|
833
|
+
}
|
|
834
|
+
return code.endsWith("\n") ? `${code}${reference}\n` : `${code}\n${reference}\n`;
|
|
835
|
+
}
|
|
836
|
+
function remapSourceMapMappings(mappings, sourceMappings) {
|
|
837
|
+
const decoded = decodeMappings(mappings);
|
|
838
|
+
for (const line of decoded) {
|
|
839
|
+
for (const segment of line) {
|
|
840
|
+
if (segment.length < 4) {
|
|
841
|
+
continue;
|
|
842
|
+
}
|
|
843
|
+
const mapper = sourceMappings.get(segment[1]);
|
|
844
|
+
if (!mapper) {
|
|
845
|
+
continue;
|
|
846
|
+
}
|
|
847
|
+
const mapped = mapTransformedPositionToOriginal(mapper, {
|
|
848
|
+
column: segment[3],
|
|
849
|
+
line: segment[2],
|
|
850
|
+
});
|
|
851
|
+
segment[2] = mapped.line;
|
|
852
|
+
segment[3] = mapped.column;
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
return encodeMappings(decoded);
|
|
856
|
+
}
|
|
857
|
+
function mapTransformedPositionToOriginal(mapper, position) {
|
|
858
|
+
let offset = lineColumnToOffset(mapper.finalCode, position.line, position.column);
|
|
859
|
+
for (let index = mapper.stages.length - 1; index >= 0; index -= 1) {
|
|
860
|
+
offset = mapOffsetToPreviousStage(offset, mapper.stages[index]);
|
|
861
|
+
}
|
|
862
|
+
return offsetToLineColumn(mapper.originalCode, offset);
|
|
863
|
+
}
|
|
864
|
+
function mapOffsetToPreviousStage(offset, stage) {
|
|
865
|
+
let delta = 0;
|
|
866
|
+
for (const edit of stage.edits) {
|
|
867
|
+
if (offset < edit.newStart) {
|
|
868
|
+
return clampOffset(offset - delta, stage.before.length);
|
|
869
|
+
}
|
|
870
|
+
if (offset < edit.newEnd) {
|
|
871
|
+
return edit.start;
|
|
872
|
+
}
|
|
873
|
+
delta += edit.code.length - (edit.end - edit.start);
|
|
874
|
+
}
|
|
875
|
+
return clampOffset(offset - delta, stage.before.length);
|
|
876
|
+
}
|
|
877
|
+
function lineColumnToOffset(source, line, column) {
|
|
878
|
+
const starts = lineStarts(source);
|
|
879
|
+
const start = starts[Math.min(Math.max(line, 0), starts.length - 1)] ?? 0;
|
|
880
|
+
return clampOffset(start + Math.max(column, 0), source.length);
|
|
881
|
+
}
|
|
882
|
+
function offsetToLineColumn(source, offset) {
|
|
883
|
+
const starts = lineStarts(source);
|
|
884
|
+
const clamped = clampOffset(offset, source.length);
|
|
885
|
+
let low = 0;
|
|
886
|
+
let high = starts.length - 1;
|
|
887
|
+
while (low <= high) {
|
|
888
|
+
const mid = (low + high) >> 1;
|
|
889
|
+
const start = starts[mid];
|
|
890
|
+
const next = starts[mid + 1] ?? Number.POSITIVE_INFINITY;
|
|
891
|
+
if (clamped < start) {
|
|
892
|
+
high = mid - 1;
|
|
893
|
+
}
|
|
894
|
+
else if (clamped >= next) {
|
|
895
|
+
low = mid + 1;
|
|
896
|
+
}
|
|
897
|
+
else {
|
|
898
|
+
return { column: clamped - start, line: mid };
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
const last = starts.length - 1;
|
|
902
|
+
return { column: clamped - (starts[last] ?? 0), line: last };
|
|
903
|
+
}
|
|
904
|
+
function lineStarts(source) {
|
|
905
|
+
const starts = [0];
|
|
906
|
+
for (let index = 0; index < source.length; index += 1) {
|
|
907
|
+
const ch = source.charCodeAt(index);
|
|
908
|
+
if (ch === 13 /* \r */) {
|
|
909
|
+
if (source.charCodeAt(index + 1) === 10 /* \n */) {
|
|
910
|
+
index += 1;
|
|
911
|
+
}
|
|
912
|
+
starts.push(index + 1);
|
|
913
|
+
}
|
|
914
|
+
else if (ch === 10 /* \n */) {
|
|
915
|
+
starts.push(index + 1);
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
return starts;
|
|
919
|
+
}
|
|
920
|
+
function clampOffset(offset, length) {
|
|
921
|
+
return Math.min(Math.max(offset, 0), length);
|
|
922
|
+
}
|
|
923
|
+
const BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
924
|
+
const BASE64_VALUES = new Map([...BASE64_CHARS].map((char, index) => [char, index]));
|
|
925
|
+
function decodeMappings(mappings) {
|
|
926
|
+
const lines = [];
|
|
927
|
+
let line = [];
|
|
928
|
+
let segment = [];
|
|
929
|
+
let index = 0;
|
|
930
|
+
const state = [0, 0, 0, 0, 0];
|
|
931
|
+
while (index < mappings.length) {
|
|
932
|
+
const char = mappings[index];
|
|
933
|
+
if (char === ";") {
|
|
934
|
+
if (segment.length > 0) {
|
|
935
|
+
line.push(segment);
|
|
936
|
+
segment = [];
|
|
937
|
+
}
|
|
938
|
+
lines.push(line);
|
|
939
|
+
line = [];
|
|
940
|
+
state[0] = 0;
|
|
941
|
+
index += 1;
|
|
942
|
+
continue;
|
|
943
|
+
}
|
|
944
|
+
if (char === ",") {
|
|
945
|
+
if (segment.length > 0) {
|
|
946
|
+
line.push(segment);
|
|
947
|
+
segment = [];
|
|
948
|
+
}
|
|
949
|
+
index += 1;
|
|
950
|
+
continue;
|
|
951
|
+
}
|
|
952
|
+
const read = readVlq(mappings, index);
|
|
953
|
+
index = read.next;
|
|
954
|
+
const field = segment.length;
|
|
955
|
+
state[field] = (state[field] ?? 0) + read.value;
|
|
956
|
+
segment.push(state[field]);
|
|
957
|
+
}
|
|
958
|
+
if (segment.length > 0) {
|
|
959
|
+
line.push(segment);
|
|
960
|
+
}
|
|
961
|
+
lines.push(line);
|
|
962
|
+
return lines;
|
|
963
|
+
}
|
|
964
|
+
function encodeMappings(lines) {
|
|
965
|
+
const state = [0, 0, 0, 0, 0];
|
|
966
|
+
return lines
|
|
967
|
+
.map((line) => {
|
|
968
|
+
state[0] = 0;
|
|
969
|
+
return line
|
|
970
|
+
.map((segment) => segment
|
|
971
|
+
.map((value, index) => {
|
|
972
|
+
const relative = value - (state[index] ?? 0);
|
|
973
|
+
state[index] = value;
|
|
974
|
+
return writeVlq(relative);
|
|
975
|
+
})
|
|
976
|
+
.join(""))
|
|
977
|
+
.join(",");
|
|
978
|
+
})
|
|
979
|
+
.join(";");
|
|
980
|
+
}
|
|
981
|
+
function readVlq(input, start) {
|
|
982
|
+
let index = start;
|
|
983
|
+
let shift = 0;
|
|
984
|
+
let value = 0;
|
|
985
|
+
while (index < input.length) {
|
|
986
|
+
const digit = BASE64_VALUES.get(input[index]);
|
|
987
|
+
if (digit === undefined) {
|
|
988
|
+
throw new Error(`ttsc: invalid source map VLQ digit ${input[index]}`);
|
|
989
|
+
}
|
|
990
|
+
index += 1;
|
|
991
|
+
const continuation = (digit & 32) !== 0;
|
|
992
|
+
value += (digit & 31) << shift;
|
|
993
|
+
shift += 5;
|
|
994
|
+
if (!continuation) {
|
|
995
|
+
const negative = (value & 1) === 1;
|
|
996
|
+
const decoded = value >> 1;
|
|
997
|
+
return { next: index, value: negative ? -decoded : decoded };
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
throw new Error("ttsc: unterminated source map VLQ segment");
|
|
1001
|
+
}
|
|
1002
|
+
function writeVlq(value) {
|
|
1003
|
+
let vlq = Math.abs(value) << 1;
|
|
1004
|
+
if (value < 0) {
|
|
1005
|
+
vlq |= 1;
|
|
1006
|
+
}
|
|
1007
|
+
let out = "";
|
|
1008
|
+
do {
|
|
1009
|
+
let digit = vlq & 31;
|
|
1010
|
+
vlq >>>= 5;
|
|
1011
|
+
if (vlq > 0) {
|
|
1012
|
+
digit |= 32;
|
|
1013
|
+
}
|
|
1014
|
+
out += BASE64_CHARS[digit];
|
|
1015
|
+
} while (vlq > 0);
|
|
1016
|
+
return out;
|
|
1017
|
+
}
|
|
517
1018
|
//# sourceMappingURL=api.js.map
|