Forbid pass non-node object to print() (#13293)

This commit is contained in:
fisker Cheung authored and GitHub committed 2022-08-25 19:19:46 +08:00
1 parent 75025561c4
commit a166544583
4 files changed
+67 -14

No files matched your search

+5 -2
View File
@@ -112,8 +112,11 @@ function printTypeParameter(path, options, print) {
const node = path.getValue();
const parts = [];
const parent = path.getParentNode();
const name = node.type === "TSTypeParameter" ? print("name") : node.name;
if (parent.type === "TSMappedType") {
parts.push("[", print("name"));
parts.push("[", name);
if (node.constraint) {
parts.push(" in ", print("constraint"));
}
@@ -139,7 +142,7 @@ function printTypeParameter(path, options, print) {
parts.push("out ");
}
parts.push(print("name"));
parts.push(name);
if (node.bound) {
parts.push(": ", print("bound"));
+51 -10
View File
@@ -89,12 +89,21 @@ import { printLiteral } from "./print/literal.js";
import { printDecorators } from "./print/decorators.js";
function genericPrint(path, options, print, args) {
const node = path.getValue();
if (node === undefined || node === null) {
return "";
}
if (process.env.NODE_ENV !== "production") {
ensurePrintingNode(path);
}
const printed = printPathNoParens(path, options, print, args);
if (!printed) {
return "";
}
const node = path.getValue();
const { type } = node;
// Their decorators are handled themselves, and they can't have parentheses
if (
@@ -170,14 +179,6 @@ function printPathNoParens(path, options, print, args) {
const node = path.getValue();
const semi = options.semi ? ";" : "";
if (!node) {
return "";
}
if (typeof node === "string") {
return node;
}
for (const printer of [
printLiteral,
printHtmlBinding,
@@ -778,7 +779,7 @@ function printPathNoParens(path, options, print, args) {
case "TaggedTemplateExpression":
return [print("tag"), print("typeParameters"), print("quasi")];
case "PrivateIdentifier":
return ["#", print("name")];
return ["#", node.name];
case "PrivateName":
return ["#", print("id")];
@@ -846,6 +847,46 @@ function canAttachComment(node) {
);
}
function ensurePrintingNode(path) {
let name = path.getName();
// AST root
if (name === null) {
return;
}
if (typeof name === "number") {
/*
Nodes in array are stored in path.stack like
```js
[
parentNode,
property, // <-
array,
index,
node,
]
```
*/
name = path.stack[path.stack.length - 4];
}
const parent = path.getParentNode();
const visitorKeys = getVisitorKeys(parent);
if (visitorKeys.includes(name)) {
return;
}
/* istanbul ignore next */
throw Object.assign(new Error("Calling `print()` on non-node object."), {
parentNode: parent,
allowedProperties: visitorKeys,
printingProperty: name,
printingValue: path.getValue(),
});
}
const printer = {
preprocess,
print: genericPrint,
@@ -10,7 +10,7 @@ const angularVisitorKeys = {
NGQuotedExpression: [],
NGMicrosyntax: ["body"],
NGMicrosyntaxKey: [],
NGMicrosyntaxExpression: ["expression", "name"],
NGMicrosyntaxExpression: ["expression", "alias"],
NGMicrosyntaxKeyedExpression: ["key", "expression"],
NGMicrosyntaxLet: ["key", "value"],
NGMicrosyntaxAs: ["key", "alias"],
@@ -46,6 +46,11 @@ const additionalVisitorKeys = {
ArrowFunctionExpression: ["predicate"],
DeclareFunction: ["predicate"],
FunctionDeclaration: ["predicate"],
ClassProperty: ["variance"],
ClassPrivateProperty: ["variance"],
EnumBooleanMember: ["init"],
Property: ["decorators"],
};
export default unionVisitorKeys([
@@ -123,12 +123,14 @@ exports[`visitor keys estree 1`] = `
"value",
"decorators",
"typeAnnotation",
"variance",
],
"ClassProperty": [
"key",
"value",
"typeAnnotation",
"decorators",
"variance",
],
"ConditionalExpression": [
"test",
@@ -212,6 +214,7 @@ exports[`visitor keys estree 1`] = `
],
"EnumBooleanMember": [
"id",
"init",
],
"EnumDeclaration": [
"id",
@@ -468,7 +471,7 @@ exports[`visitor keys estree 1`] = `
],
"NGMicrosyntaxExpression": [
"expression",
"name",
"alias",
],
"NGMicrosyntaxKey": [],
"NGMicrosyntaxKeyedExpression": [
@@ -597,6 +600,7 @@ exports[`visitor keys estree 1`] = `
"Property": [
"key",
"value",
"decorators",
],
"PropertyDefinition": [
"decorators",