Skip to content

Commit

Permalink
Fix accidental stripping of @Scoped npm packages. (#7609)
Browse files Browse the repository at this point in the history
The previous code did not accommodate the possibility that
`meteorNpm.getProdPackageNames` might return a package name that contained
one or more `/` characters.

Fixes #7579.
  • Loading branch information
benjamn committed Aug 8, 2016
1 parent cb587f6 commit a912eed
Showing 1 changed file with 45 additions and 9 deletions.
54 changes: 45 additions & 9 deletions tools/isobuild/bundler.js
Expand Up @@ -1885,7 +1885,23 @@ class JsImage {
};

if (nmd.local) {
let prodPackageNames;
const prodPackageTree = Object.create(null);
const complete = Symbol();
let maxPartCount = 0;

Object.keys(
meteorNpm.getProdPackageNames(nmd.sourcePath)
).forEach(name => {
const parts = name.split("/");
let tree = prodPackageTree;

parts.forEach(part => {
tree = tree[part] || (tree[part] = Object.create(null));
});

tree[complete] = true;
maxPartCount = Math.max(parts.length, maxPartCount);
});

// When copying a local node_modules directory, ignore any npm
// package directories not in the list of production package
Expand All @@ -1897,18 +1913,38 @@ class JsImage {
// package's "dependencies", then every copy of that package
// will be copied to the destination directory. A little bit of
// overcopying vastly simplifies the job of directoryFilter.
copyOptions.directoryFilter = function (dir) {
var base = files.pathBasename(dir);
var parentBase = files.pathBasename(files.pathDirname(dir));
if (parentBase !== "node_modules") {
copyOptions.directoryFilter = function isWithinProdPackage(dir) {
const parts = files.pathRelative(nmd.sourcePath, dir)
.split(files.pathSep);

let start = parts.lastIndexOf("node_modules") + 1;

if (parts.length - start > maxPartCount) {
// We're deep enough inside node_modules that it's safe to
// say we should have returned false earlier.
return true;
}

// Compute prodPackageNames lazily.
prodPackageNames = prodPackageNames ||
meteorNpm.getProdPackageNames(nmd.sourcePath);
let tree = prodPackageTree;

for (let pos = start; pos < parts.length; ++pos) {
const part = parts[pos];
const branch = tree[part];

if (! branch) {
// This dir is not prefixed by a production package name.
return false;
}

if (branch[complete]) {
// This dir is prefixed by a complete production package name.
break;
}

tree = branch;
}

return _.has(prodPackageNames, base);
return true;
};
}

Expand Down

0 comments on commit a912eed

Please sign in to comment.