Skip to content
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 declaration emit for JS default re-exports that resolve to modules through synthesized default exports #56340

Merged
merged 3 commits into from
Jan 3, 2024

Conversation

andrewbranch
Copy link
Member

Fixes #55082

I think this is too narrowly targeted—@weswigham is this on the right track?

@typescript-bot typescript-bot added Author: Team For Milestone Bug PRs that fix a bug with a specific milestone labels Nov 8, 2023
Copy link
Member

@weswigham weswigham left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're definitely right that this feels a little bespoke; our ability to identify synthetic default symbols is a bit rough, since the module symbol is just returned for the default member. One day we should try swapping that to a generated Alias symbol, or at least making a bespoke symbol for the export, rather than just returning the module symbol directly.

Still, for now an approach like this one is probably fine.

@@ -9707,6 +9707,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
// does not use localName because the symbol name in this case refers to the name in the exports table,
// which we must exactly preserve
const specifier = (node.parent.parent as ExportDeclaration).moduleSpecifier;
if (specifier && target?.flags & SymbolFlags.ValueModule && (node as ExportSpecifier).propertyName?.escapedText === InternalSymbolName.Default) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

target?.flags & SymbolFlags.ValueModule is also set for namespaces (via bindModuleDeclaration), which we don't want to trigger this - honestly, I think the reliable indicators would be either the symbol declarations having a source file or ambient module declaration in them.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The thing that feels weird about the line of code I wrote here is that it’s checking both the symbol structure and the original syntax. It seems like when the JS contains ESM syntax like this, the desired outcome is just to copy the syntax verbatim, but maybe there are edge cases where that’s not true? On one hand, it feels possible to do only a check of the symbol like you’re suggesting and assert that the export specifier was default, but on the other hand, I think I could also not check the symbol at all and just set the target name to default every time the original syntax did a default re-export.

@andrewbranch
Copy link
Member Author

One day we should try swapping that to a generated Alias symbol, or at least making a bespoke symbol for the export, rather than just returning the module symbol directly.

This would make things much easier to reason about. I wonder how much memory penalty it would incur.

@sandersn sandersn added this to Not started in PR Backlog Nov 16, 2023
@sandersn sandersn moved this from Not started to Waiting on reviewers in PR Backlog Nov 21, 2023
@andrewbranch
Copy link
Member Author

@weswigham can you take a look at my latest commit?

Copy link
Member

@weswigham weswigham left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is... probably fine? I can't think of a case where there'd be an export declaration named default available but we shouldn't use the name default when serializing it. Reverse-engineering the correct symbol name when the symbol's been repurposed from another location and its actual .name isn't reliable is definitely annoying. 100% on the backlog of things-to-make-better from an API usability point of view.

PR Backlog automation moved this from Waiting on reviewers to Needs merge Jan 3, 2024
@andrewbranch andrewbranch merged commit a099275 into microsoft:main Jan 3, 2024
19 checks passed
PR Backlog automation moved this from Needs merge to Done Jan 3, 2024
@andrewbranch andrewbranch deleted the bug/55082 branch January 3, 2024 21:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Author: Team For Milestone Bug PRs that fix a bug with a specific milestone
Projects
PR Backlog
  
Done
Development

Successfully merging this pull request may close these issues.

Re-exporting default from a dependency in JavaScript produces an invalid declaration file
3 participants