Repository navigation
Tags: vercel/ncc
Tags
feat: update @vercel/webpack-asset-relocator-loader to 1.10.3 (#1342) Bumps `@vercel/webpack-asset-relocator-loader` from **1.7.3** to **1.10.3** (latest). ## What's in the bump | Version | Change | | --- | --- | | 1.7.4 | Use a computed `node-gyp-build` path ([#185](vercel/webpack-asset-relocator-loader#185)) | | 1.7.5 | Fix `__nccwpck_require__ is not defined` regression ([#195](vercel/webpack-asset-relocator-loader#195)) | | 1.8.0 | Support `node:path` as an alias of `path` ([#197](vercel/webpack-asset-relocator-loader#197)) | | 1.9.0 | Load native addons from the `prebuilds` directory ([#198](vercel/webpack-asset-relocator-loader#198)) | | 1.9.1 | Support the packaging format of sharp v0.34.x ([#199](vercel/webpack-asset-relocator-loader#199)) | | 1.10.0 | Ship the loader as source instead of a prebuilt bundle ([#200](vercel/webpack-asset-relocator-loader#200)) | | 1.10.2 | Packaging/CI fixes | | 1.10.3 | Percent-decode the ESM asset base ([#220](vercel/webpack-asset-relocator-loader#220)) | Because 1.10.0 publishes `src/` rather than an ncc-built `dist/`, the loader's previously bundled dependencies are now real transitive dependencies — that accounts for the lockfile growth. The `relocate-loader` build emits no new assets, and `dist/ncc/loaders/relocate-loader.js.cache.js` actually shrinks slightly (499.37KB → 492.13KB). ## Why the unit fixtures change The loader now registers the asset base through a webpack `RuntimeModule` instead of the deprecated `mainTemplate.hooks.requireExtensions`. Two consequences show up in `test/unit/*/output*.js`: 1. The block is labelled `/* webpack/runtime/asset-relocator-loader */` instead of `/* webpack/runtime/compat */`, and is emitted earlier in the runtime. 2. Bundles that never reference `__nccwpck_require__` no longer carry the dead `if (typeof __nccwpck_require__ !== 'undefined') __nccwpck_require__.ab = ...` assignment — the runtime module is only added when `RuntimeGlobals.require` is 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__.ab` is 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: ``` 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. 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: ``` $ ncc build input.mjs -o '/tmp/out dir' Cannot find module '/tmp/out%20dir/runtime.json' ``` 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, so `import { resolve } from "node:path"` was not statically analyzable and `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. This PR originally carried the one-line fix (wrap the pathname in `decodeURIComponent`) as a `patchedDependencies` entry. **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.patch` - the matching `patchedDependencies` entry in `pnpm-workspace.yaml` (that file is now identical to `main` again) 1.10.3 is 1.10.2 plus exactly that change — `diff`ing the two published tarballs shows only the version field and the one `requireBase` line (plus an explanatory comment). Confirmed empirically: `update-fixtures.sh` regenerates every `test/unit/*/output*.js` with **zero drift** against the patched-1.10.2 fixtures already in this PR. ## Also fixed `update-fixtures.sh` invoked `node node_modules/.bin/jest` for the coverage pass. Under pnpm that path is a shell shim rather than a JS entry point, so the step crashed with `SyntaxError: missing ) after argument list` and never regenerated any `output-coverage.js`. Switched both invocations to `node_modules/jest/bin/jest.js`, matching the `test` script in `package.json`. That broken step is why two `output-coverage.js` fixtures had drifted on `main` before this PR (`import-meta-cjs` and `ts-json-resolve`). Their regenerated output here therefore contains one small change each that is unrelated to the relocator. The drift went unnoticed because `test/integration.test.js` calls `process.exit(0)` in `afterAll` under coverage, so `pnpm test-coverage` exits 0 even when `test/unit.test.js` fails. ## 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 is `binary-require.js` (`Cannot find module './hello.node'`), because `pnpm build-test-binary` needs a C++ toolchain that the machine used for this re-run does not have, so `test/integration/hello.node` was never produced. CI installs `node-gyp` and builds it, and this test passed on the previous push. - `jest --coverage --globals '{"coverage":true}' test/unit` — **28 passed** - `bash update-fixtures.sh` — regenerates all fixtures, `git status` clean afterwards - `pnpm install --frozen-lockfile` — succeeds with no config override The `%20`/`%7E` case is now covered end-to-end rather than by hand: running the `create-require-runtime` integration test with `TMPDIR="/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 reverted `decodeURIComponent` in the built loader and watched it fail with exactly the CI error: ``` Cannot find module '/tmp/tmp%20dir%7Eshort/<hash>/runtime.json' ``` Two pre-existing quirks I ran into and confirmed also reproduce on `main`, so they are **not** introduced here and are left alone: - Under `--runInBand`, if `test/watcher.test.js` runs before `test/unit.test.js` in the same process, a unit test fails with `TypeError: Cannot read properties of undefined (reading 'then')` inside webpack's `FileSystemInfo`. Reproduced at 1.7.3. - The stale coverage fixtures described above. ## One thing to flag 1.10.3 was published a few minutes before this update was pushed, and `pnpm-workspace.yaml` sets `minimumReleaseAge: 2880` (48h), so a fresh resolution of this version is blocked today. I generated the lockfile with a one-off `--config.minimumReleaseAge=0` and deliberately did **not** add a `minimumReleaseAgeExclude` entry, so the repo's supply-chain policy is unchanged. CI is unaffected: both install steps in `ci.yml` use `pnpm 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 #1307 Confirmed this bump does address it. That `TypeError: Cannot mix BigInt and other types` originates in the relocator's static evaluator (`relocate-loader.js.cache.js`), whose `BinaryExpression` handler is unguarded in 1.7.3. 1.10.x wraps it in a `try`, with a comment naming that exact error, and adds the matching guard for the `UnaryExpression` BigInt case. --------- Co-authored-by: vercel[bot] <35613825+vercel[bot]@users.noreply.github.com> Co-authored-by: Steven <229881+styfle@users.noreply.github.com>
fix: preserve runtime createRequire in ESM builds (#1334) ## Problem Since 0.38.2, an ESM build can replace a runtime `createRequire(...)` binding with `undefined`, causing the later runtime `require(...)` call to throw. ## Change - Disable Webpack's `createRequire` parser handling in ncc so Node evaluates the call at runtime. - Add a normal integration fixture with an `.mjs` entry that imports the TypeScript runtime payload and loads a runtime-selected JSON module. This keeps the fix at ncc's Webpack configuration boundary and covers the reported runtime behavior without changing dependency tracing. ## Validation - `node scripts/build.js --no-cache` - `node --expose-gc --max_old_space_size=4096 node_modules/jest/bin/jest.js test/integration.test.js --runInBand --testNamePattern create-require-runtime` - 1 passed - `pnpm test -- test/unit.test.js` - 28 passed - `node --expose-gc --max_old_space_size=4096 node_modules/jest/bin/jest.js --runInBand test/integration.test.js --testNamePattern='^(?!should execute "ncc run (?:axios\.js|canvas\.js|isomorphic-unfetch\.js|request-ts\.ts|request\.js|sharp\.js|socket\.io\.js)"$).*'` - 62 passed; 7 local environment-dependent cases skipped - Negative control with Webpack's `createRequire` parsing restored reproduced `TypeError: input_require is not a function`. ## Risk The parser option applies to all JavaScript handled by ncc. It intentionally preserves `createRequire` for Node to evaluate at runtime, so modules selected only at runtime must still be deployed with the bundle. The cross-platform Node 22/24/26 matrix remains for CI. A local CLI watch test failed with Watchpack `EMFILE` errors and reproduced identically on `origin/main`, so it is not attributed to this change. ## Out of scope - Changing how ncc traces or deploys runtime-selected modules. - Dependency or lockfile updates. ## Issue linkage Fixes #1312
feat(ci): upgrade python and remove LLVM LTO flags from MSVC build to… … fix Node 26 Windows CI (#1330) ## Root Cause Node.js 26 on Windows is compiled using Clang with thin LTO enabled (`enable_thin_lto=true`, `lto_jobs=2`). When `node-gyp rebuild` runs without `--nodedir`, it generates `build/config.gypi` from the running Node.js binary's `process.config`. This causes Node.js's `common.gypi` to inject LLVM/Clang-specific flags into the MSVC build: - `-flto=thin` → compiler/linker warning (ignored by MSVC) - `/opt:lldltojobs=2` → **fatal linker error `LNK1117`** (MSVC does not understand LLVM LTO job flags) ## Fix Modified `test/binary/binding.gyp` to strip the incompatible LLVM LTO flags when building on Windows with MSVC: - Added a `"lto_jobs%": ""` default variable as a safe fallback for Node versions that do not define this variable - Added a Windows-specific `conditions` block using GYP's `AdditionalOptions!` list-removal operator to remove `-flto=thin`, `-flto=full`, and `/opt:lldltojobs=<(lto_jobs)` from both `VCCLCompilerTool` and `VCLinkerTool` options The fix is a no-op on Node 22/24 (LTO not enabled, no flags to remove) and does not affect Linux or macOS builds. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
fix(security): Predictable global cache directory in /tmp enables sym… …link/hijack risks (#1314) ## Problem The cache directory is a fixed, shared path (`/tmp/ncc-cache`). On multi-user systems this can be pre-created or manipulated by another user (symlink/hardlink attacks), potentially causing cache poisoning, unintended file writes, or data leakage between builds/users depending on how cache files are later written. **Severity**: `medium` **File**: `src/utils/ncc-cache-dir.js` ## Solution Use a per-user/per-project cache directory with secure creation semantics (e.g., `fs.mkdtemp` under user-owned base dir), enforce permissions (`0700`), and verify path is not a symlink before writing. ## Changes - `src/utils/ncc-cache-dir.js` (modified) ## Testing - [ ] Existing tests pass - [ ] Manual review completed - [ ] No new warnings/errors introduced --------- Signed-off-by: tuanaiseo <221258316+tuanaiseo@users.noreply.github.com> Co-authored-by: Steven <steven@ceriously.com>
fix: Reorder extension resolution to prioritise TypeScript over JSON (#… …1315) When a directory contains both `test.json` and `test.ts`, an extensionless import like: ```ts import { myFunction } from './test'; ``` resolves to `test.json` instead of `test.ts`, causing all exported methods from the TypeScript file to be unresolvable during the build. Webpack resolves extensions in the order they appear in the `resolve.extensions` array. Since `.json` appears before `.ts` and `.tsx`, webpack picks the JSON file first when both exist. ### Reproduce (The test project need a `tsconfig.json` with `compilerOptions.resolveJsonModule: true`) 1. Create a directory with two files sharing the same base name: **`src/test.json`** ```json { "key": "value" } ``` **`src/test.ts`** ```ts export function greet(): string { return "hello"; } ``` 2. Import without an extension from another TypeScript file: **`src/index.ts`** ```ts import { greet } from './test'; console.log(greet()); ``` 3. Run `ncc build src/index.ts` the build fails because `./test` resolves to `test.json`, which has no `greet` export.
feat: support TypeScript 6 transpile builds (#1316) ## Summary Updates `ts-loader` to `9.5.7` so ncc's bundled TypeScript loader preserves configured `rootDir` during `transpileModule` builds. This fixes TypeScript 6 `TS5011` failures like: ```text TS5011: The common source directory of 'tsconfig.json' is './actions/javascript/...'. The 'rootDir' setting must be explicitly set to this or another path to adjust your output's file layout. ``` `ts-loader` fixed this upstream in TypeStrong/ts-loader#1679. ## Verification - Ran `yarn build`
PreviousNext