Improve @babel/types with env.BABEL_TYPES_8_BREAKING (#10917)
Co-authored-by: Justin Ridgewell <justin@ridgewell.name>
This commit is contained in:
parent
405c1aaad8
commit
e7b80a2cb9
@ -101,8 +101,12 @@ Object.keys(types.BUILDER_KEYS)
|
|||||||
}
|
}
|
||||||
if (defaultValue !== null || types.NODE_FIELDS[key][field].optional) {
|
if (defaultValue !== null || types.NODE_FIELDS[key][field].optional) {
|
||||||
fieldDescription.push(
|
fieldDescription.push(
|
||||||
" (default: `" + util.inspect(defaultValue) + "`)"
|
" (default: `" + util.inspect(defaultValue) + "`"
|
||||||
);
|
);
|
||||||
|
if (types.BUILDER_KEYS[key].indexOf(field) < 0) {
|
||||||
|
fieldDescription.push(", excluded from builder function");
|
||||||
|
}
|
||||||
|
fieldDescription.push(")");
|
||||||
} else {
|
} else {
|
||||||
fieldDescription.push(" (required)");
|
fieldDescription.push(" (required)");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -224,12 +224,12 @@ export function assertArrowFunctionExpression(
|
|||||||
export function assertClassBody(node: Object, opts?: Object = {}): void {
|
export function assertClassBody(node: Object, opts?: Object = {}): void {
|
||||||
assert("ClassBody", node, opts);
|
assert("ClassBody", node, opts);
|
||||||
}
|
}
|
||||||
export function assertClassDeclaration(node: Object, opts?: Object = {}): void {
|
|
||||||
assert("ClassDeclaration", node, opts);
|
|
||||||
}
|
|
||||||
export function assertClassExpression(node: Object, opts?: Object = {}): void {
|
export function assertClassExpression(node: Object, opts?: Object = {}): void {
|
||||||
assert("ClassExpression", node, opts);
|
assert("ClassExpression", node, opts);
|
||||||
}
|
}
|
||||||
|
export function assertClassDeclaration(node: Object, opts?: Object = {}): void {
|
||||||
|
assert("ClassDeclaration", node, opts);
|
||||||
|
}
|
||||||
export function assertExportAllDeclaration(
|
export function assertExportAllDeclaration(
|
||||||
node: Object,
|
node: Object,
|
||||||
opts?: Object = {},
|
opts?: Object = {},
|
||||||
|
|||||||
@ -225,14 +225,14 @@ export function ClassBody(...args: Array<any>): Object {
|
|||||||
return builder("ClassBody", ...args);
|
return builder("ClassBody", ...args);
|
||||||
}
|
}
|
||||||
export { ClassBody as classBody };
|
export { ClassBody as classBody };
|
||||||
export function ClassDeclaration(...args: Array<any>): Object {
|
|
||||||
return builder("ClassDeclaration", ...args);
|
|
||||||
}
|
|
||||||
export { ClassDeclaration as classDeclaration };
|
|
||||||
export function ClassExpression(...args: Array<any>): Object {
|
export function ClassExpression(...args: Array<any>): Object {
|
||||||
return builder("ClassExpression", ...args);
|
return builder("ClassExpression", ...args);
|
||||||
}
|
}
|
||||||
export { ClassExpression as classExpression };
|
export { ClassExpression as classExpression };
|
||||||
|
export function ClassDeclaration(...args: Array<any>): Object {
|
||||||
|
return builder("ClassDeclaration", ...args);
|
||||||
|
}
|
||||||
|
export { ClassDeclaration as classDeclaration };
|
||||||
export function ExportAllDeclaration(...args: Array<any>): Object {
|
export function ExportAllDeclaration(...args: Array<any>): Object {
|
||||||
return builder("ExportAllDeclaration", ...args);
|
return builder("ExportAllDeclaration", ...args);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,6 +41,12 @@ export const BINARY_OPERATORS = [
|
|||||||
...BOOLEAN_BINARY_OPERATORS,
|
...BOOLEAN_BINARY_OPERATORS,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const ASSIGNMENT_OPERATORS = [
|
||||||
|
"=",
|
||||||
|
"+=",
|
||||||
|
...NUMBER_BINARY_OPERATORS.map(op => op + "="),
|
||||||
|
];
|
||||||
|
|
||||||
export const BOOLEAN_UNARY_OPERATORS = ["delete", "!"];
|
export const BOOLEAN_UNARY_OPERATORS = ["delete", "!"];
|
||||||
export const NUMBER_UNARY_OPERATORS = ["+", "-", "~"];
|
export const NUMBER_UNARY_OPERATORS = ["+", "-", "~"];
|
||||||
export const STRING_UNARY_OPERATORS = ["typeof"];
|
export const STRING_UNARY_OPERATORS = ["typeof"];
|
||||||
|
|||||||
@ -1,9 +1,13 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import isValidIdentifier from "../validators/isValidIdentifier";
|
|
||||||
|
import esutils from "esutils";
|
||||||
|
|
||||||
|
import is from "../validators/is";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
BINARY_OPERATORS,
|
BINARY_OPERATORS,
|
||||||
LOGICAL_OPERATORS,
|
LOGICAL_OPERATORS,
|
||||||
|
ASSIGNMENT_OPERATORS,
|
||||||
UNARY_OPERATORS,
|
UNARY_OPERATORS,
|
||||||
UPDATE_OPERATORS,
|
UPDATE_OPERATORS,
|
||||||
} from "../constants";
|
} from "../constants";
|
||||||
@ -26,7 +30,7 @@ defineType("ArrayExpression", {
|
|||||||
assertNodeOrValueType("null", "Expression", "SpreadElement"),
|
assertNodeOrValueType("null", "Expression", "SpreadElement"),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
default: [],
|
default: !process.env.BABEL_TYPES_8_BREAKING ? [] : undefined,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
visitor: ["elements"],
|
visitor: ["elements"],
|
||||||
@ -36,10 +40,29 @@ defineType("ArrayExpression", {
|
|||||||
defineType("AssignmentExpression", {
|
defineType("AssignmentExpression", {
|
||||||
fields: {
|
fields: {
|
||||||
operator: {
|
operator: {
|
||||||
validate: assertValueType("string"),
|
validate: (function() {
|
||||||
|
if (!process.env.BABEL_TYPES_8_BREAKING) {
|
||||||
|
return assertValueType("string");
|
||||||
|
}
|
||||||
|
|
||||||
|
const identifier = assertOneOf(...ASSIGNMENT_OPERATORS);
|
||||||
|
const pattern = assertOneOf("=");
|
||||||
|
|
||||||
|
return function(node, key, val) {
|
||||||
|
const validator = is("Pattern", node.left) ? pattern : identifier;
|
||||||
|
validator(node, key, val);
|
||||||
|
};
|
||||||
|
})(),
|
||||||
},
|
},
|
||||||
left: {
|
left: {
|
||||||
validate: assertNodeType("LVal"),
|
validate: !process.env.BABEL_TYPES_8_BREAKING
|
||||||
|
? assertNodeType("LVal")
|
||||||
|
: assertNodeType(
|
||||||
|
"Identifier",
|
||||||
|
"MemberExpression",
|
||||||
|
"ArrayPattern",
|
||||||
|
"ObjectPattern",
|
||||||
|
),
|
||||||
},
|
},
|
||||||
right: {
|
right: {
|
||||||
validate: assertNodeType("Expression"),
|
validate: assertNodeType("Expression"),
|
||||||
@ -147,10 +170,14 @@ defineType("CallExpression", {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
...(!process.env.BABEL_TYPES_8_BREAKING
|
||||||
|
? {
|
||||||
optional: {
|
optional: {
|
||||||
validate: assertOneOf(true, false),
|
validate: assertOneOf(true, false),
|
||||||
optional: true,
|
optional: true,
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
typeArguments: {
|
typeArguments: {
|
||||||
validate: assertNodeType("TypeParameterInstantiation"),
|
validate: assertNodeType("TypeParameterInstantiation"),
|
||||||
optional: true,
|
optional: true,
|
||||||
@ -166,7 +193,7 @@ defineType("CatchClause", {
|
|||||||
visitor: ["param", "body"],
|
visitor: ["param", "body"],
|
||||||
fields: {
|
fields: {
|
||||||
param: {
|
param: {
|
||||||
validate: assertNodeType("Identifier"),
|
validate: assertNodeType("Identifier", "ArrayPattern", "ObjectPattern"),
|
||||||
optional: true,
|
optional: true,
|
||||||
},
|
},
|
||||||
body: {
|
body: {
|
||||||
@ -256,7 +283,15 @@ defineType("ForInStatement", {
|
|||||||
],
|
],
|
||||||
fields: {
|
fields: {
|
||||||
left: {
|
left: {
|
||||||
validate: assertNodeType("VariableDeclaration", "LVal"),
|
validate: !process.env.BABEL_TYPES_8_BREAKING
|
||||||
|
? assertNodeType("VariableDeclaration", "LVal")
|
||||||
|
: assertNodeType(
|
||||||
|
"VariableDeclaration",
|
||||||
|
"Identifier",
|
||||||
|
"MemberExpression",
|
||||||
|
"ArrayPattern",
|
||||||
|
"ObjectPattern",
|
||||||
|
),
|
||||||
},
|
},
|
||||||
right: {
|
right: {
|
||||||
validate: assertNodeType("Expression"),
|
validate: assertNodeType("Expression"),
|
||||||
@ -305,10 +340,8 @@ export const functionCommon = {
|
|||||||
},
|
},
|
||||||
generator: {
|
generator: {
|
||||||
default: false,
|
default: false,
|
||||||
validate: assertValueType("boolean"),
|
|
||||||
},
|
},
|
||||||
async: {
|
async: {
|
||||||
validate: assertValueType("boolean"),
|
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -359,6 +392,17 @@ defineType("FunctionDeclaration", {
|
|||||||
"Pureish",
|
"Pureish",
|
||||||
"Declaration",
|
"Declaration",
|
||||||
],
|
],
|
||||||
|
validate: (function() {
|
||||||
|
if (!process.env.BABEL_TYPES_8_BREAKING) return () => {};
|
||||||
|
|
||||||
|
const identifier = assertNodeType("Identifier");
|
||||||
|
|
||||||
|
return function(parent, key, node) {
|
||||||
|
if (!is("ExportDefaultDeclaration", parent)) {
|
||||||
|
identifier(node, "id", node.id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})(),
|
||||||
});
|
});
|
||||||
|
|
||||||
defineType("FunctionExpression", {
|
defineType("FunctionExpression", {
|
||||||
@ -405,17 +449,55 @@ defineType("Identifier", {
|
|||||||
fields: {
|
fields: {
|
||||||
...patternLikeCommon,
|
...patternLikeCommon,
|
||||||
name: {
|
name: {
|
||||||
validate: chain(function(node, key, val) {
|
validate: chain(assertValueType("string"), function(node, key, val) {
|
||||||
if (!isValidIdentifier(val)) {
|
if (!process.env.BABEL_TYPES_8_BREAKING) return;
|
||||||
// throw new TypeError(`"${val}" is not a valid identifier name`);
|
|
||||||
|
if (!esutils.keyword.isIdentifierNameES6(val)) {
|
||||||
|
throw new TypeError(`"${val}" is not a valid identifier name`);
|
||||||
}
|
}
|
||||||
}, assertValueType("string")),
|
}),
|
||||||
},
|
},
|
||||||
optional: {
|
optional: {
|
||||||
validate: assertValueType("boolean"),
|
validate: assertValueType("boolean"),
|
||||||
optional: true,
|
optional: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
validate(parent, key, node) {
|
||||||
|
if (!process.env.BABEL_TYPES_8_BREAKING) return;
|
||||||
|
|
||||||
|
const match = /\.(\w+)$/.exec(key);
|
||||||
|
if (!match) return;
|
||||||
|
|
||||||
|
const [, parentKey] = match;
|
||||||
|
const nonComp = { computed: false };
|
||||||
|
|
||||||
|
// We can't check if `parent.property === node`, because nodes are validated
|
||||||
|
// before replacing them in the AST.
|
||||||
|
if (parentKey === "property") {
|
||||||
|
if (is("MemberExpression", parent, nonComp)) return;
|
||||||
|
if (is("OptionalMemberExpression", parent, nonComp)) return;
|
||||||
|
} else if (parentKey === "key") {
|
||||||
|
if (is("Property", parent, nonComp)) return;
|
||||||
|
if (is("Method", parent, nonComp)) return;
|
||||||
|
} else if (parentKey === "exported") {
|
||||||
|
if (is("ExportSpecifier", parent)) return;
|
||||||
|
} else if (parentKey === "imported") {
|
||||||
|
if (is("ImportSpecifier", parent, { imported: node })) return;
|
||||||
|
} else if (parentKey === "meta") {
|
||||||
|
if (is("MetaProperty", parent, { meta: node })) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
// Ideally this should be strict if this node is a descendant of a block
|
||||||
|
// in strict mode. Also, we should disallow "await" in modules.
|
||||||
|
esutils.keyword.isReservedWordES6(node.name, /* strict */ false) &&
|
||||||
|
// Even if "this" is a keyword, we are using the Identifier
|
||||||
|
// node to represent it.
|
||||||
|
node.name !== "this"
|
||||||
|
) {
|
||||||
|
throw new TypeError(`"${node.name}" is not a valid identifer`);
|
||||||
|
}
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
defineType("IfStatement", {
|
defineType("IfStatement", {
|
||||||
@ -492,7 +574,14 @@ defineType("RegExpLiteral", {
|
|||||||
validate: assertValueType("string"),
|
validate: assertValueType("string"),
|
||||||
},
|
},
|
||||||
flags: {
|
flags: {
|
||||||
validate: assertValueType("string"),
|
validate: chain(assertValueType("string"), function(node, key, val) {
|
||||||
|
if (!process.env.BABEL_TYPES_8_BREAKING) return;
|
||||||
|
|
||||||
|
const invalid = /[^gimsuy]/.exec(val);
|
||||||
|
if (invalid) {
|
||||||
|
throw new TypeError(`"${invalid[0]}" is not a valid RegExp flag`);
|
||||||
|
}
|
||||||
|
}),
|
||||||
default: "",
|
default: "",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -537,10 +626,14 @@ defineType("MemberExpression", {
|
|||||||
computed: {
|
computed: {
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
...(!process.env.BABEL_TYPES_8_BREAKING
|
||||||
|
? {
|
||||||
optional: {
|
optional: {
|
||||||
validate: assertOneOf(true, false),
|
validate: assertOneOf(true, false),
|
||||||
optional: true,
|
optional: true,
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -597,19 +690,15 @@ defineType("ObjectExpression", {
|
|||||||
});
|
});
|
||||||
|
|
||||||
defineType("ObjectMethod", {
|
defineType("ObjectMethod", {
|
||||||
builder: ["kind", "key", "params", "body", "computed"],
|
builder: ["kind", "key", "params", "body", "computed", "generator", "async"],
|
||||||
fields: {
|
fields: {
|
||||||
...functionCommon,
|
...functionCommon,
|
||||||
...functionTypeAnnotationCommon,
|
...functionTypeAnnotationCommon,
|
||||||
kind: {
|
kind: {
|
||||||
validate: chain(
|
validate: assertOneOf("method", "get", "set"),
|
||||||
assertValueType("string"),
|
...(!process.env.BABEL_TYPES_8_BREAKING ? { default: "method" } : {}),
|
||||||
assertOneOf("method", "get", "set"),
|
|
||||||
),
|
|
||||||
default: "method",
|
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
validate: assertValueType("boolean"),
|
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
key: {
|
key: {
|
||||||
@ -632,6 +721,7 @@ defineType("ObjectMethod", {
|
|||||||
assertValueType("array"),
|
assertValueType("array"),
|
||||||
assertEach(assertNodeType("Decorator")),
|
assertEach(assertNodeType("Decorator")),
|
||||||
),
|
),
|
||||||
|
optional: true,
|
||||||
},
|
},
|
||||||
body: {
|
body: {
|
||||||
validate: assertNodeType("BlockStatement"),
|
validate: assertNodeType("BlockStatement"),
|
||||||
@ -657,10 +747,15 @@ defineType("ObjectMethod", {
|
|||||||
});
|
});
|
||||||
|
|
||||||
defineType("ObjectProperty", {
|
defineType("ObjectProperty", {
|
||||||
builder: ["key", "value", "computed", "shorthand", "decorators"],
|
builder: [
|
||||||
|
"key",
|
||||||
|
"value",
|
||||||
|
"computed",
|
||||||
|
"shorthand",
|
||||||
|
...(!process.env.BABEL_TYPES_8_BREAKING ? ["decorators"] : []),
|
||||||
|
],
|
||||||
fields: {
|
fields: {
|
||||||
computed: {
|
computed: {
|
||||||
validate: assertValueType("boolean"),
|
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
key: {
|
key: {
|
||||||
@ -684,7 +779,27 @@ defineType("ObjectProperty", {
|
|||||||
validate: assertNodeType("Expression", "PatternLike"),
|
validate: assertNodeType("Expression", "PatternLike"),
|
||||||
},
|
},
|
||||||
shorthand: {
|
shorthand: {
|
||||||
validate: assertValueType("boolean"),
|
validate: chain(
|
||||||
|
assertValueType("boolean"),
|
||||||
|
function(node, key, val) {
|
||||||
|
if (!process.env.BABEL_TYPES_8_BREAKING) return;
|
||||||
|
|
||||||
|
if (val && node.computed) {
|
||||||
|
throw new TypeError(
|
||||||
|
"Property shorthand of ObjectProperty cannot be true if computed is true",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
function(node, key, val) {
|
||||||
|
if (!process.env.BABEL_TYPES_8_BREAKING) return;
|
||||||
|
|
||||||
|
if (val && !is("Identifier", node.key)) {
|
||||||
|
throw new TypeError(
|
||||||
|
"Property shorthand of ObjectProperty cannot be true if key is not an Identifier",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
decorators: {
|
decorators: {
|
||||||
@ -697,6 +812,17 @@ defineType("ObjectProperty", {
|
|||||||
},
|
},
|
||||||
visitor: ["key", "value", "decorators"],
|
visitor: ["key", "value", "decorators"],
|
||||||
aliases: ["UserWhitespacable", "Property", "ObjectMember"],
|
aliases: ["UserWhitespacable", "Property", "ObjectMember"],
|
||||||
|
validate: (function() {
|
||||||
|
const pattern = assertNodeType("Identifier", "Pattern");
|
||||||
|
const expression = assertNodeType("Expression");
|
||||||
|
|
||||||
|
return function(parent, key, node) {
|
||||||
|
if (!process.env.BABEL_TYPES_8_BREAKING) return;
|
||||||
|
|
||||||
|
const validator = is("ObjectPattern", parent) ? pattern : expression;
|
||||||
|
validator(node, "value", node.value);
|
||||||
|
};
|
||||||
|
})(),
|
||||||
});
|
});
|
||||||
|
|
||||||
defineType("RestElement", {
|
defineType("RestElement", {
|
||||||
@ -707,9 +833,22 @@ defineType("RestElement", {
|
|||||||
fields: {
|
fields: {
|
||||||
...patternLikeCommon,
|
...patternLikeCommon,
|
||||||
argument: {
|
argument: {
|
||||||
validate: assertNodeType("LVal"),
|
validate: !process.env.BABEL_TYPES_8_BREAKING
|
||||||
|
? assertNodeType("LVal")
|
||||||
|
: assertNodeType("Identifier", "Pattern", "MemberExpression"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
validate(parent, key) {
|
||||||
|
if (!process.env.BABEL_TYPES_8_BREAKING) return;
|
||||||
|
|
||||||
|
const match = /(\w+)\[(\d+)\]/.exec(key);
|
||||||
|
if (!match) throw new Error("Internal Babel error: malformed key.");
|
||||||
|
|
||||||
|
const [, listKey, index] = match;
|
||||||
|
if (parent[listKey].length > index + 1) {
|
||||||
|
throw new TypeError(`RestElement must be last element of ${listKey}`);
|
||||||
|
}
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
defineType("ReturnStatement", {
|
defineType("ReturnStatement", {
|
||||||
@ -792,13 +931,23 @@ defineType("ThrowStatement", {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// todo: at least handler or finalizer should be set to be valid
|
|
||||||
defineType("TryStatement", {
|
defineType("TryStatement", {
|
||||||
visitor: ["block", "handler", "finalizer"],
|
visitor: ["block", "handler", "finalizer"],
|
||||||
aliases: ["Statement"],
|
aliases: ["Statement"],
|
||||||
fields: {
|
fields: {
|
||||||
block: {
|
block: {
|
||||||
validate: assertNodeType("BlockStatement"),
|
validate: chain(assertNodeType("BlockStatement"), function(node) {
|
||||||
|
if (!process.env.BABEL_TYPES_8_BREAKING) return;
|
||||||
|
|
||||||
|
// This validator isn't put at the top level because we can run it
|
||||||
|
// even if this node doesn't have a parent.
|
||||||
|
|
||||||
|
if (!node.handler && !node.finalizer) {
|
||||||
|
throw new TypeError(
|
||||||
|
"TryStatement expects either a handler or finalizer, or both",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
handler: {
|
handler: {
|
||||||
optional: true,
|
optional: true,
|
||||||
@ -835,7 +984,9 @@ defineType("UpdateExpression", {
|
|||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
argument: {
|
argument: {
|
||||||
validate: assertNodeType("Expression"),
|
validate: !process.env.BABEL_TYPES_8_BREAKING
|
||||||
|
? assertNodeType("Expression")
|
||||||
|
: assertNodeType("Identifier", "MemberExpression"),
|
||||||
},
|
},
|
||||||
operator: {
|
operator: {
|
||||||
validate: assertOneOf(...UPDATE_OPERATORS),
|
validate: assertOneOf(...UPDATE_OPERATORS),
|
||||||
@ -855,10 +1006,7 @@ defineType("VariableDeclaration", {
|
|||||||
optional: true,
|
optional: true,
|
||||||
},
|
},
|
||||||
kind: {
|
kind: {
|
||||||
validate: chain(
|
validate: assertOneOf("var", "let", "const"),
|
||||||
assertValueType("string"),
|
|
||||||
assertOneOf("var", "let", "const"),
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
declarations: {
|
declarations: {
|
||||||
validate: chain(
|
validate: chain(
|
||||||
@ -867,13 +1015,39 @@ defineType("VariableDeclaration", {
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
validate(parent, key, node) {
|
||||||
|
if (!process.env.BABEL_TYPES_8_BREAKING) return;
|
||||||
|
|
||||||
|
if (!is("ForXStatement", parent, { left: node })) return;
|
||||||
|
if (node.declarations.length !== 1) {
|
||||||
|
throw new TypeError(
|
||||||
|
`Exactly one VariableDeclarator is required in the VariableDeclaration of a ${parent.type}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
defineType("VariableDeclarator", {
|
defineType("VariableDeclarator", {
|
||||||
visitor: ["id", "init"],
|
visitor: ["id", "init"],
|
||||||
fields: {
|
fields: {
|
||||||
id: {
|
id: {
|
||||||
validate: assertNodeType("LVal"),
|
validate: (function() {
|
||||||
|
if (!process.env.BABEL_TYPES_8_BREAKING) {
|
||||||
|
return assertNodeType("LVal");
|
||||||
|
}
|
||||||
|
|
||||||
|
const normal = assertNodeType(
|
||||||
|
"Identifier",
|
||||||
|
"ArrayPattern",
|
||||||
|
"ObjectPattern",
|
||||||
|
);
|
||||||
|
const without = assertNodeType("Identifier");
|
||||||
|
|
||||||
|
return function(node, key, val) {
|
||||||
|
const validator = node.init ? normal : without;
|
||||||
|
validator(node, key, val);
|
||||||
|
};
|
||||||
|
})(),
|
||||||
},
|
},
|
||||||
definite: {
|
definite: {
|
||||||
optional: true,
|
optional: true,
|
||||||
@ -894,7 +1068,7 @@ defineType("WhileStatement", {
|
|||||||
validate: assertNodeType("Expression"),
|
validate: assertNodeType("Expression"),
|
||||||
},
|
},
|
||||||
body: {
|
body: {
|
||||||
validate: assertNodeType("BlockStatement", "Statement"),
|
validate: assertNodeType("Statement"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -907,7 +1081,7 @@ defineType("WithStatement", {
|
|||||||
validate: assertNodeType("Expression"),
|
validate: assertNodeType("Expression"),
|
||||||
},
|
},
|
||||||
body: {
|
body: {
|
||||||
validate: assertNodeType("BlockStatement", "Statement"),
|
validate: assertNodeType("Statement"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import defineType, {
|
|||||||
assertShape,
|
assertShape,
|
||||||
assertNodeType,
|
assertNodeType,
|
||||||
assertValueType,
|
assertValueType,
|
||||||
|
assertNodeOrValueType,
|
||||||
chain,
|
chain,
|
||||||
assertEach,
|
assertEach,
|
||||||
assertOneOf,
|
assertOneOf,
|
||||||
@ -13,6 +14,7 @@ import {
|
|||||||
functionTypeAnnotationCommon,
|
functionTypeAnnotationCommon,
|
||||||
patternLikeCommon,
|
patternLikeCommon,
|
||||||
} from "./core";
|
} from "./core";
|
||||||
|
import is from "../validators/is";
|
||||||
|
|
||||||
defineType("AssignmentPattern", {
|
defineType("AssignmentPattern", {
|
||||||
visitor: ["left", "right", "decorators" /* for legacy param decorators */],
|
visitor: ["left", "right", "decorators" /* for legacy param decorators */],
|
||||||
@ -31,11 +33,13 @@ defineType("AssignmentPattern", {
|
|||||||
right: {
|
right: {
|
||||||
validate: assertNodeType("Expression"),
|
validate: assertNodeType("Expression"),
|
||||||
},
|
},
|
||||||
|
// For TypeScript
|
||||||
decorators: {
|
decorators: {
|
||||||
validate: chain(
|
validate: chain(
|
||||||
assertValueType("array"),
|
assertValueType("array"),
|
||||||
assertEach(assertNodeType("Decorator")),
|
assertEach(assertNodeType("Decorator")),
|
||||||
),
|
),
|
||||||
|
optional: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -49,14 +53,16 @@ defineType("ArrayPattern", {
|
|||||||
elements: {
|
elements: {
|
||||||
validate: chain(
|
validate: chain(
|
||||||
assertValueType("array"),
|
assertValueType("array"),
|
||||||
assertEach(assertNodeType("PatternLike")),
|
assertEach(assertNodeOrValueType("null", "PatternLike")),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
// For TypeScript
|
||||||
decorators: {
|
decorators: {
|
||||||
validate: chain(
|
validate: chain(
|
||||||
assertValueType("array"),
|
assertValueType("array"),
|
||||||
assertEach(assertNodeType("Decorator")),
|
assertEach(assertNodeType("Decorator")),
|
||||||
),
|
),
|
||||||
|
optional: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -106,7 +112,26 @@ defineType("ClassBody", {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const classCommon = {
|
defineType("ClassExpression", {
|
||||||
|
builder: ["id", "superClass", "body", "decorators"],
|
||||||
|
visitor: [
|
||||||
|
"id",
|
||||||
|
"body",
|
||||||
|
"superClass",
|
||||||
|
"mixins",
|
||||||
|
"typeParameters",
|
||||||
|
"superTypeParameters",
|
||||||
|
"implements",
|
||||||
|
"decorators",
|
||||||
|
],
|
||||||
|
aliases: ["Scopable", "Class", "Expression", "Pureish"],
|
||||||
|
fields: {
|
||||||
|
id: {
|
||||||
|
validate: assertNodeType("Identifier"),
|
||||||
|
// In declarations, this is missing if this is the
|
||||||
|
// child of an ExportDefaultDeclaration.
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
typeParameters: {
|
typeParameters: {
|
||||||
validate: assertNodeType(
|
validate: assertNodeType(
|
||||||
"TypeParameterDeclaration",
|
"TypeParameterDeclaration",
|
||||||
@ -138,35 +163,6 @@ const classCommon = {
|
|||||||
),
|
),
|
||||||
optional: true,
|
optional: true,
|
||||||
},
|
},
|
||||||
};
|
|
||||||
|
|
||||||
defineType("ClassDeclaration", {
|
|
||||||
builder: ["id", "superClass", "body", "decorators"],
|
|
||||||
visitor: [
|
|
||||||
"id",
|
|
||||||
"body",
|
|
||||||
"superClass",
|
|
||||||
"mixins",
|
|
||||||
"typeParameters",
|
|
||||||
"superTypeParameters",
|
|
||||||
"implements",
|
|
||||||
"decorators",
|
|
||||||
],
|
|
||||||
aliases: ["Scopable", "Class", "Statement", "Declaration", "Pureish"],
|
|
||||||
fields: {
|
|
||||||
...classCommon,
|
|
||||||
declare: {
|
|
||||||
validate: assertValueType("boolean"),
|
|
||||||
optional: true,
|
|
||||||
},
|
|
||||||
abstract: {
|
|
||||||
validate: assertValueType("boolean"),
|
|
||||||
optional: true,
|
|
||||||
},
|
|
||||||
id: {
|
|
||||||
validate: assertNodeType("Identifier"),
|
|
||||||
optional: true, // Missing if this is the child of an ExportDefaultDeclaration.
|
|
||||||
},
|
|
||||||
decorators: {
|
decorators: {
|
||||||
validate: chain(
|
validate: chain(
|
||||||
assertValueType("array"),
|
assertValueType("array"),
|
||||||
@ -177,30 +173,30 @@ defineType("ClassDeclaration", {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
defineType("ClassExpression", {
|
defineType("ClassDeclaration", {
|
||||||
inherits: "ClassDeclaration",
|
inherits: "ClassExpression",
|
||||||
aliases: ["Scopable", "Class", "Expression", "Pureish"],
|
aliases: ["Scopable", "Class", "Statement", "Declaration", "Pureish"],
|
||||||
fields: {
|
fields: {
|
||||||
...classCommon,
|
declare: {
|
||||||
id: {
|
validate: assertValueType("boolean"),
|
||||||
optional: true,
|
optional: true,
|
||||||
validate: assertNodeType("Identifier"),
|
|
||||||
},
|
},
|
||||||
body: {
|
abstract: {
|
||||||
validate: assertNodeType("ClassBody"),
|
validate: assertValueType("boolean"),
|
||||||
},
|
|
||||||
superClass: {
|
|
||||||
optional: true,
|
|
||||||
validate: assertNodeType("Expression"),
|
|
||||||
},
|
|
||||||
decorators: {
|
|
||||||
validate: chain(
|
|
||||||
assertValueType("array"),
|
|
||||||
assertEach(assertNodeType("Decorator")),
|
|
||||||
),
|
|
||||||
optional: true,
|
optional: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
validate: (function() {
|
||||||
|
const identifier = assertNodeType("Identifier");
|
||||||
|
|
||||||
|
return function(parent, key, node) {
|
||||||
|
if (!process.env.BABEL_TYPES_8_BREAKING) return;
|
||||||
|
|
||||||
|
if (!is("ExportDefaultDeclaration", parent)) {
|
||||||
|
identifier(node, "id", node.id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})(),
|
||||||
});
|
});
|
||||||
|
|
||||||
defineType("ExportAllDeclaration", {
|
defineType("ExportAllDeclaration", {
|
||||||
@ -248,18 +244,53 @@ defineType("ExportNamedDeclaration", {
|
|||||||
],
|
],
|
||||||
fields: {
|
fields: {
|
||||||
declaration: {
|
declaration: {
|
||||||
validate: assertNodeType("Declaration"),
|
|
||||||
optional: true,
|
optional: true,
|
||||||
|
validate: chain(
|
||||||
|
assertNodeType("Declaration"),
|
||||||
|
function(node, key, val) {
|
||||||
|
if (!process.env.BABEL_TYPES_8_BREAKING) return;
|
||||||
|
|
||||||
|
// This validator isn't put at the top level because we can run it
|
||||||
|
// even if this node doesn't have a parent.
|
||||||
|
|
||||||
|
if (val && node.specifiers.length) {
|
||||||
|
throw new TypeError(
|
||||||
|
"Only declaration or specifiers is allowed on ExportNamedDeclaration",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
function(node, key, val) {
|
||||||
|
if (!process.env.BABEL_TYPES_8_BREAKING) return;
|
||||||
|
|
||||||
|
// This validator isn't put at the top level because we can run it
|
||||||
|
// even if this node doesn't have a parent.
|
||||||
|
|
||||||
|
if (val && node.source) {
|
||||||
|
throw new TypeError("Cannot export a declaration from a source");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
},
|
},
|
||||||
specifiers: {
|
specifiers: {
|
||||||
|
default: [],
|
||||||
validate: chain(
|
validate: chain(
|
||||||
assertValueType("array"),
|
assertValueType("array"),
|
||||||
assertEach(
|
assertEach(
|
||||||
assertNodeType(
|
(function() {
|
||||||
|
const sourced = assertNodeType(
|
||||||
"ExportSpecifier",
|
"ExportSpecifier",
|
||||||
"ExportDefaultSpecifier",
|
"ExportDefaultSpecifier",
|
||||||
"ExportNamespaceSpecifier",
|
"ExportNamespaceSpecifier",
|
||||||
),
|
);
|
||||||
|
const sourceless = assertNodeType("ExportSpecifier");
|
||||||
|
|
||||||
|
if (!process.env.BABEL_TYPES_8_BREAKING) return sourced;
|
||||||
|
|
||||||
|
return function(node, key, val) {
|
||||||
|
const validator = node.source ? sourced : sourceless;
|
||||||
|
validator(node, key, val);
|
||||||
|
};
|
||||||
|
})(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
@ -286,6 +317,7 @@ defineType("ExportSpecifier", {
|
|||||||
|
|
||||||
defineType("ForOfStatement", {
|
defineType("ForOfStatement", {
|
||||||
visitor: ["left", "right", "body"],
|
visitor: ["left", "right", "body"],
|
||||||
|
builder: ["left", "right", "body", "await"],
|
||||||
aliases: [
|
aliases: [
|
||||||
"Scopable",
|
"Scopable",
|
||||||
"Statement",
|
"Statement",
|
||||||
@ -296,7 +328,27 @@ defineType("ForOfStatement", {
|
|||||||
],
|
],
|
||||||
fields: {
|
fields: {
|
||||||
left: {
|
left: {
|
||||||
validate: assertNodeType("VariableDeclaration", "LVal"),
|
validate: (function() {
|
||||||
|
if (!process.env.BABEL_TYPES_8_BREAKING) {
|
||||||
|
return assertNodeType("VariableDeclaration", "LVal");
|
||||||
|
}
|
||||||
|
|
||||||
|
const declaration = assertNodeType("VariableDeclaration");
|
||||||
|
const lval = assertNodeType(
|
||||||
|
"Identifier",
|
||||||
|
"MemberExpression",
|
||||||
|
"ArrayPattern",
|
||||||
|
"ObjectPattern",
|
||||||
|
);
|
||||||
|
|
||||||
|
return function(node, key, val) {
|
||||||
|
if (is("VariableDeclaration", val)) {
|
||||||
|
declaration(node, key, val);
|
||||||
|
} else {
|
||||||
|
lval(node, key, val);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})(),
|
||||||
},
|
},
|
||||||
right: {
|
right: {
|
||||||
validate: assertNodeType("Expression"),
|
validate: assertNodeType("Expression"),
|
||||||
@ -306,7 +358,6 @@ defineType("ForOfStatement", {
|
|||||||
},
|
},
|
||||||
await: {
|
await: {
|
||||||
default: false,
|
default: false,
|
||||||
validate: assertValueType("boolean"),
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -380,9 +431,26 @@ defineType("MetaProperty", {
|
|||||||
visitor: ["meta", "property"],
|
visitor: ["meta", "property"],
|
||||||
aliases: ["Expression"],
|
aliases: ["Expression"],
|
||||||
fields: {
|
fields: {
|
||||||
// todo: limit to new.target
|
|
||||||
meta: {
|
meta: {
|
||||||
validate: assertNodeType("Identifier"),
|
validate: chain(assertNodeType("Identifier"), function(node, key, val) {
|
||||||
|
if (!process.env.BABEL_TYPES_8_BREAKING) return;
|
||||||
|
|
||||||
|
let property;
|
||||||
|
switch (val.name) {
|
||||||
|
case "function":
|
||||||
|
property = "sent";
|
||||||
|
break;
|
||||||
|
case "new":
|
||||||
|
property = "target";
|
||||||
|
break;
|
||||||
|
case "import":
|
||||||
|
property = "meta";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!is("Identifier", node.property, { name: property })) {
|
||||||
|
throw new TypeError("Unrecognised MetaProperty");
|
||||||
|
}
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
property: {
|
property: {
|
||||||
validate: assertNodeType("Identifier"),
|
validate: assertNodeType("Identifier"),
|
||||||
@ -396,19 +464,14 @@ export const classMethodOrPropertyCommon = {
|
|||||||
optional: true,
|
optional: true,
|
||||||
},
|
},
|
||||||
accessibility: {
|
accessibility: {
|
||||||
validate: chain(
|
validate: assertOneOf("public", "private", "protected"),
|
||||||
assertValueType("string"),
|
|
||||||
assertOneOf("public", "private", "protected"),
|
|
||||||
),
|
|
||||||
optional: true,
|
optional: true,
|
||||||
},
|
},
|
||||||
static: {
|
static: {
|
||||||
default: false,
|
default: false,
|
||||||
validate: assertValueType("boolean"),
|
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
default: false,
|
default: false,
|
||||||
validate: assertValueType("boolean"),
|
|
||||||
},
|
},
|
||||||
optional: {
|
optional: {
|
||||||
validate: assertValueType("boolean"),
|
validate: assertValueType("boolean"),
|
||||||
@ -443,10 +506,7 @@ export const classMethodOrDeclareMethodCommon = {
|
|||||||
...functionCommon,
|
...functionCommon,
|
||||||
...classMethodOrPropertyCommon,
|
...classMethodOrPropertyCommon,
|
||||||
kind: {
|
kind: {
|
||||||
validate: chain(
|
validate: assertOneOf("get", "set", "method", "constructor"),
|
||||||
assertValueType("string"),
|
|
||||||
assertOneOf("get", "set", "method", "constructor"),
|
|
||||||
),
|
|
||||||
default: "method",
|
default: "method",
|
||||||
},
|
},
|
||||||
access: {
|
access: {
|
||||||
@ -467,7 +527,16 @@ export const classMethodOrDeclareMethodCommon = {
|
|||||||
|
|
||||||
defineType("ClassMethod", {
|
defineType("ClassMethod", {
|
||||||
aliases: ["Function", "Scopable", "BlockParent", "FunctionParent", "Method"],
|
aliases: ["Function", "Scopable", "BlockParent", "FunctionParent", "Method"],
|
||||||
builder: ["kind", "key", "params", "body", "computed", "static"],
|
builder: [
|
||||||
|
"kind",
|
||||||
|
"key",
|
||||||
|
"params",
|
||||||
|
"body",
|
||||||
|
"computed",
|
||||||
|
"static",
|
||||||
|
"generator",
|
||||||
|
"async",
|
||||||
|
],
|
||||||
visitor: [
|
visitor: [
|
||||||
"key",
|
"key",
|
||||||
"params",
|
"params",
|
||||||
@ -554,7 +623,6 @@ defineType("TemplateElement", {
|
|||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
tail: {
|
tail: {
|
||||||
validate: assertValueType("boolean"),
|
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -595,7 +663,15 @@ defineType("YieldExpression", {
|
|||||||
aliases: ["Expression", "Terminatorless"],
|
aliases: ["Expression", "Terminatorless"],
|
||||||
fields: {
|
fields: {
|
||||||
delegate: {
|
delegate: {
|
||||||
validate: assertValueType("boolean"),
|
validate: chain(assertValueType("boolean"), function(node, key, val) {
|
||||||
|
if (!process.env.BABEL_TYPES_8_BREAKING) return;
|
||||||
|
|
||||||
|
if (val && !node.argument) {
|
||||||
|
throw new TypeError(
|
||||||
|
"Property delegate of YieldExpression cannot be true if there is no argument",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}),
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
argument: {
|
argument: {
|
||||||
|
|||||||
@ -26,8 +26,15 @@ defineType("AwaitExpression", {
|
|||||||
defineType("BindExpression", {
|
defineType("BindExpression", {
|
||||||
visitor: ["object", "callee"],
|
visitor: ["object", "callee"],
|
||||||
aliases: ["Expression"],
|
aliases: ["Expression"],
|
||||||
fields: {
|
fields: !process.env.BABEL_TYPES_8_BREAKING
|
||||||
// todo
|
? {}
|
||||||
|
: {
|
||||||
|
object: {
|
||||||
|
validate: assertNodeType("Expression"),
|
||||||
|
},
|
||||||
|
callee: {
|
||||||
|
validate: assertNodeType("Expression"),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -468,7 +468,7 @@ defineType("VoidTypeAnnotation", {
|
|||||||
|
|
||||||
// Enums
|
// Enums
|
||||||
defineType("EnumDeclaration", {
|
defineType("EnumDeclaration", {
|
||||||
alises: ["Declaration"],
|
aliases: ["Declaration"],
|
||||||
visitor: ["id", "body"],
|
visitor: ["id", "body"],
|
||||||
fields: {
|
fields: {
|
||||||
id: validateType("Identifier"),
|
id: validateType("Identifier"),
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import {
|
|||||||
NODE_FIELDS,
|
NODE_FIELDS,
|
||||||
BUILDER_KEYS,
|
BUILDER_KEYS,
|
||||||
DEPRECATED_KEYS,
|
DEPRECATED_KEYS,
|
||||||
|
NODE_PARENT_VALIDATIONS,
|
||||||
} from "./utils";
|
} from "./utils";
|
||||||
import {
|
import {
|
||||||
PLACEHOLDERS,
|
PLACEHOLDERS,
|
||||||
@ -43,6 +44,7 @@ export {
|
|||||||
NODE_FIELDS,
|
NODE_FIELDS,
|
||||||
BUILDER_KEYS,
|
BUILDER_KEYS,
|
||||||
DEPRECATED_KEYS,
|
DEPRECATED_KEYS,
|
||||||
|
NODE_PARENT_VALIDATIONS,
|
||||||
PLACEHOLDERS,
|
PLACEHOLDERS,
|
||||||
PLACEHOLDERS_ALIAS,
|
PLACEHOLDERS_ALIAS,
|
||||||
PLACEHOLDERS_FLIPPED_ALIAS,
|
PLACEHOLDERS_FLIPPED_ALIAS,
|
||||||
|
|||||||
@ -142,7 +142,6 @@ defineType("JSXOpeningElement", {
|
|||||||
},
|
},
|
||||||
selfClosing: {
|
selfClosing: {
|
||||||
default: false,
|
default: false,
|
||||||
validate: assertValueType("boolean"),
|
|
||||||
},
|
},
|
||||||
attributes: {
|
attributes: {
|
||||||
validate: chain(
|
validate: chain(
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import is from "../validators/is";
|
import is from "../validators/is";
|
||||||
import { validateField } from "../validators/validate";
|
import { validateField, validateChild } from "../validators/validate";
|
||||||
|
|
||||||
export const VISITOR_KEYS: { [string]: Array<string> } = {};
|
export const VISITOR_KEYS: { [string]: Array<string> } = {};
|
||||||
export const ALIAS_KEYS: { [string]: Array<string> } = {};
|
export const ALIAS_KEYS: { [string]: Array<string> } = {};
|
||||||
@ -8,14 +8,13 @@ export const FLIPPED_ALIAS_KEYS: { [string]: Array<string> } = {};
|
|||||||
export const NODE_FIELDS: { [string]: {} } = {};
|
export const NODE_FIELDS: { [string]: {} } = {};
|
||||||
export const BUILDER_KEYS: { [string]: Array<string> } = {};
|
export const BUILDER_KEYS: { [string]: Array<string> } = {};
|
||||||
export const DEPRECATED_KEYS: { [string]: string } = {};
|
export const DEPRECATED_KEYS: { [string]: string } = {};
|
||||||
|
export const NODE_PARENT_VALIDATIONS = {};
|
||||||
|
|
||||||
function getType(val) {
|
function getType(val) {
|
||||||
if (Array.isArray(val)) {
|
if (Array.isArray(val)) {
|
||||||
return "array";
|
return "array";
|
||||||
} else if (val === null) {
|
} else if (val === null) {
|
||||||
return "null";
|
return "null";
|
||||||
} else if (val === undefined) {
|
|
||||||
return "undefined";
|
|
||||||
} else {
|
} else {
|
||||||
return typeof val;
|
return typeof val;
|
||||||
}
|
}
|
||||||
@ -71,7 +70,10 @@ export function assertEach(callback: Validator): Validator {
|
|||||||
if (!Array.isArray(val)) return;
|
if (!Array.isArray(val)) return;
|
||||||
|
|
||||||
for (let i = 0; i < val.length; i++) {
|
for (let i = 0; i < val.length; i++) {
|
||||||
callback(node, `${key}[${i}]`, val[i]);
|
const subkey = `${key}[${i}]`;
|
||||||
|
const v = val[i];
|
||||||
|
callback(node, subkey, v);
|
||||||
|
if (process.env.BABEL_TYPES_8_BREAKING) validateChild(node, subkey, v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
validator.each = callback;
|
validator.each = callback;
|
||||||
@ -96,24 +98,21 @@ export function assertOneOf(...values: Array<any>): Validator {
|
|||||||
|
|
||||||
export function assertNodeType(...types: Array<string>): Validator {
|
export function assertNodeType(...types: Array<string>): Validator {
|
||||||
function validate(node, key, val) {
|
function validate(node, key, val) {
|
||||||
let valid = false;
|
|
||||||
|
|
||||||
for (const type of types) {
|
for (const type of types) {
|
||||||
if (is(type, val)) {
|
if (is(type, val)) {
|
||||||
valid = true;
|
validateChild(node, key, val);
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!valid) {
|
|
||||||
throw new TypeError(
|
throw new TypeError(
|
||||||
`Property ${key} of ${
|
`Property ${key} of ${
|
||||||
node.type
|
node.type
|
||||||
} expected node to be of a type ${JSON.stringify(types)} ` +
|
} expected node to be of a type ${JSON.stringify(
|
||||||
`but instead got ${JSON.stringify(val && val.type)}`,
|
types,
|
||||||
|
)} but instead got ${JSON.stringify(val && val.type)}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
validate.oneOfNodeTypes = types;
|
validate.oneOfNodeTypes = types;
|
||||||
|
|
||||||
@ -122,24 +121,21 @@ export function assertNodeType(...types: Array<string>): Validator {
|
|||||||
|
|
||||||
export function assertNodeOrValueType(...types: Array<string>): Validator {
|
export function assertNodeOrValueType(...types: Array<string>): Validator {
|
||||||
function validate(node, key, val) {
|
function validate(node, key, val) {
|
||||||
let valid = false;
|
|
||||||
|
|
||||||
for (const type of types) {
|
for (const type of types) {
|
||||||
if (getType(val) === type || is(type, val)) {
|
if (getType(val) === type || is(type, val)) {
|
||||||
valid = true;
|
validateChild(node, key, val);
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!valid) {
|
|
||||||
throw new TypeError(
|
throw new TypeError(
|
||||||
`Property ${key} of ${
|
`Property ${key} of ${
|
||||||
node.type
|
node.type
|
||||||
} expected node to be of a type ${JSON.stringify(types)} ` +
|
} expected node to be of a type ${JSON.stringify(
|
||||||
`but instead got ${JSON.stringify(val && val.type)}`,
|
types,
|
||||||
|
)} but instead got ${JSON.stringify(val && val.type)}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
validate.oneOfNodeOrValueTypes = types;
|
validate.oneOfNodeOrValueTypes = types;
|
||||||
|
|
||||||
@ -200,6 +196,17 @@ export function chain(...fns: Array<Validator>): Validator {
|
|||||||
return validate;
|
return validate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const validTypeOpts = [
|
||||||
|
"aliases",
|
||||||
|
"builder",
|
||||||
|
"deprecatedAlias",
|
||||||
|
"fields",
|
||||||
|
"inherits",
|
||||||
|
"visitor",
|
||||||
|
"validate",
|
||||||
|
];
|
||||||
|
const validFieldKeys = ["default", "optional", "validate"];
|
||||||
|
|
||||||
export default function defineType(
|
export default function defineType(
|
||||||
type: string,
|
type: string,
|
||||||
opts: {
|
opts: {
|
||||||
@ -211,16 +218,38 @@ export default function defineType(
|
|||||||
builder?: Array<string>,
|
builder?: Array<string>,
|
||||||
inherits?: string,
|
inherits?: string,
|
||||||
deprecatedAlias?: string,
|
deprecatedAlias?: string,
|
||||||
|
validate?: Validator,
|
||||||
} = {},
|
} = {},
|
||||||
) {
|
) {
|
||||||
const inherits = (opts.inherits && store[opts.inherits]) || {};
|
const inherits = (opts.inherits && store[opts.inherits]) || {};
|
||||||
|
|
||||||
const fields: Object = opts.fields || inherits.fields || {};
|
let fields = opts.fields;
|
||||||
|
if (!fields) {
|
||||||
|
fields = {};
|
||||||
|
if (inherits.fields) {
|
||||||
|
const keys = Object.getOwnPropertyNames(inherits.fields);
|
||||||
|
for (const key of (keys: Array<string>)) {
|
||||||
|
const field = inherits.fields[key];
|
||||||
|
fields[key] = {
|
||||||
|
default: field.default,
|
||||||
|
optional: field.optional,
|
||||||
|
validate: field.validate,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const visitor: Array<string> = opts.visitor || inherits.visitor || [];
|
const visitor: Array<string> = opts.visitor || inherits.visitor || [];
|
||||||
const aliases: Array<string> = opts.aliases || inherits.aliases || [];
|
const aliases: Array<string> = opts.aliases || inherits.aliases || [];
|
||||||
const builder: Array<string> =
|
const builder: Array<string> =
|
||||||
opts.builder || inherits.builder || opts.visitor || [];
|
opts.builder || inherits.builder || opts.visitor || [];
|
||||||
|
|
||||||
|
for (const k of (Object.keys(opts): Array<string>)) {
|
||||||
|
if (validTypeOpts.indexOf(k) === -1) {
|
||||||
|
throw new Error(`Unknown type option "${k}" on ${type}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (opts.deprecatedAlias) {
|
if (opts.deprecatedAlias) {
|
||||||
DEPRECATED_KEYS[opts.deprecatedAlias] = type;
|
DEPRECATED_KEYS[opts.deprecatedAlias] = type;
|
||||||
}
|
}
|
||||||
@ -233,14 +262,20 @@ export default function defineType(
|
|||||||
for (const key of Object.keys(fields)) {
|
for (const key of Object.keys(fields)) {
|
||||||
const field = fields[key];
|
const field = fields[key];
|
||||||
|
|
||||||
if (builder.indexOf(key) === -1) {
|
if (field.default !== undefined && builder.indexOf(key) === -1) {
|
||||||
field.optional = true;
|
field.optional = true;
|
||||||
}
|
}
|
||||||
if (field.default === undefined) {
|
if (field.default === undefined) {
|
||||||
field.default = null;
|
field.default = null;
|
||||||
} else if (!field.validate) {
|
} else if (!field.validate && field.default != null) {
|
||||||
field.validate = assertValueType(getType(field.default));
|
field.validate = assertValueType(getType(field.default));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const k of (Object.keys(field): Array<string>)) {
|
||||||
|
if (validFieldKeys.indexOf(k) === -1) {
|
||||||
|
throw new Error(`Unknown field key "${k}" on ${type}.${key}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VISITOR_KEYS[type] = opts.visitor = visitor;
|
VISITOR_KEYS[type] = opts.visitor = visitor;
|
||||||
@ -252,6 +287,10 @@ export default function defineType(
|
|||||||
FLIPPED_ALIAS_KEYS[alias].push(type);
|
FLIPPED_ALIAS_KEYS[alias].push(type);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (opts.validate) {
|
||||||
|
NODE_PARENT_VALIDATIONS[type] = opts.validate;
|
||||||
|
}
|
||||||
|
|
||||||
store[type] = opts;
|
store[type] = opts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -781,11 +781,11 @@ export function isClassBody(node: ?Object, opts?: Object): boolean {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
export function isClassDeclaration(node: ?Object, opts?: Object): boolean {
|
export function isClassExpression(node: ?Object, opts?: Object): boolean {
|
||||||
if (!node) return false;
|
if (!node) return false;
|
||||||
|
|
||||||
const nodeType = node.type;
|
const nodeType = node.type;
|
||||||
if (nodeType === "ClassDeclaration") {
|
if (nodeType === "ClassExpression") {
|
||||||
if (typeof opts === "undefined") {
|
if (typeof opts === "undefined") {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@ -795,11 +795,11 @@ export function isClassDeclaration(node: ?Object, opts?: Object): boolean {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
export function isClassExpression(node: ?Object, opts?: Object): boolean {
|
export function isClassDeclaration(node: ?Object, opts?: Object): boolean {
|
||||||
if (!node) return false;
|
if (!node) return false;
|
||||||
|
|
||||||
const nodeType = node.type;
|
const nodeType = node.type;
|
||||||
if (nodeType === "ClassExpression") {
|
if (nodeType === "ClassDeclaration") {
|
||||||
if (typeof opts === "undefined") {
|
if (typeof opts === "undefined") {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@ -3499,8 +3499,8 @@ export function isScopable(node: ?Object, opts?: Object): boolean {
|
|||||||
"SwitchStatement" === nodeType ||
|
"SwitchStatement" === nodeType ||
|
||||||
"WhileStatement" === nodeType ||
|
"WhileStatement" === nodeType ||
|
||||||
"ArrowFunctionExpression" === nodeType ||
|
"ArrowFunctionExpression" === nodeType ||
|
||||||
"ClassDeclaration" === nodeType ||
|
|
||||||
"ClassExpression" === nodeType ||
|
"ClassExpression" === nodeType ||
|
||||||
|
"ClassDeclaration" === nodeType ||
|
||||||
"ForOfStatement" === nodeType ||
|
"ForOfStatement" === nodeType ||
|
||||||
"ClassMethod" === nodeType ||
|
"ClassMethod" === nodeType ||
|
||||||
"ClassPrivateMethod" === nodeType ||
|
"ClassPrivateMethod" === nodeType ||
|
||||||
@ -3847,8 +3847,8 @@ export function isPureish(node: ?Object, opts?: Object): boolean {
|
|||||||
"NullLiteral" === nodeType ||
|
"NullLiteral" === nodeType ||
|
||||||
"BooleanLiteral" === nodeType ||
|
"BooleanLiteral" === nodeType ||
|
||||||
"ArrowFunctionExpression" === nodeType ||
|
"ArrowFunctionExpression" === nodeType ||
|
||||||
"ClassDeclaration" === nodeType ||
|
|
||||||
"ClassExpression" === nodeType ||
|
"ClassExpression" === nodeType ||
|
||||||
|
"ClassDeclaration" === nodeType ||
|
||||||
"BigIntLiteral" === nodeType ||
|
"BigIntLiteral" === nodeType ||
|
||||||
(nodeType === "Placeholder" && "StringLiteral" === node.expectedNode)
|
(nodeType === "Placeholder" && "StringLiteral" === node.expectedNode)
|
||||||
) {
|
) {
|
||||||
@ -3887,6 +3887,7 @@ export function isDeclaration(node: ?Object, opts?: Object): boolean {
|
|||||||
"InterfaceDeclaration" === nodeType ||
|
"InterfaceDeclaration" === nodeType ||
|
||||||
"OpaqueType" === nodeType ||
|
"OpaqueType" === nodeType ||
|
||||||
"TypeAlias" === nodeType ||
|
"TypeAlias" === nodeType ||
|
||||||
|
"EnumDeclaration" === nodeType ||
|
||||||
"TSDeclareFunction" === nodeType ||
|
"TSDeclareFunction" === nodeType ||
|
||||||
"TSInterfaceDeclaration" === nodeType ||
|
"TSInterfaceDeclaration" === nodeType ||
|
||||||
"TSTypeAliasDeclaration" === nodeType ||
|
"TSTypeAliasDeclaration" === nodeType ||
|
||||||
@ -4149,8 +4150,8 @@ export function isClass(node: ?Object, opts?: Object): boolean {
|
|||||||
const nodeType = node.type;
|
const nodeType = node.type;
|
||||||
if (
|
if (
|
||||||
nodeType === "Class" ||
|
nodeType === "Class" ||
|
||||||
"ClassDeclaration" === nodeType ||
|
"ClassExpression" === nodeType ||
|
||||||
"ClassExpression" === nodeType
|
"ClassDeclaration" === nodeType
|
||||||
) {
|
) {
|
||||||
if (typeof opts === "undefined") {
|
if (typeof opts === "undefined") {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@ -5,16 +5,20 @@ import esutils from "esutils";
|
|||||||
* Check if the input `name` is a valid identifier name
|
* Check if the input `name` is a valid identifier name
|
||||||
* and isn't a reserved word.
|
* and isn't a reserved word.
|
||||||
*/
|
*/
|
||||||
export default function isValidIdentifier(name: string): boolean {
|
export default function isValidIdentifier(
|
||||||
if (
|
name: string,
|
||||||
typeof name !== "string" ||
|
reserved: boolean = true,
|
||||||
esutils.keyword.isReservedWordES6(name, true)
|
): boolean {
|
||||||
) {
|
if (typeof name !== "string") return false;
|
||||||
|
|
||||||
|
if (reserved) {
|
||||||
|
if (esutils.keyword.isReservedWordES6(name, true)) {
|
||||||
return false;
|
return false;
|
||||||
} else if (name === "await") {
|
} else if (name === "await") {
|
||||||
// invalid in module, valid in script; better be safe (see #4952)
|
// invalid in module, valid in script; better be safe (see #4952)
|
||||||
return false;
|
return false;
|
||||||
} else {
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return esutils.keyword.isIdentifierNameES6(name);
|
return esutils.keyword.isIdentifierNameES6(name);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import { NODE_FIELDS } from "../definitions";
|
import { NODE_FIELDS, NODE_PARENT_VALIDATIONS } from "../definitions";
|
||||||
|
|
||||||
export default function validate(node?: Object, key: string, val: any): void {
|
export default function validate(node?: Object, key: string, val: any): void {
|
||||||
if (!node) return;
|
if (!node) return;
|
||||||
@ -9,6 +9,7 @@ export default function validate(node?: Object, key: string, val: any): void {
|
|||||||
|
|
||||||
const field = fields[key];
|
const field = fields[key];
|
||||||
validateField(node, key, val, field);
|
validateField(node, key, val, field);
|
||||||
|
validateChild(node, key, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function validateField(
|
export function validateField(
|
||||||
@ -22,3 +23,10 @@ export function validateField(
|
|||||||
|
|
||||||
field.validate(node, key, val);
|
field.validate(node, key, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function validateChild(node?: Object, key: string, val?: Object) {
|
||||||
|
if (val == null) return;
|
||||||
|
const validate = NODE_PARENT_VALIDATIONS[val.type];
|
||||||
|
if (!validate) return;
|
||||||
|
validate(node, key, val);
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user