Skip to content

Commit b485233

Browse files
committed
Tweak how the rules execute to fail comparisons on arrays and objects.
1 parent de2b418 commit b485233

File tree

3 files changed

+32
-37
lines changed

3 files changed

+32
-37
lines changed

defaultMethods.js

+16-22
Original file line numberDiff line numberDiff line change
@@ -797,21 +797,18 @@ function createComparator (name, func) {
797797
if (args.length === 2) {
798798
const a = runOptimizedOrFallback(args[0], engine, context, above)
799799
const b = runOptimizedOrFallback(args[1], engine, context, above)
800-
if (!strict && typeof a !== typeof b) {
801-
if (typeof a === 'string' && Number.isNaN(+a)) throw NaN
802-
if (typeof b === 'string' && Number.isNaN(+b)) throw NaN
803-
return func(+a, +b)
804-
}
805-
return func(a, b)
800+
if (strict || (typeof a === 'string' && typeof b === 'string')) return func(a, b)
801+
if (Number.isNaN(+precoerceNumber(a))) throw NaN
802+
if (Number.isNaN(+precoerceNumber(b))) throw NaN
803+
return func(+a, +b)
806804
}
807805
let prev = runOptimizedOrFallback(args[0], engine, context, above)
808806
for (let i = 1; i < args.length; i++) {
809807
const current = runOptimizedOrFallback(args[i], engine, context, above)
810-
if (!strict && typeof current !== typeof prev) {
811-
if (typeof current === 'string' && Number.isNaN(+current)) throw NaN
812-
if (i === 1 && typeof prev === 'string' && Number.isNaN(+prev)) throw NaN
813-
if (!func(+prev, +current)) return false
814-
} else if (!func(prev, current)) return false
808+
if (strict || (typeof current === 'string' && typeof prev === 'string')) if (!func(prev, current)) return false
809+
if (Number.isNaN(+precoerceNumber(current))) throw NaN
810+
if (i === 1 && Number.isNaN(+precoerceNumber(prev))) throw NaN
811+
if (!func(+prev, +current)) return false
815812
prev = current
816813
}
817814
return true
@@ -821,21 +818,18 @@ function createComparator (name, func) {
821818
if (args.length === 2) {
822819
const a = await runOptimizedOrFallback(args[0], engine, context, above)
823820
const b = await runOptimizedOrFallback(args[1], engine, context, above)
824-
if (!strict && typeof a !== typeof b) {
825-
if (typeof a === 'string' && Number.isNaN(+a)) throw NaN
826-
if (typeof b === 'string' && Number.isNaN(+b)) throw NaN
827-
return func(+a, +b)
828-
}
829-
return func(a, b)
821+
if (strict || (typeof a === 'string' && typeof b === 'string')) return func(a, b)
822+
if (Number.isNaN(+precoerceNumber(a))) throw NaN
823+
if (Number.isNaN(+precoerceNumber(b))) throw NaN
824+
return func(+a, +b)
830825
}
831826
let prev = await runOptimizedOrFallback(args[0], engine, context, above)
832827
for (let i = 1; i < args.length; i++) {
833828
const current = await runOptimizedOrFallback(args[i], engine, context, above)
834-
if (!strict && typeof current !== typeof prev) {
835-
if (typeof current === 'string' && Number.isNaN(+current)) throw NaN
836-
if (i === 1 && typeof prev === 'string' && Number.isNaN(+prev)) throw NaN
837-
if (!func(+prev, +current)) return false
838-
} else if (!func(prev, current)) return false
829+
if (strict || (typeof current === 'string' && typeof prev === 'string')) if (!func(prev, current)) return false
830+
if (Number.isNaN(+precoerceNumber(current))) throw NaN
831+
if (i === 1 && Number.isNaN(+precoerceNumber(prev))) throw NaN
832+
if (!func(+prev, +current)) return false
839833
prev = current
840834
}
841835
return true

optimizer.js

+5-6
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import { isDeterministic } from './compiler.js'
33
import { OriginalImpl } from './constants.js'
44
import { coerceArray } from './utilities/coerceArray.js'
5+
import { precoerceNumber } from './utilities/downgrade.js'
56
import { splitPathMemoized } from './utilities/splitPath.js'
67

78
/**
@@ -122,12 +123,10 @@ function checkIdioms (logic, engine, above) {
122123
const comparisonFunc = comparison.length === 3
123124
? _comparisonFunc
124125
: function comparisonFunc (a, b) {
125-
if (typeof a !== typeof b) {
126-
if (typeof a === 'string' && Number.isNaN(+a)) throw NaN
127-
if (typeof b === 'string' && Number.isNaN(+b)) throw NaN
128-
return _comparisonFunc(+a, +b)
129-
}
130-
return _comparisonFunc(a, b)
126+
if (typeof a === 'string' && typeof b === 'string') return _comparisonFunc(a, b)
127+
if (Number.isNaN(+precoerceNumber(a))) throw NaN
128+
if (Number.isNaN(+precoerceNumber(b))) throw NaN
129+
return _comparisonFunc(+a, +b)
131130
}
132131

133132
if (logic[comparison].length === 2) {

utilities/downgrade.js

+11-9
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,16 @@ export function assertSize (arr, size) {
2727
* @returns {number}
2828
*/
2929
export function compareCheck (item, prev, strict) {
30-
if (!strict && typeof item !== typeof prev) {
31-
if (typeof item === 'string' && Number.isNaN(+item)) throw NaN
32-
if (typeof prev === 'string' && Number.isNaN(+prev)) throw NaN
33-
// The following two checks allow us to handle null == 0 and 0 == null; it's honestly
34-
// kind of gross that JavaScript works this way out of the box. Like, why is 0 <= null true,
35-
// but null == false. It's just weird.
36-
if (prev === null && !item) return null
37-
if (item === null && !prev) return 0
38-
}
30+
if (strict || (typeof item === 'string' && typeof prev === 'string')) return item
31+
32+
if (Number.isNaN(+precoerceNumber(item))) throw NaN
33+
if (Number.isNaN(+precoerceNumber(prev))) throw NaN
34+
35+
// The following two checks allow us to handle null == 0 and 0 == null; it's honestly
36+
// kind of gross that JavaScript works this way out of the box. Like, why is 0 <= null true,
37+
// but null == false. It's just weird.
38+
if (prev === null && !item) return null
39+
if (item === null && !prev) return 0
40+
3941
return item
4042
}

0 commit comments

Comments
 (0)