Skip to content

Commit 4ccec80

Browse files
authored
fix(core): Ignore empty bin value in Manifest#load (#5743)
**What's the problem this PR addresses?** Some packages pass an invalid empty string for a `bin` entry in their `package.json`, for example [[email protected]](https://github.com/webpack-contrib/mini-css-extract-plugin/blob/v0.4.5/package.json#L10) The NodeModules linker already ignores empty entries: https://github.com/yarnpkg/berry/blob/master/packages/plugin-nm/sources/NodeModulesLinker.ts#L982 However `scriptUtils` was not, and would append `""` to the bin path (resulting in the directory itself, not a binary) Resolves #5669 **How did you fix it?** Instead of trying to fix this everywhere that might use a manifest `.bin` property, I just remove these entries from the manifest when it is being loaded, since an empty `bin` does not seem to be a valid entry. The npm docs for `package.json` make no mention of any special case for when `bin` is set to an empty string. **Checklist** <!--- Don't worry if you miss something, chores are automatically tested. --> <!--- This checklist exists to help you remember doing the chores when you submit a PR. --> <!--- Put an `x` in all the boxes that apply. --> - [X] I have read the [Contributing Guide](https://yarnpkg.com/advanced/contributing). <!-- See https://yarnpkg.com/advanced/contributing#preparing-your-pr-to-be-released for more details. --> <!-- Check with `yarn version check` and fix with `yarn version check -i` --> - [X] I have set the packages that need to be released for my changes to be effective. <!-- The "Testing chores" workflow validates that your PR follows our guidelines. --> <!-- If it doesn't pass, click on it to see details as to what your PR might be missing. --> - [X] I will check that all automated PR checks pass before the PR gets reviewed.
1 parent dc72cba commit 4ccec80

File tree

3 files changed

+58
-2
lines changed

3 files changed

+58
-2
lines changed

.yarn/versions/fe7910e2.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
releases:
2+
"@yarnpkg/cli": patch
3+
"@yarnpkg/core": patch
4+
5+
declined:
6+
- "@yarnpkg/plugin-compat"
7+
- "@yarnpkg/plugin-constraints"
8+
- "@yarnpkg/plugin-dlx"
9+
- "@yarnpkg/plugin-essentials"
10+
- "@yarnpkg/plugin-exec"
11+
- "@yarnpkg/plugin-file"
12+
- "@yarnpkg/plugin-git"
13+
- "@yarnpkg/plugin-github"
14+
- "@yarnpkg/plugin-http"
15+
- "@yarnpkg/plugin-init"
16+
- "@yarnpkg/plugin-interactive-tools"
17+
- "@yarnpkg/plugin-link"
18+
- "@yarnpkg/plugin-nm"
19+
- "@yarnpkg/plugin-npm"
20+
- "@yarnpkg/plugin-npm-cli"
21+
- "@yarnpkg/plugin-pack"
22+
- "@yarnpkg/plugin-patch"
23+
- "@yarnpkg/plugin-pnp"
24+
- "@yarnpkg/plugin-pnpm"
25+
- "@yarnpkg/plugin-stage"
26+
- "@yarnpkg/plugin-typescript"
27+
- "@yarnpkg/plugin-version"
28+
- "@yarnpkg/plugin-workspace-tools"
29+
- "@yarnpkg/builder"
30+
- "@yarnpkg/doctor"
31+
- "@yarnpkg/extensions"
32+
- "@yarnpkg/nm"
33+
- "@yarnpkg/pnpify"
34+
- "@yarnpkg/sdks"

packages/yarnpkg-core/sources/Manifest.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,14 +278,16 @@ export class Manifest {
278278

279279
this.bin = new Map();
280280
if (typeof data.bin === `string`) {
281-
if (this.name !== null) {
281+
if (data.bin.trim() === ``) {
282+
errors.push(new Error(`Invalid bin field`));
283+
} else if (this.name !== null) {
282284
this.bin.set(this.name.name, normalizeSlashes(data.bin));
283285
} else {
284286
errors.push(new Error(`String bin field, but no attached package name`));
285287
}
286288
} else if (typeof data.bin === `object` && data.bin !== null) {
287289
for (const [key, value] of Object.entries(data.bin)) {
288-
if (typeof value !== `string`) {
290+
if (typeof value !== `string` || value.trim() === ``) {
289291
errors.push(new Error(`Invalid bin definition for '${key}'`));
290292
continue;
291293
}

packages/yarnpkg-core/tests/Manifest.test.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,25 @@ describe(`Manifest`, () => {
3434
[`start`, `node index.js`],
3535
]);
3636
});
37+
38+
it(`should preserve bin if a string was specified`, () => {
39+
const manifest = Manifest.fromText(`{ "name": "name", "bin": "./bin.js" }`);
40+
expect(manifest.exportTo({}).bin).toEqual(`./bin.js`);
41+
});
42+
43+
it(`should preserve bin map if a hash was specified`, () => {
44+
const manifest = Manifest.fromText(`{ "name": "name", "bin": { "bin1": "./bin1.js", "bin2": "./bin2.js" } }`);
45+
expect(manifest.exportTo({}).bin).toEqual({bin1: `./bin1.js`, bin2: `./bin2.js`});
46+
});
47+
48+
it(`should remove bin if an empty path was specified`, () => {
49+
const manifest = Manifest.fromText(`{ "name": "name", "bin": "" }`);
50+
expect(manifest.exportTo({}).bin).toEqual(undefined);
51+
});
52+
53+
it(`should remove entries from bin map if an empty path was specified`, () => {
54+
const manifest = Manifest.fromText(`{ "name": "name", "bin": { "bin1": " ", "bin2": "./bin2.js" } }`);
55+
expect(manifest.exportTo({}).bin).toEqual({bin2: `./bin2.js`});
56+
});
3757
});
3858
});

0 commit comments

Comments
 (0)