修复 PNPM 与 Node.js 20 的兼容性问题 (ERR_INVALID_THIS)
2 min read
问题🔗
在 Node.js (>= 20.X
) 中,PNPM (< 8.3.1
) 可能会抛出 ERR_INVALID_THIS
错误。
Lockfile is up to date, resolution step is skipped
Progress: resolved 1, reused 0, downloaded 0, added 0
. | +983 ++++++++++++++++++++++++++++++++
WARN GET xxxxx error (ERR_INVALID_THIS). Will retry in 10 seconds. 2 retries left.
WARN GET xxxxx error (ERR_INVALID_THIS). Will retry in 10 seconds. 2 retries left.
WARN GET xxxxx error (ERR_INVALID_THIS). Will retry in 10 seconds. 2 retries left.
WARN GET xxxxx error (ERR_INVALID_THIS). Will retry in 10 seconds. 2 retries left.
// ...
Error: Process completed with exit code 1.
解决方案🔗
升级 PNPM 到 8.3.1
或更高版本。
pnpm install -g pnpm@latest
问题原因🔗
这个问题的根本原因在于 PNPM 模块依赖的 node-fetch
库中,URLSearchParams.prototype[p].call()
函数调用时,错误地把 this
上下文设置为了 receiver
(代理对象)而非 target
(原始对象)。将 this
上下文设置为 receiver
导致 URLSearchParams
的方法无法正确访问原始对象的属性和方法,进而抛出 ERR_INVALID_THIS
异常。
具体可以参考 pnpm/pnpm#6424 和 pnpm/node-fetch@ebe57b。
// @@ -114,7 +114,7 @@
// export default class Headers extends URLSearchParams {
validateHeaderName(name);
validateHeaderValue(name, String(value));
return URLSearchParams.prototype[p].call(
receiver,
target,
String(name).toLowerCase(),
String(value),
);
// @@ -126,7 +126,7 @@
// export default class Headers extends URLSearchParams {
return (name) => {
validateHeaderName(name);
return URLSearchParams.prototype[p].call(
receiver,
target,
String(name).toLowerCase(),
);
};
通过将 this
上下文正确地设置为 target
(原始对象),URLSearchParams
的方法可以正确访问原始对象的属性和方法,从而解决了 ERR_INVALID_THIS
异常。
总结🔗
如果你在使用 Node.js 20
和 PNPM 是遇到了 ERR_INVALID_THIS
异常,请升级到 PNPM v8.3.1
或更高版本。
⚠️ 注意: Node.js 20.0.0
版本存在异常断流问题,建议升级到 Node.js 20.1.0
或更高版本。
Previous article