mirror of
https://github.com/hanzoai/babel.git
synced 2026-09-24 16:56:45 +00:00
* fix: improve inputSourceMap URL handling * refactor: extract transformation/read-input-source-map-file * chore: keep sub in git * Improve relative upward check * address review comments --------- Co-authored-by: Hanzo Dev <[email protected]>
386 lines
11 KiB
JavaScript
386 lines
11 KiB
JavaScript
import * as babel from "../lib/index.js";
|
|
import convertSourceMap from "convert-source-map";
|
|
import path from "node:path";
|
|
import fs from "node:fs";
|
|
import { commonJS } from "$repo-utils";
|
|
|
|
const { __dirname } = commonJS(import.meta.url);
|
|
|
|
// @see packages/babel-core/src/transformation/normalize-file.ts
|
|
const EXTERNAL_SOURCEMAP_REGEX =
|
|
/^\/\/[@#][ \t]+sourceMappingURL=([^\s'"`]+)[ \t]*$/m;
|
|
|
|
function dirTreeDisplay(dirPath, indent = "") {
|
|
let result = "";
|
|
const entries = fs.readdirSync(dirPath, { withFileTypes: true });
|
|
for (let i = 0; i < entries.length; i++) {
|
|
const entry = entries[i];
|
|
const isLast = i === entries.length - 1;
|
|
result += indent + (isLast ? "ββ " : "ββ ") + entry.name + "\n";
|
|
if (entry.isDirectory()) {
|
|
result += dirTreeDisplay(
|
|
path.join(dirPath, entry.name),
|
|
indent + (isLast ? " " : "β "),
|
|
);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
function getInputSourceMapURL(inputFilePath) {
|
|
const inputCode = fs.readFileSync(inputFilePath, "utf8");
|
|
const match = inputCode.match(EXTERNAL_SOURCEMAP_REGEX);
|
|
return match ? match[1] : null;
|
|
}
|
|
|
|
function verifyInputFileSourceMapExistence(inputFilePath) {
|
|
const sourceMapURL = getInputSourceMapURL(inputFilePath);
|
|
const sourceMapPath = path.resolve(path.dirname(inputFilePath), sourceMapURL);
|
|
const sourceMap = convertSourceMap
|
|
.fromJSON(fs.readFileSync(sourceMapPath, "utf8"))
|
|
.toObject();
|
|
expect(sourceMap.sourcesContent).toHaveLength(1);
|
|
expect(sourceMap.sourcesContent[0]).toContain("const enum Msg");
|
|
}
|
|
|
|
function expectInputSourceMapIsApplied(result) {
|
|
expect(result.map.sourcesContent).toHaveLength(1);
|
|
expect(result.map.sourcesContent[0]).toContain("const enum Msg");
|
|
expect(result.map.sourcesContent[0]).toContain("This map should be loaded");
|
|
}
|
|
|
|
function expectInputSourceMapIsPresentButNotApplied(result, inputFilePath) {
|
|
expect(result.map.sourcesContent).toHaveLength(1);
|
|
expect(result.map.sourcesContent[0]).not.toContain("const enum Msg");
|
|
verifyInputFileSourceMapExistence(inputFilePath);
|
|
}
|
|
|
|
describe("input source map resolution", function () {
|
|
const base = path.join(__dirname, "fixtures/input-source-map-resolution");
|
|
|
|
let cwd;
|
|
|
|
beforeEach(function () {
|
|
cwd = process.cwd();
|
|
process.chdir(base);
|
|
});
|
|
|
|
afterEach(function () {
|
|
process.chdir(cwd);
|
|
});
|
|
|
|
it("should resolve input source map downward relative to the input file", function () {
|
|
const cwd = path.join(base, "relative-down");
|
|
process.chdir(cwd);
|
|
|
|
const inputFilePath = path.join(cwd, "input.js");
|
|
|
|
expect(dirTreeDisplay(cwd)).toMatchInlineSnapshot(`
|
|
"ββ babel.config.input.js.json
|
|
ββ input.js
|
|
ββ input.js.map
|
|
"
|
|
`);
|
|
|
|
expect(getInputSourceMapURL(inputFilePath)).toMatchInlineSnapshot(
|
|
`"input.js.map"`,
|
|
);
|
|
|
|
const result = babel.transformFileSync(inputFilePath, {
|
|
babelrc: false,
|
|
configFile: path.join(cwd, "./babel.config.input.js.json"),
|
|
inputSourceMap: true,
|
|
sourceMap: true,
|
|
});
|
|
|
|
expectInputSourceMapIsApplied(result);
|
|
});
|
|
|
|
it("should resolve input source map downward across package.json boundaries", function () {
|
|
const cwd = path.join(base, "relative-down-into-node-modules");
|
|
process.chdir(cwd);
|
|
|
|
const inputFilePath = path.join(cwd, "input.js");
|
|
|
|
expect(dirTreeDisplay(cwd)).toMatchInlineSnapshot(`
|
|
"ββ babel.config.input.js.json
|
|
ββ input.js
|
|
ββ node_modules
|
|
ββ corp-source-maps
|
|
ββ input.js.map
|
|
ββ package.json
|
|
"
|
|
`);
|
|
expect(getInputSourceMapURL(inputFilePath)).toMatchInlineSnapshot(
|
|
`"node_modules/corp-source-maps/input.js.map"`,
|
|
);
|
|
|
|
const result = babel.transformFileSync(inputFilePath, {
|
|
babelrc: false,
|
|
configFile: path.join(cwd, "./babel.config.input.js.json"),
|
|
inputSourceMap: true,
|
|
sourceMap: true,
|
|
});
|
|
|
|
expectInputSourceMapIsApplied(result);
|
|
});
|
|
|
|
it("should resolve input source map upward within the root boundary", function () {
|
|
const cwd = path.join(base, "relative-up-within-root");
|
|
process.chdir(cwd);
|
|
|
|
const inputFilePath = path.join(cwd, "root", "sub", "input.js");
|
|
|
|
expect(dirTreeDisplay(cwd)).toMatchInlineSnapshot(`
|
|
"ββ babel.config.input.js.json
|
|
ββ root
|
|
ββ input.js.map
|
|
ββ sub
|
|
ββ input.js
|
|
"
|
|
`);
|
|
|
|
expect(getInputSourceMapURL(inputFilePath)).toMatchInlineSnapshot(
|
|
`"../input.js.map"`,
|
|
);
|
|
|
|
const result = babel.transformFileSync(inputFilePath, {
|
|
babelrc: false,
|
|
root: path.join(cwd, "root"),
|
|
configFile: path.join(cwd, "./babel.config.input.js.json"),
|
|
inputSourceMap: true,
|
|
sourceMap: true,
|
|
});
|
|
|
|
expectInputSourceMapIsApplied(result);
|
|
});
|
|
|
|
it("should resolve input source map upward within the package.json boundary", function () {
|
|
const cwd = path.join(base, "relative-up-within-node-modules");
|
|
process.chdir(cwd);
|
|
|
|
const inputFilePath = path.join(
|
|
cwd,
|
|
"node_modules",
|
|
"corp-lib",
|
|
"sub",
|
|
"input.js",
|
|
);
|
|
|
|
expect(dirTreeDisplay(cwd)).toMatchInlineSnapshot(`
|
|
"ββ babel.config.input.js.json
|
|
ββ node_modules
|
|
ββ corp-lib
|
|
ββ input.js.map
|
|
ββ package.json
|
|
ββ sub
|
|
ββ input.js
|
|
"
|
|
`);
|
|
|
|
expect(getInputSourceMapURL(inputFilePath)).toMatchInlineSnapshot(
|
|
`"../input.js.map"`,
|
|
);
|
|
|
|
const result = babel.transformFileSync(inputFilePath, {
|
|
babelrc: false,
|
|
configFile: path.join(cwd, "./babel.config.input.js.json"),
|
|
inputSourceMap: true,
|
|
sourceMap: true,
|
|
});
|
|
|
|
expectInputSourceMapIsApplied(result);
|
|
});
|
|
|
|
it("should not resolve input source map upward across the package.json boundary", function () {
|
|
const cwd = path.join(base, "invalid-relative-up-across-node-modules");
|
|
process.chdir(cwd);
|
|
|
|
const inputFilePath = path.join(
|
|
cwd,
|
|
"node_modules",
|
|
"corp-lib",
|
|
"input.js",
|
|
);
|
|
|
|
expect(dirTreeDisplay(cwd)).toMatchInlineSnapshot(`
|
|
"ββ babel.config.input.js.json
|
|
ββ input.js.map
|
|
ββ node_modules
|
|
ββ corp-lib
|
|
ββ input.js
|
|
ββ package.json
|
|
"
|
|
`);
|
|
|
|
expect(getInputSourceMapURL(inputFilePath)).toMatchInlineSnapshot(
|
|
`"../../input.js.map"`,
|
|
);
|
|
|
|
const result = babel.transformFileSync(inputFilePath, {
|
|
babelrc: false,
|
|
configFile: path.join(cwd, "./babel.config.input.js.json"),
|
|
inputSourceMap: true,
|
|
sourceMap: true,
|
|
});
|
|
|
|
expectInputSourceMapIsPresentButNotApplied(result, inputFilePath);
|
|
});
|
|
|
|
it("should not resolve input source map upward across the root boundary", function () {
|
|
const cwd = path.join(base, "invalid-relative-up-across-root");
|
|
process.chdir(cwd);
|
|
|
|
const inputFilePath = path.join(process.cwd(), "root", "sub", "input.js");
|
|
|
|
expect(dirTreeDisplay(cwd)).toMatchInlineSnapshot(`
|
|
"ββ babel.config.input.js.json
|
|
ββ input.js.map
|
|
ββ root
|
|
ββ sub
|
|
ββ input.js
|
|
"
|
|
`);
|
|
|
|
expect(getInputSourceMapURL(inputFilePath)).toMatchInlineSnapshot(
|
|
`"../../input.js.map"`,
|
|
);
|
|
|
|
const result = babel.transformFileSync(inputFilePath, {
|
|
babelrc: false,
|
|
root: path.join(cwd, "root"),
|
|
configFile: path.join(cwd, "./babel.config.input.js.json"),
|
|
inputSourceMap: true,
|
|
sourceMap: true,
|
|
});
|
|
|
|
expectInputSourceMapIsPresentButNotApplied(result, inputFilePath);
|
|
});
|
|
|
|
it("should not resolve input source map upward across the root boundary and within the package.json boundary", function () {
|
|
const cwd = path.join(
|
|
base,
|
|
"invalid-relative-up-across-root-within-node-modules",
|
|
);
|
|
process.chdir(cwd);
|
|
|
|
const inputFilePath = path.join(
|
|
cwd,
|
|
"node_modules",
|
|
"corp-app",
|
|
"root",
|
|
"sub",
|
|
"input.js",
|
|
);
|
|
|
|
expect(dirTreeDisplay(cwd)).toMatchInlineSnapshot(`
|
|
"ββ babel.config.input.js.json
|
|
ββ node_modules
|
|
ββ corp-app
|
|
ββ input.js.map
|
|
ββ package.json
|
|
ββ root
|
|
ββ sub
|
|
ββ input.js
|
|
"
|
|
`);
|
|
|
|
expect(getInputSourceMapURL(inputFilePath)).toMatchInlineSnapshot(
|
|
`"../../input.js.map"`,
|
|
);
|
|
|
|
const result = babel.transformFileSync(inputFilePath, {
|
|
babelrc: false,
|
|
root: path.join(cwd, "node_modules", "corp-app", "root"),
|
|
configFile: path.join(cwd, "./babel.config.input.js.json"),
|
|
inputSourceMap: true,
|
|
sourceMap: true,
|
|
});
|
|
|
|
expectInputSourceMapIsPresentButNotApplied(result, inputFilePath);
|
|
});
|
|
|
|
it("should not resolve input source map upward across the package.json boundary and within the root boundary", function () {
|
|
const cwd = path.join(
|
|
base,
|
|
"invalid-relative-up-across-node-modules-within-root",
|
|
);
|
|
process.chdir(cwd);
|
|
|
|
const inputFilePath = path.join(
|
|
cwd,
|
|
"root",
|
|
"sub",
|
|
"node_modules",
|
|
"corp-lib",
|
|
"input.js",
|
|
);
|
|
|
|
expect(dirTreeDisplay(cwd)).toMatchInlineSnapshot(`
|
|
"ββ babel.config.input.js.json
|
|
ββ root
|
|
ββ sub
|
|
ββ input.js.map
|
|
ββ node_modules
|
|
ββ corp-lib
|
|
ββ input.js
|
|
ββ package.json
|
|
"
|
|
`);
|
|
|
|
expect(getInputSourceMapURL(inputFilePath)).toMatchInlineSnapshot(
|
|
`"../../input.js.map"`,
|
|
);
|
|
|
|
const result = babel.transformFileSync(inputFilePath, {
|
|
babelrc: false,
|
|
root: path.join(cwd, "root"),
|
|
configFile: path.join(cwd, "./babel.config.input.js.json"),
|
|
inputSourceMap: true,
|
|
sourceMap: true,
|
|
});
|
|
|
|
expectInputSourceMapIsPresentButNotApplied(result, inputFilePath);
|
|
});
|
|
|
|
it("should not resolve input source map across the package.json boundary using url not starting with ../", function () {
|
|
const cwd = path.join(
|
|
base,
|
|
"invalid-relative-up-across-node-modules-url-not-start-with-double-dot",
|
|
);
|
|
process.chdir(cwd);
|
|
|
|
const inputFilePath = path.join(
|
|
cwd,
|
|
"node_modules",
|
|
"corp-lib",
|
|
"input.js",
|
|
);
|
|
|
|
expect(dirTreeDisplay(cwd)).toMatchInlineSnapshot(`
|
|
"ββ babel.config.input.js.json
|
|
ββ input.js.map
|
|
ββ node_modules
|
|
ββ corp-lib
|
|
ββ input.js
|
|
ββ package.json
|
|
ββ sub
|
|
ββ mod.js
|
|
"
|
|
`);
|
|
|
|
expect(getInputSourceMapURL(inputFilePath)).toMatchInlineSnapshot(
|
|
`"sub/../../../input.js.map"`,
|
|
);
|
|
|
|
const result = babel.transformFileSync(inputFilePath, {
|
|
babelrc: false,
|
|
configFile: path.join(cwd, "./babel.config.input.js.json"),
|
|
inputSourceMap: true,
|
|
sourceMap: true,
|
|
});
|
|
|
|
expectInputSourceMapIsPresentButNotApplied(result, inputFilePath);
|
|
});
|
|
});
|