diff --git a/javascript/ql/lib/change-notes/2023-04-30-npm-submodule.md b/javascript/ql/lib/change-notes/2023-04-30-npm-submodule.md new file mode 100644 index 000000000000..5ef95cf7d581 --- /dev/null +++ b/javascript/ql/lib/change-notes/2023-04-30-npm-submodule.md @@ -0,0 +1,5 @@ +--- +category: minorAnalysis +--- + +- Added a support of sub modules in `node_modules`. diff --git a/javascript/ql/lib/semmle/javascript/NPM.qll b/javascript/ql/lib/semmle/javascript/NPM.qll index d05045784a67..e1059d94930a 100644 --- a/javascript/ql/lib/semmle/javascript/NPM.qll +++ b/javascript/ql/lib/semmle/javascript/NPM.qll @@ -12,8 +12,26 @@ class PackageJson extends JsonObject { this.isTopLevel() } - /** Gets the name of this package. */ - string getPackageName() { result = this.getPropStringValue("name") } + /** + * 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`. + */ + string getPackageName() { + result = this.getPropStringValue("name") + 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 + ) + } /** Gets the version of this package. */ string getVersion() { result = this.getPropStringValue("version") } diff --git a/javascript/ql/test/library-tests/NPM/src/node_modules/parent-module/main.js b/javascript/ql/test/library-tests/NPM/src/node_modules/parent-module/main.js new file mode 100644 index 000000000000..8871fb179ac2 --- /dev/null +++ b/javascript/ql/test/library-tests/NPM/src/node_modules/parent-module/main.js @@ -0,0 +1 @@ +module.exports = "parent"; diff --git a/javascript/ql/test/library-tests/NPM/src/node_modules/parent-module/package.json b/javascript/ql/test/library-tests/NPM/src/node_modules/parent-module/package.json new file mode 100644 index 000000000000..44481e79cba5 --- /dev/null +++ b/javascript/ql/test/library-tests/NPM/src/node_modules/parent-module/package.json @@ -0,0 +1,4 @@ +{ + "name": "parent-module", + "main": "main.js" +} \ No newline at end of file diff --git a/javascript/ql/test/library-tests/NPM/src/node_modules/parent-module/sub-module/main.js b/javascript/ql/test/library-tests/NPM/src/node_modules/parent-module/sub-module/main.js new file mode 100644 index 000000000000..0bf6641bb0a2 --- /dev/null +++ b/javascript/ql/test/library-tests/NPM/src/node_modules/parent-module/sub-module/main.js @@ -0,0 +1 @@ +module.exports = "sub"; diff --git a/javascript/ql/test/library-tests/NPM/src/node_modules/parent-module/sub-module/package.json b/javascript/ql/test/library-tests/NPM/src/node_modules/parent-module/sub-module/package.json new file mode 100644 index 000000000000..a60376465b81 --- /dev/null +++ b/javascript/ql/test/library-tests/NPM/src/node_modules/parent-module/sub-module/package.json @@ -0,0 +1,3 @@ +{ + "main": "main.js" +} \ No newline at end of file diff --git a/javascript/ql/test/library-tests/NPM/src/test-submodule.js b/javascript/ql/test/library-tests/NPM/src/test-submodule.js new file mode 100644 index 000000000000..f40d70a3aa15 --- /dev/null +++ b/javascript/ql/test/library-tests/NPM/src/test-submodule.js @@ -0,0 +1,2 @@ +require("parent-module"); +require("parent-module/sub-module"); diff --git a/javascript/ql/test/library-tests/NPM/tests.expected b/javascript/ql/test/library-tests/NPM/tests.expected index 48691fe01179..a75c705be266 100644 --- a/javascript/ql/test/library-tests/NPM/tests.expected +++ b/javascript/ql/test/library-tests/NPM/tests.expected @@ -8,6 +8,8 @@ importedFile | src/node_modules/nested/tst3.js:1:1:1:29 | require ... odule') | src/node_modules/third-party-module/fancy.js:0:0:0:0 | src/node_modules/third-party-module/fancy.js | | src/node_modules/nested/tst3.js:2:1:2:12 | require('a') | src/node_modules/nested/node_modules/a/index.js:0:0:0:0 | src/node_modules/nested/node_modules/a/index.js | | src/node_modules/tst2.js:1:1:1:38 | require ... cy.js') | src/node_modules/third-party-module/fancy.js:0:0:0:0 | src/node_modules/third-party-module/fancy.js | +| src/test-submodule.js:1:1:1:24 | require ... odule") | src/node_modules/parent-module/main.js:0:0:0:0 | src/node_modules/parent-module/main.js | +| src/test-submodule.js:2:1:2:35 | require ... odule") | src/node_modules/parent-module/sub-module/main.js:0:0:0:0 | src/node_modules/parent-module/sub-module/main.js | | src/tst2.js:1:1:1:12 | require(".") | src/index.js:0:0:0:0 | src/index.js | | src/tst.js:1:1:1:38 | require ... cy.js') | src/node_modules/third-party-module/fancy.js:0:0:0:0 | src/node_modules/third-party-module/fancy.js | | src/tst.js:2:1:2:37 | require ... ckage') | src/node_modules/third-party-module/package.json:0:0:0:0 | src/node_modules/third-party-module/package.json | @@ -16,18 +18,24 @@ importedModule | src/node_modules/nested/tst3.js:1:1:1:29 | require ... odule') | src/node_modules/third-party-module/fancy.js:1:1:4:0 | | | src/node_modules/nested/tst3.js:2:1:2:12 | require('a') | src/node_modules/nested/node_modules/a/index.js:1:1:1:25 | | | src/node_modules/tst2.js:1:1:1:38 | require ... cy.js') | src/node_modules/third-party-module/fancy.js:1:1:4:0 | | +| src/test-submodule.js:1:1:1:24 | require ... odule") | src/node_modules/parent-module/main.js:1:1:2:0 | | +| src/test-submodule.js:2:1:2:35 | require ... odule") | src/node_modules/parent-module/sub-module/main.js:1:1:2:0 | | | src/tst2.js:1:1:1:12 | require(".") | src/index.js:1:1:4:0 | | | src/tst.js:1:1:1:38 | require ... cy.js') | src/node_modules/third-party-module/fancy.js:1:1:4:0 | | modules | src | test-package | src/index.js:1:1:4:0 | | | src | test-package | src/lib/tst2.js:1:1:1:14 | | | src | test-package | src/lib/tst.js:1:1:4:0 | | +| src | test-package | src/test-submodule.js:1:1:3:0 | | | src | test-package | src/tst2.js:1:1:1:13 | | | src | test-package | src/tst.js:1:1:2:38 | | | src/node_modules/b | b | src/node_modules/b/lib/index.js:1:1:2:0 | | | src/node_modules/b | b | src/node_modules/b/lib/util.ts:1:1:2:0 | | | src/node_modules/c | c | src/node_modules/c/src/index.js:1:1:2:0 | | | src/node_modules/d | d | src/node_modules/d/main.js:1:1:2:0 | | +| 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 | src/node_modules/third-party-module/package.json:1:1:5:1 | {\\n "na ... y.js"\\n} | third-party-module | 23.4.0 | @@ -36,12 +44,16 @@ getMainModule | src/node_modules/b/package.json:1:1:4:1 | {\\n "na ... "lib"\\n} | b | src/node_modules/b/lib/index.js:1:1:2:0 | | | src/node_modules/c/package.json:1:1:4:1 | {\\n "na ... src/"\\n} | c | src/node_modules/c/src/index.js:1:1:2:0 | | | src/node_modules/d/package.json:1:1:4:1 | {\\n "na ... main"\\n} | d | src/node_modules/d/main.js:1:1:2:0 | | +| src/node_modules/parent-module/package.json:1:1:4:1 | {\\n "na ... n.js"\\n} | parent-module | src/node_modules/parent-module/main.js:1:1:2:0 | | +| src/node_modules/parent-module/sub-module/package.json:1:1:3:1 | {\\n "ma ... n.js"\\n} | parent-module/sub-module | src/node_modules/parent-module/sub-module/main.js:1:1:2:0 | | | src/node_modules/third-party-module/package.json:1:1:5:1 | {\\n "na ... y.js"\\n} | third-party-module | src/node_modules/third-party-module/fancy.js:1:1:4:0 | | | src/package.json:1:1:20:1 | {\\n "na ... "\\n }\\n} | test-package | src/index.js:1:1:4:0 | | packageJson | src/node_modules/b/package.json:1:1:4:1 | {\\n "na ... "lib"\\n} | | src/node_modules/c/package.json:1:1:4:1 | {\\n "na ... src/"\\n} | | src/node_modules/d/package.json:1:1:4:1 | {\\n "na ... main"\\n} | +| src/node_modules/parent-module/package.json:1:1:4:1 | {\\n "na ... n.js"\\n} | +| src/node_modules/parent-module/sub-module/package.json:1:1:3:1 | {\\n "ma ... n.js"\\n} | | src/node_modules/third-party-module/package.json:1:1:5:1 | {\\n "na ... y.js"\\n} | | src/package.json:1:1:20:1 | {\\n "na ... "\\n }\\n} | dependencyInfo @@ -53,5 +65,6 @@ dependencyInfo | src/package.json:11:20:11:37 | "1.2.3-alpha.beta" | something | unknown | | src/package.json:12:14:12:57 | "! garb ... arse %" | foo | unknown | | src/package.json:15:16:15:20 | "1.0" | mocha | 1.0 | +| src/test-submodule.js:1:1:3:0 | | test-package | 0.1.0 | | src/tst2.js:1:1:1:13 | | test-package | 0.1.0 | | src/tst.js:1:1:2:38 | | test-package | 0.1.0 |