-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Fixed a printer crash caused by empty parameter modifiers #60537
base: main
Are you sure you want to change the base?
Fixed a printer crash caused by empty parameter modifiers #60537
Conversation
This PR doesn't have any linked issues. Please open an issue that references this PR. From there we can discuss and prioritise. |
src/compiler/expressionToTypeNode.ts
Outdated
@@ -1114,7 +1114,7 @@ export function createSyntacticTypeNodeBuilder( | |||
function ensureParameter(p: ParameterDeclaration, context: SyntacticTypeNodeBuilderContext) { | |||
return factory.updateParameterDeclaration( | |||
p, | |||
[], | |||
p.modifiers, |
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 crash was caused by getPos
rying to read .__pos
that is meant to be added by onBeforeEmitNodeArray
(called by emitDecoratorsAndModifiers
, called by emitParameter
). But since this list was empty it just bailed on it:
TypeScript/src/compiler/emitter.ts
Lines 4435 to 4436 in b3c67d3
function emitDecoratorsAndModifiers(node: Node, modifiers: NodeArray<ModifierLike> | undefined, allowDecorators: boolean) { | |
if (modifiers?.length) { |
This fix tries to reuse existing p.modifiers
(it feels like ensureParameter
shouldn't try to los information). Since the parameters in question don't have any modifiers an undefined
gets "reused". So then the printer doesn't crash on lacking .__pos
because it doesn't even have see the related node array as it wasn't created in the first place.
This, of course, means that this can still crash, in a similar way, on empty modifiers if they are ever returned.
I think it would be best to keep the current fix (it avoids allocating a redundant empty array) but also call onBeforeEmitNodeArray
on empty modifiers
in emitDecoratorsAndModifiers
. I glanced through the whole emitter.ts
and it seems like it's the only function that avoids it. Do you think there is some extra test case to be written that would prove it needs to be done there?
This, of course, means that any similar
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.
@jakebailey perhaps you could take a look at this one?
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.
Why not just set it to undefined
?
Note that declaration emit does something entirely different (see the other ensureParameter
).
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.
Why not just set it to undefined?
It felt safer to use p.modifiers
since some modifiers could be present on this. updateParameterDeclaration
isn't like a partial that updates only what has been passed in. It requires everything to be passed in at each invocation.
But knowing a little bit more about this now... this probably should use reuseNode
or similar to cover for that possibility 🤔
Note that declaration emit does something entirely different (see the other ensureParameter).
That maps modifierMask
to modifiers
- it ultimately isn't that different, I think, from what happens here. It's just that here we actually might have access to the modifiers so there is no need to create them from a mask (which we don't have here).
I'll try to come up with a test case that would have a parameter modifier to see what happens.
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.
What's here is already the empty array, so we can't have copied anything over to date.
I don't think there should be any parameter modifiers, honestly; I thought that could only be used for something like parameter properties, which are not emitted in d.ts files.
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.
yeah, you are right - using undefined
here is better. I've also played around with constructor
and modifiers but it's not even treated as a class member completion and it isn't suggested so it can lead to any funkiness here.
fixes crash reported here: #60527 (comment)