Require decoratorsBeforeExport option for decorators (#8465)
* Require decoratorsBeforeExport option for syntax-decorators * Also babylon * Enable test
This commit is contained in:
parent
1e0b649485
commit
d79b5eeeff
@ -23,7 +23,9 @@ describe("parse", function() {
|
||||
const output = require(fixture("output.json"));
|
||||
|
||||
const result = parse(input, {
|
||||
parserOpts: { plugins: ["decorators"] },
|
||||
parserOpts: {
|
||||
plugins: [["decorators", { decoratorsBeforeExport: false }]],
|
||||
},
|
||||
cwd: fixture(),
|
||||
});
|
||||
expect(JSON.parse(JSON.stringify(result))).toEqual(output);
|
||||
|
||||
@ -41,15 +41,28 @@ export function getPluginOption(
|
||||
const PIPELINE_PROPOSALS = ["minimal"];
|
||||
|
||||
export function validatePlugins(plugins: PluginList) {
|
||||
if (
|
||||
hasPlugin(plugins, "decorators") &&
|
||||
hasPlugin(plugins, "decorators-legacy")
|
||||
) {
|
||||
if (hasPlugin(plugins, "decorators")) {
|
||||
if (hasPlugin(plugins, "decorators-legacy")) {
|
||||
throw new Error(
|
||||
"Cannot use the decorators and decorators-legacy plugin together",
|
||||
);
|
||||
}
|
||||
|
||||
const decoratorsBeforeExport = getPluginOption(
|
||||
plugins,
|
||||
"decorators",
|
||||
"decoratorsBeforeExport",
|
||||
);
|
||||
if (decoratorsBeforeExport == null) {
|
||||
throw new Error(
|
||||
"The 'decorators' plugin requires a" +
|
||||
" 'decoratorsBeforeExport' option, whose value must be a boolean.",
|
||||
);
|
||||
} else if (typeof decoratorsBeforeExport !== "boolean") {
|
||||
throw new Error("'decoratorsBeforeExport' must be a boolean.");
|
||||
}
|
||||
}
|
||||
|
||||
if (hasPlugin(plugins, "flow") && hasPlugin(plugins, "typescript")) {
|
||||
throw new Error("Cannot combine flow and typescript plugins.");
|
||||
}
|
||||
|
||||
@ -1,3 +1,7 @@
|
||||
{
|
||||
"plugins": ["classProperties", "classPrivateProperties", "decorators"]
|
||||
"plugins": [
|
||||
"classProperties",
|
||||
"classPrivateProperties",
|
||||
["decorators", { "decoratorsBeforeExport": false }]
|
||||
]
|
||||
}
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
{
|
||||
"plugins": ["decorators", "classProperties"]
|
||||
"plugins": [
|
||||
["decorators", { "decoratorsBeforeExport": false }],
|
||||
"classProperties"
|
||||
]
|
||||
}
|
||||
|
||||
@ -0,0 +1,6 @@
|
||||
{
|
||||
"plugins": [
|
||||
["decorators", { "decoratorsBeforeExport": "yes" }]
|
||||
],
|
||||
"throws": "'decoratorsBeforeExport' must be a boolean."
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
{
|
||||
"plugins": ["decorators"],
|
||||
"throws": "The 'decorators' plugin requires a 'decoratorsBeforeExport' option, whose value must be a boolean."
|
||||
}
|
||||
@ -1,3 +1,5 @@
|
||||
{
|
||||
"plugins": ["decorators"]
|
||||
"plugins": [
|
||||
["decorators", { "decoratorsBeforeExport": false }]
|
||||
]
|
||||
}
|
||||
|
||||
@ -1,3 +1,7 @@
|
||||
{
|
||||
"plugins": ["classProperties", "classPrivateProperties", "decorators"]
|
||||
"plugins": [
|
||||
"classProperties",
|
||||
"classPrivateProperties",
|
||||
["decorators", { "decoratorsBeforeExport": false }]
|
||||
]
|
||||
}
|
||||
|
||||
@ -1,3 +1,6 @@
|
||||
{
|
||||
"plugins": ["classProperties", "decorators"]
|
||||
"plugins": [
|
||||
"classProperties",
|
||||
["decorators", { "decoratorsBeforeExport": false }]
|
||||
]
|
||||
}
|
||||
|
||||
@ -9,19 +9,56 @@ describe("plugin options", function() {
|
||||
// NOTE: This test is not specific about decorators, it can be applied
|
||||
// to any plugin with options.
|
||||
|
||||
it("when they aren't specified", function() {
|
||||
const WITHOUT_FLAG = "flow";
|
||||
const WITH_FLAG = ["flow", { all: true }];
|
||||
|
||||
const CODE = "new Foo<x>(y)";
|
||||
|
||||
const AST_WITHOUT_FLAG = {
|
||||
type: "BinaryExpression",
|
||||
operator: ">",
|
||||
left: {
|
||||
type: "BinaryExpression",
|
||||
operator: "<",
|
||||
left: { type: "NewExpression" },
|
||||
right: { type: "Identifier" },
|
||||
},
|
||||
right: { type: "Identifier", extra: { parenthesized: true } },
|
||||
};
|
||||
|
||||
const AST_WITH_FLAG = {
|
||||
type: "NewExpression",
|
||||
callee: { type: "Identifier" },
|
||||
arguments: [{ type: "Identifier" }],
|
||||
typeArguments: {
|
||||
type: "TypeParameterInstantiation",
|
||||
params: [
|
||||
{ type: "GenericTypeAnnotation", id: { type: "Identifier" } },
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
expect(
|
||||
getParser(CODE, [WITHOUT_FLAG, WITH_FLAG])().program.body[0].expression,
|
||||
).toMatchObject(AST_WITHOUT_FLAG);
|
||||
|
||||
expect(
|
||||
getParser(CODE, [WITHOUT_FLAG])().program.body[0].expression,
|
||||
).toMatchObject(AST_WITHOUT_FLAG);
|
||||
|
||||
expect(
|
||||
getParser(CODE, [WITH_FLAG])().program.body[0].expression,
|
||||
).toMatchObject(AST_WITH_FLAG);
|
||||
});
|
||||
|
||||
it("when they are specified", function() {
|
||||
const NAME = "decorators";
|
||||
const OPT_1 = [NAME, { decoratorsBeforeExport: true }];
|
||||
const OPT_2 = [NAME, { decoratorsBeforeExport: false }];
|
||||
const SYNTAX_1 = "@dec export class C {}";
|
||||
const SYNTAX_2 = "export @dec class C {}";
|
||||
const SYNTAX_DEFAULT = "export @dec class C {}";
|
||||
|
||||
it("when they aren't specified", function() {
|
||||
expect(getParser(SYNTAX_DEFAULT, [NAME, OPT_1])).not.toThrow();
|
||||
expect(getParser(SYNTAX_DEFAULT, [NAME, OPT_2])).not.toThrow();
|
||||
});
|
||||
|
||||
it("when they are specified", function() {
|
||||
expect(getParser(SYNTAX_1, [OPT_1, OPT_2])).not.toThrow();
|
||||
expect(getParser(SYNTAX_2, [OPT_2, OPT_1])).not.toThrow();
|
||||
expect(getParser(SYNTAX_1, [OPT_2, OPT_1])).toThrow();
|
||||
|
||||
@ -17,7 +17,14 @@ export default declare((api, options) => {
|
||||
}
|
||||
|
||||
const { decoratorsBeforeExport } = options;
|
||||
if (decoratorsBeforeExport !== undefined) {
|
||||
if (decoratorsBeforeExport === undefined) {
|
||||
if (!legacy) {
|
||||
throw new Error(
|
||||
"The '@babel/plugin-syntax-decorators' plugin requires a" +
|
||||
" 'decoratorsBeforeExport' option, whose value must be a boolean.",
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (legacy) {
|
||||
throw new Error(
|
||||
"'decoratorsBeforeExport' can't be used with legacy decorators.",
|
||||
|
||||
@ -37,6 +37,10 @@ describe("'decoratorsBeforeExport' option", function() {
|
||||
expect(makeParser("", { decoratorsBeforeExport: "before" })).toThrow();
|
||||
});
|
||||
|
||||
test.skip("is required", function() {
|
||||
expect(makeParser("", { legacy: false })).toThrow(/decoratorsBeforeExport/);
|
||||
});
|
||||
|
||||
test("is incompatible with legacy", function() {
|
||||
expect(
|
||||
makeParser("", { decoratorsBeforeExport: false, legacy: true }),
|
||||
@ -47,8 +51,6 @@ describe("'decoratorsBeforeExport' option", function() {
|
||||
const AFTER = "export @dec class Foo {}";
|
||||
|
||||
// These are skipped
|
||||
run(BEFORE, undefined, true);
|
||||
run(AFTER, undefined, false);
|
||||
run(BEFORE, true, false);
|
||||
run(AFTER, true, true);
|
||||
run(BEFORE, false, true);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user