diff --git a/javascript/ql/lib/semmle/javascript/NPM.qll b/javascript/ql/lib/semmle/javascript/NPM.qll index 92e349594144..cbe580b45689 100644 --- a/javascript/ql/lib/semmle/javascript/NPM.qll +++ b/javascript/ql/lib/semmle/javascript/NPM.qll @@ -22,6 +22,13 @@ class PackageJson extends JsonObject { pragma[nomagic] string getDeclaredPackageName() { result = this.getPropStringValue("name") } + /** + * Gets the nearest `package.json` file found in the parent directories, if any. + */ + PackageJson getEnclosingPackage() { + result.getFolder() = packageInternalParent*(this.getFolder().getParentContainer()) + } + /** * Gets the name of this package. * If the package is located under the package `pkg1` and its relative path is `foo/bar`, then the resulting package name will be `pkg1/foo/bar`. @@ -29,18 +36,13 @@ class PackageJson extends JsonObject { string getPackageName() { result = this.getDeclaredPackageName() or - exists( - PackageJson parentPkg, Container currentDir, Container parentDir, string parentPkgName, - string pkgNameDiff - | - currentDir = this.getJsonFile().getParentContainer() and - parentDir = parentPkg.getJsonFile().getParentContainer() and - parentPkgName = parentPkg.getPropStringValue("name") and - parentDir.getAChildContainer+() = currentDir and - pkgNameDiff = currentDir.getAbsolutePath().suffix(parentDir.getAbsolutePath().length()) and - not exists(pkgNameDiff.indexOf("/node_modules/")) and - result = parentPkgName + pkgNameDiff and - not parentPkg.isPrivate() + not exists(this.getDeclaredPackageName()) and + exists(PackageJson parent | + parent = this.getEnclosingPackage() and + not parent.isPrivate() and + result = + parent.getDeclaredPackageName() + + this.getFolder().getRelativePath().suffix(parent.getFolder().getRelativePath().length()) ) } @@ -405,5 +407,6 @@ class NpmPackage extends @folder { */ private Folder packageInternalParent(Container c) { result = c.getParentContainer() and - not c.(Folder).getBaseName() = "node_modules" + not c.(Folder).getBaseName() = "node_modules" and + not c = any(PackageJson pkg).getFolder() } diff --git a/javascript/ql/src/NodeJS/UnresolvableImport.ql b/javascript/ql/src/NodeJS/UnresolvableImport.ql index 28c46229cf6a..972a6b21ccb9 100644 --- a/javascript/ql/src/NodeJS/UnresolvableImport.ql +++ b/javascript/ql/src/NodeJS/UnresolvableImport.ql @@ -36,7 +36,7 @@ where not exists(r.getImportedModule()) and // no enclosing NPM package declares a dependency on `mod` forex(NpmPackage pkg, PackageJson pkgJson | - pkg.getAModule() = r.getTopLevel() and pkgJson = pkg.getPackageJson() + pkg.getAModule() = r.getTopLevel() and pkgJson = pkg.getPackageJson().getEnclosingPackage*() | not pkgJson.declaresDependency(mod, _) and not pkgJson.getPeerDependencies().getADependency(mod, _) and diff --git a/javascript/ql/test/library-tests/NPM/tests.expected b/javascript/ql/test/library-tests/NPM/tests.expected index 568bd0a7a821..59970dcd3d67 100644 --- a/javascript/ql/test/library-tests/NPM/tests.expected +++ b/javascript/ql/test/library-tests/NPM/tests.expected @@ -39,7 +39,6 @@ modules | src/node_modules/nested | nested | src/node_modules/nested/tst3.js:1:1:2:13 | | | src/node_modules/nested/node_modules/a | a | src/node_modules/nested/node_modules/a/index.js:1:1:1:25 | | | src/node_modules/parent-module | parent-module | src/node_modules/parent-module/main.js:1:1:2:0 | | -| src/node_modules/parent-module | parent-module | src/node_modules/parent-module/sub-module/main.js:1:1:2:0 | | | src/node_modules/parent-module/sub-module | parent-module/sub-module | src/node_modules/parent-module/sub-module/main.js:1:1:2:0 | | | src/node_modules/third-party-module | third-party-module | src/node_modules/third-party-module/fancy.js:1:1:4:0 | | npm