SIGN IN SIGN UP

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