@@ -129,6 +129,39 @@ predicate noSideEffects(Expr e) {
129129 )
130130}
131131
132+ /**
133+ * Holds if `e` contains a DOM property access in a context where it would
134+ * be evaluated for side effects.
135+ */
136+ predicate containsDomPropertyAccess ( Expr e ) {
137+ isDomProperty ( e .( PropAccess ) .getPropertyName ( ) )
138+ or
139+ exists ( LogicalBinaryExpr logical | logical = e |
140+ containsDomPropertyAccess ( logical .getLeftOperand ( ) ) or
141+ containsDomPropertyAccess ( logical .getRightOperand ( ) )
142+ )
143+ or
144+ exists ( SeqExpr seq | seq = e | containsDomPropertyAccess ( seq .getAnOperand ( ) ) )
145+ or
146+ exists ( ParExpr paren | paren = e | containsDomPropertyAccess ( paren .getExpression ( ) ) )
147+ or
148+ exists ( ConditionalExpr cond | cond = e | containsDomPropertyAccess ( cond .getCondition ( ) ) )
149+ }
150+
151+ /**
152+ * Holds if `e` is an expression that might appear useless but contains
153+ * DOM side effects that make it meaningful.
154+ */
155+ predicate hasHiddenDomSideEffects ( Expr e ) {
156+ (
157+ e instanceof LogicalBinaryExpr or
158+ e instanceof SeqExpr or
159+ e instanceof ParExpr or
160+ e instanceof BinaryExpr
161+ ) and
162+ containsDomPropertyAccess ( e )
163+ }
164+
132165/**
133166 * Holds if the expression `e` should be reported as having no effect.
134167 */
@@ -145,6 +178,7 @@ predicate hasNoEffect(Expr e) {
145178 not isDeclaration ( e ) and
146179 // exclude DOM properties, which sometimes have magical auto-update properties
147180 not isDomProperty ( e .( PropAccess ) .getPropertyName ( ) ) and
181+ not hasHiddenDomSideEffects ( e ) and
148182 // exclude xUnit.js annotations
149183 not e instanceof XUnitAnnotation and
150184 // exclude common patterns that are most likely intentional
0 commit comments