Skip to content

Commit

Permalink
Add option to visualize source maps in tests
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolo-ribaudo committed Sep 5, 2023
1 parent 2c07574 commit 9606dd1
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 3 deletions.
@@ -1,4 +1,5 @@
{
"plugins": ["transform-arrow-functions", "transform-function-name"],
"sourceMaps": true
"sourceMaps": true,
"sourceMapVisual": true
}
@@ -0,0 +1,41 @@
(1:0) var t <-- (1:0) var t
^ ^

(1:4) var t = x <-- (1:4) var t = f
^ ^

(1:5) ar t = x <-- (1:5) ar t = fu
^ ^

(1:8) t = x => <-- (1:8) t = funct
^ ^

(1:4) var t = x <-- (1:17) ion t(x)
^ ^

(1:5) ar t = x <-- (1:18) on t(x) {
^ ^

(1:8) t = x => <-- (1:19) n t(x) {
^ ^

(1:9) = x => x <-- (1:20) t(x) {
^ ^

(1:9) = x => x <-- (2:2) retur
^ ^

(1:13) => x * x <-- (2:9) urn x * x
^ ^

(1:14) => x * x; <-- (2:10) rn x * x;
^ ^

(1:17) x * x; <-- (2:13) x * x;
^ ^

(1:18) * x; <-- (2:14) * x;
^ ^

(1:18) * x; <-- (3:0) };
^ ^
15 changes: 13 additions & 2 deletions packages/babel-helper-fixtures/src/index.ts
Expand Up @@ -41,6 +41,8 @@ export interface Test {
inputSourceMap?: EncodedSourceMap;
sourceMap: string;
sourceMapFile: TestFile;
sourceMapVisual: TestFile;
validateSourceMapVisual: boolean;
validateLogs: boolean;
}

Expand All @@ -51,6 +53,7 @@ export interface TaskOptions extends InputOptions {
ignoreOutput?: boolean;
minNodeVersion?: string;
sourceMap?: boolean;
sourceMapVisual?: boolean;
os?: string | string[];
validateLogs?: boolean;
throws?: boolean | string;
Expand Down Expand Up @@ -129,6 +132,7 @@ function pushTask(
stdoutLoc,
stderrLoc,
sourceMapLoc,
sourceMapVisualLoc,
inputSourceMap;

const taskOpts: TaskOptions = JSON.parse(JSON.stringify(suite.options));
Expand All @@ -155,10 +159,12 @@ function pushTask(
taskOptsLoc = loc;
Object.assign(taskOpts, require(taskOptsLoc));
break;
case "source-map": {
case "source-map":
sourceMapLoc = loc;
break;
}
case "source-map-visual":
sourceMapVisualLoc = loc;
break;
case "input-source-map":
inputSourceMap = JSON.parse(readFile(loc));
break;
Expand Down Expand Up @@ -230,9 +236,14 @@ function pushTask(
expect: buildTestFile(expectLoc, true),
sourceMap: sourceMapFile.code,
sourceMapFile,
sourceMapVisual: buildTestFile(sourceMapVisualLoc),
validateSourceMapVisual: taskOpts.sourceMapVisual,
inputSourceMap,
};

// Not an option to pass to Babel
delete taskOpts.sourceMapVisual;

if (
test.exec.code &&
test.actual.code &&
Expand Down
Expand Up @@ -19,6 +19,7 @@
"@babel/core": "workspace:^",
"@babel/helper-check-duplicate-nodes": "workspace:^",
"@babel/helper-fixtures": "workspace:^",
"@jridgewell/trace-mapping": "^0.3.17",
"lru-cache": "condition:BABEL_8_BREAKING ? ^7.14.1 : ^5.1.1"
},
"engines": {
Expand Down
16 changes: 16 additions & 0 deletions packages/babel-helper-transform-fixture-test-runner/src/index.ts
Expand Up @@ -14,6 +14,7 @@ import {
} from "@babel/helper-fixtures";
import { codeFrameColumns } from "@babel/code-frame";
import * as helpers from "./helpers.ts";
import visualizeSourceMap from "./source-map-visualizer.ts";
import assert from "assert";
import fs from "fs";
import path from "path";
Expand Down Expand Up @@ -385,6 +386,21 @@ async function run(task: Test) {
}
}

if (task.validateSourceMapVisual === true) {
const visual = visualizeSourceMap(inputCode, result.code, result.map);
try {
expect(visual).toEqual(task.sourceMapVisual.code);
} catch (e) {
if (!process.env.OVERWRITE && task.sourceMapVisual.code) throw e;

console.log(`Updated test file: ${task.sourceMapVisual.loc}`);
fs.writeFileSync(
task.sourceMapVisual.loc ?? task.taskDir + "/source-map-visual.txt",
visual + "\n",
);
}
}

if (opts.sourceMaps === true) {
try {
expect(result.map).toEqual(task.sourceMap);
Expand Down
@@ -0,0 +1,58 @@
import { TraceMap, eachMapping } from "@jridgewell/trace-mapping";

const CONTEXT_SIZE = 4;
const MAX_LOC_SIZE = 10;

function simpleCodeFrame(lines: string[], line: number, col: number) {
const start = Math.max(col - CONTEXT_SIZE, 0);
const end = Math.min(col + CONTEXT_SIZE + 1, lines[line - 1].length);
const marker = col - start;
const code = lines[line - 1].slice(start, end);
const loc = `(${line}:${col}) `.padStart(MAX_LOC_SIZE, " ");
return loc + code + "\n" + " ".repeat(marker + loc.length) + "^";
}

function joinMultiline(left: string, right: string, leftLen?: number) {
const leftLines = left.split("\n");
const rightLines = right.split("\n");

leftLen ??= leftLines.reduce((len, line) => Math.max(len, line.length), 0);

const linesCount = Math.max(leftLines.length, rightLines.length);
let res = "";
for (let i = 0; i < linesCount; i++) {
if (res !== "") res += "\n";
if (i < leftLines.length) res += leftLines[i].padEnd(leftLen, " ");
else res += " ".repeat(leftLen);
if (i < rightLines.length) res += rightLines[i];
}
return res;
}

export default function visualize(input: string, output: string, map: any) {
const inputLines = input.split("\n");
const outputLines = output.split("\n");

const res: string[] = [];
eachMapping(new TraceMap(map), mapping => {
const input = simpleCodeFrame(
inputLines,
mapping.originalLine,
mapping.originalColumn,
);
const output = simpleCodeFrame(
outputLines,
mapping.generatedLine,
mapping.generatedColumn,
);

res.push(
joinMultiline(
joinMultiline(input, " <-- ", MAX_LOC_SIZE + CONTEXT_SIZE * 2 + 5),
output,
),
);
});

return res.join("\n\n");
}
1 change: 1 addition & 0 deletions yarn.lock
Expand Up @@ -1126,6 +1126,7 @@ __metadata:
"@babel/core": "workspace:^"
"@babel/helper-check-duplicate-nodes": "workspace:^"
"@babel/helper-fixtures": "workspace:^"
"@jridgewell/trace-mapping": ^0.3.17
lru-cache: "condition:BABEL_8_BREAKING ? ^7.14.1 : ^5.1.1"
languageName: unknown
linkType: soft
Expand Down

0 comments on commit 9606dd1

Please sign in to comment.