isaacs / rimraf

A `rm -rf` util for nodejs
ISC License
5.66k stars 252 forks source link

AbortController is not defined (Node 14) #269

Closed ssoworld closed 1 year ago

ssoworld commented 1 year ago

(node:30444) [ENOTSUP] NO_ABORT_CONTROLLER: AbortController is not defined. If using lru-cache in node 14, load an AbortController polyfill from the `node-abort-controller` package. A minimal polyfill is provided for LRUCache.fetch(), but this may cause undesirable behavior in other APIs that use AbortController.

This looks to be a recent add - running node 14.19.1 and npm 6.14.16 and unable to upgrade due to environment requirements. See also https://github.com/vercel/next.js/discussions/32736

isaacs commented 1 year ago

Yeah, that's a valid warning. Everything should still work, but the way lru-cache's AbortController/AbortSignal polyfill is implemented right now, it's putting it in the global space, which can potentially confuse other modules that might feature-detect and then find something that they think is a fully spec-compliant AbortController, but actually isn't.

Prior to adding that warning in lru-cache, there was actually an issue where rimraf and glob were stating that their engines supported node v14, but lru-cache was requiring node 16. Hence, lru-cache didn't think it needed a warning or polyfill (because AbortController was guaranteed to exist already), but could lead to bad things happening at run-time.

Glob and rimraf don't use cache.fetch(), so they weren't ever going to trigger the issue, but still, not a "correct" setup. The engines field should always be a strict subset of all a module's dependencies engine requirements.

I can probably soften the hazard a bit by making LRUCache keep a reference to AbortController/AbortSignal as a module-local variable, and keep its polyfill to itself. There'd still be a warning that it's using an AC that is a hazard to pass elsewhere. Eg, if you have a fetchMethod that passes the signal option to fetch(...), then it might be weird.

That vercel/next.js error isn't related to this at all, it's just another case of AbortController not being in a given node version.

You can of course deal with the situation in a couple of ways:

The passive yolo approach: just don't worry about it.

The aggressive yolo approach: run your program with --no-warnings on the command line, or `NODE_OPTIONS="--no-warnings" in the environment. (This will silence all warnings, probably not what you want, but it is an option.)

The polyfill approach: Install node-abort-controller and put something like this at the start of your program (or even in a --require module):

if (typeof AbortController === 'undefined') {
  Object.assign(globalThis, require('node-abort-controller'))
}
isaacs commented 1 year ago

Softened the impact of the polyfill a bit, and provided a way to disable that warning with an environment variable. So moving forward, you can disable the warning with LRU_CACHE_IGNORE_AC_WARNING=1 in the environment.