Files
pnpm/pnpm11/worker/test/storedRequiresBuild.test.ts
Zoltan KochanandClaude Opus 5.5 16af1b1665 fix(store): tighten the gypfile recheck of stored requiresBuild (#15635)
Follow-up to the review of pnpm/pnpm#14900.

- The v11 worker parsed the store's package.json with a bare
  JSON.parse, so a manifest starting with a byte-order mark failed to
  parse and kept the stale `requiresBuild: true`. It now uses
  `parseJsonBufferSync`, which strips the mark, as store ingestion does.
- Both stacks answer from the manifest's install scripts before
  scanning the file index, and the TypeScript check no longer copies
  the index.
- The predicate is renamed to `stored_requires_build_needs_manifest_check`
  / `storedRequiresBuildNeedsManifestCheck`, and its docs state the
  current contract.
- `checkBindingGyp`'s JSDoc states that its caller decides whether the
  synthesized script applies.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 10:48:32 +02:00

41 lines
1.8 KiB
TypeScript

import fs from 'node:fs'
import os from 'node:os'
import path from 'node:path'
import { afterAll, expect, test } from '@jest/globals'
import type { PackageFilesIndex } from '@pnpm/store.cafs'
import { StoreIndex } from '@pnpm/store.index'
import { addFilesFromDir, finishWorkers, readPkgFromCafs } from '../lib/index.js'
afterAll(() => finishWorkers())
test('a stored requiresBuild that predates gypfile is rechecked against the package.json in the store', async () => {
expect(await readLegacyRowRequiresBuild({ name: 'opted-out', version: '1.0.0', gypfile: false })).toBe(false)
expect(await readLegacyRowRequiresBuild({ name: 'not-opted-out', version: '1.0.0' })).toBe(true)
})
test('a package.json with a byte-order mark is rechecked like any other', async () => {
expect(await readLegacyRowRequiresBuild({ name: 'bom', version: '1.0.0', gypfile: false }, '\uFEFF')).toBe(false)
})
async function readLegacyRowRequiresBuild (manifest: Record<string, unknown>, prefix = ''): Promise<boolean> {
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'pnpm-stored-requires-build-'))
const dir = path.join(tmp, 'pkg')
fs.mkdirSync(dir)
fs.writeFileSync(path.join(dir, 'package.json'), prefix + JSON.stringify(manifest))
fs.writeFileSync(path.join(dir, 'binding.gyp'), '{}')
const storeDir = path.join(tmp, 'store')
const storeIndex = new StoreIndex(storeDir)
const filesIndexFile = path.join(storeDir, 'pkg.json')
await addFilesFromDir({ storeDir, dir, filesIndexFile, storeIndex })
const row = storeIndex.get(filesIndexFile) as PackageFilesIndex
delete row.manifest?.gypfile
storeIndex.set(filesIndexFile, { ...row, requiresBuild: true })
const result = await readPkgFromCafs({ storeDir, verifyStoreIntegrity: false }, filesIndexFile)
storeIndex.close()
return result.files.requiresBuild
}