Add rc.sortBy custom operator - #7504
Open
ajpallares wants to merge 8 commits into
Open
Conversation
Orders an array by a key computed per item, ascending, with ties keeping their input order. Keys must be all strings or all numbers so the two engines never have to invent a cross-type ordering. Co-authored-by: Cursor <cursoragent@cursor.com>
A NaN key compares false in both directions, so every pair tied and the input came back unsorted with no error. Negating a string key to attempt a descending sort produced exactly that. Co-authored-by: Cursor <cursoragent@cursor.com>
…-rc-sort-by Co-authored-by: Cursor <cursoragent@cursor.com> # Conflicts: # Tests/UnitTests/RulesEngine/PredicateFixtureTests.swift
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
rickvdl
approved these changes
Aug 26, 2026
Swift's < orders by Unicode scalar and treats canonically equivalent strings as equal, while JS and Kotlin order by UTF-16 code unit. The two disagree once a scalar above the surrogate range meets an astral one, so the same rule would sort differently on iOS and Android. Co-authored-by: Cursor <cursoragent@cursor.com>
2 tasks
The fixture files are byte-identical across the iOS and Android engines, so a description that explains the contract in terms of one host language's string comparison does not read correctly in the other repository. Co-authored-by: Cursor <cursoragent@cursor.com>
ajpallares
added a commit
to RevenueCat/purchases-android
that referenced
this pull request
Aug 26, 2026
Kotlin's String.compareTo already compares code units, so this only ports the fixtures added to RevenueCat/purchases-ios#7504 to keep the two fixture sets byte-identical. Co-authored-by: Cursor <cursoragent@cursor.com>
❌ CI Job Failed —
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Checklist
purchases-androidand hybridsMotivation
Ordering a list is the one thing
reducecannot fake: comparing an item against the others in the same collection needs a scope the engine does not expose. Sorting throughrc.entrieskey ordering is the closest workaround, and it collapses duplicate keys and misorders numbers.Description
{"rc.sortBy": [array, keyExpression]}returns the original items in ascending key order. The key template is evaluated once per item with scope rebound to it, exactly asmapdoes, sorc.rootVaris how a key reaches top-level data.typeMismatchrather than inventing a cross-type ordering. String keys compare by UTF-16 code unit, as JS and Kotlin do, not by Swift's<.sorted(by:)is stable, so the tiebreak is explicit.{"-": [0, {"var": "score"}]}.Note
Medium Risk
New Rules Engine operator affects predicate evaluation for any rule using
rc.sortBy; behavior is heavily specified (UTF-16, stability, errors) but cross-platform parity with Android/hybrids is still a follow-up per the PR checklist.Overview
Adds
rc.sortByto the Rules Engine so predicates can return an array’s original elements in ascending order by a per-item key expression—addressing cases wherereduceorrc.entriesordering cannot compare items in-collection or preserve duplicates.The operator takes
[array, keyExpression]; the key is evaluated with scope rebound to each item (likemap), wired throughCustomOperatorsand a newSortByOperator. Keys must be homogeneous strings or numbers (numeric compare for numbers, UTF-16 code unit order for strings to match JS/Kotlin); mixed or invalid types, wrong arity, and non-finite numeric keys throwtypeMismatch. Stable ties use explicit index tie-breaking because Swift’s sort is not guaranteed stable. Descending numeric sort is done by negating the key; negating string dates is rejected (NaN).Conformance coverage adds
rc_sort_by.jsonfixtures and bumps the pinned predicate fixture count 519 → 544.Reviewed by Cursor Bugbot for commit 5319a48. Bugbot is set up for automated code reviews on this repo. Configure here.