From dbf19076f328d4b0ddec609b058b22665eeeae1f Mon Sep 17 00:00:00 2001 From: Armaan Aggarwal <49625265+Armster15@users.noreply.github.com> Date: Thu, 30 Apr 2026 08:04:53 -0700 Subject: [PATCH] fix: negated `os` / `cpu` skipped under multi-platform `supportedArchitectures` (#11375) * fix: bug with checkList fn * refactor: simplify checkList, add changeset --------- Co-authored-by: Zoltan Kochan --- .changeset/check-platform-multi-negation.md | 6 +++++ .../src/checkPlatform.ts | 6 ++--- .../test/checkPlatform.ts | 26 +++++++++++++++++++ 3 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 .changeset/check-platform-multi-negation.md diff --git a/.changeset/check-platform-multi-negation.md b/.changeset/check-platform-multi-negation.md new file mode 100644 index 0000000000..83691c1815 --- /dev/null +++ b/.changeset/check-platform-multi-negation.md @@ -0,0 +1,6 @@ +--- +"@pnpm/config.package-is-installable": patch +"pnpm": patch +--- + +Fix negated `os` / `cpu` entries (e.g. `["!win32"]`) being incorrectly rejected when `supportedArchitectures` expands to multiple platforms [#11375](https://github.com/pnpm/pnpm/pull/11375). \ No newline at end of file diff --git a/config/package-is-installable/src/checkPlatform.ts b/config/package-is-installable/src/checkPlatform.ts index 7e3420a41f..ae66c2a649 100644 --- a/config/package-is-installable/src/checkPlatform.ts +++ b/config/package-is-installable/src/checkPlatform.ts @@ -56,7 +56,6 @@ export type WantedPlatform = Partial function checkList (value: string | string[], list: string | string[]): boolean { let tmp let match = false - let blc = 0 if (typeof list === 'string') { list = [list] @@ -76,13 +75,14 @@ function checkList (value: string | string[], list: string | string[]): boolean if (tmp === value) { return false } - ++blc } else { match = match || tmp === value } } } - return match || blc === list.length + // No negation rejected any value. Accept if a positive entry matched, or if the list + // contains only negations (no positive constraints to satisfy). + return match || list.every(entry => entry[0] === '!') } function dedupeCurrent (current: string, supported: string[]): string[] { diff --git a/config/package-is-installable/test/checkPlatform.ts b/config/package-is-installable/test/checkPlatform.ts index ea6e91bdfe..242b04a49e 100644 --- a/config/package-is-installable/test/checkPlatform.ts +++ b/config/package-is-installable/test/checkPlatform.ts @@ -151,3 +151,29 @@ test('accept another libc', () => { libc: ['current', 'glibc'], })).toBeNull() }) + +test('accept negated os with multi-valued supportedArchitectures', () => { + expect(checkPlatform(packageId, { cpu: 'any', os: ['!win32'], libc: 'any' }, { + os: ['linux', 'current'], + cpu: ['current'], + libc: ['current'], + })).toBeNull() +}) + +test('accept negated cpu with multi-valued supportedArchitectures', () => { + expect(checkPlatform(packageId, { cpu: ['!ia32'], os: 'any', libc: 'any' }, { + os: ['current'], + cpu: ['x64', 'current'], + libc: ['current'], + })).toBeNull() +}) + +test('reject negated os when any supported value matches the negation', () => { + const err = checkPlatform(packageId, { cpu: 'any', os: ['!win32'], libc: 'any' }, { + os: ['win32', 'current'], + cpu: ['current'], + libc: ['current'], + }) + expect(err).toBeTruthy() + expect(err?.code).toBe('ERR_PNPM_UNSUPPORTED_PLATFORM') +})