mirror of
https://github.com/hanzoai/babel.git
synced 2026-09-24 16:56:45 +00:00
323 lines
9.3 KiB
JavaScript
323 lines
9.3 KiB
JavaScript
import { parse } from "@babel/parser";
|
|
import path from "node:path";
|
|
import fixtures from "@babel/helper-fixtures";
|
|
import * as babel from "@babel/core";
|
|
import pluginTransformTypeScript from "@babel/plugin-transform-typescript";
|
|
import { commonJS } from "$repo-utils";
|
|
import { cloneNode } from "@babel/types";
|
|
|
|
import generate from "../lib/index.js";
|
|
|
|
const { __dirname } = commonJS(import.meta.url);
|
|
|
|
const suites = fixtures(path.join(__dirname, "fixtures"));
|
|
|
|
const FAILURES = [
|
|
// Todo: support trailing comments spanned across trailing comma
|
|
"import-phases/source-expression-comments/input.js",
|
|
"import-phases/source-expression-options-comments/input.js",
|
|
|
|
// These tests are either explicitly about re-formatting the decorators position,
|
|
// or about an old decorators version
|
|
"comments/decorators-after-export-to-before/input.js",
|
|
"comments/decorators-before-export-to-after/input.js",
|
|
"decoratorsBeforeExport/false-to-true/input.js",
|
|
"decoratorsBeforeExport/true-to-false/input.js",
|
|
|
|
// The 'experimental_preserveFormat' option does not fully support Flow
|
|
"flow/array-types/input.js",
|
|
"flow/arrow-functions/input.js",
|
|
"flow/call-properties/input.js",
|
|
"flow/declare-module/input.js",
|
|
"flow/declare-exports/input.js",
|
|
"flow/declare-statements/input.js",
|
|
"flow/indexed-access-types/input.js",
|
|
"flow/interfaces-module-and-script/input.js",
|
|
"flow/iterator-inside-declare/input.js",
|
|
"flow/iterator-inside-interface/input.js",
|
|
"flow/iterator-inside-types/input.js",
|
|
"flow/object-literal-types/input.js",
|
|
"flow/opaque-type-alias/input.js",
|
|
"flow/parentheses/input.js",
|
|
"flow/predicates/input.js",
|
|
"flow/this-param/input.js",
|
|
"flow/tuples/input.js",
|
|
"flow/type-alias/input.js",
|
|
"flow/type-annotations/input.js",
|
|
"flow/type-union-intersection/input.js",
|
|
"flow/typecasts/input.js",
|
|
"flowUsesCommas/ObjectExpression/input.js",
|
|
|
|
// These tests are explicitly about changing the output
|
|
"importAttributesKeyword/assertions-assert-to-with/input.js",
|
|
"importAttributesKeyword/assertions-assert-to-with-legacy/input.js",
|
|
"importAttributesKeyword/assertions-with-to-assert/input.js",
|
|
"importAttributesKeyword/assertions-with-to-with-legacy/input.js",
|
|
"importAttributesKeyword/attributes-assert-to-default/input.js",
|
|
"importAttributesKeyword/attributes-assert-to-default-babel-7/input.js",
|
|
"importAttributesKeyword/attributes-assert-to-with/input.js",
|
|
"importAttributesKeyword/attributes-assert-to-with-legacy/input.js",
|
|
"importAttributesKeyword/attributes-with-to-assert/input.js",
|
|
"importAttributesKeyword/attributes-with-to-with-legacy/input.js",
|
|
"importAttributesKeyword/legacy-module-attributes-to-assert/input.js",
|
|
"importAttributesKeyword/legacy-module-attributes-to-with/input.js",
|
|
|
|
// These tests are about old proposals
|
|
"types/Decorator/input.js",
|
|
];
|
|
|
|
describe("experimental_preserveFormat", () => {
|
|
describe("generation", () => {
|
|
suites.forEach(testSuite => {
|
|
describe(`${testSuite.title}`, () => {
|
|
testSuite.tests.forEach(function (task) {
|
|
if (task.options.throws) return;
|
|
|
|
const testFn = task.disabled ? it.skip : it;
|
|
|
|
const shouldFail = FAILURES.some(f =>
|
|
task.actual.loc.replace(/\\/g, "/").endsWith(f),
|
|
);
|
|
|
|
const parserOpts = {
|
|
filename: task.actual.loc,
|
|
plugins: task.options.plugins || [],
|
|
strictMode: task.options.strictMode === false ? false : true,
|
|
sourceType: "module",
|
|
...task.options.parserOpts,
|
|
createParenthesizedExpressions: true,
|
|
tokens: true,
|
|
};
|
|
const generatorOpts = {
|
|
sourceFileName: path.relative(__dirname, task.actual.loc),
|
|
...task.options,
|
|
retainLines: true,
|
|
experimental_preserveFormat: true,
|
|
comments: true,
|
|
jsescOption: null,
|
|
minified: false,
|
|
compact: false,
|
|
};
|
|
|
|
const input = task.actual.code.replace(/\r\n?/g, "\n");
|
|
|
|
testFn(task.title, () => {
|
|
const ast = parse(input, parserOpts);
|
|
const ok = generate(ast, generatorOpts, input).code === input;
|
|
|
|
if (!ok && shouldFail) {
|
|
expect(1).toBe(1);
|
|
return;
|
|
}
|
|
if (ok) {
|
|
expect(shouldFail).toBe(false);
|
|
}
|
|
|
|
expect(generate(ast, generatorOpts, input).code).toBe(input);
|
|
});
|
|
|
|
if (!shouldFail) {
|
|
testFn(`${task.title} without loc`, () => {
|
|
const ast = parse(input, parserOpts);
|
|
ast.program = cloneNode(ast.program, true, true);
|
|
|
|
const code = generate(ast, generatorOpts, input).code;
|
|
try {
|
|
parse(code, parserOpts);
|
|
} catch (error) {
|
|
expect([code, error]).toEqual([input, null]);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("code transforms", () => {
|
|
it("type stripping with arrow functions", () => {
|
|
const input = `
|
|
const a = (x: string):
|
|
number => 2 as const;
|
|
`;
|
|
const expected = `
|
|
const a = (x )=>
|
|
2 ;
|
|
`;
|
|
|
|
const out = babel.transformSync(input, {
|
|
configFile: false,
|
|
plugins: [pluginTransformTypeScript],
|
|
sourceMaps: true,
|
|
parserOpts: {
|
|
createParenthesizedExpressions: true,
|
|
tokens: true,
|
|
},
|
|
generatorOpts: {
|
|
retainLines: true,
|
|
experimental_preserveFormat: true,
|
|
},
|
|
});
|
|
|
|
expect(out.code.trimEnd()).toBe(expected.trimEnd());
|
|
|
|
expect(out.map.mappings).toMatchInlineSnapshot(
|
|
`";QACQ,MAAM,EAAE,EAAE,CAAC,SAAS;kCACM,UAAU"`,
|
|
);
|
|
});
|
|
|
|
it("identifier renaming", () => {
|
|
const input = `
|
|
const foo = 3;
|
|
const bar = 3;
|
|
|
|
foo( x, y, z );
|
|
bar( x, y, z );
|
|
`;
|
|
const expected = `
|
|
const x = 3;
|
|
const longer=3;
|
|
|
|
x ( x, y, z );
|
|
longer(x,y,z );
|
|
`;
|
|
|
|
const out = babel.transformSync(input, {
|
|
configFile: false,
|
|
plugins: [
|
|
() => ({
|
|
visitor: {
|
|
Program(path) {
|
|
path.scope.rename("foo", "x");
|
|
path.scope.rename("bar", "longer");
|
|
},
|
|
},
|
|
}),
|
|
],
|
|
parserOpts: {
|
|
createParenthesizedExpressions: true,
|
|
tokens: true,
|
|
},
|
|
generatorOpts: {
|
|
retainLines: true,
|
|
experimental_preserveFormat: true,
|
|
},
|
|
});
|
|
|
|
expect(out.code.trimEnd()).toBe(expected.trimEnd());
|
|
});
|
|
|
|
it("node injection", () => {
|
|
const input = `
|
|
const foo
|
|
= 3;
|
|
const bar =
|
|
3;
|
|
bax
|
|
`;
|
|
const expected = `
|
|
const foo
|
|
= 3;hello;
|
|
const bar =
|
|
3;
|
|
bax
|
|
`;
|
|
|
|
const out = babel.transformSync(input, {
|
|
configFile: false,
|
|
plugins: [
|
|
({ types: t }) => ({
|
|
visitor: {
|
|
Program(path) {
|
|
path
|
|
.get("body.0")
|
|
.insertAfter(t.expressionStatement(t.identifier("hello")));
|
|
},
|
|
},
|
|
}),
|
|
],
|
|
parserOpts: {
|
|
createParenthesizedExpressions: true,
|
|
tokens: true,
|
|
},
|
|
generatorOpts: {
|
|
retainLines: true,
|
|
experimental_preserveFormat: true,
|
|
},
|
|
});
|
|
|
|
expect(out.code.trimEnd()).toBe(expected.trimEnd());
|
|
});
|
|
|
|
it("injects new semicolon when needed", () => {
|
|
const input = `
|
|
const foo = 3
|
|
`;
|
|
const expected = `
|
|
const foo = 3;hello;
|
|
`;
|
|
|
|
const out = babel.transformSync(input, {
|
|
configFile: false,
|
|
plugins: [
|
|
({ types: t }) => ({
|
|
visitor: {
|
|
Program(path) {
|
|
path.pushContainer(
|
|
"body",
|
|
t.expressionStatement(t.identifier("hello")),
|
|
);
|
|
},
|
|
},
|
|
}),
|
|
],
|
|
parserOpts: {
|
|
createParenthesizedExpressions: true,
|
|
tokens: true,
|
|
},
|
|
generatorOpts: {
|
|
retainLines: true,
|
|
experimental_preserveFormat: true,
|
|
},
|
|
});
|
|
|
|
expect(out.code.trimEnd()).toBe(expected.trimEnd());
|
|
});
|
|
|
|
it("injects new semicolon when needed, after a comment", () => {
|
|
const input = `
|
|
const foo = 3 /* comment */
|
|
`;
|
|
const expected = `
|
|
const foo = 3 /* comment */;hello;
|
|
`;
|
|
|
|
const out = babel.transformSync(input, {
|
|
configFile: false,
|
|
plugins: [
|
|
({ types: t }) => ({
|
|
visitor: {
|
|
Program(path) {
|
|
path.pushContainer(
|
|
"body",
|
|
t.expressionStatement(t.identifier("hello")),
|
|
);
|
|
},
|
|
},
|
|
}),
|
|
],
|
|
parserOpts: {
|
|
createParenthesizedExpressions: true,
|
|
tokens: true,
|
|
},
|
|
generatorOpts: {
|
|
retainLines: true,
|
|
experimental_preserveFormat: true,
|
|
},
|
|
});
|
|
|
|
expect(out.code.trimEnd()).toBe(expected.trimEnd());
|
|
});
|
|
});
|
|
});
|