-
Notifications
You must be signed in to change notification settings - Fork 1.8k
JS: Support sub modules #12975
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JS: Support sub modules #12975
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly OK 👍
But I got a few comments.
parentPackageName = parentPackage.getPropStringValue("name") and | ||
parentDir.indexOf("node_modules") != -1 and | ||
currentDir != parentDir and | ||
currentDir.indexOf(parentDir) = 0 and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are doing a string-comparison here, and I'm not a fan of that.
You could instead drop the .getAbsolutePath()
, and then do something like:
parentDir.getAChildContainer+() = currentDir
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you!
That looks better!
I refactored the codes here.
@@ -0,0 +1 @@ | |||
export default "parent"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You have a typo in the folder name.
You have named the folder parent-modue
instead of parent-module
.
I tried to run your test-case locally using node
(to confirm that the behavior is correct), and it failed due to the typo.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, sorry.
I'll fix it soon.
exists(PackageJson parentPkg, Container currentDir, Container parentDir | | ||
currentDir = this.getJsonFile().getParentContainer() and | ||
parentDir = parentPkg.getJsonFile().getParentContainer() and | ||
parentDir.getParentContainer+().getBaseName() = "node_modules" and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
parentDir.getParentContainer+().getBaseName() = "node_modules" and | |
parentDir.getParentContainer().getBaseName() = "node_modules" and |
I'm not sure I like that transitive closure.
Your test only covers that the parentDir
is directly contained within node_modules
, and I'm not sure what happens if parentDir
is not directly inside node_modules
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a scoped package such as @babel/core
.
In this case pakcage.json
located in node_modules/@babel/core/
and there is no package in node_modules/@babel/
.
AFAIK, this is the only case that parentDir
is not directly inside node_modules
.
Do you think it is better to rewrite this code to the following one?
parentDir.getParentContainer().getBaseName() = "node_modules" or parentDir.getParentContainer().getParentContainer().getBaseName() = "node_modules" and
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think it is better to rewrite this code to the following one?
Yes, that could work.
And in the .getParentContainer().getParentContainer()
case you can check that the packagename of the parentPkg
contains "/"
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi, I fixed the code.
Thanks for your review!
parentPkgName = parentPkg.getPropStringValue("name") and | ||
( | ||
parentDir.getParentContainer().getBaseName() = "node_modules" | ||
or | ||
// Scoped package is located in node_modules/@scope/pkgname | ||
parentDir.getParentContainer().getParentContainer().getBaseName() = "node_modules" and | ||
exists(parentPkgName.indexOf("/")) | ||
) and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
parentPkgName = parentPkg.getPropStringValue("name") and | |
( | |
parentDir.getParentContainer().getBaseName() = "node_modules" | |
or | |
// Scoped package is located in node_modules/@scope/pkgname | |
parentDir.getParentContainer().getParentContainer().getBaseName() = "node_modules" and | |
exists(parentPkgName.indexOf("/")) | |
) and | |
parentPkgName = parentPkg.getPropStringValue("name") and |
On further thought (sorry for the many rounds of feedback).
Do we need to restrict to just packages contained within a node_modules
folder?
Monorepos that contain many packages could experience this pattern without a node_module
folder being part of it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think developers need to define exports
property in package.json
to access other packages, if they aren't located in node_modules
.
I think removing these codes might cause some false positives, but they might be rare case, so we might be able to accept them...?
I looked at some packages and in the case of @github/webauthn-json
, they defined exports
property so that @github/webauthn-json/extended
will work.
This means that the package name is defined independently of the directory structure.
https://github.com/github/webauthn-json/blob/e932b3585fa70b0bd5b5a4012ba7dbad7b0a0d0f/package.json#L18
https://nodejs.org/api/packages.html#exports-sugar
If we remove the exports property, @github/webauthn-json/extended
will not work.
$ node -e 'console.log(require("@github/webauthn-json/extended"))'
{
base64urlToBuffer: [Getter],
...
supported: [Getter]
}
$ gsed -i 's/exports/foobar/' package.json
$ node -e 'console.log(require("@github/webauthn-json/extended"))'
node:internal/modules/cjs/loader:936
throw err;
^
Error: Cannot find module '@github/webauthn-json/extended'
In https://github.com/keystonejs/keystone, we can call subpath modules like @keystone-6/core/admin-ui/router
after npm install
.
In this case, npm workspaces put the symlinks in the node_modules
directory.
https://github.com/keystonejs/keystone/blob/5ac8ef453/package.json#L109
https://docs.npmjs.com/cli/v7/using-npm/workspaces
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think developers need to define exports property in package.json to access other packages, if they aren't located in node_modules.
We already have some support for "exports"
elsewhere.
My thinking was that we most of the time ignore node_modules
folder when we parse a project, so your contribution is very rarely relevant.
but they might be rare case, so we might be able to accept them...?
I'll run an evaluation if you try to remove the node_modules
restriction.
If the results are noisy (or if the performance goes bad), then we can revert the change again.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok!
I committed your suggestion.👌
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The failing tests (see the CI below) revealed something interesting.
We get some package names that include node_modules
.
E.g. the Dependencies.ql
test finds a new package-name: test-package/node_modules/bundled-package
.
I don't think that was what you meant with this contribution? so maybe filter those out?
I did some evaluations (internal links: one, two), and that looks fine.
Nothing happened in those evaluations, everything is the same.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh I see.
I'll filter them out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks fine now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks OK.
I'll run an evaluation on it later, but our system for doing so is having some issues right now.
And I'm on PTO thursday+friday, so it might be until early next week before I can check it out.
Don't worry, I haven't forgotten about your PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
Enjoy your holiday! 😀
Co-authored-by: Erik Krogh Kristensen <erik-krogh@github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good 👍
Evaluation (internal link) looks OK.
Some npm packages have sub modules which have path suffix after the module name.
For example,
@github/webauthn-json
has sub module@github/webauthn-json/extended
and its structure looks like this.I updated
NPM.qll
so that the CodeQL finds these modules.https://nodejs.org/api/modules.html#loading-from-node_modules-folders