-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Fix(50751): Undefined entity with immediate and prototype expression causing crash #52646
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
base: main
Are you sure you want to change the base?
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.
@typescript-bot test this
@typescript-bot test top100
@typescript-bot user test this
@typescript-bot user test tsserver
@typescript-bot test tsserver top100
@typescript-bot run dt
@typescript-bot perf test this
src/compiler/binder.ts
Outdated
@@ -3340,6 +3341,9 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { | |||
} | |||
}); | |||
} | |||
if (isPrototypeProperty && namespaceSymbol && namespaceSymbol.valueDeclaration) { | |||
if (isAssignmentDeclaration(namespaceSymbol.valueDeclaration)) containerIsClass = false; |
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.
Nit, but:
if (isAssignmentDeclaration(namespaceSymbol.valueDeclaration)) containerIsClass = false; | |
if (isAssignmentDeclaration(namespaceSymbol.valueDeclaration)) { | |
containerIsClass = false; | |
} |
In general my impression is that we avoid one-liner things like this unless they are just return
or break
or something
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.
Also consider just smushing the two if
s together.
Well, I guess the bot doesn't read the "main" review comment. @typescript-bot test this |
Heya @jakebailey, I've started to run the extended test suite on this PR at 01e9982. You can monitor the build here. |
Heya @jakebailey, I've started to run the perf test suite on this PR at 01e9982. You can monitor the build here. Update: The results are in! |
Heya @jakebailey, I've started to run the diff-based user code test suite (tsserver) on this PR at 01e9982. You can monitor the build here. Update: The results are in! |
Heya @jakebailey, I've started to run the diff-based top-repos suite (tsserver) on this PR at 01e9982. You can monitor the build here. Update: The results are in! |
Heya @jakebailey, I've started to run the diff-based top-repos suite on this PR at 01e9982. You can monitor the build here. Update: The results are in! |
Heya @jakebailey, I've started to run the diff-based user code test suite on this PR at 01e9982. You can monitor the build here. Update: The results are in! |
Heya @jakebailey, I've started to run the parallelized Definitely Typed test suite on this PR at 01e9982. You can monitor the build here. |
@jakebailey Here are the results of running the user test suite comparing Everything looks good! |
1 similar comment
@jakebailey Here are the results of running the user test suite comparing Everything looks good! |
Heya @jakebailey, I've run the RWC suite on this PR - assuming you're on the TS core team, you can view the resulting diff here. |
@jakebailey Here they are:
CompilerComparison Report - main..52646
System
Hosts
Scenarios
TSServerComparison Report - main..52646
System
Hosts
Scenarios
StartupComparison Report - main..52646
System
Hosts
Scenarios
Developer Information: |
@jakebailey Here are the results of running the top-repos suite comparing Something interesting changed - please have a look. Detailsapache/echarts
|
@jakebailey Here are the results of running the top-repos suite comparing Everything looks good! |
@@ -3340,6 +3341,9 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { | |||
} | |||
}); | |||
} | |||
if (isPrototypeProperty && namespaceSymbol && namespaceSymbol.valueDeclaration && isAssignmentDeclaration(namespaceSymbol.valueDeclaration)) { | |||
containerIsClass = false; | |||
} | |||
if (containerIsClass && namespaceSymbol && namespaceSymbol.valueDeclaration) { |
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 you can combine the checks from the above as well and just do an early return in the "bad" case.
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'm not sure I understand this. Do you mean I should add it as an else if
with return namespaceSymbol;
?
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.
Something like that - you're setting containerIsClass
to false
, which makes you indirectly skip the next check; maybe that's fine, but you also have to repeat the same checks for namespaceSymbol
. So I would write something like
if (namespaceSymbol?.valueDeclaration) {
// We may have needed to make an assumption that the container symbol is a class
// due to an assignment like `Foo.prototype.method = ...`. However,
// if we never found a valueDeclaration that's suited as an old-style class,
// we should bail out here.
if (isPrototypeProperty && isAssignmentDeclaration(namespaceSymbol.valueDeclaration)) {
return namespaceSymbol;
}
if (containerIsClass) {
addDeclarationToSymbol(namespaceSymbol, namespaceSymbol.valueDeclaration, SymbolFlags.Class);
}
}
You can even simplify further, but I think this is fine.
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.
On that note - maybe for the bail-out case it would be better to say
If the
valueDeclaration
is not a class or constructor function
instead of
If the
valueDeclaration
is an assignment function
That way we can't end up with more accidental cases like this. But it's up to you.
@@ -3340,6 +3341,9 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { | |||
} | |||
}); | |||
} | |||
if (isPrototypeProperty && namespaceSymbol && namespaceSymbol.valueDeclaration && isAssignmentDeclaration(namespaceSymbol.valueDeclaration)) { |
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 this check needs an explanation of how we could've gotten into this state and what this does to fix it - 2-3 sentences should do.
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.
something like "A prototype property assignment to something that looks class-like shouldn't actually count if the class-likeness came from an assignment declaration. The checker requires an actual class/constructor function to attach the prototype property to."
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.
Suggestion for wording of the comment @DanielRosenwasser requested.
@@ -3340,6 +3341,9 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { | |||
} | |||
}); | |||
} | |||
if (isPrototypeProperty && namespaceSymbol && namespaceSymbol.valueDeclaration && isAssignmentDeclaration(namespaceSymbol.valueDeclaration)) { |
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.
something like "A prototype property assignment to something that looks class-like shouldn't actually count if the class-likeness came from an assignment declaration. The checker requires an actual class/constructor function to attach the prototype property to."
//A prototype property assignment to something that looks class-like shouldn't actually count if the class-likeness came from an assignment declaration. | ||
//The checker requires an actual class/constructor function to attach the prototype property to. |
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.
Just saw that you also left a comment - if you want to stick to this comment, try to shorten the line and add a space after each //
//A prototype property assignment to something that looks class-like shouldn't actually count if the class-likeness came from an assignment declaration. | |
//The checker requires an actual class/constructor function to attach the prototype property to. | |
// A prototype property assignment to something that looks class-like | |
// shouldn't actually count if the class-likeness came from an assignment declaration. | |
// The checker requires an actual class/constructor function to attach the prototype property to. | |
Fixes #50751