diff --git a/lib/rules/no-octal-escape.js b/lib/rules/no-octal-escape.js index a2860ca5bf8..7f6845ec70f 100644 --- a/lib/rules/no-octal-escape.js +++ b/lib/rules/no-octal-escape.js @@ -20,7 +20,11 @@ module.exports = { url: "https://eslint.org/docs/rules/no-octal-escape" }, - schema: [] + schema: [], + + messages: { + octalEscapeSequence: "Don't use octal: '\\{{sequence}}'. Use '\\u....' instead." + } }, create(context) { @@ -32,15 +36,17 @@ module.exports = { return; } - const match = node.raw.match(/^([^\\]|\\[^0-7])*\\([0-3][0-7]{1,2}|[4-7][0-7]|[0-7])/u); + // \0 represents a valid NULL character if it isn't followed by a digit. + const match = node.raw.match( + /^(?:[^\\]|\\.)*?\\([0-3][0-7]{1,2}|[4-7][0-7]|[1-7])/u + ); if (match) { - const octalDigit = match[2]; - - // \0 is actually not considered an octal - if (match[2] !== "0" || typeof match[3] !== "undefined") { - context.report({ node, message: "Don't use octal: '\\{{octalDigit}}'. Use '\\u....' instead.", data: { octalDigit } }); - } + context.report({ + node, + messageId: "octalEscapeSequence", + data: { sequence: match[1] } + }); } } diff --git a/tests/lib/rules/no-octal-escape.js b/tests/lib/rules/no-octal-escape.js index b15416ebf95..cd555ab607e 100644 --- a/tests/lib/rules/no-octal-escape.js +++ b/tests/lib/rules/no-octal-escape.js @@ -24,13 +24,34 @@ ruleTester.run("no-octal-escape", rule, { "var foo = \"\\x51\";", "var foo = \"foo \\\\251 bar\";", "var foo = /([abc]) \\1/g;", - "var foo = '\\0';" + "var foo = '\\0';", + "'\\0 '", + "'\\0a'", + "'\\\\1'", + "'\\\\01'", + "'\\08'", + "'\\09'" ], invalid: [ + + // Test full message { code: "var foo = \"foo \\01 bar\";", errors: [{ message: "Don't use octal: '\\01'. Use '\\u....' instead.", type: "Literal" }] }, - { code: "var foo = \"foo \\251 bar\";", errors: [{ message: "Don't use octal: '\\251'. Use '\\u....' instead.", type: "Literal" }] }, - { code: "var foo = \"\\751\";", errors: [{ message: "Don't use octal: '\\75'. Use '\\u....' instead.", type: "Literal" }] }, - { code: "var foo = \"\\3s51\";", errors: [{ message: "Don't use octal: '\\3'. Use '\\u....' instead.", type: "Literal" }] }, - { code: "var foo = \"\\\\\\751\";", errors: [{ message: "Don't use octal: '\\75'. Use '\\u....' instead.", type: "Literal" }] } + + { code: "var foo = \"foo \\251 bar\";", errors: [{ messageId: "octalEscapeSequence", data: { sequence: "251" }, type: "Literal" }] }, + { code: "var foo = \"\\751\";", errors: [{ messageId: "octalEscapeSequence", data: { sequence: "75" }, type: "Literal" }] }, + { code: "var foo = \"\\3s51\";", errors: [{ messageId: "octalEscapeSequence", data: { sequence: "3" }, type: "Literal" }] }, + { code: "var foo = \"\\\\\\751\";", errors: [{ messageId: "octalEscapeSequence", data: { sequence: "75" }, type: "Literal" }] }, + { code: "'\\0\\1'", errors: [{ messageId: "octalEscapeSequence", data: { sequence: "1" }, type: "Literal" }] }, + { code: "'\\0 \\1'", errors: [{ messageId: "octalEscapeSequence", data: { sequence: "1" }, type: "Literal" }] }, + { code: "'\\0\\01'", errors: [{ messageId: "octalEscapeSequence", data: { sequence: "01" }, type: "Literal" }] }, + { code: "'\\0 \\01'", errors: [{ messageId: "octalEscapeSequence", data: { sequence: "01" }, type: "Literal" }] }, + { code: "'\\08\\1'", errors: [{ messageId: "octalEscapeSequence", data: { sequence: "1" }, type: "Literal" }] }, + { code: "'\\08\\01'", errors: [{ messageId: "octalEscapeSequence", data: { sequence: "01" }, type: "Literal" }] }, + + // Only the first one is reported + { code: "'\\01\\02'", errors: [{ messageId: "octalEscapeSequence", data: { sequence: "01" }, type: "Literal" }] }, + { code: "'\\02\\01'", errors: [{ messageId: "octalEscapeSequence", data: { sequence: "02" }, type: "Literal" }] }, + { code: "'\\01\\2'", errors: [{ messageId: "octalEscapeSequence", data: { sequence: "01" }, type: "Literal" }] }, + { code: "'\\2\\01'", errors: [{ messageId: "octalEscapeSequence", data: { sequence: "2" }, type: "Literal" }] } ] });