diff --git a/src/Package.js b/src/Package.js index 0eb2da6..f79fb5d 100644 --- a/src/Package.js +++ b/src/Package.js @@ -12,7 +12,7 @@ const debug = require('debug')('analyze-module-size:Package') */ class Package { /** - * Create a new Packageobject + * Create a new Package object * @param {object} packageJson the parsed package.json file * @param {PackageStats} stats the statistics object */ @@ -49,13 +49,23 @@ class Package { } totalStats () { - return this.stats.merge(this.dependencies.map((dep) => { - return dep.totalStats() - })) + return this.stats.merge(Array.from(this.collectDependencies()).map((dep) => dep.stats)) } totalDependencies () { - return this.dependencies.reduce((sum, dep) => sum + dep.totalDependencies() + 1, 0) + return this.collectDependencies().size + } + + /** + * Reduce-function that not reduces the direct and recursive dependencies + */ + collectDependencies (collector = new Set()) { + this.dependencies.forEach(function (dep) { + if (collector.has(dep)) return + collector.add(dep) + dep.collectDependencies(collector) + }) + return collector } location () { diff --git a/test/Package-spec.js b/test/Package-spec.js index 59ce73e..ad5bb50 100644 --- a/test/Package-spec.js +++ b/test/Package-spec.js @@ -121,6 +121,15 @@ describe('The Package-class:', function () { Package.connectAll(base, [pkg1, pkg2, pkg3]) expect(base.totalDependencies()).to.equal(2) }) + + it('should ignore cyclic dependencies', function () { + const base = dummy('base@1.0.0', undefined, undefined) + const pkg1 = dummy('one@1.0.0', '/one', ['/', '/three']) + const pkg2 = dummy('two@1.0.0', '/two', ['/one']) + const pkg3 = dummy('dev@1.0.0', '/three', ['/two']) + Package.connectAll(base, [pkg1, pkg2, pkg3]) + expect(base.totalDependencies()).to.equal(3) + }) }) describe('The #totalStats method', function () { @@ -145,6 +154,14 @@ describe('The Package-class:', function () { Package.connectAll(base, [pkg1, pkg2, pkg3]) expect(base.totalStats()).to.deep.equal(new PackageStats('/base@1.0.0', []).merge([stats1, stats2])) }) + + it('should stop traversing at dependency cycles', function () { + const base = dummy('base@1.0.0', undefined, undefined) + const pkg1 = dummy('one@1.0.0', '/one', ['/', '/two'], stats1) + const pkg2 = dummy('two@1.0.0', '/two', ['/one'], stats2) + Package.connectAll(base, [pkg1, pkg2]) + expect(base.totalStats()).to.deep.equal(new PackageStats('/base@1.0.0', []).merge([stats1, stats2])) + }) }) })