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
Under jsx: preserve, actually preserve expressions which contain only comments #41757
Under jsx: preserve, actually preserve expressions which contain only comments #41757
Conversation
src/compiler/emitter.ts
Outdated
@@ -3378,8 +3379,8 @@ namespace ts { | |||
} | |||
|
|||
function emitJsxExpression(node: JsxExpression) { | |||
if (node.expression) { | |||
writePunctuation("{"); | |||
if (node.expression || (!commentsDisabled && !nodeIsSynthesized(node) && getTextOfNode(node).length > 2 && getTextOfNode(node).indexOf("/*") > -1)) { // preserve empty expressions if they contain comments! |
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.
hasCommentAtPosition
isn't a thing we currently have, but this does a, okay job of approximating it. Obviously doesn't handle something like
const x = <div>
{ // first line
/*last line*/}
</div>;
Maybe it's worth doing a full check with forEachTrailingCommentRange
? @rbuckton - your opinion?
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 we care about //
comments? The new check only handles /**/
comments, right?
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.
Yep. That's why I'm asking if it's worth doing a full comment range iteration to check if there are any comments attached to the position.
@@ -1790,7 +1790,7 @@ namespace ts { | |||
const name = importDeclaration.propertyName || importDeclaration.name; | |||
return setTextRange( | |||
factory.createPropertyAccessExpression( | |||
factory.getGeneratedNameForNode(importDeclaration.parent.parent.parent), | |||
factory.getGeneratedNameForNode(importDeclaration.parent?.parent?.parent || importDeclaration), |
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.
This change (and the similar ones in system
) are what fix the crash mentioned in the OP. The non-module file has a reference to a synthetic import that, since it's never actually inserted into the file (since it's not a module), is never parented, and thus has no name. We emit a (admittedly type system, rather than grammar/program) error in these cases usually (module "react/jsx-runtime" not found
), so the emitted JS being nonfunctional is probably fine, but this case might need a more descriptive error added. The emit simply uses an arbitrary name now (_a
), rather than crashing.
Since this part fixes a crash, I'm wondering if I should (partially?) port this to the 4.1 branch or no? @DanielRosenwasser ?
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.
This comment may actually be referring to the crash fixed here (assuming the input file is exactly what the user in that comment says, odd as a top-level return
is, since we wouldn't mark that as a module), though the stack is very different than the on the OP of that thread refers to (and is definitely a separate issue).
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.
Seems reasonable although (1) I'm not an expert here (2) I'd like to know what happens for
{
// comment
}
maybe this is nonsensical for JSX though.
tests/baselines/reference/commentsOnJSXExpressionsArePreserved(jsx=preserve,module=commonjs).js
Outdated
Show resolved
Hide resolved
src/compiler/emitter.ts
Outdated
@@ -3378,8 +3379,8 @@ namespace ts { | |||
} | |||
|
|||
function emitJsxExpression(node: JsxExpression) { | |||
if (node.expression) { | |||
writePunctuation("{"); | |||
if (node.expression || (!commentsDisabled && !nodeIsSynthesized(node) && getTextOfNode(node).length > 2 && getTextOfNode(node).indexOf("/*") > -1)) { // preserve empty expressions if they contain comments! |
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 we care about //
comments? The new check only handles /**/
comments, right?
e358fc9
to
d1db247
Compare
@sandersn since nobody else weighed in, I opted to change this to do a full comment scan. It's ready for another look. @typescript-bot perf test this - this hopefully doesn't hurt |
Heya @weswigham, I've started to run the perf test suite on this PR at d1db247. You can monitor the build here. Update: The results are in! |
@weswigham Here they are:Comparison Report - master..41757
System
Hosts
Scenarios
|
Eyyy, and we don't have emit on for |
And, perhaps more importantly, fixes a crash caused by the interaction of the
module
orsystem
transformers and the newjsx
transforms discovered along the way (in the same test case).Fixes #41754