string-charCodeAt-oob.js (3349B)
1 // Test String.prototype.charCodeAt with out-of-bounds indices. 2 3 function* characters(...ranges) { 4 for (let [start, end] of ranges) { 5 for (let i = start; i <= end; ++i) { 6 yield i; 7 } 8 } 9 } 10 11 const empty = []; 12 13 const ascii = [...characters( 14 [0x41, 0x5A], // A..Z 15 [0x61, 0x7A], // a..z 16 )]; 17 18 const latin1 = [...characters( 19 [0xC0, 0xFF], // À..ÿ 20 )]; 21 22 const twoByte = [...characters( 23 [0x100, 0x17E], // Ā..ž 24 )]; 25 26 function atomize(s) { 27 return Object.keys({[s]: 0})[0]; 28 } 29 30 function codePoints() { 31 return [empty, ascii, latin1, twoByte]; 32 } 33 34 function toRope(s) { 35 // Ropes have at least two characters. 36 if (s.length < 2) { 37 return s; 38 } 39 if (s.length === 2) { 40 return newRope(s[0], s[1]); 41 } 42 return newRope(s[0], s.substring(1)); 43 } 44 45 function makeStrings() { 46 let strings = codePoints() 47 .map(codePoints => String.fromCodePoint(...codePoints)) 48 .flatMap(x => [ 49 x, 50 toRope(x), 51 newString(x, {twoByte: true}), 52 atomize(x), 53 ]); 54 return strings; 55 } 56 57 function testNegativeIndexConstant() { 58 let strings = makeStrings(); 59 for (let i = 0; i < 200; ++i) { 60 let str = strings[i % strings.length]; 61 let ch = str.charCodeAt(-1); 62 assertEq(ch, NaN); 63 } 64 } 65 for (let i = 0; i < 2; ++i) { 66 testNegativeIndexConstant(); 67 } 68 69 function testNegativeIndexVariable() { 70 let indices = [-1, -2]; 71 let strings = makeStrings(); 72 for (let i = 0; i < 200; ++i) { 73 let str = strings[i % strings.length]; 74 let ch = str.charCodeAt(indices[i & 1]); 75 assertEq(ch, NaN); 76 } 77 } 78 for (let i = 0; i < 2; ++i) { 79 testNegativeIndexVariable(); 80 } 81 82 function testNegativeOrValidIndex() { 83 let indices = [-1, 0]; 84 let strings = makeStrings(); 85 86 // Number of string kinds created in makeStrings. 87 const N = 4; 88 89 let cpoints = codePoints(); 90 assertEq(strings.length, cpoints.length * N); 91 92 for (let i = 0; i < 200; ++i) { 93 let str = strings[i % strings.length]; 94 let index = indices[i & 1]; 95 let ch = str.charCodeAt(index); 96 97 let cp = cpoints[Math.trunc((i % strings.length) / N)]; 98 assertEq(ch, (0 <= index && index < cp.length ? cp[index] : NaN)); 99 } 100 } 101 for (let i = 0; i < 2; ++i) { 102 testNegativeOrValidIndex(); 103 } 104 105 function testTooLargeIndexConstant() { 106 let strings = makeStrings(); 107 for (let i = 0; i < 200; ++i) { 108 let str = strings[i % strings.length]; 109 let ch = str.charCodeAt(1000); 110 assertEq(ch, NaN); 111 } 112 } 113 for (let i = 0; i < 2; ++i) { 114 testTooLargeIndexConstant(); 115 } 116 117 function testTooLargeIndexVariable() { 118 let indices = [1000, 2000]; 119 let strings = makeStrings(); 120 for (let i = 0; i < 200; ++i) { 121 let str = strings[i % strings.length]; 122 let ch = str.charCodeAt(indices[i & 1]); 123 assertEq(ch, NaN); 124 } 125 } 126 for (let i = 0; i < 2; ++i) { 127 testTooLargeIndexVariable(); 128 } 129 130 function testTooLargeOrValidIndex() { 131 let indices = [1000, 0]; 132 let strings = makeStrings(); 133 134 // Number of string kinds created in makeStrings. 135 const N = 4; 136 137 let cpoints = codePoints(); 138 assertEq(strings.length, cpoints.length * N); 139 140 for (let i = 0; i < 200; ++i) { 141 let str = strings[i % strings.length]; 142 let index = indices[i & 1]; 143 let ch = str.charCodeAt(index); 144 145 let cp = cpoints[Math.trunc((i % strings.length) / N)]; 146 assertEq(ch, (0 <= index && index < cp.length ? cp[index] : NaN)); 147 } 148 } 149 for (let i = 0; i < 2; ++i) { 150 testTooLargeOrValidIndex(); 151 }