-
Notifications
You must be signed in to change notification settings - Fork 246
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
fix(jsii): dependency submodules are not tagged #1663
Conversation
The Assembler used to ignore any export that was coined as an external library import by the TypeScript resolver. However, when traversing dependencies to collect their submodule structure, everything is an external library import (which basically is a check that the import path has a `/node_modules/` in it). This commit changes the way external imports are skipped so that when investigating submodules of a particular dependency, a different logic is used to determine whether they are external (checks that the file is under the same root; and that it is not under a `/node_modules/` subdirectory of that root). > **Note:** > This is difficult to test for in the contect of a mono-repo, as it > requires an external dependency (dependencies within the mono-repo are > resolved to their "canonical" path, which does not include the > `/node_modules/` path element, and thus is not reported as an external > library import, apparently).
AWS CodeBuild CI Report
Powered by github-codebuild-logs, available on the AWS Serverless Application Repository |
AWS CodeBuild CI Report
Powered by github-codebuild-logs, available on the AWS Serverless Application Repository |
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 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 have added some questions, nothing blocking mostly for my understanding as I have been spending time in this codepath lately :)
if (resolution.resolvedModule.isExternalLibraryImport) { | ||
if ( | ||
// We're not looking into a dependency's namespace exports, and the resolution says it's external | ||
(packageRoot === this.projectInfo.projectRoot && resolution.resolvedModule.isExternalLibraryImport) |
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.
Can this two conditions ever happen together?
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.
Yes. They'll do in the phase where we're actually compiling our project (as opposed to crawling dependencies).
// Or the module is under one the current dependency's node_modules subtree | ||
|| resolution.resolvedModule.resolvedFileName.split(path.sep).filter(entry => entry === 'node_modules').length | ||
!== packageRoot.split(path.sep).filter(entry => entry === 'node_modules').length | ||
) { |
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.
Help me out here, why does a different number of node_modules folder in a path mean we don't want to register 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.
When we reach here, we've already established that the file resolved within the same root (foo/node_modules/<dependency>/<some_file>
). This means the file belongs do <dependency>
, unless it happens to be a dependency that wasn't de-duplicated up (foo/node_modules/<dependency>/node_modules/<dependency-of-dependency>
), at which point this is effectively a re-export of another module, and we don't want to duplicate those types (it'd be SUPER awkward in Java & C# at the very least)
// We're not looking into a dependency's namespace exports, and the resolution says it's external | ||
(packageRoot === this.projectInfo.projectRoot && resolution.resolvedModule.isExternalLibraryImport) | ||
// Or the module resolves outside of the current dependency's tree entirely | ||
|| !resolution.resolvedModule.resolvedFileName.startsWith(packageRoot) | ||
// Or the module is under one the current dependency's node_modules subtree | ||
|| resolution.resolvedModule.resolvedFileName.split(path.sep).filter(entry => entry === 'node_modules').length | ||
!== packageRoot.split(path.sep).filter(entry => entry === 'node_modules').length | ||
) { | ||
// External re-exports are "pure-javascript" sugar; they need not be | ||
// represented in the jsii Assembly since the types in there will be | ||
// resolved through dependencies. | ||
return; | ||
} |
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.
To give me more context, is this if
an optimization? If not, what are we preventing?
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.
We are preventing creating a second name for the same actual type, because while TypeScript will totally follow the re-export and understand the type is just being aliased; other languages that do not feature structural type-checking will consider the two instances of the type as entirely distinct entities - that is no bueno.
Thank you for contributing! ❤️ I will now look into making sure the PR is up-to-date, then proceed to try and merge it! |
Merging (with squash)... |
AWS CodeBuild CI Report
Powered by github-codebuild-logs, available on the AWS Serverless Application Repository |
Thank you for contributing! ❤️ I will now look into making sure the PR is up-to-date, then proceed to try and merge it! |
Merging (with squash)... |
Commit Message
fix(jsii): dependency submodules are not tagged (#1663)
The Assembler used to ignore any export that was coined as an external
library import by the TypeScript resolver. However, when traversing
dependencies to collect their submodule structure, everything is an
external library import (which basically is a check that the import
path has a
/node_modules/
in it).This commit changes the way external imports are skipped so that when
investigating submodules of a particular dependency, a different logic
is used to determine whether they are external (checks that the file
is under the same root; and that it is not under a
/node_modules/
subdirectory of that root).
End Commit Message
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.