Add rc.lower and rc.upper custom operators (#4051)
### Checklist - [x] If applicable, unit tests - [ ] If applicable, create follow-up issues for `purchases-ios` and hybrids ### Motivation Port of RevenueCat/purchases-ios#7436. Case-insensitive audience matching is impossible today — a rule comparing a country code or substring regardless of case either fails or becomes silently case-sensitive. ### Description - Add `rc.lower` and `rc.upper`: locale-independent Unicode case mapping via the parameterless `lowercase()` / `uppercase()`, matching JS `toLowerCase` / `toUpperCase` rather than the locale-sensitive variants. - Non-string input throws a type mismatch instead of being coerced, so a missing `var` can't compare equal to `"null"`. Consistent with `rc.length`. - Eighteen fixtures copied byte-for-byte from iOS (400 total), pinning the Turkish *I* mapping in both directions. ### Notes Stacked on #4047. The `jsNumberString` doc correction is doc-only, with Kotlin's own formatting examples since JVM and Swift diverge from JS differently. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Touches the rules engine used for audience matching: new operators change which predicates evaluate, and type-mismatch-on-non-string is a deliberate JS divergence. > > **Overview** > Adds **`rc.lower`** and **`rc.upper`** so JSON Logic rules can do case-insensitive matching (e.g. country codes, substring `in`) without depending on device locale. > > Conversion uses parameterless Kotlin `lowercase()`/`uppercase()` (Unicode default mapping, matching JS `toLowerCase`/`toUpperCase`, not locale variants). Non-strings throw `TypeMismatch` instead of coercing, so a missing `var` cannot silently equal `"null"`. Extra args follow json-logic-js first-arg-only spread. > > Also expands `jsNumberString` docs with Kotlin vs JS scientific-notation examples. Conformance fixtures cover ASCII, Turkish I, non-ASCII, type errors, and motivating equality/`in` cases. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 88a80bf9cef8097933c664ecfd4a2387dcd4b929. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
A
Antonio Pallares committed
43ceaaf701fa07c966ffbe7e73227b09beada290
Parent: ba3fc44
Committed by GitHub <noreply@github.com>
on 8/24/2026, 11:06:42 AM