sindresorhus / eslint-plugin-unicorn

More than 100 powerful ESLint rules
MIT License
3.98k stars 361 forks source link

`unicorn/prefer-top-level-await`: await is only valid in async functions and the top level bodies of modules #2378

Closed ericbn closed 3 weeks ago

ericbn commented 3 weeks ago

Description

Adding a top level await in a node script fails with:

SyntaxError: await is only valid in async functions and the top level bodies of modules

The unicorn/prefer-top-level-await rule should not apply to scripts.

Fail

#!/usr/bin/env node
async function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}
await sleep(1);

Pass

#!/usr/bin/env node
async function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}
sleep(1);

Additional Info

The code in the "Fail" example currently passes the linting rule, but the script fails to be executed:

$ ./test.js
/path/to/test.js:6
await sleep(1);
^^^^^

SyntaxError: await is only valid in async functions and the top level bodies of modules
    at internalCompileFunction (node:internal/vm:76:18)
    at wrapSafe (node:internal/modules/cjs/loader:1283:20)
    at Module._compile (node:internal/modules/cjs/loader:1328:27)
    at Module._extensions..js (node:internal/modules/cjs/loader:1422:10)
    at Module.load (node:internal/modules/cjs/loader:1203:32)
    at Module._load (node:internal/modules/cjs/loader:1019:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:128:12)
    at node:internal/main/run_main_module:28:49

Node.js v18.20.2

On the other hand, the code in the "Pass" example currently fails the linting rule:

$ eslint .

/path/to/test.js
  6:1  error  Prefer top-level await over an async function `test` call  unicorn/prefer-top-level-await
sindresorhus commented 3 weeks ago

of modules

It needs to be in a module (ESM), not CommonJS.

fisker commented 3 weeks ago

Maybe it's possible to check sourceType via context.languageOptions

ericbn commented 3 weeks ago

Thanks for the heads up. Maybe this should have been part of the unicorn/prefer-module rule? Or maybe the prefer-top-level-await.md documentation should mention that the rule should be used with module (ESM), not CommonJS?