well-formed.js (3921B)
1 // |reftest| skip-if(!xulRuntime.shell) 2 function IsLatin1String(str) { 3 for (var i = 0; i < str.length; ++i) { 4 if (str.charCodeAt(i) > 0xff) { 5 return false; 6 } 7 } 8 return true; 9 } 10 11 function IsTwoByteString(str) { 12 return !IsLatin1String(str); 13 } 14 15 const latin1Strings = [ 16 // Empty string. 17 "", 18 19 // Single character string. 20 "a", 21 "\0", 22 "\u{80}", 23 "\u{ff}", 24 25 // Inline strings. 26 "ascii", 27 "látïñ-¹", 28 29 // Too large for inline string storage. 30 "This is an ASCII string which is too large for inline storage", 31 "This is a látïñ-¹ string which is too large for inline storage", 32 ]; 33 34 assertEq(latin1Strings.every(IsLatin1String), true); 35 36 const twoByteStrings = [ 37 // Single code point string. 38 "\u{100}", 39 "\u{10ffff}", 40 41 // Leading two-byte character. 42 ...latin1Strings.map(s => "\u{100}" + s), 43 44 // Trailing two-byte character. 45 ...latin1Strings.map(s => s + "\u{100}"), 46 47 // Interspersed two-byte character. 48 ...latin1Strings.map(s => s + "\u{100}" + "-"), 49 ...latin1Strings.map(s => "-" + "\u{100}" + s), 50 ]; 51 52 assertEq(twoByteStrings.every(IsTwoByteString), true); 53 54 const unpairedSurrogates = [ 55 // LeadSurrogateMin and LeadSurrogateMax 56 "\u{D800}", 57 "\u{DBFF}", 58 59 // TrailSurrogateMin and TrailSurrogateMax 60 "\u{DC00}", 61 "\u{DFFF}", 62 ]; 63 64 const strings = [ 65 ...latin1Strings, 66 ...twoByteStrings, 67 68 // In case we've missed some special cases above. 69 // (Assumes it doesn't return a string with unpaired surrogates.) 70 ...representativeStringArray(), 71 ]; 72 73 function toRope(string) { 74 try { 75 let rope = newRope(string[0], string.slice(1)); 76 return {rope, filler: ""}; 77 } catch {} 78 79 // |newRope| fails if the input is too short. Add some characters to make 80 // the input large enough. 81 let filler = "012345678901234567890123456789"; 82 let rope = newRope(string, filler); 83 return {rope, filler}; 84 } 85 86 for (let string of strings) { 87 assertEq(string.isWellFormed(), true); 88 assertEq(string.toWellFormed(), string); 89 90 // Need at least two characters to make a rope. 91 if (string.length >= 2) { 92 let {rope, filler} = toRope(string); 93 assertEq(rope.isWellFormed(), true); 94 assertEq(rope.toWellFormed(), string + filler); 95 } 96 97 // Copy the string to create a non-atom string. (Unless |string| is a static string.) 98 let copy = newString(string); 99 assertEq(copy.isWellFormed(), true); 100 assertEq(copy.toWellFormed(), string); 101 102 let twoByte = newString(string, {twoByte: true}); 103 assertEq(twoByte.isWellFormed(), true); 104 assertEq(twoByte.toWellFormed(), string); 105 } 106 107 // Single unpaired surrogates. 108 for (let unpaired of unpairedSurrogates) { 109 assertEq(unpaired.isWellFormed(), false); 110 assertEq(unpaired.toWellFormed(), "\u{FFFD}"); 111 } 112 113 // Add unpaired surrogates. 114 for (let unpaired of unpairedSurrogates.flatMap(unpaired => { 115 return [ 116 // Single unpaired. 117 unpaired, 118 119 // Two consecutive unpaired. 120 unpaired + unpaired, 121 122 // Two separate unpaired. 123 unpaired + "-" + unpaired 124 ]; 125 })) { 126 for (let string of strings.flatMap(string => { 127 return [ 128 // Leading unpaired. 129 unpaired + string, 130 131 // Trailing unpaired. 132 string + unpaired, 133 134 // Interspersed unpaired. 135 string + unpaired + "-", 136 "-" + unpaired + string, 137 string + unpaired + string, 138 ]; 139 })) { 140 assertEq(string.isWellFormed(), false); 141 assertEq(string.toWellFormed() === string, false); 142 143 // Need at least two characters to make a rope. 144 if (string.length >= 2) { 145 let {rope, filler} = toRope(string); 146 assertEq(rope.isWellFormed(), false); 147 assertEq(rope.toWellFormed() === string + filler, false); 148 } 149 150 // Copy the string to create a non-atom string. (Unless |string| is a static string.) 151 let copy = newString(string); 152 assertEq(copy.isWellFormed(), false); 153 assertEq(copy.toWellFormed() === string, false); 154 } 155 } 156 157 if (typeof reportCompare === "function") 158 reportCompare(true, true);