Replies: 3 comments
|
I converted this failure mode into an operator-focused, source-pinned guide: Fix pnpm global native-binding plugin resolution. The guide keeps three boundaries separate:
For users on an affected release, the least invasive A/B is to preserve the failing global tree and run the same exact published version from a disposable project-local install. A release acceptance test should use a fresh isolated global prefix, mount a real bare plugin, cold-restart, and verify that the documented optional-package opt-out remains explicit. Broad hoisting, copied native binaries, and permanent The source references are pinned to |
|
确认一个 macOS arm64 的复现,补充两点细节: 环境:Node v24.11.0,dsh 0.1.0-rc.7( 根因链路(与主楼一致,附新证据):
对照:仓库内 Confirming a macOS arm64 reproduction, with two additional details: Environment: Node v24.11.0, dsh 0.1.0-rc.7 ( Root-cause chain (matches the original report, new evidence attached):
Contrast: |
|
Confirmed this is still reproducible with published DSH 0.1.1-rc.2, Node 22.23.2, pnpm 11.24.0, macOS arm64, and both native-addon packages at 0.1.5. The
With the published DSH runtime, the isolated path then reports These tests kept the original profile intact and did not patch the pnpm store, copy native binaries into dependencies, add internal Node flags, or disable release-age/script-approval checks. Adding current-release evidence to this existing report; the dependency-ownership fix is still needed in an official release. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Affected scenario
这个问题发生在发布版 DSH CLI 通过 pnpm 安装到用户级全局目录时,而不是在源码仓库中运行
pnpm dsh web:触发条件是全局安装采用隔离的 content-addressed / global virtual-store 布局:
node-addon-require-builtin、共享的node-addon-native-custom-loader和当前平台包位于不同的物理包根目录,没有依赖 pnpm hoist。Node 22+ 正常启动,不额外传入--expose-internals。What the user sees
dsh web在挂载 profile 中的 bare plugin specifier 时失败,错误形态是:报错中的插件包实际上已经安装。用户通常看不到真正更早的错误,因为 Loader 会把 native bridge 当作可选能力并吞掉它:
随后
ModuleLoader.fromInternal()返回undefined,bare plugin import 改走普通动态导入,并从 vendored Loader 包而不是 profile / 已安装应用解析,于是产生误导性的二次Cannot find module。Root cause
node-addon-require-builtin持有当前平台包作为自己的 optional dependency,并委托node-addon-native-custom-loader选择和加载平台包。共享 custom loader 却从自己的物理模块位置执行平台包require()。在 pnpm global virtual-store 中,平台包仍然存在并且能从 entry package 的依赖目录解析,但不在共享 custom loader 的祖先搜索路径中,因此 native entry 加载失败。
最小回归测试使用 rc.7 锁文件中的三个真实 0.1.4 包构造该布局,并证明:
No usable native binding;ModuleLoader.fromInternal()能得到 Node internal loader。Fix
正常 native entry 加载失败后,Loader 按依赖所有权从 entry package 自己的依赖目录解析 custom loader 与平台包,再调用 platform bridge。
NARB_DISABLE_OPTIONAL_PACKAGE=1仍会明确禁用该路径,普通动态导入行为保持不变。完整修复(基于 rc.7 的
99f6f02,共 2 commits):Validation
Scope
这项改动只修复 pnpm 用户级全局安装中的 native platform-package 解析路径。它不是 #2699 中“源码启动 + watch-only HMR 依赖契约”问题的修复,也不表示所有
dsh web启动错误都有相同根因。请维护者 review 这项依赖所有权解析修复是否符合 Loader 的预期语义;完整两提交已经可以供内部移植或 squash。
All reactions