diff --git a/docs/configs/index.md b/docs/configs/index.md
index 0ab22bbf..f8fcc355 100644
--- a/docs/configs/index.md
+++ b/docs/configs/index.md
@@ -1029,6 +1029,34 @@ export default [
}
```
+## no-explicit-resource-management
+
+disallow proposal ES2026 [Explicit Resource Management](https://github.com/tc39/proposal-explicit-resource-management)\
+⚠️ This config will be changed in the minor versions of this plugin.
+
+This configs includes rules for [es-x/no-asyncdisposablestack](../rules/no-asyncdisposablestack.md), [es-x/no-disposablestack](../rules/no-disposablestack.md), [es-x/no-suppressederror](../rules/no-suppressederror.md), and [es-x/no-using-declarations](../rules/no-using-declarations.md).
+
+### [Config (Flat Config)]
+
+eslint.config.js:
+
+```js
+import pluginESx from "eslint-plugin-es-x"
+export default [
+ pluginESx.configs['flat/no-explicit-resource-management']
+]
+```
+
+### [Legacy Config]
+
+.eslintrc.*:
+
+```json
+{
+ "extends": ["plugin:es-x/no-explicit-resource-management"],
+}
+```
+
## no-float16array
disallow proposal ES2025 [Float16Array](https://github.com/tc39/proposal-float16array)\
diff --git a/docs/rules/index.md b/docs/rules/index.md
index 6ed80c73..e66db543 100644
--- a/docs/rules/index.md
+++ b/docs/rules/index.md
@@ -11,7 +11,11 @@ There is a config that enables the rules in this category: [`no-new-in-esnext`]
| Rule ID | Description | |
|:--------|:------------|:--:|
| [es-x/no-array-fromasync](./no-array-fromasync.md) | disallow the `Array.fromAsync` method. | |
+| [es-x/no-asyncdisposablestack](./no-asyncdisposablestack.md) | disallow the `AsyncDisposableStack` class. | |
+| [es-x/no-disposablestack](./no-disposablestack.md) | disallow the `DisposableStack` class. | |
| [es-x/no-error-iserror](./no-error-iserror.md) | disallow the `Error.isError` method. | |
+| [es-x/no-suppressederror](./no-suppressederror.md) | disallow the `SuppressedError` class. | |
+| [es-x/no-using-declarations](./no-using-declarations.md) | disallow `using` and `await using` declarations. | |
## ES2025
@@ -409,6 +413,8 @@ Rules in this category are not included in any preset.
| [es-x/no-nonstandard-array-prototype-properties](./no-nonstandard-array-prototype-properties.md) | disallow non-standard properties on Array instance. | |
| [es-x/no-nonstandard-arraybuffer-properties](./no-nonstandard-arraybuffer-properties.md) | disallow non-standard static properties on `ArrayBuffer` class. | |
| [es-x/no-nonstandard-arraybuffer-prototype-properties](./no-nonstandard-arraybuffer-prototype-properties.md) | disallow non-standard properties on ArrayBuffer instance. | |
+| [es-x/no-nonstandard-asyncdisposablestack-properties](./no-nonstandard-asyncdisposablestack-properties.md) | disallow non-standard static properties on `AsyncDisposableStack` class. | |
+| [es-x/no-nonstandard-asyncdisposablestack-prototype-properties](./no-nonstandard-asyncdisposablestack-prototype-properties.md) | disallow non-standard properties on AsyncDisposableStack instance. | |
| [es-x/no-nonstandard-atomics-properties](./no-nonstandard-atomics-properties.md) | disallow non-standard static properties on `Atomics`. | |
| [es-x/no-nonstandard-bigint-properties](./no-nonstandard-bigint-properties.md) | disallow non-standard static properties on `BigInt` class. | |
| [es-x/no-nonstandard-bigint-prototype-properties](./no-nonstandard-bigint-prototype-properties.md) | disallow non-standard properties on BigInt instance. | |
@@ -418,6 +424,8 @@ Rules in this category are not included in any preset.
| [es-x/no-nonstandard-dataview-prototype-properties](./no-nonstandard-dataview-prototype-properties.md) | disallow non-standard properties on DataView instance. | |
| [es-x/no-nonstandard-date-properties](./no-nonstandard-date-properties.md) | disallow non-standard static properties on `Date` class. | |
| [es-x/no-nonstandard-date-prototype-properties](./no-nonstandard-date-prototype-properties.md) | disallow non-standard properties on Date instance. | |
+| [es-x/no-nonstandard-disposablestack-properties](./no-nonstandard-disposablestack-properties.md) | disallow non-standard static properties on `DisposableStack` class. | |
+| [es-x/no-nonstandard-disposablestack-prototype-properties](./no-nonstandard-disposablestack-prototype-properties.md) | disallow non-standard properties on DisposableStack instance. | |
| [es-x/no-nonstandard-error-properties](./no-nonstandard-error-properties.md) | disallow non-standard static properties on `Error` class. | |
| [es-x/no-nonstandard-finalizationregistry-properties](./no-nonstandard-finalizationregistry-properties.md) | disallow non-standard static properties on `FinalizationRegistry` class. | |
| [es-x/no-nonstandard-finalizationregistry-prototype-properties](./no-nonstandard-finalizationregistry-prototype-properties.md) | disallow non-standard properties on FinalizationRegistry instance. | |
diff --git a/docs/rules/no-asyncdisposablestack.md b/docs/rules/no-asyncdisposablestack.md
new file mode 100644
index 00000000..60e9d93f
--- /dev/null
+++ b/docs/rules/no-asyncdisposablestack.md
@@ -0,0 +1,33 @@
+---
+title: "es-x/no-asyncdisposablestack"
+description: "disallow the `AsyncDisposableStack` class"
+---
+
+# es-x/no-asyncdisposablestack
+> disallow the `AsyncDisposableStack` class
+
+- ❗ ***This rule has not been released yet.***
+- ✅ The following configurations enable this rule: [no-explicit-resource-management] and [no-new-in-esnext]
+
+This rule reports ES2026 [`AsyncDisposableStack` class](https://github.com/tc39/proposal-explicit-resource-management) as errors.
+
+## 💡 Examples
+
+⛔ Examples of **incorrect** code for this rule:
+
+
+
+```js
+/*eslint es-x/no-asyncdisposablestack: error */
+let asyncdisposablestack = new AsyncDisposableStack()
+```
+
+
+
+## 📚 References
+
+- [Rule source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/lib/rules/no-asyncdisposablestack.js)
+- [Test source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/tests/lib/rules/no-asyncdisposablestack.js)
+
+[no-explicit-resource-management]: ../configs/index.md#no-explicit-resource-management
+[no-new-in-esnext]: ../configs/index.md#no-new-in-esnext
diff --git a/docs/rules/no-disposablestack.md b/docs/rules/no-disposablestack.md
new file mode 100644
index 00000000..3a048d0a
--- /dev/null
+++ b/docs/rules/no-disposablestack.md
@@ -0,0 +1,33 @@
+---
+title: "es-x/no-disposablestack"
+description: "disallow the `DisposableStack` class"
+---
+
+# es-x/no-disposablestack
+> disallow the `DisposableStack` class
+
+- ❗ ***This rule has not been released yet.***
+- ✅ The following configurations enable this rule: [no-explicit-resource-management] and [no-new-in-esnext]
+
+This rule reports ES2026 [`DisposableStack` class](https://github.com/tc39/proposal-explicit-resource-management) as errors.
+
+## 💡 Examples
+
+⛔ Examples of **incorrect** code for this rule:
+
+
+
+```js
+/*eslint es-x/no-disposablestack: error */
+let disposablestack = new DisposableStack()
+```
+
+
+
+## 📚 References
+
+- [Rule source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/lib/rules/no-disposablestack.js)
+- [Test source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/tests/lib/rules/no-disposablestack.js)
+
+[no-explicit-resource-management]: ../configs/index.md#no-explicit-resource-management
+[no-new-in-esnext]: ../configs/index.md#no-new-in-esnext
diff --git a/docs/rules/no-nonstandard-asyncdisposablestack-properties.md b/docs/rules/no-nonstandard-asyncdisposablestack-properties.md
new file mode 100644
index 00000000..2f4bdb09
--- /dev/null
+++ b/docs/rules/no-nonstandard-asyncdisposablestack-properties.md
@@ -0,0 +1,56 @@
+---
+title: "es-x/no-nonstandard-asyncdisposablestack-properties"
+description: "disallow non-standard static properties on `AsyncDisposableStack` class"
+---
+
+# es-x/no-nonstandard-asyncdisposablestack-properties
+> disallow non-standard static properties on `AsyncDisposableStack` class
+
+- ❗ ***This rule has not been released yet.***
+
+This rule reports non-standard static properties on `AsyncDisposableStack` class as errors.
+
+## 💡 Examples
+
+⛔ Examples of **incorrect** code for this rule:
+
+
+
+```js
+/*eslint es-x/no-nonstandard-asyncdisposablestack-properties: error */
+AsyncDisposableStack.unknown();
+```
+
+
+
+## 🔧 Options
+
+This rule has an option.
+
+```jsonc
+{
+ "rules": {
+ "es-x/no-nonstandard-asyncdisposablestack-properties": [
+ "error",
+ {
+ "allow": [],
+ "allowTestedProperty": false
+ }
+ ]
+ }
+}
+```
+
+### allow: string[]
+
+An array of non-standard property names to allow.
+
+### allowTestedProperty: boolean
+
+Configure the allowTestedProperty mode for only this rule.
+This is prior to the `settings['es-x'].allowTestedProperty` setting.
+
+## 📚 References
+
+- [Rule source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/lib/rules/no-nonstandard-asyncdisposablestack-properties.js)
+- [Test source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/tests/lib/rules/no-nonstandard-asyncdisposablestack-properties.js)
diff --git a/docs/rules/no-nonstandard-asyncdisposablestack-prototype-properties.md b/docs/rules/no-nonstandard-asyncdisposablestack-prototype-properties.md
new file mode 100644
index 00000000..d8767688
--- /dev/null
+++ b/docs/rules/no-nonstandard-asyncdisposablestack-prototype-properties.md
@@ -0,0 +1,57 @@
+---
+title: "es-x/no-nonstandard-asyncdisposablestack-prototype-properties"
+description: "disallow non-standard properties on AsyncDisposableStack instance"
+---
+
+# es-x/no-nonstandard-asyncdisposablestack-prototype-properties
+> disallow non-standard properties on AsyncDisposableStack instance
+
+- ❗ ***This rule has not been released yet.***
+
+This rule reports non-standard properties on AsyncDisposableStack instance as errors.
+
+## 💡 Examples
+
+⛔ Examples of **incorrect** code for this rule:
+
+
+
+```js
+/*eslint es-x/no-nonstandard-asyncdisposablestack-prototype-properties: error */
+const foo = new AsyncDisposableStack();
+foo.unknown();
+```
+
+
+
+## 🔧 Options
+
+This rule has an option.
+
+```jsonc
+{
+ "rules": {
+ "es-x/no-nonstandard-asyncdisposablestack-prototype-properties": [
+ "error",
+ {
+ "allow": [],
+ "allowTestedProperty": false
+ }
+ ]
+ }
+}
+```
+
+### allow: string[]
+
+An array of non-standard property names to allow.
+
+### allowTestedProperty: boolean
+
+Configure the allowTestedProperty mode for only this rule.
+This is prior to the `settings['es-x'].allowTestedProperty` setting.
+
+## 📚 References
+
+- [Rule source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/lib/rules/no-nonstandard-asyncdisposablestack-prototype-properties.js)
+- [Test source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/tests/lib/rules/no-nonstandard-asyncdisposablestack-prototype-properties.js)
diff --git a/docs/rules/no-nonstandard-disposablestack-properties.md b/docs/rules/no-nonstandard-disposablestack-properties.md
new file mode 100644
index 00000000..ca21a2a4
--- /dev/null
+++ b/docs/rules/no-nonstandard-disposablestack-properties.md
@@ -0,0 +1,56 @@
+---
+title: "es-x/no-nonstandard-disposablestack-properties"
+description: "disallow non-standard static properties on `DisposableStack` class"
+---
+
+# es-x/no-nonstandard-disposablestack-properties
+> disallow non-standard static properties on `DisposableStack` class
+
+- ❗ ***This rule has not been released yet.***
+
+This rule reports non-standard static properties on `DisposableStack` class as errors.
+
+## 💡 Examples
+
+⛔ Examples of **incorrect** code for this rule:
+
+
+
+```js
+/*eslint es-x/no-nonstandard-disposablestack-properties: error */
+DisposableStack.unknown();
+```
+
+
+
+## 🔧 Options
+
+This rule has an option.
+
+```jsonc
+{
+ "rules": {
+ "es-x/no-nonstandard-disposablestack-properties": [
+ "error",
+ {
+ "allow": [],
+ "allowTestedProperty": false
+ }
+ ]
+ }
+}
+```
+
+### allow: string[]
+
+An array of non-standard property names to allow.
+
+### allowTestedProperty: boolean
+
+Configure the allowTestedProperty mode for only this rule.
+This is prior to the `settings['es-x'].allowTestedProperty` setting.
+
+## 📚 References
+
+- [Rule source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/lib/rules/no-nonstandard-disposablestack-properties.js)
+- [Test source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/tests/lib/rules/no-nonstandard-disposablestack-properties.js)
diff --git a/docs/rules/no-nonstandard-disposablestack-prototype-properties.md b/docs/rules/no-nonstandard-disposablestack-prototype-properties.md
new file mode 100644
index 00000000..a4c0cee7
--- /dev/null
+++ b/docs/rules/no-nonstandard-disposablestack-prototype-properties.md
@@ -0,0 +1,57 @@
+---
+title: "es-x/no-nonstandard-disposablestack-prototype-properties"
+description: "disallow non-standard properties on DisposableStack instance"
+---
+
+# es-x/no-nonstandard-disposablestack-prototype-properties
+> disallow non-standard properties on DisposableStack instance
+
+- ❗ ***This rule has not been released yet.***
+
+This rule reports non-standard properties on DisposableStack instance as errors.
+
+## 💡 Examples
+
+⛔ Examples of **incorrect** code for this rule:
+
+
+
+```js
+/*eslint es-x/no-nonstandard-disposablestack-prototype-properties: error */
+const foo = new DisposableStack();
+foo.unknown();
+```
+
+
+
+## 🔧 Options
+
+This rule has an option.
+
+```jsonc
+{
+ "rules": {
+ "es-x/no-nonstandard-disposablestack-prototype-properties": [
+ "error",
+ {
+ "allow": [],
+ "allowTestedProperty": false
+ }
+ ]
+ }
+}
+```
+
+### allow: string[]
+
+An array of non-standard property names to allow.
+
+### allowTestedProperty: boolean
+
+Configure the allowTestedProperty mode for only this rule.
+This is prior to the `settings['es-x'].allowTestedProperty` setting.
+
+## 📚 References
+
+- [Rule source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/lib/rules/no-nonstandard-disposablestack-prototype-properties.js)
+- [Test source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/tests/lib/rules/no-nonstandard-disposablestack-prototype-properties.js)
diff --git a/docs/rules/no-suppressederror.md b/docs/rules/no-suppressederror.md
new file mode 100644
index 00000000..7b3e2b15
--- /dev/null
+++ b/docs/rules/no-suppressederror.md
@@ -0,0 +1,33 @@
+---
+title: "es-x/no-suppressederror"
+description: "disallow the `SuppressedError` class"
+---
+
+# es-x/no-suppressederror
+> disallow the `SuppressedError` class
+
+- ❗ ***This rule has not been released yet.***
+- ✅ The following configurations enable this rule: [no-explicit-resource-management] and [no-new-in-esnext]
+
+This rule reports ES2026 [`SuppressedError` class](https://github.com/tc39/proposal-explicit-resource-management) as errors.
+
+## 💡 Examples
+
+⛔ Examples of **incorrect** code for this rule:
+
+
+
+```js
+/*eslint es-x/no-suppressederror: error */
+let suppressederror = new SuppressedError()
+```
+
+
+
+## 📚 References
+
+- [Rule source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/lib/rules/no-suppressederror.js)
+- [Test source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/tests/lib/rules/no-suppressederror.js)
+
+[no-explicit-resource-management]: ../configs/index.md#no-explicit-resource-management
+[no-new-in-esnext]: ../configs/index.md#no-new-in-esnext
diff --git a/docs/rules/no-using-declarations.md b/docs/rules/no-using-declarations.md
new file mode 100644
index 00000000..0724664c
--- /dev/null
+++ b/docs/rules/no-using-declarations.md
@@ -0,0 +1,43 @@
+---
+title: "es-x/no-using-declarations"
+description: "disallow `using` and `await using` declarations"
+---
+
+# es-x/no-using-declarations
+> disallow `using` and `await using` declarations
+
+- ❗ ***This rule has not been released yet.***
+- ✅ The following configurations enable this rule: [no-explicit-resource-management] and [no-new-in-esnext]
+
+This rule reports ES2026 [`using` and `await using` declarations](https://github.com/tc39/proposal-explicit-resource-management) as errors.
+
+## 💡 Examples
+
+⛔ Examples of **incorrect** code for this rule:
+
+
+
+```js
+/*eslint es-x/no-using-declarations: error */
+
+// async disposal
+async function * g() {
+ using stream = acquireStream(); // block-scoped critical resource
+ // ...
+} // cleanup
+
+{
+ await using obj = g(); // block-scoped declaration
+ const r = await obj.next();
+} // calls finally blocks in `g`
+```
+
+
+
+## 📚 References
+
+- [Rule source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/lib/rules/no-using-declarations.js)
+- [Test source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/tests/lib/rules/no-using-declarations.js)
+
+[no-explicit-resource-management]: ../configs/index.md#no-explicit-resource-management
+[no-new-in-esnext]: ../configs/index.md#no-new-in-esnext
diff --git a/lib/configs/flat/no-explicit-resource-management.js b/lib/configs/flat/no-explicit-resource-management.js
new file mode 100644
index 00000000..8a77e01c
--- /dev/null
+++ b/lib/configs/flat/no-explicit-resource-management.js
@@ -0,0 +1,19 @@
+/**
+ * DON'T EDIT THIS FILE.
+ * This file was generated by "scripts/update-lib-flat-configs.js" script.
+ */
+"use strict"
+
+module.exports = {
+ plugins: {
+ get "es-x"() {
+ return require("../../index.js")
+ },
+ },
+ rules: {
+ "es-x/no-asyncdisposablestack": "error",
+ "es-x/no-disposablestack": "error",
+ "es-x/no-suppressederror": "error",
+ "es-x/no-using-declarations": "error",
+ },
+}
diff --git a/lib/configs/flat/no-new-in-esnext.js b/lib/configs/flat/no-new-in-esnext.js
index 28cfbc96..0788279e 100644
--- a/lib/configs/flat/no-new-in-esnext.js
+++ b/lib/configs/flat/no-new-in-esnext.js
@@ -12,7 +12,11 @@ module.exports = {
},
rules: {
"es-x/no-array-fromasync": "error",
+ "es-x/no-asyncdisposablestack": "error",
+ "es-x/no-disposablestack": "error",
"es-x/no-error-iserror": "error",
+ "es-x/no-suppressederror": "error",
+ "es-x/no-using-declarations": "error",
"es-x/no-dataview-prototype-getfloat16-setfloat16": "error",
"es-x/no-dynamic-import-options": "error",
"es-x/no-float16array": "error",
diff --git a/lib/configs/no-explicit-resource-management.js b/lib/configs/no-explicit-resource-management.js
new file mode 100644
index 00000000..7e3ee511
--- /dev/null
+++ b/lib/configs/no-explicit-resource-management.js
@@ -0,0 +1,15 @@
+/**
+ * DON'T EDIT THIS FILE.
+ * This file was generated by "scripts/update-lib-configs.js" script.
+ */
+"use strict"
+
+module.exports = {
+ plugins: ["es-x"],
+ rules: {
+ "es-x/no-asyncdisposablestack": "error",
+ "es-x/no-disposablestack": "error",
+ "es-x/no-suppressederror": "error",
+ "es-x/no-using-declarations": "error",
+ },
+}
diff --git a/lib/configs/no-new-in-esnext.js b/lib/configs/no-new-in-esnext.js
index 0fcfcc43..843a36cf 100644
--- a/lib/configs/no-new-in-esnext.js
+++ b/lib/configs/no-new-in-esnext.js
@@ -8,7 +8,11 @@ module.exports = {
plugins: ["es-x"],
rules: {
"es-x/no-array-fromasync": "error",
+ "es-x/no-asyncdisposablestack": "error",
+ "es-x/no-disposablestack": "error",
"es-x/no-error-iserror": "error",
+ "es-x/no-suppressederror": "error",
+ "es-x/no-using-declarations": "error",
"es-x/no-dataview-prototype-getfloat16-setfloat16": "error",
"es-x/no-dynamic-import-options": "error",
"es-x/no-float16array": "error",
diff --git a/lib/index.js b/lib/index.js
index 70df62d5..a2f2c106 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -13,6 +13,7 @@ module.exports = {
"flat/no-array-grouping": require("./configs/flat/no-array-grouping"),
"flat/no-change-array-by-copy": require("./configs/flat/no-change-array-by-copy"),
"flat/no-class-fields": require("./configs/flat/no-class-fields"),
+ "flat/no-explicit-resource-management": require("./configs/flat/no-explicit-resource-management"),
"flat/no-float16array": require("./configs/flat/no-float16array"),
"flat/no-import-attributes": require("./configs/flat/no-import-attributes"),
"flat/no-intl-numberformat-v3": require("./configs/flat/no-intl-numberformat-v3"),
@@ -67,6 +68,7 @@ module.exports = {
"no-array-grouping": require("./configs/no-array-grouping"),
"no-change-array-by-copy": require("./configs/no-change-array-by-copy"),
"no-class-fields": require("./configs/no-class-fields"),
+ "no-explicit-resource-management": require("./configs/no-explicit-resource-management"),
"no-float16array": require("./configs/no-float16array"),
"no-import-attributes": require("./configs/no-import-attributes"),
"no-intl-numberformat-v3": require("./configs/no-intl-numberformat-v3"),
@@ -179,6 +181,7 @@ module.exports = {
"no-arrow-functions": require("./rules/no-arrow-functions"),
"no-async-functions": require("./rules/no-async-functions"),
"no-async-iteration": require("./rules/no-async-iteration"),
+ "no-asyncdisposablestack": require("./rules/no-asyncdisposablestack"),
"no-atomics": require("./rules/no-atomics"),
"no-atomics-waitasync": require("./rules/no-atomics-waitasync"),
"no-bigint": require("./rules/no-bigint"),
@@ -199,6 +202,7 @@ module.exports = {
"no-date-prototype-togmtstring": require("./rules/no-date-prototype-togmtstring"),
"no-default-parameters": require("./rules/no-default-parameters"),
"no-destructuring": require("./rules/no-destructuring"),
+ "no-disposablestack": require("./rules/no-disposablestack"),
"no-dynamic-import": require("./rules/no-dynamic-import"),
"no-dynamic-import-options": require("./rules/no-dynamic-import-options"),
"no-error-cause": require("./rules/no-error-cause"),
@@ -277,6 +281,8 @@ module.exports = {
"no-nonstandard-array-prototype-properties": require("./rules/no-nonstandard-array-prototype-properties"),
"no-nonstandard-arraybuffer-properties": require("./rules/no-nonstandard-arraybuffer-properties"),
"no-nonstandard-arraybuffer-prototype-properties": require("./rules/no-nonstandard-arraybuffer-prototype-properties"),
+ "no-nonstandard-asyncdisposablestack-properties": require("./rules/no-nonstandard-asyncdisposablestack-properties"),
+ "no-nonstandard-asyncdisposablestack-prototype-properties": require("./rules/no-nonstandard-asyncdisposablestack-prototype-properties"),
"no-nonstandard-atomics-properties": require("./rules/no-nonstandard-atomics-properties"),
"no-nonstandard-bigint-properties": require("./rules/no-nonstandard-bigint-properties"),
"no-nonstandard-bigint-prototype-properties": require("./rules/no-nonstandard-bigint-prototype-properties"),
@@ -286,6 +292,8 @@ module.exports = {
"no-nonstandard-dataview-prototype-properties": require("./rules/no-nonstandard-dataview-prototype-properties"),
"no-nonstandard-date-properties": require("./rules/no-nonstandard-date-properties"),
"no-nonstandard-date-prototype-properties": require("./rules/no-nonstandard-date-prototype-properties"),
+ "no-nonstandard-disposablestack-properties": require("./rules/no-nonstandard-disposablestack-properties"),
+ "no-nonstandard-disposablestack-prototype-properties": require("./rules/no-nonstandard-disposablestack-prototype-properties"),
"no-nonstandard-error-properties": require("./rules/no-nonstandard-error-properties"),
"no-nonstandard-finalizationregistry-properties": require("./rules/no-nonstandard-finalizationregistry-properties"),
"no-nonstandard-finalizationregistry-prototype-properties": require("./rules/no-nonstandard-finalizationregistry-prototype-properties"),
@@ -444,6 +452,7 @@ module.exports = {
"no-string-prototype-trimstart-trimend": require("./rules/no-string-prototype-trimstart-trimend"),
"no-string-raw": require("./rules/no-string-raw"),
"no-subclassing-builtins": require("./rules/no-subclassing-builtins"),
+ "no-suppressederror": require("./rules/no-suppressederror"),
"no-symbol": require("./rules/no-symbol"),
"no-symbol-prototype-description": require("./rules/no-symbol-prototype-description"),
"no-template-literals": require("./rules/no-template-literals"),
@@ -453,6 +462,7 @@ module.exports = {
"no-trailing-function-commas": require("./rules/no-trailing-function-commas"),
"no-typed-arrays": require("./rules/no-typed-arrays"),
"no-unicode-codepoint-escapes": require("./rules/no-unicode-codepoint-escapes"),
+ "no-using-declarations": require("./rules/no-using-declarations"),
"no-weak-map": require("./rules/no-weak-map"),
"no-weak-set": require("./rules/no-weak-set"),
"no-weakrefs": require("./rules/no-weakrefs"),
diff --git a/lib/rules/no-asyncdisposablestack.js b/lib/rules/no-asyncdisposablestack.js
new file mode 100644
index 00000000..649262c8
--- /dev/null
+++ b/lib/rules/no-asyncdisposablestack.js
@@ -0,0 +1,24 @@
+"use strict"
+
+const { defineGlobalsHandler } = require("../util/define-globals-handler")
+
+module.exports = {
+ meta: {
+ docs: {
+ description: "disallow the `AsyncDisposableStack` class.",
+ category: "ES2026",
+ proposal: "explicit-resource-management",
+ recommended: false,
+ url: "http://eslint-community.github.io/eslint-plugin-es-x/rules/no-asyncdisposablestack.html",
+ },
+ fixable: null,
+ messages: {
+ forbidden: "ES2026 '{{name}}' class is forbidden.",
+ },
+ schema: [],
+ type: "problem",
+ },
+ create(context) {
+ return defineGlobalsHandler(context, ["AsyncDisposableStack"])
+ },
+}
diff --git a/lib/rules/no-disposablestack.js b/lib/rules/no-disposablestack.js
new file mode 100644
index 00000000..e9371607
--- /dev/null
+++ b/lib/rules/no-disposablestack.js
@@ -0,0 +1,24 @@
+"use strict"
+
+const { defineGlobalsHandler } = require("../util/define-globals-handler")
+
+module.exports = {
+ meta: {
+ docs: {
+ description: "disallow the `DisposableStack` class.",
+ category: "ES2026",
+ proposal: "explicit-resource-management",
+ recommended: false,
+ url: "http://eslint-community.github.io/eslint-plugin-es-x/rules/no-disposablestack.html",
+ },
+ fixable: null,
+ messages: {
+ forbidden: "ES2026 '{{name}}' class is forbidden.",
+ },
+ schema: [],
+ type: "problem",
+ },
+ create(context) {
+ return defineGlobalsHandler(context, ["DisposableStack"])
+ },
+}
diff --git a/lib/rules/no-nonstandard-asyncdisposablestack-properties.js b/lib/rules/no-nonstandard-asyncdisposablestack-properties.js
new file mode 100644
index 00000000..085cb2df
--- /dev/null
+++ b/lib/rules/no-nonstandard-asyncdisposablestack-properties.js
@@ -0,0 +1,49 @@
+"use strict"
+
+const {
+ defineNonstandardStaticPropertiesHandler,
+} = require("../util/define-nonstandard-static-properties-handler")
+const {
+ asyncDisposableStackProperties,
+} = require("../util/well-known-properties")
+
+module.exports = {
+ meta: {
+ docs: {
+ description:
+ "disallow non-standard static properties on `AsyncDisposableStack` class",
+ category: "nonstandard",
+ recommended: false,
+ url: "http://eslint-community.github.io/eslint-plugin-es-x/rules/no-nonstandard-asyncdisposablestack-properties.html",
+ },
+ fixable: null,
+ messages: {
+ forbidden: "Non-standard '{{name}}' property is forbidden.",
+ },
+ schema: [
+ {
+ type: "object",
+ properties: {
+ allow: {
+ type: "array",
+ items: { type: "string" },
+ uniqueItems: true,
+ },
+ allowTestedProperty: { type: "boolean" },
+ },
+ additionalProperties: false,
+ },
+ ],
+ type: "problem",
+ },
+ create(context) {
+ /** @type {Set} */
+ const allows = new Set([
+ ...(context.options[0]?.allow || []),
+ ...asyncDisposableStackProperties,
+ ])
+ return defineNonstandardStaticPropertiesHandler(context, {
+ AsyncDisposableStack: allows,
+ })
+ },
+}
diff --git a/lib/rules/no-nonstandard-asyncdisposablestack-prototype-properties.js b/lib/rules/no-nonstandard-asyncdisposablestack-prototype-properties.js
new file mode 100644
index 00000000..c37c6fc1
--- /dev/null
+++ b/lib/rules/no-nonstandard-asyncdisposablestack-prototype-properties.js
@@ -0,0 +1,49 @@
+"use strict"
+
+const {
+ defineNonstandardPrototypePropertiesHandler,
+} = require("../util/define-nonstandard-prototype-properties-handler")
+const {
+ asyncDisposableStackPrototypeProperties,
+} = require("../util/well-known-properties")
+
+module.exports = {
+ meta: {
+ docs: {
+ description:
+ "disallow non-standard properties on AsyncDisposableStack instance",
+ category: "nonstandard",
+ recommended: false,
+ url: "http://eslint-community.github.io/eslint-plugin-es-x/rules/no-nonstandard-asyncdisposablestack-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,
+ },
+ allowTestedProperty: { type: "boolean" },
+ },
+ additionalProperties: false,
+ },
+ ],
+ type: "problem",
+ },
+ create(context) {
+ /** @type {Set} */
+ const allows = new Set([
+ ...(context.options[0]?.allow || []),
+ ...asyncDisposableStackPrototypeProperties,
+ ])
+ return defineNonstandardPrototypePropertiesHandler(context, {
+ AsyncDisposableStack: allows,
+ })
+ },
+}
diff --git a/lib/rules/no-nonstandard-disposablestack-properties.js b/lib/rules/no-nonstandard-disposablestack-properties.js
new file mode 100644
index 00000000..ee9b1464
--- /dev/null
+++ b/lib/rules/no-nonstandard-disposablestack-properties.js
@@ -0,0 +1,47 @@
+"use strict"
+
+const {
+ defineNonstandardStaticPropertiesHandler,
+} = require("../util/define-nonstandard-static-properties-handler")
+const { disposableStackProperties } = require("../util/well-known-properties")
+
+module.exports = {
+ meta: {
+ docs: {
+ description:
+ "disallow non-standard static properties on `DisposableStack` class",
+ category: "nonstandard",
+ recommended: false,
+ url: "http://eslint-community.github.io/eslint-plugin-es-x/rules/no-nonstandard-disposablestack-properties.html",
+ },
+ fixable: null,
+ messages: {
+ forbidden: "Non-standard '{{name}}' property is forbidden.",
+ },
+ schema: [
+ {
+ type: "object",
+ properties: {
+ allow: {
+ type: "array",
+ items: { type: "string" },
+ uniqueItems: true,
+ },
+ allowTestedProperty: { type: "boolean" },
+ },
+ additionalProperties: false,
+ },
+ ],
+ type: "problem",
+ },
+ create(context) {
+ /** @type {Set} */
+ const allows = new Set([
+ ...(context.options[0]?.allow || []),
+ ...disposableStackProperties,
+ ])
+ return defineNonstandardStaticPropertiesHandler(context, {
+ DisposableStack: allows,
+ })
+ },
+}
diff --git a/lib/rules/no-nonstandard-disposablestack-prototype-properties.js b/lib/rules/no-nonstandard-disposablestack-prototype-properties.js
new file mode 100644
index 00000000..a1b72323
--- /dev/null
+++ b/lib/rules/no-nonstandard-disposablestack-prototype-properties.js
@@ -0,0 +1,49 @@
+"use strict"
+
+const {
+ defineNonstandardPrototypePropertiesHandler,
+} = require("../util/define-nonstandard-prototype-properties-handler")
+const {
+ disposableStackPrototypeProperties,
+} = require("../util/well-known-properties")
+
+module.exports = {
+ meta: {
+ docs: {
+ description:
+ "disallow non-standard properties on DisposableStack instance",
+ category: "nonstandard",
+ recommended: false,
+ url: "http://eslint-community.github.io/eslint-plugin-es-x/rules/no-nonstandard-disposablestack-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,
+ },
+ allowTestedProperty: { type: "boolean" },
+ },
+ additionalProperties: false,
+ },
+ ],
+ type: "problem",
+ },
+ create(context) {
+ /** @type {Set} */
+ const allows = new Set([
+ ...(context.options[0]?.allow || []),
+ ...disposableStackPrototypeProperties,
+ ])
+ return defineNonstandardPrototypePropertiesHandler(context, {
+ DisposableStack: allows,
+ })
+ },
+}
diff --git a/lib/rules/no-suppressederror.js b/lib/rules/no-suppressederror.js
new file mode 100644
index 00000000..5da34f79
--- /dev/null
+++ b/lib/rules/no-suppressederror.js
@@ -0,0 +1,24 @@
+"use strict"
+
+const { defineGlobalsHandler } = require("../util/define-globals-handler")
+
+module.exports = {
+ meta: {
+ docs: {
+ description: "disallow the `SuppressedError` class.",
+ category: "ES2026",
+ proposal: "explicit-resource-management",
+ recommended: false,
+ url: "http://eslint-community.github.io/eslint-plugin-es-x/rules/no-suppressederror.html",
+ },
+ fixable: null,
+ messages: {
+ forbidden: "ES2026 '{{name}}' class is forbidden.",
+ },
+ schema: [],
+ type: "problem",
+ },
+ create(context) {
+ return defineGlobalsHandler(context, ["SuppressedError"])
+ },
+}
diff --git a/lib/rules/no-using-declarations.js b/lib/rules/no-using-declarations.js
new file mode 100644
index 00000000..4e2ecfae
--- /dev/null
+++ b/lib/rules/no-using-declarations.js
@@ -0,0 +1,34 @@
+"use strict"
+
+module.exports = {
+ meta: {
+ docs: {
+ description: "disallow `using` and `await using` declarations",
+ category: "ES2026",
+ proposal: "explicit-resource-management",
+ recommended: false,
+ url: "http://eslint-community.github.io/eslint-plugin-es-x/rules/no-using-declarations.html",
+ },
+ fixable: null,
+ messages: {
+ forbidden: "ES2026 '{{kind}}' declarations are forbidden.",
+ },
+ schema: [],
+ type: "problem",
+ },
+ create(context) {
+ return {
+ VariableDeclaration(node) {
+ if (node.kind === "using" || node.kind === "await using") {
+ context.report({
+ node,
+ messageId: "forbidden",
+ data: {
+ kind: node.kind,
+ },
+ })
+ }
+ },
+ }
+ },
+}
diff --git a/lib/util/type-checker/es-types.js b/lib/util/type-checker/es-types.js
index 392b3f63..610576fd 100644
--- a/lib/util/type-checker/es-types.js
+++ b/lib/util/type-checker/es-types.js
@@ -367,6 +367,20 @@ const WELLKNOWN_GLOBALS = {
from: { type: "Function", return: { type: "Iterator" } },
},
},
+ DisposableStack: {
+ type: "Function",
+ return: { type: "DisposableStack" },
+ prototypeType: "DisposableStack",
+ /** @type {Record} */
+ properties: {},
+ },
+ AsyncDisposableStack: {
+ type: "Function",
+ return: { type: "AsyncDisposableStack" },
+ prototypeType: "AsyncDisposableStack",
+ /** @type {Record} */
+ properties: {},
+ },
WeakRef: {
type: "Function",
return: { type: "WeakRef" },
@@ -815,6 +829,24 @@ const WELLKNOWN_PROTOTYPE = /** @type {WellKnownPrototypes} */ ({
every: RETURN_BOOLEAN,
find: { type: "Function" },
},
+ /** @type {Record} */
+ DisposableStack: {
+ adopt: { type: "Function" },
+ dispose: { type: "Function" },
+ defer: { type: "Function" },
+ disposed: { type: "Boolean" },
+ move: { type: "Function", return: { type: "DisposableStack" } },
+ use: { type: "Function" },
+ },
+ /** @type {Record} */
+ AsyncDisposableStack: {
+ adopt: { type: "Function", return: { type: "Promise" } },
+ disposeAsync: { type: "Function" },
+ defer: { type: "Function" },
+ disposed: { type: "Boolean" },
+ move: { type: "Function", return: { type: "AsyncDisposableStack" } },
+ use: { type: "Function" },
+ },
/** @type {Record} */
WeakRef: {
deref: { type: "Function" },
diff --git a/lib/util/type-checker/types.d.ts b/lib/util/type-checker/types.d.ts
index 5ee56e52..ce1d0d75 100644
--- a/lib/util/type-checker/types.d.ts
+++ b/lib/util/type-checker/types.d.ts
@@ -36,6 +36,8 @@ export type TypeName =
| "Boolean"
| "BigInt"
| "Iterator"
+ | "DisposableStack"
+ | "AsyncDisposableStack"
| "Map"
| "Set"
| "WeakMap"
@@ -79,6 +81,7 @@ type ExcludePrototypeProperty =
| typeof Symbol.matchAll
| typeof Symbol.species
| typeof Symbol.dispose
+ | typeof Symbol.asyncDispose
| typeof Symbol.metadata;
export type ObjectProperty = keyof typeof Object;
@@ -209,6 +212,16 @@ export type IteratorPrototypeProperty = Exclude<
keyof IteratorObject,
ExcludePrototypeProperty
>;
+export type DisposableStackProperty = Exclude;
+export type DisposableStackPrototypeProperty = Exclude<
+ keyof DisposableStack,
+ ExcludePrototypeProperty
+>;
+export type AsyncDisposableStackProperty = Exclude;
+export type AsyncDisposableStackPrototypeProperty = Exclude<
+ keyof AsyncDisposableStack,
+ ExcludePrototypeProperty
+>;
export type TypedArrayProperty = Exclude<
keyof typeof Int8Array,
ExcludeProperty
diff --git a/lib/util/well-known-properties.js b/lib/util/well-known-properties.js
index 7f90fb98..e57adfa4 100644
--- a/lib/util/well-known-properties.js
+++ b/lib/util/well-known-properties.js
@@ -95,7 +95,9 @@ const symbolProperties = new Set([
...functionPrototypeProperties,
// https://tc39.es/ecma262/multipage/fundamental-objects.html#sec-properties-of-the-symbol-constructor
+ "asyncDispose",
"asyncIterator",
+ "dispose",
"for",
"hasInstance",
"isConcatSpreadable",
@@ -889,6 +891,51 @@ const iteratorPrototypeProperties = new Set([
// [ %Symbol.asyncIterator%% ]
])
+const disposableStackProperties = new Set([
+ ...objectPrototypeProperties,
+ ...functionPrototypeProperties,
+
+ // https://tc39.es/ecma262/multipage/control-abstraction-objects.html#sec-properties-of-the-disposablestack-constructor
+ "prototype",
+])
+
+const disposableStackPrototypeProperties = new Set([
+ ...objectPrototypeProperties,
+
+ // https://tc39.es/ecma262/multipage/control-abstraction-objects.html#sec-properties-of-the-disposablestack-prototype-object
+ "adopt",
+ "constructor",
+ "defer",
+ "dispose",
+ "disposed",
+ "move",
+ "use",
+ // [ %Symbol.dispose% ]
+ // [ %Symbol.toStringTag% ]
+])
+
+const asyncDisposableStackProperties = new Set([
+ ...objectPrototypeProperties,
+ ...functionPrototypeProperties,
+
+ // https://tc39.es/ecma262/multipage/control-abstraction-objects.html#sec-properties-of-the-asyncdisposablestack-constructor
+ "prototype",
+])
+
+const asyncDisposableStackPrototypeProperties = new Set([
+ ...objectPrototypeProperties,
+ // https://tc39.es/ecma262/multipage/control-abstraction-objects.html#sec-properties-of-the-asyncdisposablestack-prototype-object
+ "adopt",
+ "constructor",
+ "defer",
+ "disposeAsync",
+ "disposed",
+ "move",
+ "use",
+ // [ %Symbol.asyncDispose% ]
+ // [ %Symbol.toStringTag% ]
+])
+
const promiseProperties = new Set([
...objectPrototypeProperties,
...functionPrototypeProperties,
@@ -1228,6 +1275,11 @@ module.exports = {
finalizationRegistryPrototypeProperties,
iteratorProperties,
iteratorPrototypeProperties,
+ disposableStackProperties,
+ disposableStackPrototypeProperties,
+ asyncDisposableStackProperties,
+ asyncDisposableStackPrototypeProperties,
+
promiseProperties,
promisePrototypeProperties,
reflectProperties,
diff --git a/package.json b/package.json
index ad3bcc80..e3ca6eda 100644
--- a/package.json
+++ b/package.json
@@ -18,6 +18,7 @@
"eslint-compat-utils": "^0.6.3"
},
"devDependencies": {
+ "@clack/prompts": "^0.11.0",
"@typescript-eslint/parser": "^8.0.0",
"env-cmd": "^10.1.0",
"eslint": "^9.1.0",
@@ -27,7 +28,7 @@
"eslint-plugin-prettier": "^5.0.0",
"eslint-plugin-vue": "^10.0.0",
"espree": "^10.3.0",
- "globals": "^16.0.0",
+ "globals": "^16.2.0",
"jsdom": "^26.0.0",
"mocha": "^11.0.0",
"monaco-editor": "^0.52.0",
diff --git a/scripts/new-rule.js b/scripts/new-rule.js
index 8a87cd34..cd95a6b5 100644
--- a/scripts/new-rule.js
+++ b/scripts/new-rule.js
@@ -7,13 +7,21 @@
const cp = require("child_process")
const fs = require("fs")
const path = require("path")
+const prompts = require("@clack/prompts")
const { LATEST_ES_YEAR } = require("./rules")
const logger = console
const maxESVersion = LATEST_ES_YEAR + 1
+main(
+ String(process.argv[2])
+ .toLowerCase()
+ .replace(/[.]/gu, "-")
+ .replace(/[()]/gu, ""),
+)
+
// main
-;((ruleId) => {
+async function main(ruleId) {
if (ruleId == null) {
logger.error("Usage: npm run new ")
process.exitCode = 1
@@ -29,9 +37,548 @@ const maxESVersion = LATEST_ES_YEAR + 1
const testFile = path.resolve(__dirname, `../tests/lib/rules/${ruleId}.js`)
const docFile = path.resolve(__dirname, `../docs/rules/${ruleId}.md`)
- fs.writeFileSync(
- ruleFile,
- `"use strict"
+ prompts.intro("Create the new rule!")
+
+ const kind = await unwrapPrompt(
+ prompts.select({
+ message: `What kind of rule is ${ruleId}?`,
+ options: [
+ {
+ value: "global-object",
+ label: "The rule forbids the use of global objects.",
+ },
+ // {
+ // value: "static-properties",
+ // label: "The rule forbids the use of static properties.",
+ // },
+ // {
+ // value: "prototype-properties",
+ // label: "The rule forbids the use of prototype properties.",
+ // },
+ {
+ value: "nonstandard-static-properties",
+ label: "The rule forbids the use of non-standard static properties.",
+ },
+ {
+ value: "nonstandard-prototype-properties",
+ label: "The rule forbids the use of non-standard prototype properties.",
+ },
+ {
+ value: "default",
+ label: "There is no option",
+ },
+ ],
+ }),
+ )
+
+ const resourceOptions = {
+ ruleId,
+ kind,
+ object: "",
+ properties: /** @type {string[]} */ [],
+ }
+
+ if (
+ kind === "global-object" ||
+ kind === "static-properties" ||
+ kind === "prototype-properties" ||
+ kind === "nonstandard-static-properties" ||
+ kind === "nonstandard-prototype-properties"
+ ) {
+ resourceOptions.object = await unwrapPrompt(
+ prompts.text({
+ message: "What is the global object that the rule checks?",
+ placeholder: "e.g. Set, Map, Math",
+ validate(value) {
+ if (value.trim().length === 0) {
+ return "The global object name must not be empty."
+ }
+ return undefined
+ },
+ }),
+ )
+ }
+
+ if (kind === "static-properties" || kind === "prototype-properties") {
+ const promptObject = globalThis[resourceOptions.object]
+ const promptProperties = promptObject
+ ? kind === "static-properties"
+ ? Object.getOwnPropertyNames(promptObject)
+ : Object.getOwnPropertyNames(promptObject.prototype)
+ : []
+ resourceOptions.properties = (
+ await unwrapPrompt(
+ prompts.text({
+ message: "What is the property names that the rule checks?",
+ placeholder: promptProperties.length
+ ? `e.g. ${promptProperties.join(", ")}`
+ : undefined,
+ validate(value) {
+ const names = value
+ .split(",")
+ .map((s) => s.trim())
+ .filter((s) => s)
+ if (names.length === 0) {
+ return "The property names must not be empty."
+ }
+ return undefined
+ },
+ }),
+ )
+ )
+ .split(",")
+ .map((s) => s.trim())
+ .filter((s) => s)
+ }
+
+ const resources =
+ kind === "global-object"
+ ? buildGlobalObjectRuleResources(resourceOptions)
+ : kind === "nonstandard-static-properties"
+ ? buildNonStandardStaticPropertiesRuleResources(resourceOptions)
+ : kind === "nonstandard-prototype-properties"
+ ? buildNonStandardPrototypePropertiesRuleResources(
+ resourceOptions,
+ )
+ : buildDefaultResources(resourceOptions)
+
+ fs.writeFileSync(ruleFile, resources.rule)
+ fs.writeFileSync(testFile, resources.test)
+ fs.writeFileSync(docFile, resources.doc)
+
+ cp.execSync(`code "${ruleFile}"`)
+ cp.execSync(`code "${testFile}"`)
+ cp.execSync(`code "${docFile}"`)
+
+ const yellow = "\u001b[33m"
+
+ const reset = "\u001b[0m"
+
+ console.log(`Test Command:
+
+${yellow}npx mocha "tests/**/${ruleId}.js" --reporter dot --timeout 60000${reset}
+
+`)
+}
+
+/**
+ * @template T
+ * @param {Promise} maybeCancelPromise
+ * @returns {Promise}
+ */
+async function unwrapPrompt(maybeCancelPromise) {
+ const result = await maybeCancelPromise
+
+ if (prompts.isCancel(result)) {
+ prompts.cancel("✖ Operation cancelled")
+ // eslint-disable-next-line no-process-exit
+ process.exit(0)
+ }
+ return result
+}
+
+function buildGlobalObjectRuleResources({ ruleId, object }) {
+ return {
+ rule: `"use strict"
+
+const { defineGlobalsHandler } = require("../util/define-globals-handler")
+
+module.exports = {
+ meta: {
+ docs: {
+ description: "disallow the \`${object}\` class.",
+ category: "ES${maxESVersion}",
+ recommended: false,
+ url: "",
+ },
+ fixable: null,
+ messages: {
+ forbidden: "ES${maxESVersion} '{{name}}' class is forbidden.",
+ },
+ schema: [],
+ type: "problem",
+ },
+ create(context) {
+ return defineGlobalsHandler(context, ["${object}"])
+ },
+}
+`,
+ test: `"use strict"
+
+const RuleTester = require("../../tester")
+const rule = require("../../../lib/rules/${ruleId}.js")
+
+new RuleTester().run("${ruleId}", rule, {
+ valid: ["Array", "Object", "let ${object} = 0; ${object}"],
+ invalid: [
+ {
+ code: "${object}",
+ errors: ["ES${maxESVersion} '${object}' class is forbidden."],
+ },
+ {
+ code: "function f() { ${object} }",
+ errors: ["ES${maxESVersion} '${object}' class is forbidden."],
+ },
+ ],
+})
+`,
+ doc: `# es-x/${ruleId}
+>
+
+This rule reports ES${maxESVersion} [\`${object}\` class]($$LINK$$) as errors.
+
+## 💡 Examples
+
+⛔ Examples of **incorrect** code for this rule:
+
+
+
+\`\`\`js
+/*eslint es-x/${ruleId}: error */
+let ${object.toLowerCase()} = new ${object}()
+\`\`\`
+
+
+`,
+ }
+}
+
+function buildNonStandardStaticPropertiesRuleResources({ ruleId, object }) {
+ const camelObject = camelCase(object)
+ return {
+ rule: `"use strict"
+
+const {
+ defineNonstandardStaticPropertiesHandler,
+} = require("../util/define-nonstandard-static-properties-handler")
+const { ${camelObject}Properties } = require("../util/well-known-properties")
+
+module.exports = {
+ meta: {
+ docs: {
+ description: "disallow non-standard static properties on \`${object}\` class",
+ category: "nonstandard",
+ recommended: false,
+ url: "",
+ },
+ fixable: null,
+ messages: {
+ forbidden: "Non-standard '{{name}}' property is forbidden.",
+ },
+ schema: [
+ {
+ type: "object",
+ properties: {
+ allow: {
+ type: "array",
+ items: { type: "string" },
+ uniqueItems: true,
+ },
+ allowTestedProperty: { type: "boolean" },
+ },
+ additionalProperties: false,
+ },
+ ],
+ type: "problem",
+ },
+ create(context) {
+ /** @type {Set} */
+ const allows = new Set([
+ ...(context.options[0]?.allow || []),
+ ...${camelObject}Properties,
+ ])
+ return defineNonstandardStaticPropertiesHandler(context, {
+ '${object}': allows,
+ })
+ },
+}
+`,
+ test: `"use strict"
+
+const RuleTester = require("../../tester")
+const rule = require("../../../lib/rules/${ruleId}.js")
+const { ${camelObject}Properties } = require("../../../lib/util/well-known-properties")
+
+new RuleTester().run("${ruleId}", rule, {
+ valid: [
+ ...[...${camelObject}Properties].map((p) => \`${object}.\${p}\`),
+ { code: "${object}.unknown()", options: [{ allow: ["unknown"] }] },
+ ],
+ invalid: [
+ {
+ code: "${object}.unknown()",
+ errors: ["Non-standard '${object}.unknown' property is forbidden."],
+ },
+ {
+ code: "${object}.foo",
+ errors: ["Non-standard '${object}.foo' property is forbidden."],
+ },
+ ],
+})
+`,
+ doc: `# es-x/${ruleId}
+>
+
+This rule reports non-standard static properties on \`${object}\` class as errors.
+
+## 💡 Examples
+
+⛔ Examples of **incorrect** code for this rule:
+
+
+
+\`\`\`js
+/*eslint es-x/${ruleId}: error */
+${object}.unknown();
+\`\`\`
+
+
+
+## 🔧 Options
+
+This rule has an option.
+
+\`\`\`jsonc
+{
+ "rules": {
+ "es-x/${ruleId}": [
+ "error",
+ {
+ "allow": [],
+ "allowTestedProperty": false
+ }
+ ]
+ }
+}
+\`\`\`
+
+### allow: string[]
+
+An array of non-standard property names to allow.
+
+### allowTestedProperty: boolean
+
+Configure the allowTestedProperty mode for only this rule.
+This is prior to the \`settings['es-x'].allowTestedProperty\` setting.
+`,
+ }
+}
+
+function buildNonStandardPrototypePropertiesRuleResources({ ruleId, object }) {
+ const camelObject = camelCase(object)
+ return {
+ rule: `"use strict"
+
+const {
+ defineNonstandardPrototypePropertiesHandler,
+} = require("../util/define-nonstandard-prototype-properties-handler")
+const { ${camelObject}PrototypeProperties } = require("../util/well-known-properties")
+
+module.exports = {
+ meta: {
+ docs: {
+ description: "disallow non-standard properties on ${object} instance",
+ category: "nonstandard",
+ recommended: false,
+ url: "",
+ },
+ fixable: null,
+ messages: {
+ forbidden: "Non-standard '{{name}}' property is forbidden.",
+ },
+ schema: [
+ {
+ type: "object",
+ properties: {
+ allow: {
+ type: "array",
+ items: { type: "string" },
+ uniqueItems: true,
+ },
+ allowTestedProperty: { type: "boolean" },
+ },
+ additionalProperties: false,
+ },
+ ],
+ type: "problem",
+ },
+ create(context) {
+ /** @type {Set} */
+ const allows = new Set([
+ ...(context.options[0]?.allow || []),
+ ...${camelObject}PrototypeProperties,
+ ])
+ return defineNonstandardPrototypePropertiesHandler(context, {
+ '${object}': allows,
+ })
+ },
+}
+`,
+ test: `"use strict"
+
+const path = require("path")
+const RuleTester = require("../../tester")
+const rule = require("../../../lib/rules/${ruleId}.js")
+const {
+ ${camelObject}PrototypeProperties,
+} = require("../../../lib/util/well-known-properties")
+const ruleId = "${ruleId}"
+
+new RuleTester().run(ruleId, rule, {
+ valid: [
+ "foo",
+ "foo.toString",
+ "foo.foo",
+ ...[...${camelObject}PrototypeProperties].map((p) => \`(new ${object}()).\${p}\`),
+ { code: "(new ${object}()).unknown()", options: [{ allow: ["unknown"] }] },
+ ],
+ invalid: [
+ {
+ code: "(new ${object}()).unknown()",
+ errors: [
+ "Non-standard '${object}.prototype.unknown' property is forbidden.",
+ ],
+ },
+ {
+ code: "(new ${object}()).foo",
+ errors: [
+ "Non-standard '${object}.prototype.foo' property is forbidden.",
+ ],
+ },
+ {
+ code: "(new ${object}())[0]",
+ errors: [
+ "Non-standard '${object}.prototype.0' property is forbidden.",
+ ],
+ },
+ {
+ code: "(new ${object}())['01']",
+ errors: [
+ "Non-standard '${object}.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" },
+ ...[...${camelObject}PrototypeProperties].map((p) => ({
+ filename,
+ code: \`(new ${object}()).\${p}\`,
+ })),
+ ],
+ invalid: [
+ {
+ filename,
+ code: "(new ${object}()).foo",
+ errors: [
+ "Non-standard '${object}.prototype.foo' property is forbidden.",
+ ],
+ },
+ {
+ filename,
+ code: "(new ${object}())[0]",
+ errors: [
+ "Non-standard '${object}.prototype.0' property is forbidden.",
+ ],
+ },
+ {
+ filename,
+ code: "(new ${object}())['01']",
+ errors: [
+ "Non-standard '${object}.prototype.01' property is forbidden.",
+ ],
+ },
+ {
+ filename,
+ code: "let foo = (new ${object}()); foo.foo",
+ errors: [
+ "Non-standard '${object}.prototype.foo' property is forbidden.",
+ ],
+ },
+ {
+ filename,
+ code: "function f(a: T) { a.baz }",
+ errors: [
+ "Non-standard '${object}.prototype.baz' property is forbidden.",
+ ],
+ },
+ ],
+})
+`,
+ doc: `# es-x/${ruleId}
+>
+
+This rule reports non-standard properties on ${object} instance as errors.
+
+## 💡 Examples
+
+⛔ Examples of **incorrect** code for this rule:
+
+
+
+\`\`\`js
+/*eslint es-x/${ruleId}: error */
+const foo = new ${object}();
+foo.unknown();
+\`\`\`
+
+
+
+## 🔧 Options
+
+This rule has an option.
+
+\`\`\`jsonc
+{
+ "rules": {
+ "es-x/${ruleId}": [
+ "error",
+ {
+ "allow": [],
+ "allowTestedProperty": false
+ }
+ ]
+ }
+}
+\`\`\`
+
+### allow: string[]
+
+An array of non-standard property names to allow.
+
+### allowTestedProperty: boolean
+
+Configure the allowTestedProperty mode for only this rule.
+This is prior to the \`settings['es-x'].allowTestedProperty\` setting.
+`,
+ }
+}
+
+function buildDefaultResources({ ruleId }) {
+ return {
+ rule: `"use strict"
module.exports = {
meta: {
@@ -53,10 +600,7 @@ module.exports = {
},
}
`,
- )
- fs.writeFileSync(
- testFile,
- `"use strict"
+ test: `"use strict"
const RuleTester = require("../../tester")
const rule = require("../../../lib/rules/${ruleId}.js")
@@ -72,10 +616,7 @@ new RuleTester().run("${ruleId}", rule, {
invalid: [],
})
`,
- )
- fs.writeFileSync(
- docFile,
- `# es-x/${ruleId}
+ doc: `# es-x/${ruleId}
>
This rule reports ??? as errors.
@@ -93,24 +634,12 @@ This rule reports ??? as errors.
`,
- )
-
- cp.execSync(`code "${ruleFile}"`)
- cp.execSync(`code "${testFile}"`)
- cp.execSync(`code "${docFile}"`)
-
- const yellow = "\u001b[33m"
-
- const reset = "\u001b[0m"
-
- console.log(`Test Command:
-
-${yellow}npx mocha "tests/**/${ruleId}.js" --reporter dot --timeout 60000${reset}
+ }
+}
-`)
-})(
- String(process.argv[2])
- .toLowerCase()
- .replace(/[.]/gu, "-")
- .replace(/[()]/gu, ""),
-)
+function camelCase(str) {
+ const base = /[_.-]/u.test(str)
+ ? str.replace(/[_.-](\w|$)/gu, (_, x) => x.toUpperCase())
+ : str
+ return `${base[0].toLowerCase()}${base.slice(1)}`
+}
diff --git a/scripts/proposals.js b/scripts/proposals.js
index 4e6dcb1f..091b8473 100644
--- a/scripts/proposals.js
+++ b/scripts/proposals.js
@@ -13,6 +13,10 @@ module.exports = {
title: "Class Fields",
link: "https://github.com/tc39/proposal-class-fields",
},
+ "explicit-resource-management": {
+ title: "Explicit Resource Management",
+ link: "https://github.com/tc39/proposal-explicit-resource-management",
+ },
float16array: {
title: "Float16Array",
link: "https://github.com/tc39/proposal-float16array",
diff --git a/tests/lib/rules/no-asyncdisposablestack.js b/tests/lib/rules/no-asyncdisposablestack.js
new file mode 100644
index 00000000..24376e97
--- /dev/null
+++ b/tests/lib/rules/no-asyncdisposablestack.js
@@ -0,0 +1,22 @@
+"use strict"
+
+const RuleTester = require("../../tester")
+const rule = require("../../../lib/rules/no-asyncdisposablestack.js")
+
+new RuleTester().run("no-asyncdisposablestack", rule, {
+ valid: [
+ "Array",
+ "Object",
+ "let AsyncDisposableStack = 0; AsyncDisposableStack",
+ ],
+ invalid: [
+ {
+ code: "AsyncDisposableStack",
+ errors: ["ES2026 'AsyncDisposableStack' class is forbidden."],
+ },
+ {
+ code: "function f() { AsyncDisposableStack }",
+ errors: ["ES2026 'AsyncDisposableStack' class is forbidden."],
+ },
+ ],
+})
diff --git a/tests/lib/rules/no-disposablestack.js b/tests/lib/rules/no-disposablestack.js
new file mode 100644
index 00000000..a6d670c6
--- /dev/null
+++ b/tests/lib/rules/no-disposablestack.js
@@ -0,0 +1,18 @@
+"use strict"
+
+const RuleTester = require("../../tester")
+const rule = require("../../../lib/rules/no-disposablestack.js")
+
+new RuleTester().run("no-disposablestack", rule, {
+ valid: ["Array", "Object", "let DisposableStack = 0; DisposableStack"],
+ invalid: [
+ {
+ code: "DisposableStack",
+ errors: ["ES2026 'DisposableStack' class is forbidden."],
+ },
+ {
+ code: "function f() { DisposableStack }",
+ errors: ["ES2026 'DisposableStack' class is forbidden."],
+ },
+ ],
+})
diff --git a/tests/lib/rules/no-nonstandard-asyncdisposablestack-properties.js b/tests/lib/rules/no-nonstandard-asyncdisposablestack-properties.js
new file mode 100644
index 00000000..4261b3d9
--- /dev/null
+++ b/tests/lib/rules/no-nonstandard-asyncdisposablestack-properties.js
@@ -0,0 +1,33 @@
+"use strict"
+
+const RuleTester = require("../../tester")
+const rule = require("../../../lib/rules/no-nonstandard-asyncdisposablestack-properties.js")
+const {
+ asyncDisposableStackProperties,
+} = require("../../../lib/util/well-known-properties")
+
+new RuleTester().run("no-nonstandard-asyncdisposablestack-properties", rule, {
+ valid: [
+ ...[...asyncDisposableStackProperties].map(
+ (p) => `AsyncDisposableStack.${p}`,
+ ),
+ {
+ code: "AsyncDisposableStack.unknown()",
+ options: [{ allow: ["unknown"] }],
+ },
+ ],
+ invalid: [
+ {
+ code: "AsyncDisposableStack.unknown()",
+ errors: [
+ "Non-standard 'AsyncDisposableStack.unknown' property is forbidden.",
+ ],
+ },
+ {
+ code: "AsyncDisposableStack.foo",
+ errors: [
+ "Non-standard 'AsyncDisposableStack.foo' property is forbidden.",
+ ],
+ },
+ ],
+})
diff --git a/tests/lib/rules/no-nonstandard-asyncdisposablestack-prototype-properties.js b/tests/lib/rules/no-nonstandard-asyncdisposablestack-prototype-properties.js
new file mode 100644
index 00000000..ee2fd253
--- /dev/null
+++ b/tests/lib/rules/no-nonstandard-asyncdisposablestack-prototype-properties.js
@@ -0,0 +1,121 @@
+"use strict"
+
+const path = require("path")
+const RuleTester = require("../../tester")
+const rule = require("../../../lib/rules/no-nonstandard-asyncdisposablestack-prototype-properties.js")
+const {
+ asyncDisposableStackPrototypeProperties,
+} = require("../../../lib/util/well-known-properties")
+const ruleId = "no-nonstandard-asyncdisposablestack-prototype-properties"
+
+new RuleTester().run(ruleId, rule, {
+ valid: [
+ "foo",
+ "foo.toString",
+ "foo.foo",
+ ...[...asyncDisposableStackPrototypeProperties].map(
+ (p) => `(new AsyncDisposableStack()).${p}`,
+ ),
+ {
+ code: "(new AsyncDisposableStack()).unknown()",
+ options: [{ allow: ["unknown"] }],
+ },
+ ],
+ invalid: [
+ {
+ code: "(new AsyncDisposableStack()).unknown()",
+ errors: [
+ "Non-standard 'AsyncDisposableStack.prototype.unknown' property is forbidden.",
+ ],
+ },
+ {
+ code: "(new AsyncDisposableStack()).foo",
+ errors: [
+ "Non-standard 'AsyncDisposableStack.prototype.foo' property is forbidden.",
+ ],
+ },
+ {
+ code: "(new AsyncDisposableStack())[0]",
+ errors: [
+ "Non-standard 'AsyncDisposableStack.prototype.0' property is forbidden.",
+ ],
+ },
+ {
+ code: "(new AsyncDisposableStack())['01']",
+ errors: [
+ "Non-standard 'AsyncDisposableStack.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(
+ "no-nonstandard-asyncdisposablestack-prototype-properties TS Full Type Information",
+ rule,
+ {
+ valid: [
+ { filename, code: "foo" },
+ { filename, code: "foo.toString" },
+ { filename, code: "foo.foo" },
+ { filename, code: "let foo = {}; foo.foo" },
+ ...[...asyncDisposableStackPrototypeProperties].map((p) => ({
+ filename,
+ code: `(new AsyncDisposableStack()).${p}`,
+ })),
+ ],
+ invalid: [
+ {
+ filename,
+ code: "(new AsyncDisposableStack()).foo",
+ errors: [
+ "Non-standard 'AsyncDisposableStack.prototype.foo' property is forbidden.",
+ ],
+ },
+ {
+ filename,
+ code: "(new AsyncDisposableStack())[0]",
+ errors: [
+ "Non-standard 'AsyncDisposableStack.prototype.0' property is forbidden.",
+ ],
+ },
+ {
+ filename,
+ code: "(new AsyncDisposableStack())['01']",
+ errors: [
+ "Non-standard 'AsyncDisposableStack.prototype.01' property is forbidden.",
+ ],
+ },
+ {
+ filename,
+ code: "let foo = (new AsyncDisposableStack()); foo.foo",
+ errors: [
+ "Non-standard 'AsyncDisposableStack.prototype.foo' property is forbidden.",
+ ],
+ },
+ {
+ filename,
+ code: "function f(a: T) { a.baz }",
+ errors: [
+ "Non-standard 'AsyncDisposableStack.prototype.baz' property is forbidden.",
+ ],
+ },
+ ],
+ },
+)
diff --git a/tests/lib/rules/no-nonstandard-disposablestack-properties.js b/tests/lib/rules/no-nonstandard-disposablestack-properties.js
new file mode 100644
index 00000000..4c91cfed
--- /dev/null
+++ b/tests/lib/rules/no-nonstandard-disposablestack-properties.js
@@ -0,0 +1,31 @@
+"use strict"
+
+const RuleTester = require("../../tester")
+const rule = require("../../../lib/rules/no-nonstandard-disposablestack-properties.js")
+const {
+ disposableStackProperties,
+} = require("../../../lib/util/well-known-properties")
+
+new RuleTester().run("no-nonstandard-disposablestack-properties", rule, {
+ valid: [
+ ...[...disposableStackProperties].map((p) => `DisposableStack.${p}`),
+ {
+ code: "DisposableStack.unknown()",
+ options: [{ allow: ["unknown"] }],
+ },
+ ],
+ invalid: [
+ {
+ code: "DisposableStack.unknown()",
+ errors: [
+ "Non-standard 'DisposableStack.unknown' property is forbidden.",
+ ],
+ },
+ {
+ code: "DisposableStack.foo",
+ errors: [
+ "Non-standard 'DisposableStack.foo' property is forbidden.",
+ ],
+ },
+ ],
+})
diff --git a/tests/lib/rules/no-nonstandard-disposablestack-prototype-properties.js b/tests/lib/rules/no-nonstandard-disposablestack-prototype-properties.js
new file mode 100644
index 00000000..8452edfa
--- /dev/null
+++ b/tests/lib/rules/no-nonstandard-disposablestack-prototype-properties.js
@@ -0,0 +1,121 @@
+"use strict"
+
+const path = require("path")
+const RuleTester = require("../../tester")
+const rule = require("../../../lib/rules/no-nonstandard-disposablestack-prototype-properties.js")
+const {
+ disposableStackPrototypeProperties,
+} = require("../../../lib/util/well-known-properties")
+const ruleId = "no-nonstandard-disposablestack-prototype-properties"
+
+new RuleTester().run(ruleId, rule, {
+ valid: [
+ "foo",
+ "foo.toString",
+ "foo.foo",
+ ...[...disposableStackPrototypeProperties].map(
+ (p) => `(new DisposableStack()).${p}`,
+ ),
+ {
+ code: "(new DisposableStack()).unknown()",
+ options: [{ allow: ["unknown"] }],
+ },
+ ],
+ invalid: [
+ {
+ code: "(new DisposableStack()).unknown()",
+ errors: [
+ "Non-standard 'DisposableStack.prototype.unknown' property is forbidden.",
+ ],
+ },
+ {
+ code: "(new DisposableStack()).foo",
+ errors: [
+ "Non-standard 'DisposableStack.prototype.foo' property is forbidden.",
+ ],
+ },
+ {
+ code: "(new DisposableStack())[0]",
+ errors: [
+ "Non-standard 'DisposableStack.prototype.0' property is forbidden.",
+ ],
+ },
+ {
+ code: "(new DisposableStack())['01']",
+ errors: [
+ "Non-standard 'DisposableStack.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(
+ "no-nonstandard-disposablestack-prototype-properties TS Full Type Information",
+ rule,
+ {
+ valid: [
+ { filename, code: "foo" },
+ { filename, code: "foo.toString" },
+ { filename, code: "foo.foo" },
+ { filename, code: "let foo = {}; foo.foo" },
+ ...[...disposableStackPrototypeProperties].map((p) => ({
+ filename,
+ code: `(new DisposableStack()).${p}`,
+ })),
+ ],
+ invalid: [
+ {
+ filename,
+ code: "(new DisposableStack()).foo",
+ errors: [
+ "Non-standard 'DisposableStack.prototype.foo' property is forbidden.",
+ ],
+ },
+ {
+ filename,
+ code: "(new DisposableStack())[0]",
+ errors: [
+ "Non-standard 'DisposableStack.prototype.0' property is forbidden.",
+ ],
+ },
+ {
+ filename,
+ code: "(new DisposableStack())['01']",
+ errors: [
+ "Non-standard 'DisposableStack.prototype.01' property is forbidden.",
+ ],
+ },
+ {
+ filename,
+ code: "let foo = (new DisposableStack()); foo.foo",
+ errors: [
+ "Non-standard 'DisposableStack.prototype.foo' property is forbidden.",
+ ],
+ },
+ {
+ filename,
+ code: "function f(a: T) { a.baz }",
+ errors: [
+ "Non-standard 'DisposableStack.prototype.baz' property is forbidden.",
+ ],
+ },
+ ],
+ },
+)
diff --git a/tests/lib/rules/no-suppressederror.js b/tests/lib/rules/no-suppressederror.js
new file mode 100644
index 00000000..7c64eeb2
--- /dev/null
+++ b/tests/lib/rules/no-suppressederror.js
@@ -0,0 +1,18 @@
+"use strict"
+
+const RuleTester = require("../../tester")
+const rule = require("../../../lib/rules/no-suppressederror.js")
+
+new RuleTester().run("no-suppressederror", rule, {
+ valid: ["Array", "Object", "let SuppressedError = 0; SuppressedError"],
+ invalid: [
+ {
+ code: "SuppressedError",
+ errors: ["ES2026 'SuppressedError' class is forbidden."],
+ },
+ {
+ code: "function f() { SuppressedError }",
+ errors: ["ES2026 'SuppressedError' class is forbidden."],
+ },
+ ],
+})
diff --git a/tests/lib/rules/no-using-declarations.js b/tests/lib/rules/no-using-declarations.js
new file mode 100644
index 00000000..cc944773
--- /dev/null
+++ b/tests/lib/rules/no-using-declarations.js
@@ -0,0 +1,35 @@
+"use strict"
+
+const semver = require("semver")
+const RuleTester = require("../../tester")
+const rule = require("../../../lib/rules/no-using-declarations.js")
+
+// if (!RuleTester.isSupported(2026)) {
+// //eslint-disable-next-line no-console
+// console.log("Skip the tests of no-using-declarations.")
+// return
+// }
+if (semver.lt(require("@typescript-eslint/parser").version, "8.0.0")) {
+ //eslint-disable-next-line no-console
+ console.log("Skip the tests of no-using-declarations.")
+ return
+}
+
+new RuleTester({
+ languageOptions: {
+ sourceType: "module",
+ parser: require("@typescript-eslint/parser"), // espree does not support `using` yet.
+ },
+}).run("no-using-declarations", rule, {
+ valid: ["let x = y", "const x = y", "var x = y", "const x = await y"],
+ invalid: [
+ {
+ code: "using x = y",
+ errors: ["ES2026 'using' declarations are forbidden."],
+ },
+ {
+ code: "await using x = y",
+ errors: ["ES2026 'await using' declarations are forbidden."],
+ },
+ ],
+})
diff --git a/tests/tester.js b/tests/tester.js
index 5cf3e94d..1a6b1bd7 100644
--- a/tests/tester.js
+++ b/tests/tester.js
@@ -31,11 +31,9 @@ RuleTester.setDefaultConfig({
ecmaVersion,
sourceType: "script",
globals: {
- AggregateError: "readonly",
- FinalizationRegistry: "readonly",
- WeakRef: "readonly",
- Intl: "readonly",
- Float16Array: "readonly",
+ AsyncDisposableStack: "readonly",
+ DisposableStack: "readonly",
+ SuppressedError: "readonly",
...builtin,
},
},