File tree Expand file tree Collapse file tree
main/kotlin/org/usvm/machine/operator
kotlin/org/usvm/samples/operators
resources/samples/operators Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -384,10 +384,16 @@ sealed interface TsBinaryOperator {
384384 rhs : UHeapRef ,
385385 scope : TsStepScope ,
386386 ): UBoolExpr {
387- // Note: in JavaScript, `undefined == null`
388- if (lhs == mkUndefinedValue() && rhs == mkTsNullValue()) return mkTrue()
389- if (lhs == mkTsNullValue() && rhs == mkUndefinedValue()) return mkTrue()
390- return mkEq(lhs, rhs)
387+ // Note: in JavaScript, `null == undefined`
388+ val lhsIsNull = mkEq(lhs, mkTsNullValue())
389+ val rhsIsNull = mkEq(rhs, mkTsNullValue())
390+ val lhsIsUndefined = mkEq(lhs, mkUndefinedValue())
391+ val rhsIsUndefined = mkEq(rhs, mkUndefinedValue())
392+ return mkOr(
393+ mkAnd(lhsIsUndefined, rhsIsNull),
394+ mkAnd(lhsIsNull, rhsIsUndefined),
395+ mkHeapRefEq(lhs, rhs)
396+ )
391397 }
392398
393399 override fun TsContext.resolveFakeObject (
Original file line number Diff line number Diff line change @@ -181,4 +181,29 @@ class Equality : TsMethodTestRunner() {
181181 )
182182 )
183183 }
184+
185+ @Test
186+ fun `test eqAnyWithNull` () {
187+ val method = getMethod(" eqAnyWithNull" )
188+ discoverProperties<TsTestValue , TsTestValue .TsNumber >(
189+ method,
190+ { a, r ->
191+ (r eq 1 ) && (a is TsTestValue .TsNull )
192+ },
193+ { a, r ->
194+ (r eq 2 ) && (a is TsTestValue .TsUndefined )
195+ },
196+ { a, r ->
197+ (r eq 5 ) && (a !is TsTestValue .TsNull )
198+ },
199+ { a, r ->
200+ (r eq 10 ) && (a !is TsTestValue .TsNull ) && (a !is TsTestValue .TsUndefined )
201+ },
202+ invariants = arrayOf(
203+ { _, r -> r.number > 0 },
204+ { a, r -> if (r eq 1 ) a is TsTestValue .TsNull else true },
205+ { a, r -> if (r eq 2 ) a is TsTestValue .TsUndefined else true },
206+ )
207+ )
208+ }
184209}
Original file line number Diff line number Diff line change @@ -76,4 +76,28 @@ class Equality {
7676 if ( undefined == null ) return 1 ;
7777 return - 1 ; // unreachable
7878 }
79+
80+ eqAnyWithNull ( a : any ) : number {
81+ if ( typeof a === "object" ) {
82+ // Note: `a == null` is true when `a` is null or undefined,
83+ // but here `a` cannot be undefined because `typeof undefined` is "undefined".
84+ // Thus, `a == null` is true only if `a === null`.
85+ if ( a == null ) {
86+ if ( a === null ) return 1 ; // null
87+ return - 1 ; // unreachable
88+ }
89+ return 5 ; // non-null object
90+ }
91+ if ( typeof a === "undefined" ) {
92+ // Note: `a == null` is true when `a` is null or undefined,
93+ // but here `a` cannot be null because `typeof null` is "object".
94+ // Thus, `a == null` is true only if `a === undefined`.
95+ if ( a == null ) {
96+ if ( a === undefined ) return 2 ; // undefined
97+ return - 1 ; // unreachable
98+ }
99+ return - 1 ; // unreachable
100+ }
101+ return 100 ; // non-object, non-undefined
102+ }
79103}
You can’t perform that action at this time.
0 commit comments