Skip to content

Commit ca393a9

Browse files
committed
JS: Do not override AST methods in React model
1 parent b4d6cb6 commit ca393a9

File tree

1 file changed

+23
-11
lines changed
  • javascript/ql/lib/semmle/javascript/frameworks

1 file changed

+23
-11
lines changed

javascript/ql/lib/semmle/javascript/frameworks/React.qll

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -311,14 +311,15 @@ class FunctionalComponent extends ReactComponent, Function {
311311
/**
312312
* A React/Preact component implemented as a class.
313313
*/
314-
abstract private class SharedReactPreactClassComponent extends ReactComponent, ClassDefinition {
314+
abstract private class SharedReactPreactClassComponent extends ReactComponent instanceof ClassDefinition
315+
{
315316
override Function getInstanceMethod(string name) {
316317
result = ClassDefinition.super.getInstanceMethod(name)
317318
}
318319

319320
override Function getStaticMethod(string name) {
320321
exists(MethodDeclaration decl |
321-
decl = this.getMethod(name) and
322+
decl = ClassDefinition.super.getMethod(name) and
322323
decl.isStatic() and
323324
result = decl.getBody()
324325
)
@@ -327,7 +328,8 @@ abstract private class SharedReactPreactClassComponent extends ReactComponent, C
327328
override DataFlow::SourceNode getADirectPropsAccess() {
328329
result = this.getAnInstanceReference().getAPropertyRead("props")
329330
or
330-
result = DataFlow::parameterNode(this.getConstructor().getBody().getParameter(0))
331+
result =
332+
DataFlow::parameterNode(ClassDefinition.super.getConstructor().getBody().getParameter(0))
331333
}
332334

333335
override AbstractValue getAbstractComponent() { result = AbstractInstance::of(this) }
@@ -340,7 +342,7 @@ abstract private class SharedReactPreactClassComponent extends ReactComponent, C
340342

341343
override DataFlow::SourceNode getACandidateStateSource() {
342344
result = ReactComponent.super.getACandidateStateSource() or
343-
result.flowsToExpr(this.getField("state").getInit())
345+
result.flowsToExpr(ClassDefinition.super.getField("state").getInit())
344346
}
345347

346348
override DataFlow::SourceNode getADefaultPropsSource() {
@@ -349,6 +351,17 @@ abstract private class SharedReactPreactClassComponent extends ReactComponent, C
349351
DataFlow::valueNode(this).(DataFlow::SourceNode).hasPropertyWrite("defaultProps", props)
350352
)
351353
}
354+
355+
/** Gets the expression denoting the super class of the defined class, if any. */
356+
Expr getSuperClass() { result = ClassDefinition.super.getSuperClass() }
357+
358+
/**
359+
* Gets the constructor of this class.
360+
*
361+
* Note that every class has a constructor: if no explicit constructor
362+
* is declared, it has a synthetic default constructor.
363+
*/
364+
ConstructorDeclaration getConstructor() { result = ClassDefinition.super.getAMethod() }
352365
}
353366

354367
/**
@@ -362,7 +375,7 @@ abstract class ES2015Component extends SharedReactPreactClassComponent { }
362375
*/
363376
private class DefiniteES2015Component extends ES2015Component {
364377
DefiniteES2015Component() {
365-
exists(DataFlow::SourceNode sup | sup.flowsToExpr(this.getSuperClass()) |
378+
exists(DataFlow::SourceNode sup | sup.flowsToExpr(this.(ClassDefinition).getSuperClass()) |
366379
exists(PropAccess access, string globalReactName |
367380
(globalReactName = "react" or globalReactName = "React") and
368381
access = sup.asExpr()
@@ -400,7 +413,7 @@ abstract class PreactComponent extends SharedReactPreactClassComponent {
400413
*/
401414
private class DefinitePreactComponent extends PreactComponent {
402415
DefinitePreactComponent() {
403-
exists(DataFlow::SourceNode sup | sup.flowsToExpr(this.getSuperClass()) |
416+
exists(DataFlow::SourceNode sup | sup.flowsToExpr(this.(ClassDefinition).getSuperClass()) |
404417
exists(PropAccess access, string globalPreactName |
405418
(globalPreactName = "preact" or globalPreactName = "Preact") and
406419
access = sup.asExpr()
@@ -419,12 +432,11 @@ private class DefinitePreactComponent extends PreactComponent {
419432
* - extends class called `Component`
420433
* - has a `render` method that returns JSX or React elements.
421434
*/
422-
private class HeuristicReactPreactComponent extends ClassDefinition, PreactComponent,
423-
ES2015Component
424-
{
435+
private class HeuristicReactPreactComponent extends PreactComponent, ES2015Component {
425436
HeuristicReactPreactComponent() {
426-
any(DataFlow::GlobalVarRefNode c | c.getName() = "Component").flowsToExpr(this.getSuperClass()) and
427-
alwaysReturnsJsxOrReactElements(ClassDefinition.super.getInstanceMethod("render"))
437+
any(DataFlow::GlobalVarRefNode c | c.getName() = "Component")
438+
.flowsToExpr(this.(ClassDefinition).getSuperClass()) and
439+
alwaysReturnsJsxOrReactElements(this.(ClassDefinition).getInstanceMethod("render"))
428440
}
429441
}
430442

0 commit comments

Comments
 (0)