diff --git a/docs/rules/README.md b/docs/rules/README.md
index 04d9046c1..208c25a51 100644
--- a/docs/rules/README.md
+++ b/docs/rules/README.md
@@ -380,6 +380,7 @@ The following rules extend the rules provided by ESLint itself and apply them to
| [vue/no-empty-pattern](./no-empty-pattern.md) | disallow empty destructuring patterns | |
| [vue/no-extra-parens](./no-extra-parens.md) | disallow unnecessary parentheses | :wrench: |
| [vue/no-irregular-whitespace](./no-irregular-whitespace.md) | disallow irregular whitespace | |
+| [vue/no-loss-of-precision](./no-loss-of-precision.md) | disallow literal numbers that lose precision | |
| [vue/no-restricted-syntax](./no-restricted-syntax.md) | disallow specified syntax | |
| [vue/no-sparse-arrays](./no-sparse-arrays.md) | disallow sparse arrays | |
| [vue/no-useless-concat](./no-useless-concat.md) | disallow unnecessary concatenation of literals or template literals | |
diff --git a/docs/rules/no-loss-of-precision.md b/docs/rules/no-loss-of-precision.md
new file mode 100644
index 000000000..2c253c786
--- /dev/null
+++ b/docs/rules/no-loss-of-precision.md
@@ -0,0 +1,30 @@
+---
+pageClass: rule-details
+sidebarDepth: 0
+title: vue/no-loss-of-precision
+description: disallow literal numbers that lose precision
+---
+# vue/no-loss-of-precision
+
+> disallow literal numbers that lose precision
+
+- :exclamation: ***This rule has not been released yet.***
+
+This rule is the same rule as core [no-loss-of-precision] rule but it applies to the expressions in ``.
+
+:::warning
+You must be using ESLint v7.1.0 or later to use this rule.
+:::
+
+## :books: Further Reading
+
+- [no-loss-of-precision]
+
+[no-loss-of-precision]: https://eslint.org/docs/rules/no-loss-of-precision
+
+## :mag: Implementation
+
+- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/no-loss-of-precision.js)
+- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/no-loss-of-precision.js)
+
+Taken with ❤️ [from ESLint core](https://eslint.org/docs/rules/no-loss-of-precision)
diff --git a/lib/index.js b/lib/index.js
index ba2185a91..dc9216945 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -93,6 +93,7 @@ module.exports = {
'no-irregular-whitespace': require('./rules/no-irregular-whitespace'),
'no-lifecycle-after-await': require('./rules/no-lifecycle-after-await'),
'no-lone-template': require('./rules/no-lone-template'),
+ 'no-loss-of-precision': require('./rules/no-loss-of-precision'),
'no-multi-spaces': require('./rules/no-multi-spaces'),
'no-multiple-objects-in-class': require('./rules/no-multiple-objects-in-class'),
'no-multiple-slot-args': require('./rules/no-multiple-slot-args'),
diff --git a/lib/rules/no-loss-of-precision.js b/lib/rules/no-loss-of-precision.js
new file mode 100644
index 000000000..6e6b85a02
--- /dev/null
+++ b/lib/rules/no-loss-of-precision.js
@@ -0,0 +1,16 @@
+/**
+ * @author Yosuke Ota
+ * See LICENSE file in root directory for full license.
+ */
+'use strict'
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+const utils = require('../utils')
+
+// eslint-disable-next-line no-invalid-meta, no-invalid-meta-docs-categories
+module.exports = utils.wrapCoreRule('no-loss-of-precision', {
+ applyDocument: true
+})
diff --git a/lib/utils/index.js b/lib/utils/index.js
index 5c49d15f2..dca98b0de 100644
--- a/lib/utils/index.js
+++ b/lib/utils/index.js
@@ -68,11 +68,11 @@ let ruleMap = null
/**
* Get the core rule implementation from the rule name
* @param {string} name
- * @returns {RuleModule}
+ * @returns {RuleModule | null}
*/
function getCoreRule(name) {
const map = ruleMap || (ruleMap = new (require('eslint').Linter)().getRules())
- return map.get(name) || require(`eslint/lib/rules/${name}`)
+ return map.get(name) || null
}
/**
@@ -331,6 +331,26 @@ module.exports = {
*/
wrapCoreRule(coreRuleName, options) {
const coreRule = getCoreRule(coreRuleName)
+ if (!coreRule) {
+ return {
+ meta: {
+ type: 'problem',
+ docs: {
+ url: `https://eslint.vuejs.org/rules/${coreRuleName}.html`
+ }
+ },
+ create(context) {
+ return defineTemplateBodyVisitor(context, {
+ "VElement[name='template'][parent.type='VDocumentFragment']"(node) {
+ context.report({
+ node,
+ message: `Failed to extend ESLint core rule "${coreRuleName}". You may be able to use this rule by upgrading the version of ESLint. If you cannot upgrade it, turn off this rule.`
+ })
+ }
+ })
+ }
+ }
+ }
const {
categories,
skipDynamicArguments,
diff --git a/tests/lib/rules/no-loss-of-precision.js b/tests/lib/rules/no-loss-of-precision.js
new file mode 100644
index 000000000..5608f8e11
--- /dev/null
+++ b/tests/lib/rules/no-loss-of-precision.js
@@ -0,0 +1,93 @@
+/**
+ * @author Yosuke Ota
+ * See LICENSE file in root directory for full license.
+ */
+'use strict'
+
+const { RuleTester, ESLint } = require('../../eslint-compat')
+const semver = require('semver')
+const rule = require('../../../lib/rules/no-loss-of-precision')
+
+const tester = new RuleTester({
+ parser: require.resolve('vue-eslint-parser'),
+ parserOptions: {
+ ecmaVersion: 2020,
+ sourceType: 'module'
+ }
+})
+tester.run('no-loss-of-precision', rule, {
+ valid: [
+ ...(semver.gte(ESLint.version, '7.1.0')
+ ? [
+ {
+ filename: 'test.vue',
+ code: `
+
+ {{12345}}
+ {{123.45}}
+
+ `
+ },
+ {
+ filename: 'test.vue',
+ code: `
+
+
+
+ `
+ }
+ ]
+ : [])
+ ],
+ invalid: [
+ ...(semver.gte(ESLint.version, '7.1.0')
+ ? [
+ {
+ filename: 'test.vue',
+ code: `
+
+ {{12345678901234567890}}
+ {{0.12345678901234567890}}
+
+ `,
+ errors: [
+ {
+ message: 'This number literal will lose precision at runtime.',
+ line: 3
+ },
+ {
+ message: 'This number literal will lose precision at runtime.',
+ line: 4
+ }
+ ]
+ },
+ {
+ filename: 'test.vue',
+ code: `
+
+
+
+ `,
+ errors: [
+ {
+ message: 'This number literal will lose precision at runtime.',
+ line: 3
+ }
+ ]
+ }
+ ]
+ : [
+ {
+ filename: 'test.vue',
+ code: `
+
+
+
+ `,
+ errors: [
+ 'Failed to extend ESLint core rule "no-loss-of-precision". You may be able to use this rule by upgrading the version of ESLint. If you cannot upgrade it, turn off this rule.'
+ ]
+ }
+ ])
+ ]
+})
diff --git a/tests/lib/utils/core-rules/wrap-core-rule.js b/tests/lib/utils/core-rules/wrap-core-rule.js
new file mode 100644
index 000000000..912957aa6
--- /dev/null
+++ b/tests/lib/utils/core-rules/wrap-core-rule.js
@@ -0,0 +1,41 @@
+'use strict'
+
+const RuleTester = require('eslint').RuleTester
+const utils = require('../../../../lib/utils/index')
+
+const rule = utils.wrapCoreRule('foo')
+
+const tester = new RuleTester({
+ parser: require.resolve('vue-eslint-parser'),
+ parserOptions: {
+ ecmaVersion: 2020,
+ sourceType: 'module'
+ }
+})
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+tester.run('wrap-core-rule-with-unknown', rule, {
+ valid: [
+ {
+ filename: 'test.js',
+ code: `var a`
+ }
+ ],
+ invalid: [
+ {
+ filename: 'test.vue',
+ code: ``,
+ errors: [
+ {
+ message:
+ 'Failed to extend ESLint core rule "foo". You may be able to use this rule by upgrading the version of ESLint. If you cannot upgrade it, turn off this rule.',
+ line: 1,
+ column: 1
+ }
+ ]
+ }
+ ]
+})