@@ -8,10 +8,10 @@ import {
88 ResolutionReason ,
99} from './types' ;
1010
11- type PathArray = ( string | number ) [ ] ;
12-
1311const MAX_REGEX_INPUT_LENGTH = 10_000 ;
1412
13+ type PathArray = ( string | number ) [ ] ;
14+
1515function exhaustivenessCheck ( _ : never ) : never {
1616 throw new Error ( 'Exhaustiveness check failed' ) ;
1717}
@@ -56,7 +56,9 @@ function isArray(input: unknown): input is unknown[] {
5656}
5757
5858function lower ( input : unknown ) : unknown {
59- return typeof input === 'string' ? input . toLowerCase ( ) : input ;
59+ if ( typeof input === 'string' ) return input . toLowerCase ( ) ;
60+ if ( Array . isArray ( input ) ) return input . map ( lower ) ;
61+ return input ;
6062}
6163
6264function matchTargetList < T > (
@@ -131,64 +133,45 @@ function matchConditions<T>(
131133 params : EvaluationParams < T > ,
132134) : boolean {
133135 return conditions . every ( ( condition ) => {
134- const [ lhsAccessor , cmpKey , rhs , options ] = condition ;
135- const ci = options && 'ci' in options && options . ci === true ;
136+ const [ lhsAccessor , cmpKey , rawRhs , options ] = condition ;
137+ const ci = options !== undefined && options . ci === true ;
136138
139+ // ci is not applicable to segment conditions (segments are internal IDs)
137140 if ( lhsAccessor === Packed . AccessorType . SEGMENT ) {
138- return rhs && matchSegmentCondition ( cmpKey , rhs , params ) ;
141+ return rawRhs && matchSegmentCondition ( cmpKey , rawRhs , params ) ;
139142 }
140143
141- const lhs = access ( lhsAccessor , params ) ;
144+ const rawLhs = access ( lhsAccessor , params ) ;
145+ const lhs = ci ? lower ( rawLhs ) : rawLhs ;
146+ const rhs = ci ? lower ( rawRhs ) : rawRhs ;
147+
142148 try {
143149 switch ( cmpKey ) {
144150 case Comparator . EQ :
145- return ci ? lower ( lhs ) === lower ( rhs ) : lhs === rhs ;
151+ return lhs === rhs ;
146152 case Comparator . NOT_EQ :
147- return ci ? lower ( lhs ) !== lower ( rhs ) : lhs !== rhs ;
153+ return lhs !== rhs ;
148154 case Comparator . ONE_OF :
149- if ( ! isArray ( rhs ) ) return false ;
150- return ci ? rhs . map ( lower ) . includes ( lower ( lhs ) ) : rhs . includes ( lhs ) ;
155+ return isArray ( rhs ) && rhs . includes ( lhs ) ;
151156 case Comparator . NOT_ONE_OF :
157+ // lhs is undefined when the entity value was not provided, in which
158+ // case we should not match the rule
152159 if ( ! isArray ( rhs ) || typeof lhs === 'undefined' ) return false ;
153- return ci ? ! rhs . map ( lower ) . includes ( lower ( lhs ) ) : ! rhs . includes ( lhs ) ;
160+ return ! rhs . includes ( lhs ) ;
154161 case Comparator . CONTAINS_ALL_OF : {
155162 if ( ! Array . isArray ( rhs ) || ! Array . isArray ( lhs ) ) return false ;
156163
157- const lhsSet = new Set (
158- ci
159- ? lhs . filter ( isString ) . map ( ( s ) => s . toLowerCase ( ) )
160- : lhs . filter ( isString ) ,
161- ) ;
164+ const lhsSet = new Set ( lhs . filter ( isString ) ) ;
162165
163166 if ( lhsSet . size === lhs . length ) {
164- return rhs
165- . filter ( isString )
166- . every ( ( item ) => lhsSet . has ( ci ? item . toLowerCase ( ) : item ) ) ;
167+ return rhs . filter ( isString ) . every ( ( item ) => lhsSet . has ( item ) ) ;
167168 }
168169
169- return ci
170- ? rhs . every ( ( item ) =>
171- lhs . some (
172- ( l ) =>
173- isString ( l ) &&
174- isString ( item ) &&
175- l . toLowerCase ( ) === item . toLowerCase ( ) ,
176- ) ,
177- )
178- : rhs . every ( ( item ) => lhs . includes ( item ) ) ;
170+ return rhs . every ( ( item ) => lhs . includes ( item ) ) ;
179171 }
180172 case Comparator . CONTAINS_ANY_OF : {
181173 if ( ! Array . isArray ( rhs ) || ! Array . isArray ( lhs ) ) return false ;
182174
183- if ( ci ) {
184- const rhsSet = new Set (
185- rhs . filter ( isString ) . map ( ( s ) => s . toLowerCase ( ) ) ,
186- ) ;
187- return lhs
188- . filter ( isString )
189- . some ( ( item ) => rhsSet . has ( item . toLowerCase ( ) ) ) ;
190- }
191-
192175 const rhsSet = new Set ( rhs . filter ( isString ) ) ;
193176 return lhs . some (
194177 rhsSet . size === rhs . length
@@ -200,15 +183,6 @@ function matchConditions<T>(
200183 if ( ! Array . isArray ( rhs ) ) return false ;
201184 if ( ! Array . isArray ( lhs ) ) return true ;
202185
203- if ( ci ) {
204- const rhsSet = new Set (
205- rhs . filter ( isString ) . map ( ( s ) => s . toLowerCase ( ) ) ,
206- ) ;
207- return lhs
208- . filter ( isString )
209- . every ( ( item ) => ! rhsSet . has ( item . toLowerCase ( ) ) ) ;
210- }
211-
212186 const rhsSet = new Set ( rhs . filter ( isString ) ) ;
213187 return lhs . every (
214188 rhsSet . size === rhs . length
@@ -217,93 +191,69 @@ function matchConditions<T>(
217191 ) ;
218192 }
219193 case Comparator . STARTS_WITH :
220- return ci
221- ? isString ( lhs ) &&
222- isString ( rhs ) &&
223- lhs . toLowerCase ( ) . startsWith ( rhs . toLowerCase ( ) )
224- : isString ( lhs ) && isString ( rhs ) && lhs . startsWith ( rhs ) ;
194+ return isString ( lhs ) && isString ( rhs ) && lhs . startsWith ( rhs ) ;
225195 case Comparator . NOT_STARTS_WITH :
226- return ci
227- ? isString ( lhs ) &&
228- isString ( rhs ) &&
229- ! lhs . toLowerCase ( ) . startsWith ( rhs . toLowerCase ( ) )
230- : isString ( lhs ) && isString ( rhs ) && ! lhs . startsWith ( rhs ) ;
196+ return isString ( lhs ) && isString ( rhs ) && ! lhs . startsWith ( rhs ) ;
231197 case Comparator . ENDS_WITH :
232- return ci
233- ? isString ( lhs ) &&
234- isString ( rhs ) &&
235- lhs . toLowerCase ( ) . endsWith ( rhs . toLowerCase ( ) )
236- : isString ( lhs ) && isString ( rhs ) && lhs . endsWith ( rhs ) ;
198+ return isString ( lhs ) && isString ( rhs ) && lhs . endsWith ( rhs ) ;
237199 case Comparator . NOT_ENDS_WITH :
238- return ci
239- ? isString ( lhs ) &&
240- isString ( rhs ) &&
241- ! lhs . toLowerCase ( ) . endsWith ( rhs . toLowerCase ( ) )
242- : isString ( lhs ) && isString ( rhs ) && ! lhs . endsWith ( rhs ) ;
200+ return isString ( lhs ) && isString ( rhs ) && ! lhs . endsWith ( rhs ) ;
243201 case Comparator . CONTAINS :
244- return ci
245- ? isString ( lhs ) &&
246- isString ( rhs ) &&
247- lhs . toLowerCase ( ) . includes ( rhs . toLowerCase ( ) )
248- : isString ( lhs ) && isString ( rhs ) && lhs . includes ( rhs ) ;
202+ return isString ( lhs ) && isString ( rhs ) && lhs . includes ( rhs ) ;
249203 case Comparator . NOT_CONTAINS :
250- return ci
251- ? isString ( lhs ) &&
252- isString ( rhs ) &&
253- ! lhs . toLowerCase ( ) . includes ( rhs . toLowerCase ( ) )
254- : isString ( lhs ) && isString ( rhs ) && ! lhs . includes ( rhs ) ;
204+ return isString ( lhs ) && isString ( rhs ) && ! lhs . includes ( rhs ) ;
255205 case Comparator . EXISTS :
256- return lhs !== undefined && lhs !== null ;
206+ return rawLhs !== undefined && rawLhs !== null ;
257207 case Comparator . NOT_EXISTS :
258- return lhs === undefined || lhs === null ;
208+ return rawLhs === undefined || rawLhs === null ;
259209 case Comparator . GT :
260210 // NaN will return false for any comparisons
261- if ( lhs === null || lhs === undefined ) return false ;
262- return ( isNumber ( rhs ) || isString ( rhs ) ) && lhs > rhs ;
211+ if ( rawLhs === null || rawLhs === undefined ) return false ;
212+ return ( isNumber ( rawRhs ) || isString ( rawRhs ) ) && rawLhs > rawRhs ;
263213 case Comparator . GTE :
264- if ( lhs === null || lhs === undefined ) return false ;
265- return ( isNumber ( rhs ) || isString ( rhs ) ) && lhs >= rhs ;
214+ if ( rawLhs === null || rawLhs === undefined ) return false ;
215+ return ( isNumber ( rawRhs ) || isString ( rawRhs ) ) && rawLhs >= rawRhs ;
266216 case Comparator . LT :
267- if ( lhs === null || lhs === undefined ) return false ;
268- return ( isNumber ( rhs ) || isString ( rhs ) ) && lhs < rhs ;
217+ if ( rawLhs === null || rawLhs === undefined ) return false ;
218+ return ( isNumber ( rawRhs ) || isString ( rawRhs ) ) && rawLhs < rawRhs ;
269219 case Comparator . LTE :
270- if ( lhs === null || lhs === undefined ) return false ;
271- return ( isNumber ( rhs ) || isString ( rhs ) ) && lhs <= rhs ;
220+ if ( rawLhs === null || rawLhs === undefined ) return false ;
221+ return ( isNumber ( rawRhs ) || isString ( rawRhs ) ) && rawLhs <= rawRhs ;
272222 case Comparator . REGEX :
273223 if (
274- isString ( lhs ) &&
275- lhs . length <= MAX_REGEX_INPUT_LENGTH &&
276- typeof rhs === 'object' &&
277- ! Array . isArray ( rhs ) &&
278- rhs ?. type === 'regex'
224+ isString ( rawLhs ) &&
225+ rawLhs . length <= MAX_REGEX_INPUT_LENGTH &&
226+ typeof rawRhs === 'object' &&
227+ ! Array . isArray ( rawRhs ) &&
228+ rawRhs ?. type === 'regex'
279229 ) {
280- return new RegExp ( rhs . pattern , rhs . flags ) . test ( lhs ) ;
230+ return new RegExp ( rawRhs . pattern , rawRhs . flags ) . test ( rawLhs ) ;
281231 }
282232 return false ;
283233
284234 case Comparator . NOT_REGEX :
285235 if (
286- isString ( lhs ) &&
287- lhs . length <= MAX_REGEX_INPUT_LENGTH &&
288- typeof rhs === 'object' &&
289- ! Array . isArray ( rhs ) &&
290- rhs ?. type === 'regex'
236+ isString ( rawLhs ) &&
237+ rawLhs . length <= MAX_REGEX_INPUT_LENGTH &&
238+ typeof rawRhs === 'object' &&
239+ ! Array . isArray ( rawRhs ) &&
240+ rawRhs ?. type === 'regex'
291241 ) {
292- return ! new RegExp ( rhs . pattern , rhs . flags ) . test ( lhs ) ;
242+ return ! new RegExp ( rawRhs . pattern , rawRhs . flags ) . test ( rawLhs ) ;
293243 }
294244 return false ;
295245 case Comparator . BEFORE : {
296- if ( ! isString ( lhs ) || ! isString ( rhs ) ) return false ;
297- const a = new Date ( lhs ) ;
298- const b = new Date ( rhs ) ;
246+ if ( ! isString ( rawLhs ) || ! isString ( rawRhs ) ) return false ;
247+ const a = new Date ( rawLhs ) ;
248+ const b = new Date ( rawRhs ) ;
299249 // if any date fails to parse getTime will return NaN, which will cause
300250 // comparisons to fail.
301251 return a . getTime ( ) < b . getTime ( ) ;
302252 }
303253 case Comparator . AFTER : {
304- if ( ! isString ( lhs ) || ! isString ( rhs ) ) return false ;
305- const a = new Date ( lhs ) ;
306- const b = new Date ( rhs ) ;
254+ if ( ! isString ( rawLhs ) || ! isString ( rawRhs ) ) return false ;
255+ const a = new Date ( rawLhs ) ;
256+ const b = new Date ( rawRhs ) ;
307257 return a . getTime ( ) > b . getTime ( ) ;
308258 }
309259 default : {
0 commit comments