diff options
author | Ionică Bizău <bizauionica@gmail.com> | 2016-09-19 09:11:19 +0300 |
---|---|---|
committer | Rebecca Turner <me@re-becca.org> | 2016-10-07 01:14:04 +0300 |
commit | 952f1e109a070ab4066179f6104ba9394300e342 (patch) | |
tree | 948179dfcabdf8709b8e50e9c994cbcbec1fb4b6 | |
parent | 1089878f58977559414c8a9addfc69a9c68905b0 (diff) |
deps: Guard against null "bin" values in package.json
Fixes: #13997
Credit: @IonicaBizau
PR-URL: https://github.com/npm/npm/pull/13999
Reviewed-By: @iarna
-rw-r--r-- | lib/install/deps.js | 6 | ||||
-rw-r--r-- | test/tap/install-bin-null.js | 91 |
2 files changed, 94 insertions, 3 deletions
diff --git a/lib/install/deps.js b/lib/install/deps.js index 96b88f84c..4d315ab18 100644 --- a/lib/install/deps.js +++ b/lib/install/deps.js @@ -612,13 +612,13 @@ var earliestInstallable = exports.earliestInstallable = function (requiredBy, tr // If any of the children of this tree have conflicting // binaries then we need to decline to install this package here. - var binaryMatches = typeof pkg.bin === 'object' && tree.children.some(function (child) { - if (child.removed) return false - if (typeof child.package.bin !== 'object') return false + var binaryMatches = pkg.bin && tree.children.some(function (child) { + if (child.removed || !child.package.bin) return false return Object.keys(child.package.bin).some(function (bin) { return pkg.bin[bin] }) }) + if (binaryMatches) return null // if this tree location requested the same module then we KNOW it diff --git a/test/tap/install-bin-null.js b/test/tap/install-bin-null.js new file mode 100644 index 000000000..f45528a75 --- /dev/null +++ b/test/tap/install-bin-null.js @@ -0,0 +1,91 @@ +var fs = require('graceful-fs') +var path = require('path') + +var mkdirp = require('mkdirp') +var osenv = require('osenv') +var rimraf = require('rimraf') +var test = require('tap').test + +var common = require('../common-tap.js') + +var pkg = path.join(__dirname, 'install-bin-null') + +var EXEC_OPTS = { cwd: pkg } + +var parentPkg = { + name: 'parent-package', + version: '0.0.0', + dependencies: { + 'child-package-a': 'file:./child-package-a', + 'child-package-b': 'file:./child-package-b' + } +} + +var childPkgA = { + name: 'child-package-a', + version: '0.0.0', + bin: 'index.js' +} + +var childPkgB = { + name: 'child-package-b', + version: '0.0.0', + dependencies: { + 'grandchild-package': 'file:../grandchild-package' + } +} + +var grandchildPkg = { + name: 'grandchild-package', + version: '0.0.0', + bin: null +} + +var pkgs = [childPkgA, childPkgB, grandchildPkg] + +test('the grandchild has bin:null', function (t) { + setup() + common.npm(['install'], EXEC_OPTS, function (err, code, stdout, stderr) { + t.ifErr(err, 'npm link finished without error') + t.equal(code, 0, 'exited ok') + t.ok(stdout, 'output indicating success') + t.notOk(stderr, 'no output stderr') + t.end() + }) +}) + +test('cleanup', function (t) { + cleanup() + t.end() +}) + +function cleanup () { + process.chdir(osenv.tmpdir()) + rimraf.sync(pkg) +} + +function setup () { + cleanup() + mkdirp.sync(pkg) + fs.writeFileSync( + path.join(pkg, 'package.json'), + JSON.stringify(parentPkg, null, 2) + ) + pkgs.forEach(function (json) { + process.chdir(mkPkg(json)) + }) + fs.writeFileSync( + path.join(pkg, childPkgA.name, 'index.js'), + '' + ) +} + +function mkPkg (json) { + var pkgPath = path.resolve(pkg, json.name) + mkdirp.sync(pkgPath) + fs.writeFileSync( + path.join(pkgPath, 'package.json'), + JSON.stringify(json, null, 2) + ) + return pkgPath +} |