diff --git a/docs/configs/index.md b/docs/configs/index.md
index dfd2cdd3..7eb6099f 100644
--- a/docs/configs/index.md
+++ b/docs/configs/index.md
@@ -28,6 +28,32 @@ export default [
}
```
+## no-new-in-esnext-intl-api
+
+disallow the new stuff to be planned for the next yearly ECMAScript Intl API (ECMA-402) snapshot.\
+⚠️ This config will be changed in the minor versions of this plugin.
+
+### [Config (Flat Config)]
+
+eslint.config.js:
+
+```js
+import pluginESx from "eslint-plugin-es-x"
+export default [
+ pluginESx.configs['flat/no-new-in-esnext-intl-api']
+]
+```
+
+### [Legacy Config]
+
+.eslintrc.*:
+
+```json
+{
+ "extends": ["plugin:es-x/no-new-in-esnext-intl-api"],
+}
+```
+
## no-new-in-es2024
disallow new stuff in ES2024.
diff --git a/docs/rules/index.md b/docs/rules/index.md
index 59a69421..c5d0f97e 100644
--- a/docs/rules/index.md
+++ b/docs/rules/index.md
@@ -37,6 +37,14 @@ There is a config that enables the rules in this category: [`no-new-in-esnext`]
| [es-x/no-set-prototype-union](./no-set-prototype-union.md) | disallow the `Set.prototype.union` method. | |
| [es-x/no-trailing-dynamic-import-commas](./no-trailing-dynamic-import-commas.md) | disallow trailing commas in `import()`. | 🔧 |
+## ES2025 Intl API
+
+There is a config that enables the rules in this category: [`no-new-in-esnext-intl-api`]
+
+| Rule ID | Description | |
+|:--------|:------------|:--:|
+| [es-x/no-intl-durationformat](./no-intl-durationformat.md) | disallow the `Intl.DurationFormat` object. | |
+
## ES2024
There are multiple configs that enable all rules in this category: [`no-new-in-es2024`], [`restrict-to-es3`], [`restrict-to-es5`], [`restrict-to-es2015`], [`restrict-to-es2016`], [`restrict-to-es2017`], [`restrict-to-es2018`], [`restrict-to-es2019`], [`restrict-to-es2020`], [`restrict-to-es2021`], [`restrict-to-es2022`], and [`restrict-to-es2023`]
@@ -406,6 +414,8 @@ Rules in this category are not included in any preset.
| [es-x/no-nonstandard-intl-datetimeformat-prototype-properties](./no-nonstandard-intl-datetimeformat-prototype-properties.md) | disallow non-standard properties on Intl.DateTimeFormat instance. | |
| [es-x/no-nonstandard-intl-displaynames-properties](./no-nonstandard-intl-displaynames-properties.md) | disallow non-standard static properties on `Intl.DisplayNames` class. | |
| [es-x/no-nonstandard-intl-displaynames-prototype-properties](./no-nonstandard-intl-displaynames-prototype-properties.md) | disallow non-standard properties on Intl.DisplayNames instance. | |
+| [es-x/no-nonstandard-intl-durationformat-properties](./no-nonstandard-intl-durationformat-properties.md) | disallow non-standard static properties on `Intl.DurationFormat` class. | |
+| [es-x/no-nonstandard-intl-durationformat-prototype-properties](./no-nonstandard-intl-durationformat-prototype-properties.md) | disallow non-standard properties on Intl.DurationFormat instance. | |
| [es-x/no-nonstandard-intl-listformat-properties](./no-nonstandard-intl-listformat-properties.md) | disallow non-standard static properties on `Intl.ListFormat` class. | |
| [es-x/no-nonstandard-intl-listformat-prototype-properties](./no-nonstandard-intl-listformat-prototype-properties.md) | disallow non-standard properties on Intl.ListFormat instance. | |
| [es-x/no-nonstandard-intl-locale-properties](./no-nonstandard-intl-locale-properties.md) | disallow non-standard static properties on `Intl.Locale` class. | |
@@ -463,6 +473,7 @@ Rules in this category are not included in any preset.
| [es-x/no-string-prototype-iswellformed-towellformed](./no-string-prototype-iswellformed-towellformed.md) | [es-x/no-string-prototype-iswellformed](./no-string-prototype-iswellformed.md), [es-x/no-string-prototype-towellformed](./no-string-prototype-towellformed.md) |
[`no-new-in-esnext`]: ../configs/index.md#no-new-in-esnext
+[`no-new-in-esnext-intl-api`]: ../configs/index.md#no-new-in-esnext-intl-api
[`no-new-in-es2024`]: ../configs/index.md#no-new-in-es2024
[`restrict-to-es2023`]: ../configs/index.md#restrict-to-es2023
[`restrict-to-es2023-intl-api`]: ../configs/index.md#restrict-to-es2023-intl-api
diff --git a/docs/rules/no-intl-durationformat.md b/docs/rules/no-intl-durationformat.md
new file mode 100644
index 00000000..d0691803
--- /dev/null
+++ b/docs/rules/no-intl-durationformat.md
@@ -0,0 +1,38 @@
+---
+title: "es-x/no-intl-durationformat"
+description: "disallow the `Intl.DurationFormat` object"
+---
+
+# es-x/no-intl-durationformat
+> disallow the `Intl.DurationFormat` object
+
+- ❗ ***This rule has not been released yet.***
+- ✅ The following configurations enable this rule: [no-new-in-esnext-intl-api]
+
+This rule reports ES2025 Intl API `Intl.DurationFormat` object as errors.
+
+## 💡 Examples
+
+⛔ Examples of **incorrect** code for this rule:
+
+
+
+```js
+/*eslint es-x/no-intl-durationformat: error */
+const df = new Intl.DurationFormat("fr-FR", { style: "long" });
+
+df.format({
+ hours: 1,
+ minutes: 46,
+ seconds: 40,
+});
+```
+
+
+
+## 📚 References
+
+- [Rule source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/lib/rules/no-intl-durationformat.js)
+- [Test source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/tests/lib/rules/no-intl-durationformat.js)
+
+[no-new-in-esnext-intl-api]: ../configs/index.md#no-new-in-esnext-intl-api
diff --git a/docs/rules/no-nonstandard-intl-durationformat-properties.md b/docs/rules/no-nonstandard-intl-durationformat-properties.md
new file mode 100644
index 00000000..6f049dae
--- /dev/null
+++ b/docs/rules/no-nonstandard-intl-durationformat-properties.md
@@ -0,0 +1,50 @@
+---
+title: "es-x/no-nonstandard-intl-durationformat-properties"
+description: "disallow non-standard static properties on `Intl.DurationFormat` class"
+---
+
+# es-x/no-nonstandard-intl-durationformat-properties
+> disallow non-standard static properties on `Intl.DurationFormat` class
+
+- ❗ ***This rule has not been released yet.***
+
+This rule reports non-standard static properties on `Intl.DurationFormat` class as errors.
+
+## 💡 Examples
+
+⛔ Examples of **incorrect** code for this rule:
+
+
+
+```js
+/*eslint es-x/no-nonstandard-intl-durationformat-properties: error */
+Intl.DurationFormat.unknown();
+```
+
+
+
+## 🔧 Options
+
+This rule has an option.
+
+```jsonc
+{
+ "rules": {
+ "es-x/no-nonstandard-intl-durationformat-properties": [
+ "error",
+ {
+ "allow": []
+ }
+ ]
+ }
+}
+```
+
+### allow: string[]
+
+An array of non-standard property names to allow.
+
+## 📚 References
+
+- [Rule source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/lib/rules/no-nonstandard-intl-durationformat-properties.js)
+- [Test source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/tests/lib/rules/no-nonstandard-intl-durationformat-properties.js)
diff --git a/docs/rules/no-nonstandard-intl-durationformat-prototype-properties.md b/docs/rules/no-nonstandard-intl-durationformat-prototype-properties.md
new file mode 100644
index 00000000..f9e8e994
--- /dev/null
+++ b/docs/rules/no-nonstandard-intl-durationformat-prototype-properties.md
@@ -0,0 +1,51 @@
+---
+title: "es-x/no-nonstandard-intl-durationformat-prototype-properties"
+description: "disallow non-standard properties on Intl.DurationFormat instance"
+---
+
+# es-x/no-nonstandard-intl-durationformat-prototype-properties
+> disallow non-standard properties on Intl.DurationFormat instance
+
+- ❗ ***This rule has not been released yet.***
+
+This rule reports non-standard properties on Intl.DurationFormat instance as errors.
+
+## 💡 Examples
+
+⛔ Examples of **incorrect** code for this rule:
+
+
+
+```js
+/*eslint es-x/no-nonstandard-intl-durationformat-prototype-properties: error */
+const df = new Intl.DurationFormat("fr-FR", { style: "long" });
+df.unknown();
+```
+
+
+
+## 🔧 Options
+
+This rule has an option.
+
+```jsonc
+{
+ "rules": {
+ "es-x/no-nonstandard-intl-durationformat-prototype-properties": [
+ "error",
+ {
+ "allow": []
+ }
+ ]
+ }
+}
+```
+
+### allow: string[]
+
+An array of non-standard property names to allow.
+
+## 📚 References
+
+- [Rule source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/lib/rules/no-nonstandard-intl-durationformat-prototype-properties.js)
+- [Test source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/tests/lib/rules/no-nonstandard-intl-durationformat-prototype-properties.js)
diff --git a/lib/configs/flat/no-new-in-esnext-intl-api.js b/lib/configs/flat/no-new-in-esnext-intl-api.js
index 270272d3..91a1feab 100644
--- a/lib/configs/flat/no-new-in-esnext-intl-api.js
+++ b/lib/configs/flat/no-new-in-esnext-intl-api.js
@@ -10,5 +10,5 @@ module.exports = {
return require("../../index.js")
},
},
- rules: {},
+ rules: { "es-x/no-intl-durationformat": "error" },
}
diff --git a/lib/configs/no-new-in-esnext-intl-api.js b/lib/configs/no-new-in-esnext-intl-api.js
index f42c5997..71e35c13 100644
--- a/lib/configs/no-new-in-esnext-intl-api.js
+++ b/lib/configs/no-new-in-esnext-intl-api.js
@@ -4,4 +4,7 @@
*/
"use strict"
-module.exports = { plugins: ["es-x"], rules: {} }
+module.exports = {
+ plugins: ["es-x"],
+ rules: { "es-x/no-intl-durationformat": "error" },
+}
diff --git a/lib/index.js b/lib/index.js
index f49eb1ae..aed64d3b 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -213,6 +213,7 @@ module.exports = {
"no-intl-datetimeformat-prototype-formatrange": require("./rules/no-intl-datetimeformat-prototype-formatrange"),
"no-intl-datetimeformat-prototype-formattoparts": require("./rules/no-intl-datetimeformat-prototype-formattoparts"),
"no-intl-displaynames": require("./rules/no-intl-displaynames"),
+ "no-intl-durationformat": require("./rules/no-intl-durationformat"),
"no-intl-getcanonicallocales": require("./rules/no-intl-getcanonicallocales"),
"no-intl-listformat": require("./rules/no-intl-listformat"),
"no-intl-locale": require("./rules/no-intl-locale"),
@@ -287,6 +288,8 @@ module.exports = {
"no-nonstandard-intl-datetimeformat-prototype-properties": require("./rules/no-nonstandard-intl-datetimeformat-prototype-properties"),
"no-nonstandard-intl-displaynames-properties": require("./rules/no-nonstandard-intl-displaynames-properties"),
"no-nonstandard-intl-displaynames-prototype-properties": require("./rules/no-nonstandard-intl-displaynames-prototype-properties"),
+ "no-nonstandard-intl-durationformat-properties": require("./rules/no-nonstandard-intl-durationformat-properties"),
+ "no-nonstandard-intl-durationformat-prototype-properties": require("./rules/no-nonstandard-intl-durationformat-prototype-properties"),
"no-nonstandard-intl-listformat-properties": require("./rules/no-nonstandard-intl-listformat-properties"),
"no-nonstandard-intl-listformat-prototype-properties": require("./rules/no-nonstandard-intl-listformat-prototype-properties"),
"no-nonstandard-intl-locale-properties": require("./rules/no-nonstandard-intl-locale-properties"),
diff --git a/lib/rules/no-intl-durationformat.js b/lib/rules/no-intl-durationformat.js
new file mode 100644
index 00000000..ffe8d888
--- /dev/null
+++ b/lib/rules/no-intl-durationformat.js
@@ -0,0 +1,27 @@
+"use strict"
+
+const {
+ defineStaticPropertiesHandler,
+} = require("../util/define-static-properties-handler")
+
+module.exports = {
+ meta: {
+ docs: {
+ description: "disallow the `Intl.DurationFormat` object.",
+ category: "ES2025-Intl-API",
+ recommended: false,
+ url: "http://eslint-community.github.io/eslint-plugin-es-x/rules/no-intl-durationformat.html",
+ },
+ fixable: null,
+ messages: {
+ forbidden: "ES2025 Intl API '{{name}}' object is forbidden.",
+ },
+ schema: [],
+ type: "problem",
+ },
+ create(context) {
+ return defineStaticPropertiesHandler(context, {
+ Intl: ["DurationFormat"],
+ })
+ },
+}
diff --git a/lib/rules/no-nonstandard-intl-durationformat-properties.js b/lib/rules/no-nonstandard-intl-durationformat-properties.js
new file mode 100644
index 00000000..ee991a5a
--- /dev/null
+++ b/lib/rules/no-nonstandard-intl-durationformat-properties.js
@@ -0,0 +1,48 @@
+"use strict"
+
+const {
+ defineNonstandardStaticPropertiesHandler,
+} = require("../util/define-nonstandard-static-properties-handler")
+const {
+ intlDurationFormatProperties,
+} = require("../util/well-known-properties")
+
+module.exports = {
+ meta: {
+ docs: {
+ description:
+ "disallow non-standard static properties on `Intl.DurationFormat` class",
+ category: "nonstandard",
+ recommended: false,
+ url: "http://eslint-community.github.io/eslint-plugin-es-x/rules/no-nonstandard-intl-durationformat-properties.html",
+ },
+ fixable: null,
+ messages: {
+ forbidden: "Non-standard '{{name}}' property is forbidden.",
+ },
+ schema: [
+ {
+ type: "object",
+ properties: {
+ allow: {
+ type: "array",
+ items: { type: "string" },
+ uniqueItems: true,
+ },
+ },
+ additionalProperties: false,
+ },
+ ],
+ type: "problem",
+ },
+ create(context) {
+ /** @type {Set} */
+ const allows = new Set([
+ ...(context.options[0]?.allow || []),
+ ...intlDurationFormatProperties,
+ ])
+ return defineNonstandardStaticPropertiesHandler(context, {
+ "Intl.DurationFormat": allows,
+ })
+ },
+}
diff --git a/lib/rules/no-nonstandard-intl-durationformat-prototype-properties.js b/lib/rules/no-nonstandard-intl-durationformat-prototype-properties.js
new file mode 100644
index 00000000..7769da6a
--- /dev/null
+++ b/lib/rules/no-nonstandard-intl-durationformat-prototype-properties.js
@@ -0,0 +1,48 @@
+"use strict"
+
+const {
+ defineNonstandardPrototypePropertiesHandler,
+} = require("../util/define-nonstandard-prototype-properties-handler")
+const {
+ intlDurationFormatPrototypeProperties,
+} = require("../util/well-known-properties")
+
+module.exports = {
+ meta: {
+ docs: {
+ description:
+ "disallow non-standard properties on Intl.DurationFormat instance",
+ category: "nonstandard",
+ recommended: false,
+ url: "http://eslint-community.github.io/eslint-plugin-es-x/rules/no-nonstandard-intl-durationformat-prototype-properties.html",
+ },
+ fixable: null,
+ messages: {
+ forbidden: "Non-standard '{{name}}' property is forbidden.",
+ },
+ schema: [
+ {
+ type: "object",
+ properties: {
+ allow: {
+ type: "array",
+ items: { type: "string" },
+ uniqueItems: true,
+ },
+ },
+ additionalProperties: false,
+ },
+ ],
+ type: "problem",
+ },
+ create(context) {
+ /** @type {Set} */
+ const allows = new Set([
+ ...(context.options[0]?.allow || []),
+ ...intlDurationFormatPrototypeProperties,
+ ])
+ return defineNonstandardPrototypePropertiesHandler(context, {
+ "Intl.DurationFormat": allows,
+ })
+ },
+}
diff --git a/lib/util/type-checker/es-types.js b/lib/util/type-checker/es-types.js
index 98cc05ee..bd1c293e 100644
--- a/lib/util/type-checker/es-types.js
+++ b/lib/util/type-checker/es-types.js
@@ -335,6 +335,11 @@ const WELLKNOWN_GLOBALS = {
return: { type: "Intl.DisplayNames" },
prototypeType: "Intl.DisplayNames",
},
+ DurationFormat: {
+ type: "Function",
+ return: { type: "Intl.DurationFormat" },
+ prototypeType: "Intl.DurationFormat",
+ },
Locale: {
type: "Function",
return: { type: "Intl.Locale" },
diff --git a/lib/util/type-checker/types.d.ts b/lib/util/type-checker/types.d.ts
index 151ac039..ed921be1 100644
--- a/lib/util/type-checker/types.d.ts
+++ b/lib/util/type-checker/types.d.ts
@@ -11,6 +11,7 @@ export type TypeName =
| "Intl.Segmenter"
| "Intl.DisplayNames"
| "Intl.Locale"
+ | "Intl.DurationFormat"
| "Promise"
| "RegExp"
| "String"
@@ -193,7 +194,7 @@ export type FinalizationRegistryPrototypeProperty = Exclude<
keyof FinalizationRegistry,
ExcludePrototypeProperty
>;
-export type IntlProperty = Exclude;
+export type IntlProperty = Exclude | 'DurationFormat';
export type IteratorProperty = Exclude;
export type IteratorPrototypeProperty = Exclude<
keyof IteratorObject,
diff --git a/lib/util/well-known-properties.js b/lib/util/well-known-properties.js
index 806d1752..c4e0db40 100644
--- a/lib/util/well-known-properties.js
+++ b/lib/util/well-known-properties.js
@@ -949,6 +949,7 @@ const intlProperties = new Set([
"Collator",
"DateTimeFormat",
"DisplayNames",
+ "DurationFormat",
"ListFormat",
"Locale",
"NumberFormat",
@@ -1022,6 +1023,26 @@ const intlDisplayNamesPrototypeProperties = new Set([
"resolvedOptions",
])
+const intlDurationFormatProperties = new Set([
+ ...objectPrototypeProperties,
+ ...functionPrototypeProperties,
+
+ // https://tc39.es/ecma402/#sec-properties-of-intl-durationformat-constructor
+ "prototype",
+ "supportedLocalesOf",
+])
+
+const intlDurationFormatPrototypeProperties = new Set([
+ ...objectPrototypeProperties,
+
+ // https://tc39.es/ecma402/#sec-properties-of-intl-durationformat-prototype-object
+ "constructor",
+ // [ %Symbol.toStringTag% ]
+ "format",
+ "formatToParts",
+ "resolvedOptions",
+])
+
const intlListFormatProperties = new Set([
...objectPrototypeProperties,
...functionPrototypeProperties,
@@ -1213,6 +1234,8 @@ module.exports = {
intlDateTimeFormatPrototypeProperties,
intlDisplayNamesProperties,
intlDisplayNamesPrototypeProperties,
+ intlDurationFormatProperties,
+ intlDurationFormatPrototypeProperties,
intlListFormatProperties,
intlListFormatPrototypeProperties,
intlLocaleProperties,
diff --git a/package.json b/package.json
index a79e151d..9fb10380 100644
--- a/package.json
+++ b/package.json
@@ -36,7 +36,7 @@
"opener": "^1.5.1",
"rimraf": "^6.0.0",
"semver": "^7.0.0",
- "typescript": "^5.6.3",
+ "typescript": "^5.7.2",
"vite-plugin-eslint4b": "^0.5.0",
"vitepress": "^1.0.0",
"vue-eslint-parser": "^9.0.0"
diff --git a/scripts/new-rule.js b/scripts/new-rule.js
index 86c0b7fc..9de241ba 100644
--- a/scripts/new-rule.js
+++ b/scripts/new-rule.js
@@ -7,14 +7,10 @@
const cp = require("child_process")
const fs = require("fs")
const path = require("path")
-const { categories } = require("./rules")
+const { LATEST_ES_YEAR } = require("./rules")
const logger = console
-const maxESVersion = Math.max(
- ...Object.keys(categories).map((esVersion) =>
- /^ES\d+$/u.test(esVersion) ? Number(esVersion.slice(2)) : 0,
- ),
-)
+const maxESVersion = LATEST_ES_YEAR + 1
// main
;((ruleId) => {
diff --git a/scripts/rules.js b/scripts/rules.js
index 090942da..978331f9 100644
--- a/scripts/rules.js
+++ b/scripts/rules.js
@@ -41,7 +41,7 @@ const LATEST_ES_YEAR = 2024
/** @type {Record} */
const categories = [
...(function* () {
- const max = new Date().getFullYear() + 1
+ const max = new Date().getFullYear() + 2
for (let year = max; year >= 2015; year--) {
yield year
}
@@ -195,4 +195,4 @@ const rules = []
}
})(libRoot)
-module.exports = { categories, rules }
+module.exports = { categories, rules, LATEST_ES_YEAR }
diff --git a/tests/fixtures/tsconfig.json b/tests/fixtures/tsconfig.json
index b843eb5a..2e6e7a54 100644
--- a/tests/fixtures/tsconfig.json
+++ b/tests/fixtures/tsconfig.json
@@ -3,5 +3,5 @@
"strict": true,
"lib": ["ESNext"]
},
- "include": ["test.ts"]
+ "include": ["test.ts", "types.d.ts"]
}
diff --git a/tests/fixtures/types.d.ts b/tests/fixtures/types.d.ts
new file mode 100644
index 00000000..b453fd87
--- /dev/null
+++ b/tests/fixtures/types.d.ts
@@ -0,0 +1,14 @@
+/* Since typescript doesn't define the types yet, we'll work around the issue by defining the types ourselves. */
+declare namespace Intl {
+ interface DurationFormat {
+ format(duration: any): any;
+ formatToParts(duration: any): any;
+ resolvedOptions(): any;
+ }
+
+ const DurationFormat: {
+ prototype: DurationFormat;
+ new (...args:any[]): DurationFormat;
+ supportedLocalesOf(...args:any[]): any;
+ };
+}
diff --git a/tests/lib/rules/no-intl-durationformat.js b/tests/lib/rules/no-intl-durationformat.js
new file mode 100644
index 00000000..5b845ced
--- /dev/null
+++ b/tests/lib/rules/no-intl-durationformat.js
@@ -0,0 +1,21 @@
+"use strict"
+
+const RuleTester = require("../../tester")
+const rule = require("../../../lib/rules/no-intl-durationformat")
+
+new RuleTester().run("no-intl-durationformat", rule, {
+ valid: [
+ "Intl",
+ "Intl.DateTimeFormat",
+ "Intl.NumberFormat",
+ "let Intl = 0; Intl.DurationFormat",
+ ],
+ invalid: [
+ {
+ code: "Intl.DurationFormat",
+ errors: [
+ "ES2025 Intl API 'Intl.DurationFormat' object is forbidden.",
+ ],
+ },
+ ],
+})
diff --git a/tests/lib/rules/no-nonstandard-intl-durationformat-properties.js b/tests/lib/rules/no-nonstandard-intl-durationformat-properties.js
new file mode 100644
index 00000000..099930a1
--- /dev/null
+++ b/tests/lib/rules/no-nonstandard-intl-durationformat-properties.js
@@ -0,0 +1,39 @@
+"use strict"
+
+const RuleTester = require("../../tester")
+const rule = require("../../../lib/rules/no-nonstandard-intl-durationformat-properties.js")
+const {
+ intlDurationFormatProperties,
+} = require("../../../lib/util/well-known-properties")
+
+new RuleTester().run("no-nonstandard-intl-durationformat-properties", rule, {
+ valid: [
+ ...[...intlDurationFormatProperties].map(
+ (p) => `Intl.DurationFormat.${p}`,
+ ),
+ {
+ code: "Intl.DurationFormat.unknown()",
+ options: [{ allow: ["unknown"] }],
+ },
+ ],
+ invalid: [
+ {
+ code: "Intl.DurationFormat.unknown()",
+ errors: [
+ "Non-standard 'Intl.DurationFormat.unknown' property is forbidden.",
+ ],
+ },
+ {
+ code: "Intl.DurationFormat.foo",
+ errors: [
+ "Non-standard 'Intl.DurationFormat.foo' property is forbidden.",
+ ],
+ },
+ {
+ code: "Intl.DurationFormat.bar",
+ errors: [
+ "Non-standard 'Intl.DurationFormat.bar' property is forbidden.",
+ ],
+ },
+ ],
+})
diff --git a/tests/lib/rules/no-nonstandard-intl-durationformat-prototype-properties.js b/tests/lib/rules/no-nonstandard-intl-durationformat-prototype-properties.js
new file mode 100644
index 00000000..cc804359
--- /dev/null
+++ b/tests/lib/rules/no-nonstandard-intl-durationformat-prototype-properties.js
@@ -0,0 +1,143 @@
+"use strict"
+
+const path = require("path")
+const RuleTester = require("../../tester")
+const rule = require("../../../lib/rules/no-nonstandard-intl-durationformat-prototype-properties.js")
+const {
+ intlDurationFormatPrototypeProperties,
+} = require("../../../lib/util/well-known-properties")
+const ruleId = "no-nonstandard-intl-durationformat-prototype-properties"
+
+new RuleTester().run(ruleId, rule, {
+ valid: [
+ "foo",
+ "foo.toString",
+ "foo.foo",
+ ...[...intlDurationFormatPrototypeProperties].map(
+ (p) => `new Intl.DurationFormat().${p}`,
+ ),
+ {
+ code: "new Intl.DurationFormat().unknown()",
+ options: [{ allow: ["unknown"] }],
+ },
+ ],
+ invalid: [
+ {
+ code: "new Intl.DurationFormat().unknown()",
+ errors: [
+ "Non-standard 'Intl.DurationFormat.prototype.unknown' property is forbidden.",
+ ],
+ },
+ {
+ code: "new Intl.DurationFormat().foo",
+ errors: [
+ "Non-standard 'Intl.DurationFormat.prototype.foo' property is forbidden.",
+ ],
+ },
+ {
+ code: "new Intl.DurationFormat().bar",
+ errors: [
+ "Non-standard 'Intl.DurationFormat.prototype.bar' property is forbidden.",
+ ],
+ },
+ {
+ code: "new Intl.DurationFormat()[0]",
+ errors: [
+ "Non-standard 'Intl.DurationFormat.prototype.0' property is forbidden.",
+ ],
+ },
+ {
+ code: "new Intl.DurationFormat()['0']",
+ errors: [
+ "Non-standard 'Intl.DurationFormat.prototype.0' property is forbidden.",
+ ],
+ },
+ {
+ code: "new Intl.DurationFormat()['01']",
+ errors: [
+ "Non-standard 'Intl.DurationFormat.prototype.01' property is forbidden.",
+ ],
+ },
+ ],
+})
+
+// -----------------------------------------------------------------------------
+// TypeScript
+// -----------------------------------------------------------------------------
+const parser = require("@typescript-eslint/parser")
+const tsconfigRootDir = path.resolve(__dirname, "../../fixtures")
+const project = "tsconfig.json"
+const filename = path.join(tsconfigRootDir, "test.ts")
+
+new RuleTester({
+ languageOptions: {
+ parser,
+ parserOptions: {
+ tsconfigRootDir,
+ project,
+ disallowAutomaticSingleRunInference: true,
+ },
+ },
+}).run(`${ruleId} TS Full Type Information`, rule, {
+ valid: [
+ { filename, code: "foo" },
+ { filename, code: "foo.toString" },
+ { filename, code: "foo.foo" },
+ { filename, code: "let foo = {}; foo.foo" },
+ ...[...intlDurationFormatPrototypeProperties].map((p) => ({
+ filename,
+ code: `new Intl.DurationFormat().${p}`,
+ })),
+ ],
+ invalid: [
+ {
+ filename,
+ code: "new Intl.DurationFormat().foo",
+ errors: [
+ "Non-standard 'Intl.DurationFormat.prototype.foo' property is forbidden.",
+ ],
+ },
+ {
+ filename,
+ code: "new Intl.DurationFormat().bar",
+ errors: [
+ "Non-standard 'Intl.DurationFormat.prototype.bar' property is forbidden.",
+ ],
+ },
+ {
+ filename,
+ code: "new Intl.DurationFormat()[0]",
+ errors: [
+ "Non-standard 'Intl.DurationFormat.prototype.0' property is forbidden.",
+ ],
+ },
+ {
+ filename,
+ code: "new Intl.DurationFormat()['0']",
+ errors: [
+ "Non-standard 'Intl.DurationFormat.prototype.0' property is forbidden.",
+ ],
+ },
+ {
+ filename,
+ code: "new Intl.DurationFormat()['01']",
+ errors: [
+ "Non-standard 'Intl.DurationFormat.prototype.01' property is forbidden.",
+ ],
+ },
+ {
+ filename,
+ code: "let foo = new Intl.DurationFormat(); foo.foo",
+ errors: [
+ "Non-standard 'Intl.DurationFormat.prototype.foo' property is forbidden.",
+ ],
+ },
+ {
+ filename,
+ code: "function f(a: T) { a.baz }",
+ errors: [
+ "Non-standard 'Intl.DurationFormat.prototype.baz' property is forbidden.",
+ ],
+ },
+ ],
+})