"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.isStaticValueIdentifier = exports.validateNode = void 0; const errors_1 = require("./errors"); const token_store_1 = require("./token-store"); const utils_1 = require("./utils"); const require_utils_1 = require("./modules/require-utils"); const lineBreakPattern = /\r\n|[\n\r\u2028\u2029]/u; const octalNumericLiteralPattern = /^0[Oo]/u; const legacyOctalNumericLiteralPattern = /^0\d/u; const binaryNumericLiteralPattern = /^0[Bb]/u; let cacheCodePointEscapeMatcher; function getCodePointEscapeMatcher() { if (!cacheCodePointEscapeMatcher) { const utils = (0, require_utils_1.loadNewest)([ { getPkg() { return (0, require_utils_1.requireFromCwd)("eslint-utils/package.json"); }, get() { return (0, require_utils_1.requireFromCwd)("eslint-utils"); }, }, { getPkg() { return (0, require_utils_1.requireFromLinter)("eslint-utils/package.json"); }, get() { return (0, require_utils_1.requireFromLinter)("eslint-utils"); }, }, { getPkg() { return require("eslint-utils/package.json"); }, get() { return require("eslint-utils"); }, }, ]); cacheCodePointEscapeMatcher = new utils.PatternMatcher(/\\u\{[\dA-Fa-f]+\}/gu); } return cacheCodePointEscapeMatcher; } function validateNode(node, tokens, ctx) { if (node.type === "ObjectExpression") { validateObjectExpressionNode(node, tokens, ctx); return; } if (node.type === "Property") { validatePropertyNode(node, tokens, ctx); return; } if (node.type === "ArrayExpression") { validateArrayExpressionNode(node, tokens, ctx); return; } if (node.type === "Literal") { validateLiteralNode(node, tokens, ctx); return; } if (node.type === "UnaryExpression") { validateUnaryExpressionNode(node, tokens, ctx); return; } if (node.type === "Identifier") { validateIdentifierNode(node, tokens, ctx); return; } if (node.type === "TemplateLiteral") { validateTemplateLiteralNode(node, tokens, ctx); return; } if (node.type === "TemplateElement") { validateTemplateElementNode(node, tokens); return; } throw (0, errors_1.throwUnexpectedNodeError)(node, tokens); } exports.validateNode = validateNode; function validateObjectExpressionNode(node, tokens, ctx) { if (node.type !== "ObjectExpression") { throw (0, errors_1.throwUnexpectedNodeError)(node, tokens); } for (const prop of node.properties) { setParent(prop, node); } if (!ctx.trailingCommas) { const token = tokens.getTokenBefore(tokens.getLastToken(node)); if (token && (0, token_store_1.isComma)(token)) { throw (0, errors_1.throwUnexpectedTokenError)(",", token); } } } function validatePropertyNode(node, tokens, ctx) { if (node.type !== "Property") { throw (0, errors_1.throwUnexpectedNodeError)(node, tokens); } setParent(node.key, node); setParent(node.value, node); if (node.computed) { throw (0, errors_1.throwUnexpectedNodeError)(node, tokens); } if (node.method) { throw (0, errors_1.throwUnexpectedNodeError)(node.value, tokens); } if (node.shorthand) { throw (0, errors_1.throwExpectedTokenError)(":", node); } if (node.kind !== "init") { throw (0, errors_1.throwExpectedTokenError)(":", tokens.getFirstToken(node)); } if (node.key.type === "Literal") { const keyValueType = typeof node.key.value; if (keyValueType === "number") { if (!ctx.numberProperties) { throw (0, errors_1.throwUnexpectedNodeError)(node.key, tokens); } } else if (keyValueType !== "string") { throw (0, errors_1.throwUnexpectedNodeError)(node.key, tokens); } } else if (node.key.type === "Identifier") { if (!ctx.unquoteProperties) { throw (0, errors_1.throwUnexpectedNodeError)(node.key, tokens); } } else { throw (0, errors_1.throwUnexpectedNodeError)(node.key, tokens); } if (node.value.type === "Identifier") { if (!isStaticValueIdentifier(node.value, ctx)) { throw (0, errors_1.throwUnexpectedNodeError)(node.value, tokens); } } } function validateArrayExpressionNode(node, tokens, ctx) { if (node.type !== "ArrayExpression") { throw (0, errors_1.throwUnexpectedNodeError)(node, tokens); } if (!ctx.trailingCommas) { const token = tokens.getTokenBefore(tokens.getLastToken(node)); if (token && (0, token_store_1.isComma)(token)) { throw (0, errors_1.throwUnexpectedTokenError)(",", token); } } node.elements.forEach((child, index) => { if (!child) { if (ctx.sparseArrays) { return; } const beforeIndex = index - 1; const before = beforeIndex >= 0 ? tokens.getLastToken(node.elements[beforeIndex]) : tokens.getFirstToken(node); throw (0, errors_1.throwUnexpectedTokenError)(",", tokens.getTokenAfter(before, token_store_1.isComma)); } if (child.type === "Identifier") { if (!isStaticValueIdentifier(child, ctx)) { throw (0, errors_1.throwUnexpectedNodeError)(child, tokens); } } setParent(child, node); }); } function validateLiteralNode(node, tokens, ctx) { if (node.type !== "Literal") { throw (0, errors_1.throwUnexpectedNodeError)(node, tokens); } if ((0, utils_1.isRegExpLiteral)(node)) { if (!ctx.regExpLiterals) { throw (0, errors_1.throwUnexpectedNodeError)(node, tokens); } } else if (node.bigint) { if (!ctx.bigintLiterals) { throw (0, errors_1.throwUnexpectedNodeError)(node, tokens); } } else { validateLiteral(node, ctx); } } function validateLiteral(node, ctx) { const value = node.value; if ((!ctx.invalidJsonNumbers || !ctx.leadingOrTrailingDecimalPoints || !ctx.numericSeparators) && typeof value === "number") { const text = node.raw; if (!ctx.leadingOrTrailingDecimalPoints) { if (text.startsWith(".")) { throw (0, errors_1.throwUnexpectedTokenError)(".", node); } if (text.endsWith(".")) { throw (0, errors_1.throwUnexpectedTokenError)(".", { range: [node.range[1] - 1, node.range[1]], loc: { start: { line: node.loc.end.line, column: node.loc.end.column - 1, }, end: node.loc.end, }, }); } } if (!ctx.numericSeparators) { if (text.includes("_")) { const index = text.indexOf("_"); throw (0, errors_1.throwUnexpectedTokenError)("_", { range: [node.range[0] + index, node.range[0] + index + 1], loc: { start: { line: node.loc.start.line, column: node.loc.start.column + index, }, end: { line: node.loc.start.line, column: node.loc.start.column + index + 1, }, }, }); } } if (!ctx.octalNumericLiterals) { if (octalNumericLiteralPattern.test(text)) { throw (0, errors_1.throwUnexpectedError)("octal numeric literal", node); } } if (!ctx.legacyOctalNumericLiterals) { if (legacyOctalNumericLiteralPattern.test(text)) { throw (0, errors_1.throwUnexpectedError)("legacy octal numeric literal", node); } } if (!ctx.binaryNumericLiterals) { if (binaryNumericLiteralPattern.test(text)) { throw (0, errors_1.throwUnexpectedError)("binary numeric literal", node); } } if (!ctx.invalidJsonNumbers) { try { JSON.parse(text); } catch (_a) { throw (0, errors_1.throwInvalidNumberError)(text, node); } } } if ((!ctx.multilineStrings || !ctx.singleQuotes || !ctx.unicodeCodepointEscapes) && typeof value === "string") { if (!ctx.singleQuotes) { if (node.raw.startsWith("'")) { throw (0, errors_1.throwUnexpectedError)("single quoted", node); } } if (!ctx.multilineStrings) { if (lineBreakPattern.test(node.raw)) { throw (0, errors_1.throwUnexpectedError)("multiline string", node); } } if (!ctx.unicodeCodepointEscapes) { if (getCodePointEscapeMatcher().test(node.raw)) { throw (0, errors_1.throwUnexpectedError)("unicode codepoint escape", node); } } } return undefined; } function validateUnaryExpressionNode(node, tokens, ctx) { if (node.type !== "UnaryExpression") { throw (0, errors_1.throwUnexpectedNodeError)(node, tokens); } const operator = node.operator; if (operator === "+") { if (!ctx.plusSigns) { throw (0, errors_1.throwUnexpectedTokenError)("+", node); } } else if (operator !== "-") { throw (0, errors_1.throwUnexpectedNodeError)(node, tokens); } const argument = node.argument; if (argument.type === "Literal") { if (typeof argument.value !== "number") { throw (0, errors_1.throwUnexpectedNodeError)(argument, tokens); } } else if (argument.type === "Identifier") { if (!isNumberIdentifier(argument, ctx)) { throw (0, errors_1.throwUnexpectedNodeError)(argument, tokens); } } else { throw (0, errors_1.throwUnexpectedNodeError)(argument, tokens); } if (!ctx.spacedSigns) { if (node.range[0] + 1 < argument.range[0]) { throw (0, errors_1.throwUnexpectedSpaceError)(tokens.getFirstToken(node)); } } setParent(argument, node); } function validateIdentifierNode(node, tokens, ctx) { if (node.type !== "Identifier") { throw (0, errors_1.throwUnexpectedNodeError)(node, tokens); } if (!ctx.escapeSequenceInIdentifier) { if (node.name.length < node.range[1] - node.range[0]) { throw (0, errors_1.throwUnexpectedError)("escape sequence", node); } } } function validateTemplateLiteralNode(node, tokens, ctx) { if (node.type !== "TemplateLiteral") { throw (0, errors_1.throwUnexpectedNodeError)(node, tokens); } if (!ctx.templateLiterals) { throw (0, errors_1.throwUnexpectedNodeError)(node, tokens); } if (node.expressions.length) { const token = tokens.getFirstToken(node.quasis[0]); const loc = { loc: { start: { line: token.loc.end.line, column: token.loc.end.column - 2, }, end: token.loc.end, }, range: [token.range[1] - 2, token.range[1]], }; throw (0, errors_1.throwUnexpectedTokenError)("$", loc); } if (!ctx.unicodeCodepointEscapes) { if (getCodePointEscapeMatcher().test(node.quasis[0].value.raw)) { throw (0, errors_1.throwUnexpectedError)("unicode codepoint escape", node); } } for (const q of node.quasis) { setParent(q, node); } } function validateTemplateElementNode(node, tokens) { if (node.type !== "TemplateElement") { throw (0, errors_1.throwUnexpectedNodeError)(node, tokens); } const { cooked } = node.value; if (cooked == null) { throw (0, errors_1.throwUnexpectedNodeError)(node, tokens); } const startOffset = -1; const endOffset = node.tail ? 1 : 2; node.start += startOffset; node.end += endOffset; node.range[0] += startOffset; node.range[1] += endOffset; node.loc.start.column += startOffset; node.loc.end.column += endOffset; } function isStaticValueIdentifier(node, ctx) { if (isNumberIdentifier(node, ctx)) { return true; } return node.name === "undefined" && ctx.undefinedKeywords; } exports.isStaticValueIdentifier = isStaticValueIdentifier; function isNumberIdentifier(node, ctx) { if (node.name === "Infinity" && ctx.infinities) { return true; } if (node.name === "NaN" && ctx.nans) { return true; } return false; } function setParent(prop, parent) { ; prop.parent = parent; }