Skip to content

Commit b0902a7

Browse files
wmaddenclaude
andcommitted
refactor(contract): extract compareCodeUnits helper; trim test comment
Address review on #721: name the deterministic comparator so its intent reads from the code (not a bare `<`/`>`), and drop the verbose inline comment from the regression test (the test name carries the intent). No behavioural change — still UTF-16 code-unit, collation-independent order. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: Will Madden <madden@prisma.io>
1 parent a9b0b88 commit b0902a7

2 files changed

Lines changed: 8 additions & 4 deletions

File tree

packages/1-framework/0-foundation/contract/src/canonicalization-storage-sort.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,17 @@ function isPlainRecord(value: unknown): value is Record<string, unknown> {
1111
return typeof value === 'object' && value !== null && !Array.isArray(value);
1212
}
1313

14+
// Order by UTF-16 code unit, not locale collation: canonicalization feeds
15+
// storageHash, which must be byte-identical across hosts, and locale
16+
// collation (localeCompare/Intl) varies by the engine's ICU build.
17+
function compareCodeUnits(a: string, b: string): number {
18+
return a < b ? -1 : a > b ? 1 : 0;
19+
}
20+
1421
export function compareByNameProperty(a: unknown, b: unknown): number {
1522
const nameA = isPlainRecord(a) && typeof a['name'] === 'string' ? a['name'] : '';
1623
const nameB = isPlainRecord(b) && typeof b['name'] === 'string' ? b['name'] : '';
17-
return nameA < nameB ? -1 : nameA > nameB ? 1 : 0;
24+
return compareCodeUnits(nameA, nameB);
1825
}
1926

2027
function sortArrayKeysOnRecord(

packages/1-framework/0-foundation/contract/test/canonicalization-storage-sort.test.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,6 @@ describe('compareByNameProperty', () => {
9797
expect(compareByNameProperty({}, { name: 'a' })).toBeLessThan(0);
9898
});
9999

100-
// Locale-independence regression: comparator must use code-unit order, not locale collation.
101-
// Code-unit: 'Z' = U+005A < 'a' = U+0061, so { name: 'Z' } sorts before { name: 'a' }.
102-
// Most locales sort 'a' before 'Z' (case-insensitive), so localeCompare would return > 0 here.
103100
it('uses code-unit order, not locale collation (Z < a)', () => {
104101
expect(compareByNameProperty({ name: 'Z' }, { name: 'a' })).toBeLessThan(0);
105102
});

0 commit comments

Comments
 (0)