@@ -46,9 +46,46 @@ const { entries, fromEntries, setPrototypeOf, is } = Object;
46
46
*/
47
47
const sameValueZero = ( x , y ) => x === y || is ( x , y ) ;
48
48
49
+ /**
50
+ * @param {any } left
51
+ * @param {any } right
52
+ * @returns {RankComparison }
53
+ */
49
54
export const trivialComparator = ( left , right ) =>
50
55
// eslint-disable-next-line no-nested-ternary, @endo/restrict-comparison-operands
51
56
left < right ? - 1 : left === right ? 0 : 1 ;
57
+ harden ( trivialComparator ) ;
58
+
59
+ // Apparently eslint confused about whether the function can ever exit
60
+ // without an explicit return.
61
+ // eslint-disable-next-line jsdoc/require-returns-check
62
+ /**
63
+ * @param {string } left
64
+ * @param {string } right
65
+ * @returns {RankComparison }
66
+ */
67
+ export const compareByCodePoints = ( left , right ) => {
68
+ const leftIter = left [ Symbol . iterator ] ( ) ;
69
+ const rightIter = right [ Symbol . iterator ] ( ) ;
70
+ for ( ; ; ) {
71
+ const { value : leftChar } = leftIter . next ( ) ;
72
+ const { value : rightChar } = rightIter . next ( ) ;
73
+ if ( leftChar === undefined && rightChar === undefined ) {
74
+ return 0 ;
75
+ } else if ( leftChar === undefined ) {
76
+ // left is a prefix of right.
77
+ return - 1 ;
78
+ } else if ( rightChar === undefined ) {
79
+ // right is a prefix of left.
80
+ return 1 ;
81
+ }
82
+ const leftCodepoint = /** @type {number } */ ( leftChar . codePointAt ( 0 ) ) ;
83
+ const rightCodepoint = /** @type {number } */ ( rightChar . codePointAt ( 0 ) ) ;
84
+ if ( leftCodepoint < rightCodepoint ) return - 1 ;
85
+ if ( leftCodepoint > rightCodepoint ) return 1 ;
86
+ }
87
+ } ;
88
+ harden ( compareByCodePoints ) ;
52
89
53
90
/**
54
91
* @typedef {Record<PassStyle, { index: number, cover: RankCover }> } PassStyleRanksRecord
@@ -140,8 +177,7 @@ export const makeComparatorKit = (compareRemotables = (_x, _y) => 0) => {
140
177
return 0 ;
141
178
}
142
179
case 'boolean' :
143
- case 'bigint' :
144
- case 'string' : {
180
+ case 'bigint' : {
145
181
// Within each of these passStyles, the rank ordering agrees with
146
182
// JavaScript's relational operators `<` and `>`.
147
183
if ( left < right ) {
@@ -151,6 +187,9 @@ export const makeComparatorKit = (compareRemotables = (_x, _y) => 0) => {
151
187
return 1 ;
152
188
}
153
189
}
190
+ case 'string' : {
191
+ return compareByCodePoints ( left , right ) ;
192
+ }
154
193
case 'symbol' : {
155
194
return comparator (
156
195
nameForPassableSymbol ( left ) ,
0 commit comments