diff --git a/docs/rules/no-loss-of-precision.md b/docs/rules/no-loss-of-precision.md index e1fcc4e09d7..62d065981e6 100644 --- a/docs/rules/no-loss-of-precision.md +++ b/docs/rules/no-loss-of-precision.md @@ -16,6 +16,7 @@ const x = 5123000000000000000000000000001 const x = 1230000000000000000000000.0 const x = .1230000000000000000000000 const x = 0X20000000000001 +const x = 0X2_000000000_0001; ``` Examples of **correct** code for this rule: @@ -29,4 +30,5 @@ const x = 123e34 const x = 12300000000000000000000000 const x = 0x1FFFFFFFFFFFFF const x = 9007199254740991 +const x = 9007_1992547409_91 ``` diff --git a/lib/rules/no-loss-of-precision.js b/lib/rules/no-loss-of-precision.js index b95677c2e0b..9e2811809f6 100644 --- a/lib/rules/no-loss-of-precision.js +++ b/lib/rules/no-loss-of-precision.js @@ -36,6 +36,14 @@ module.exports = { return typeof node.value === "number"; } + /** + * Gets the source code of the given number literal. Removes `_` numeric separators from the result. + * @param {Node} node the number `Literal` node + * @returns {string} raw source code of the literal, without numeric separators + */ + function getRaw(node) { + return node.raw.replace(/_/gu, ""); + } /** * Checks whether the number is base ten @@ -55,7 +63,7 @@ module.exports = { * @returns {boolean} true if they do not match */ function notBaseTenLosesPrecision(node) { - const rawString = node.raw.toUpperCase(); + const rawString = getRaw(node).toUpperCase(); let base = 0; if (rawString.startsWith("0B")) { @@ -161,7 +169,7 @@ module.exports = { * @returns {boolean} true if they do not match */ function baseTenLosesPrecision(node) { - const normalizedRawNumber = convertNumberToScientificNotation(node.raw); + const normalizedRawNumber = convertNumberToScientificNotation(getRaw(node)); const requestedPrecision = normalizedRawNumber.split("e")[0].replace(".", "").length; if (requestedPrecision > 100) { diff --git a/tests/lib/rules/no-loss-of-precision.js b/tests/lib/rules/no-loss-of-precision.js index fd2fb204524..c690dd7e1bc 100644 --- a/tests/lib/rules/no-loss-of-precision.js +++ b/tests/lib/rules/no-loss-of-precision.js @@ -47,14 +47,33 @@ ruleTester.run("no-loss-of-precision", rule, { "var x = 0195", "var x = 0e5", + { code: "var x = 12_34_56", parserOptions: { ecmaVersion: 2021 } }, + { code: "var x = 12_3.4_56", parserOptions: { ecmaVersion: 2021 } }, + { code: "var x = -12_3.4_56", parserOptions: { ecmaVersion: 2021 } }, + { code: "var x = -12_34_56", parserOptions: { ecmaVersion: 2021 } }, + { code: "var x = 12_3e3_4", parserOptions: { ecmaVersion: 2021 } }, + { code: "var x = 123.0e3_4", parserOptions: { ecmaVersion: 2021 } }, + { code: "var x = 12_3e-3_4", parserOptions: { ecmaVersion: 2021 } }, + { code: "var x = 12_3.0e-3_4", parserOptions: { ecmaVersion: 2021 } }, + { code: "var x = -1_23e-3_4", parserOptions: { ecmaVersion: 2021 } }, + { code: "var x = -1_23.8e-3_4", parserOptions: { ecmaVersion: 2021 } }, + { code: "var x = 1_230000000_00000000_00000_000", parserOptions: { ecmaVersion: 2021 } }, + { code: "var x = -1_230000000_00000000_00000_000", parserOptions: { ecmaVersion: 2021 } }, + { code: "var x = 0.0_00_000000000_000000000_00123", parserOptions: { ecmaVersion: 2021 } }, + { code: "var x = -0.0_00_000000000_000000000_00123", parserOptions: { ecmaVersion: 2021 } }, + { code: "var x = 0e5_3", parserOptions: { ecmaVersion: 2021 } }, { code: "var x = 0b11111111111111111111111111111111111111111111111111111", parserOptions: { ecmaVersion: 6 } }, + { code: "var x = 0b111_111_111_111_1111_11111_111_11111_1111111111_11111111_111_111", parserOptions: { ecmaVersion: 2021 } }, + { code: "var x = 0B11111111111111111111111111111111111111111111111111111", parserOptions: { ecmaVersion: 6 } }, + { code: "var x = 0B111_111_111_111_1111_11111_111_11111_1111111111_11111111_111_111", parserOptions: { ecmaVersion: 2021 } }, { code: "var x = 0o377777777777777777", parserOptions: { ecmaVersion: 6 } }, + { code: "var x = 0o3_77_777_777_777_777_777", parserOptions: { ecmaVersion: 2021 } }, { code: "var x = 0O377777777777777777", parserOptions: { ecmaVersion: 6 } }, - "var x = 0377777777777777777", + "var x = 0377777777777777777", "var x = 0x1FFFFFFFFFFFFF", "var x = 0X1FFFFFFFFFFFFF", "var x = true", @@ -65,8 +84,10 @@ ruleTester.run("no-loss-of-precision", rule, { "var x = {}", "var x = ['a', 'b']", "var x = new Date()", - "var x = '9007199254740993'" + "var x = '9007199254740993'", + { code: "var x = 0x1FFF_FFFF_FFF_FFF", parserOptions: { ecmaVersion: 2021 } }, + { code: "var x = 0X1_FFF_FFFF_FFF_FFF", parserOptions: { ecmaVersion: 2021 } } ], invalid: [ { @@ -93,7 +114,36 @@ ruleTester.run("no-loss-of-precision", rule, { code: "var x = -900719.9254740994", errors: [{ messageId: "noLossOfPrecision" }] }, - + { + code: "var x = 900719925474099_3", + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "noLossOfPrecision" }] + }, + { + code: "var x = 90_0719925_4740.9_93e3", + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "noLossOfPrecision" }] + }, + { + code: "var x = 9.0_0719925_474099_3e15", + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "noLossOfPrecision" }] + }, + { + code: "var x = -9_00719_9254_740993", + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "noLossOfPrecision" }] + }, + { + code: "var x = 900_719.92_54740_994", + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "noLossOfPrecision" }] + }, + { + code: "var x = -900_719.92_5474_0994", + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "noLossOfPrecision" }] + }, { code: "var x = 5123000000000000000000000000001", errors: [{ messageId: "noLossOfPrecision" }] @@ -153,7 +203,71 @@ ruleTester.run("no-loss-of-precision", rule, { { code: "var x = 0X20000000000001", errors: [{ messageId: "noLossOfPrecision" }] + }, + { + code: "var x = 5123_00000000000000000000000000_1", + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "noLossOfPrecision" }] + }, + { + code: "var x = -5_12300000000000000000000_0000001", + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "noLossOfPrecision" }] + }, + { + code: "var x = 123_00000000000000000000_00.0_0", + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "noLossOfPrecision" }] + }, + { + code: "var x = 1.0_00000000000000000_0000123", + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "noLossOfPrecision" }] + }, + { + code: "var x = 174_980057982_640953949800178169_409709228253554471456994_914061648512796239935950073857881054_1618443059_2", + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "noLossOfPrecision" }] + }, + { + code: "var x = 2e9_99", + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "noLossOfPrecision" }] + }, + { + code: "var x = .1_23000000000000_00000_0000_0", + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "noLossOfPrecision" }] + }, + { + code: "var x = 0b1_0000000000000000000000000000000000000000000000000000_1", + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "noLossOfPrecision" }] + }, + { + code: "var x = 0B10000000000_0000000000000000000000000000_000000000000001", + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "noLossOfPrecision" }] + }, + { + code: "var x = 0o4_00000000000000_001", + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "noLossOfPrecision" }] + }, + { + code: "var x = 0O4_0000000000000000_1", + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "noLossOfPrecision" }] + }, + { + code: "var x = 0x2_0000000000001", + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "noLossOfPrecision" }] + }, + { + code: "var x = 0X200000_0000000_1", + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "noLossOfPrecision" }] } - ] });