feat: update @vercel/webpack-asset-relocator-loader to 1.10.3 - #1342
Merged
Conversation
Bumps the asset relocator loader from 1.7.3 to 1.10.2, picking up: - 1.7.4 — use a computed node-gyp-build path (#185) - 1.7.5 — fix `__nccwpck_require__ is not defined` regression (#195) - 1.8.0 — support `node:path` as an alias of `path` (#197) - 1.9.0 — load native addons from the `prebuilds` directory (#198) - 1.9.1 — support the packaging format of sharp v0.34.x (#199) - 1.10.0 — ship the loader as source instead of a prebuilt bundle (#200) Since 1.10.0 publishes `src/` rather than an ncc-built `dist/`, the loader's former bundled dependencies are now real transitive deps, which is why the lockfile grows. The relocate-loader build emits no new assets. Unit fixtures are regenerated because the loader now registers its asset base via a webpack RuntimeModule instead of the deprecated `mainTemplate.hooks.requireExtensions`: - the block is labelled `/* webpack/runtime/asset-relocator-loader */` instead of `/* webpack/runtime/compat */`, and is emitted earlier - bundles that never reference `__nccwpck_require__` no longer carry a dead `if (typeof __nccwpck_require__ !== 'undefined')` assignment Verified that `__nccwpck_require__.ab` is still emitted wherever it is referenced, for CJS, ESM and concatenated TypeScript builds, and that the asset-heavy integration tests (sharp, canvas, ffmpeg, oracledb, leveldown, binary-require) still pass. Also fixes the coverage step of update-fixtures.sh, which invoked `node node_modules/.bin/jest` — a shell shim under pnpm, not a JS entry point — so it crashed with a SyntaxError before regenerating any output-coverage.js fixtures. Co-Authored-By: Steven <229881+styfle@users.noreply.github.com>
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
The Windows CI jobs failed on `ncc run create-require-runtime.mjs` with:
Cannot find module 'C:/Users/RUNNER%7E1/AppData/Local/Temp/.../runtime.json'
The relocator derives the ESM asset base from
`new URL('.', import.meta.url).pathname`, which is percent-encoded, so any
output directory containing a character that needs escaping produces a
broken path. The Windows runner's temp dir is an 8.3 short name
(`RUNNER~1`), so `~` became `%7E`. Paths containing spaces break the same
way on every platform:
$ ncc build input.mjs -o '/tmp/out dir'
Cannot find module '/tmp/out%20dir/runtime.json'
This expression is byte-identical in 1.7.3 and 1.10.2, so the bug is not
new. It was previously unreachable for this fixture because 1.7.3 had no
`node:` specifier support: `import { resolve } from "node:path"` was not
statically analyzable, so `runtime.json` was never relocated. 1.8.0 added
`node:path` as an alias of `path`, so the reference is now resolved,
emitted as an asset, and rewritten to `__nccwpck_require__.ab + ...` —
which is where the latent bug surfaces.
Patch the loader to wrap the pathname in `decodeURIComponent`. Slicing
still happens after decoding, and it only trims a leading `/` on Windows
drive paths and the trailing `/`, neither of which decoding can alter.
The CJS branch uses `__dirname` and is untouched.
This uses pnpm's patchedDependencies, as the repo already does for
unfetch. It should be dropped once the fix is released upstream in
vercel/webpack-asset-relocator-loader.
Co-Authored-By: Steven <229881+styfle@users.noreply.github.com>
styfle
added a commit
to vercel/webpack-asset-relocator-loader
that referenced
this pull request
Aug 13, 2026
ESM builds derive `__webpack_require__.ab` from
`new URL('.', import.meta.url).pathname`, which is percent-encoded. Any
output directory whose name contains an escaped character therefore
produced an asset base that does not exist on disk:
$ ncc build input.mjs -o '/tmp/out dir'
Cannot find module '/tmp/out%20dir/runtime.json'
Spaces (`%20`), tildes (`%7E`) and non-ASCII characters (`%C3%A4`) all
hit this. It is not platform-specific, but Windows runs into it without
trying, because the GitHub Actions temp directory is an 8.3 short name
(`RUNNER~1` -> `RUNNER%7E1`).
Fixed by decoding the pathname before slicing. Slicing still happens
after decoding, and it only trims a leading `/` on Windows drive paths
and the trailing `/`, neither of which decoding can alter. The CJS
branch uses `__dirname` and is untouched.
vercel/ncc#1342 currently carries this exact change as a
`patchedDependencies` entry; it can be dropped once this ships.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Steven <229881+styfle@users.noreply.github.com>
styfle
added a commit
to vercel/webpack-asset-relocator-loader
that referenced
this pull request
Aug 13, 2026
## Why ncc needs a `.patch` today [vercel/ncc#1342](vercel/ncc#1342) bumps this loader to 1.10.2 and has to carry `patches/@vercel__webpack-asset-relocator-loader@1.10.2.patch` because of a latent bug here. This PR is that fix, upstreamed with a test, so the patch can be dropped. ### The bug ESM builds derive `__webpack_require__.ab` from `new URL('.', import.meta.url).pathname` ([`src/asset-relocator.js#L345`](https://github.com/vercel/webpack-asset-relocator-loader/blob/main/src/asset-relocator.js#L345)), and that pathname is **percent-encoded**. Any output directory whose name contains an escaped character yields an asset base that does not exist on disk: ```console $ ncc build input.mjs -o '/tmp/out dir' $ node '/tmp/out dir/index.js' Error: ENOENT: no such file or directory, open '/tmp/out%20dir/runtime.json' ``` Spaces (`%20`), tildes (`%7E`) and non-ASCII characters (`%C3%A4`) all trigger it. It is **not** platform-specific, but Windows hits it without trying: the GitHub Actions temp directory is an 8.3 short name, so `RUNNER~1` becomes `RUNNER%7E1`. That is exactly how ncc#1342 found it — green on Linux and macOS, red on all three Windows jobs. ### Why it only surfaced now The expression is byte-identical in 1.7.3 and 1.10.2, so the bug is pre-existing — ncc's fixture just could not reach it. 1.7.3 had no `node:` specifier support, so `import { resolve } from "node:path"` was not statically analyzable and the asset was never relocated. [#197](#197) added `node:path` as an alias of `path` in 1.8.0, so the reference now resolves, gets emitted as an asset, and is rewritten to `__nccwpck_require__.ab + ...` — which is where the latent bug shows up. ## The fix ```diff -new URL('.', import.meta.url).pathname.slice(...) +decodeURIComponent(new URL('.', import.meta.url).pathname).slice(...) ``` Slicing still happens after decoding, and it only trims a leading `/` on Windows drive paths and the trailing `/`, neither of which decoding can alter. The CJS branch uses `__dirname` and is untouched. This is **byte-identical** to the replacement line in ncc#1342's patch file, so that PR can delete `patches/` and the `patchedDependencies` entry with no other change once this ships. ## Tests New `test/esm-asset-base.test.js` builds an ESM bundle that reads an asset relative to `__dirname`, writes it to a real temp directory, and **executes the output with `node`** — so it asserts the asset actually loads, not just that the emitted string looks right. Three output directories, one per escape class: | Directory | Encodes to | Before | After | | --- | --- | --- | --- | | `plain` | — | ✅ pass | ✅ pass | | `out ~dir` | `out%20%7Edir` | ❌ `ENOENT .../out%20%7Edir/asset.txt` | ✅ pass | | `ütf8` | `%C3%BCtf8` | ❌ `ENOENT .../%C3%BCtf8/asset.txt` | ✅ pass | The `plain` case is the control: it passes either way, showing the decode does not regress ordinary paths. `test/unit/esm-dirname/output{,-coverage}.js` are regenerated for the one changed runtime line. ### One extra commit-adjacent change Adding a third test file perturbs jest's suite ordering, which exposed a **pre-existing** cwd leak: `test/project.test.js` calls `process.chdir()` and never restores it, and `test/index.test.js` resolves `filterAssetBase: path.resolve('test')` against the cwd. Whenever the two share a process with `project` first, 69 unit tests fail. Reproducible on stock `main`: ```console $ jest --runInBand --testSequencer ./seq.js # forces project.test.js first PASS test/project.test.js FAIL test/index.test.js Tests: 69 failed, 16 passed, 85 total ``` Rather than let my new file take the blame for a flaky run, `test/project.test.js` now restores the cwd in `afterAll`, making the suite order-independent. My own test uses `__dirname`-absolute paths throughout and is unaffected either way. ### Results Green on all six CI jobs — Node 22/24 × ubuntu / macOS / **windows** — at **88 passed, 3 suites** (baseline on `main` is 85). Windows matters here: it is the platform that surfaced the bug in ncc#1342, and the two Windows jobs now exercise all three cases against a real 8.3 short-name temp path. Locally on Node 22.22.2 / Linux, also green in every run mode, including with jest's ordering forced against it: - `yarn test` — 88 passed - `yarn test --runInBand`, both natural and forced `project`-first order — 88 passed - `yarn test-coverage` — 88 passed, thresholds met 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: vercel[bot] <35613825+vercel[bot]@users.noreply.github.com> Co-authored-by: Steven <229881+styfle@users.noreply.github.com>
1.10.3 ships the percent-decoding fix for the ESM asset base upstream (vercel/webpack-asset-relocator-loader#220), so the local patch added in the previous commit is no longer needed and is removed here. 1.10.3 is otherwise byte-identical to 1.10.2 plus that one-line change, so no test fixtures move: `update-fixtures.sh` regenerates every `test/unit/*/output*.js` with no drift. Co-Authored-By: Steven <229881+styfle@users.noreply.github.com>
styfle
enabled auto-merge (squash)
August 13, 2026 02:37
Timer
approved these changes
Aug 13, 2026
|
🎉 This PR is included in version 0.45.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bumps
@vercel/webpack-asset-relocator-loaderfrom 1.7.3 to 1.10.3 (latest).What's in the bump
node-gyp-buildpath (#185)__nccwpck_require__ is not definedregression (#195)node:pathas an alias ofpath(#197)prebuildsdirectory (#198)Because 1.10.0 publishes
src/rather than an ncc-builtdist/, the loader's previously bundled dependencies are now real transitive dependencies — that accounts for the lockfile growth. Therelocate-loaderbuild emits no new assets, anddist/ncc/loaders/relocate-loader.js.cache.jsactually shrinks slightly (499.37KB → 492.13KB).Why the unit fixtures change
The loader now registers the asset base through a webpack
RuntimeModuleinstead of the deprecatedmainTemplate.hooks.requireExtensions. Two consequences show up intest/unit/*/output*.js:/* webpack/runtime/asset-relocator-loader */instead of/* webpack/runtime/compat */, and is emitted earlier in the runtime.__nccwpck_require__no longer carry the deadif (typeof __nccwpck_require__ !== 'undefined') __nccwpck_require__.ab = ...assignment — the runtime module is only added whenRuntimeGlobals.requireis actually in the tree. The guard was always false in those bundles, so this is dead-code removal, not a behaviour change.I specifically checked that the second point is not a regression.
__nccwpck_require__.abis still emitted wherever it is referenced, verified by hand for CJS, ESM, and concatenated-TypeScript builds that relocate an asset, and by the asset-heavy integration tests (sharp,canvas,ffmpeg,oracledb,leveldown,binary-require), which all pass.The Windows fix now comes from upstream
The first push was green on Linux and macOS but failed on all three Windows jobs:
The relocator derives the ESM asset base from
new URL('.', import.meta.url).pathname, which is percent-encoded. The Windows runner's temp dir is an 8.3 short name (RUNNER~1), so~became%7E. This is not platform-specific — paths containing spaces break identically everywhere:That expression is byte-identical in 1.7.3 and 1.10.2, so the bug is pre-existing. It was simply unreachable for this fixture before: 1.7.3 had no
node:specifier support, soimport { resolve } from "node:path"was not statically analyzable andruntime.jsonwas never relocated. 1.8.0 addednode:pathas an alias ofpath, so the reference is now resolved, emitted as an asset, and rewritten to__nccwpck_require__.ab + ...— which is where the latent bug surfaces.This PR originally carried the one-line fix (wrap the pathname in
decodeURIComponent) as apatchedDependenciesentry. That patch has now shipped upstream in 1.10.3, so this PR bumps to 1.10.3 and deletes:patches/@vercel__webpack-asset-relocator-loader@1.10.2.patchpatchedDependenciesentry inpnpm-workspace.yaml(that file is now identical tomainagain)1.10.3 is 1.10.2 plus exactly that change —
diffing the two published tarballs shows only the version field and the onerequireBaseline (plus an explanatory comment). Confirmed empirically:update-fixtures.shregenerates everytest/unit/*/output*.jswith zero drift against the patched-1.10.2 fixtures already in this PR.Also fixed
update-fixtures.shinvokednode node_modules/.bin/jestfor the coverage pass. Under pnpm that path is a shell shim rather than a JS entry point, so the step crashed withSyntaxError: missing ) after argument listand never regenerated anyoutput-coverage.js. Switched both invocations tonode_modules/jest/bin/jest.js, matching thetestscript inpackage.json.That broken step is why two
output-coverage.jsfixtures had drifted onmainbefore this PR (import-meta-cjsandts-json-resolve). Their regenerated output here therefore contains one small change each that is unrelated to the relocator. The drift went unnoticed becausetest/integration.test.jscallsprocess.exit(0)inafterAllunder coverage, sopnpm test-coverageexits 0 even whentest/unit.test.jsfails.Testing
Re-run on Linux / Node 22.22.2 after the bump to 1.10.3:
pnpm test— 121 passed, 1 failed. The only failure isbinary-require.js(Cannot find module './hello.node'), becausepnpm build-test-binaryneeds a C++ toolchain that the machine used for this re-run does not have, sotest/integration/hello.nodewas never produced. CI installsnode-gypand builds it, and this test passed on the previous push.jest --coverage --globals '{"coverage":true}' test/unit— 28 passedbash update-fixtures.sh— regenerates all fixtures,git statusclean afterwardspnpm install --frozen-lockfile— succeeds with no config overrideThe
%20/%7Ecase is now covered end-to-end rather than by hand: running thecreate-require-runtimeintegration test withTMPDIR="/tmp/tmp dir~short"reproduces the Windows failure mode on Linux. It passes on 1.10.3, and to confirm the check is actually sensitive I reverteddecodeURIComponentin the built loader and watched it fail with exactly the CI error:Two pre-existing quirks I ran into and confirmed also reproduce on
main, so they are not introduced here and are left alone:--runInBand, iftest/watcher.test.jsruns beforetest/unit.test.jsin the same process, a unit test fails withTypeError: Cannot read properties of undefined (reading 'then')inside webpack'sFileSystemInfo. Reproduced at 1.7.3.One thing to flag
1.10.3 was published a few minutes before this update was pushed, and
pnpm-workspace.yamlsetsminimumReleaseAge: 2880(48h), so a fresh resolution of this version is blocked today. I generated the lockfile with a one-off--config.minimumReleaseAge=0and deliberately did not add aminimumReleaseAgeExcludeentry, so the repo's supply-chain policy is unchanged. CI is unaffected: both install steps inci.ymlusepnpm install --frozen-lockfile, which skips resolution and installs 1.10.3 from the lockfile (verified locally — it succeeds with no override). Once 1.10.3 is 48h old the constraint stops mattering entirely — hold this PR until then if you'd rather the policy not be bypassed at all.Related
Fixes TypeError with BigInt data types #1307
Confirmed this bump does address it. That
TypeError: Cannot mix BigInt and other typesoriginates in the relocator's static evaluator (relocate-loader.js.cache.js), whoseBinaryExpressionhandler is unguarded in 1.7.3. 1.10.x wraps it in atry, with a comment naming that exact error, and adds the matching guard for theUnaryExpressionBigInt case.