diff --git a/.changeset/empty-turtles-attack.md b/.changeset/empty-turtles-attack.md new file mode 100644 index 00000000..7755739e --- /dev/null +++ b/.changeset/empty-turtles-attack.md @@ -0,0 +1,5 @@ +--- +"eslint-plugin-es-x": minor +--- + +Add `es-x/no-atomics-pause` rule diff --git a/docs/rules/index.md b/docs/rules/index.md index e66db543..dea358a2 100644 --- a/docs/rules/index.md +++ b/docs/rules/index.md @@ -12,6 +12,7 @@ There is a config that enables the rules in this category: [`no-new-in-esnext`] |:--------|:------------|:--:| | [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-atomics-pause](./no-atomics-pause.md) | disallow the `Atomics.pause` method. | | | [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. | | diff --git a/docs/rules/no-atomics-pause.md b/docs/rules/no-atomics-pause.md new file mode 100644 index 00000000..dc506da8 --- /dev/null +++ b/docs/rules/no-atomics-pause.md @@ -0,0 +1,54 @@ +--- +title: "es-x/no-atomics-pause" +description: "disallow the `Atomics.pause` method" +--- + +# es-x/no-atomics-pause +> disallow the `Atomics.pause` method + +- ❗ ***This rule has not been released yet.*** +- ✅ The following configurations enable this rule: [no-new-in-esnext] + +This rule reports ES2026 [`Atomics.pause` method](https://github.com/tc39/proposal-atomics-microwait) as errors. + +## 💡 Examples + +⛔ Examples of **incorrect** code for this rule: + + + +```js +/*eslint es-x/no-atomics-pause: [error] */ +Atomics.pause() +``` + + + +## 🔧 Options + +This rule has an option. + +```jsonc +{ + "rules": { + "es-x/no-atomics-pause": [ + "error", + { + "allowTestedProperty": false + } + ] + } +} +``` + +### 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-atomics-pause.js) +- [Test source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/tests/lib/rules/no-atomics-pause.js) + +[no-new-in-esnext]: ../configs/index.md#no-new-in-esnext diff --git a/lib/configs/flat/no-new-in-esnext.js b/lib/configs/flat/no-new-in-esnext.js index 0788279e..f1b57aff 100644 --- a/lib/configs/flat/no-new-in-esnext.js +++ b/lib/configs/flat/no-new-in-esnext.js @@ -13,6 +13,7 @@ module.exports = { rules: { "es-x/no-array-fromasync": "error", "es-x/no-asyncdisposablestack": "error", + "es-x/no-atomics-pause": "error", "es-x/no-disposablestack": "error", "es-x/no-error-iserror": "error", "es-x/no-suppressederror": "error", diff --git a/lib/configs/no-new-in-esnext.js b/lib/configs/no-new-in-esnext.js index 843a36cf..acf856fe 100644 --- a/lib/configs/no-new-in-esnext.js +++ b/lib/configs/no-new-in-esnext.js @@ -9,6 +9,7 @@ module.exports = { rules: { "es-x/no-array-fromasync": "error", "es-x/no-asyncdisposablestack": "error", + "es-x/no-atomics-pause": "error", "es-x/no-disposablestack": "error", "es-x/no-error-iserror": "error", "es-x/no-suppressederror": "error", diff --git a/lib/index.js b/lib/index.js index a2f2c106..79968ad3 100644 --- a/lib/index.js +++ b/lib/index.js @@ -183,6 +183,7 @@ module.exports = { "no-async-iteration": require("./rules/no-async-iteration"), "no-asyncdisposablestack": require("./rules/no-asyncdisposablestack"), "no-atomics": require("./rules/no-atomics"), + "no-atomics-pause": require("./rules/no-atomics-pause"), "no-atomics-waitasync": require("./rules/no-atomics-waitasync"), "no-bigint": require("./rules/no-bigint"), "no-binary-numeric-literals": require("./rules/no-binary-numeric-literals"), diff --git a/lib/rules/no-atomics-pause.js b/lib/rules/no-atomics-pause.js new file mode 100644 index 00000000..9af6f564 --- /dev/null +++ b/lib/rules/no-atomics-pause.js @@ -0,0 +1,35 @@ +"use strict" + +const { + defineStaticPropertiesHandler, +} = require("../util/define-static-properties-handler") + +module.exports = { + meta: { + docs: { + description: "disallow the `Atomics.pause` method.", + category: "ES2026", + recommended: false, + url: "http://eslint-community.github.io/eslint-plugin-es-x/rules/no-atomics-pause.html", + }, + fixable: null, + messages: { + forbidden: "ES2026 '{{name}}' method is forbidden.", + }, + schema: [ + { + type: "object", + properties: { + allowTestedProperty: { type: "boolean" }, + }, + additionalProperties: false, + }, + ], + type: "problem", + }, + create(context) { + return defineStaticPropertiesHandler(context, { + Atomics: { pause: "function" }, + }) + }, +} diff --git a/lib/util/type-checker/es-types.js b/lib/util/type-checker/es-types.js index 610576fd..dbacccdf 100644 --- a/lib/util/type-checker/es-types.js +++ b/lib/util/type-checker/es-types.js @@ -459,6 +459,35 @@ const WELLKNOWN_GLOBALS = { stackTraceLimit: { type: "Number" }, }, }, + Atomics: { + type: "Object", + /** @type {Record} */ + properties: { + add: RETURN_NUMBER, + and: RETURN_NUMBER, + compareExchange: RETURN_NUMBER, + exchange: RETURN_NUMBER, + isLockFree: RETURN_BOOLEAN, + load: RETURN_NUMBER, + notify: RETURN_NUMBER, + or: RETURN_NUMBER, + store: RETURN_NUMBER, + sub: RETURN_NUMBER, + wait: RETURN_STRING, + waitAsync: { + type: "Function", + return: { + type: "Object", + properties: { + async: { type: "Boolean" }, + // value: { type: "Promise" or "String" }, + }, + }, + }, + xor: RETURN_NUMBER, + pause: { type: "Function" }, + }, + }, } /** @type {Record} */ diff --git a/lib/util/type-checker/types.d.ts b/lib/util/type-checker/types.d.ts index ce1d0d75..b91c7ad1 100644 --- a/lib/util/type-checker/types.d.ts +++ b/lib/util/type-checker/types.d.ts @@ -234,3 +234,6 @@ export type MathProperty = Exclude; export type ErrorProperty = | Exclude | "isError"; +export type AtomicsProperty = + | Exclude + | "pause"; diff --git a/lib/util/well-known-properties.js b/lib/util/well-known-properties.js index e57adfa4..32db1b5a 100644 --- a/lib/util/well-known-properties.js +++ b/lib/util/well-known-properties.js @@ -801,6 +801,8 @@ const atomicsProperties = new Set([ "notify", "xor", // [ %Symbol.toStringTag% ] + + "pause", ]) const jsonProperties = new Set([ diff --git a/tests/lib/rules/no-atomics-pause.js b/tests/lib/rules/no-atomics-pause.js new file mode 100644 index 00000000..41cfd107 --- /dev/null +++ b/tests/lib/rules/no-atomics-pause.js @@ -0,0 +1,14 @@ +"use strict" + +const RuleTester = require("../../tester") +const rule = require("../../../lib/rules/no-atomics-pause.js") + +new RuleTester().run("no-atomics-pause", rule, { + valid: ["Atomics", "Atomics.wait", "let Atomics = 0; Atomics.pause"], + invalid: [ + { + code: "Atomics.pause", + errors: ["ES2026 'Atomics.pause' method is forbidden."], + }, + ], +}) diff --git a/tests/lib/rules/no-atomics-waitasync.js b/tests/lib/rules/no-atomics-waitasync.js index 4e877a0b..1fad7b72 100644 --- a/tests/lib/rules/no-atomics-waitasync.js +++ b/tests/lib/rules/no-atomics-waitasync.js @@ -4,7 +4,7 @@ const RuleTester = require("../../tester") const rule = require("../../../lib/rules/no-atomics-waitasync.js") new RuleTester().run("no-atomics-waitasync", rule, { - valid: ["Atomics", "Atomics.wait", "let Atomics = 0; Atomics.watiAsync"], + valid: ["Atomics", "Atomics.wait", "let Atomics = 0; Atomics.waitAsync"], invalid: [ { code: "Atomics.waitAsync",