github.com/nuvolaris/goja@v0.0.0-20230825100449-967811910c6d/builtin_string_test.go (about) 1 package goja 2 3 import "testing" 4 5 func TestSubstr(t *testing.T) { 6 const SCRIPT = ` 7 assert.sameValue('abc'.substr(0, false), '', 'start: 0, length: false'); 8 assert.sameValue('abc'.substr(1, false), '', 'start: 1, length: false'); 9 assert.sameValue('abc'.substr(2, false), '', 'start: 2, length: false'); 10 assert.sameValue('abc'.substr(3, false), '', 'start: 3, length: false'); 11 12 assert.sameValue('abc'.substr(0, NaN), '', 'start: 0, length: NaN'); 13 assert.sameValue('abc'.substr(1, NaN), '', 'start: 1, length: NaN'); 14 assert.sameValue('abc'.substr(2, NaN), '', 'start: 2, length: NaN'); 15 assert.sameValue('abc'.substr(3, NaN), '', 'start: 3, length: NaN'); 16 17 assert.sameValue('abc'.substr(0, ''), '', 'start: 0, length: ""'); 18 assert.sameValue('abc'.substr(1, ''), '', 'start: 1, length: ""'); 19 assert.sameValue('abc'.substr(2, ''), '', 'start: 2, length: ""'); 20 assert.sameValue('abc'.substr(3, ''), '', 'start: 3, length: ""'); 21 22 assert.sameValue('abc'.substr(0, null), '', 'start: 0, length: null'); 23 assert.sameValue('abc'.substr(1, null), '', 'start: 1, length: null'); 24 assert.sameValue('abc'.substr(2, null), '', 'start: 2, length: null'); 25 assert.sameValue('abc'.substr(3, null), '', 'start: 3, length: null'); 26 27 assert.sameValue('abc'.substr(0, -1), '', '0, -1'); 28 assert.sameValue('abc'.substr(0, -2), '', '0, -2'); 29 assert.sameValue('abc'.substr(0, -3), '', '0, -3'); 30 assert.sameValue('abc'.substr(0, -4), '', '0, -4'); 31 32 assert.sameValue('abc'.substr(1, -1), '', '1, -1'); 33 assert.sameValue('abc'.substr(1, -2), '', '1, -2'); 34 assert.sameValue('abc'.substr(1, -3), '', '1, -3'); 35 assert.sameValue('abc'.substr(1, -4), '', '1, -4'); 36 37 assert.sameValue('abc'.substr(2, -1), '', '2, -1'); 38 assert.sameValue('abc'.substr(2, -2), '', '2, -2'); 39 assert.sameValue('abc'.substr(2, -3), '', '2, -3'); 40 assert.sameValue('abc'.substr(2, -4), '', '2, -4'); 41 42 assert.sameValue('abc'.substr(3, -1), '', '3, -1'); 43 assert.sameValue('abc'.substr(3, -2), '', '3, -2'); 44 assert.sameValue('abc'.substr(3, -3), '', '3, -3'); 45 assert.sameValue('abc'.substr(3, -4), '', '3, -4'); 46 47 assert.sameValue('abc'.substr(0, 1), 'a', '0, 1'); 48 assert.sameValue('abc'.substr(0, 2), 'ab', '0, 1'); 49 assert.sameValue('abc'.substr(0, 3), 'abc', '0, 1'); 50 assert.sameValue('abc'.substr(0, 4), 'abc', '0, 1'); 51 52 assert.sameValue('abc'.substr(1, 1), 'b', '1, 1'); 53 assert.sameValue('abc'.substr(1, 2), 'bc', '1, 1'); 54 assert.sameValue('abc'.substr(1, 3), 'bc', '1, 1'); 55 assert.sameValue('abc'.substr(1, 4), 'bc', '1, 1'); 56 57 assert.sameValue('abc'.substr(2, 1), 'c', '2, 1'); 58 assert.sameValue('abc'.substr(2, 2), 'c', '2, 1'); 59 assert.sameValue('abc'.substr(2, 3), 'c', '2, 1'); 60 assert.sameValue('abc'.substr(2, 4), 'c', '2, 1'); 61 62 assert.sameValue('abc'.substr(3, 1), '', '3, 1'); 63 assert.sameValue('abc'.substr(3, 2), '', '3, 1'); 64 assert.sameValue('abc'.substr(3, 3), '', '3, 1'); 65 assert.sameValue('abc'.substr(3, 4), '', '3, 1'); 66 67 assert.sameValue('abc'.substr(0), 'abc', 'start: 0, length: unspecified'); 68 assert.sameValue('abc'.substr(1), 'bc', 'start: 1, length: unspecified'); 69 assert.sameValue('abc'.substr(2), 'c', 'start: 2, length: unspecified'); 70 assert.sameValue('abc'.substr(3), '', 'start: 3, length: unspecified'); 71 72 assert.sameValue( 73 'abc'.substr(0, undefined), 'abc', 'start: 0, length: undefined' 74 ); 75 assert.sameValue( 76 'abc'.substr(1, undefined), 'bc', 'start: 1, length: undefined' 77 ); 78 assert.sameValue( 79 'abc'.substr(2, undefined), 'c', 'start: 2, length: undefined' 80 ); 81 assert.sameValue( 82 'abc'.substr(3, undefined), '', 'start: 3, length: undefined' 83 ); 84 85 assert.sameValue('A—', String.fromCharCode(65, 0x2014)); 86 87 ` 88 89 testScriptWithTestLib(SCRIPT, _undefined, t) 90 } 91 92 func TestStringMatchSym(t *testing.T) { 93 const SCRIPT = ` 94 function Prefix(p) { 95 this.p = p; 96 } 97 98 Prefix.prototype[Symbol.match] = function(s) { 99 return s.substring(0, this.p.length) === this.p; 100 } 101 102 var prefix1 = new Prefix("abc"); 103 var prefix2 = new Prefix("def"); 104 105 "abc123".match(prefix1) === true && "abc123".match(prefix2) === false && 106 "def123".match(prefix1) === false && "def123".match(prefix2) === true; 107 ` 108 testScript(SCRIPT, valueTrue, t) 109 } 110 111 func TestStringMatchAllSym(t *testing.T) { 112 const SCRIPT = ` 113 function Prefix(p) { 114 this.p = p; 115 } 116 117 Prefix.prototype[Symbol.matchAll] = function(s) { 118 return s.substring(0, this.p.length) === this.p; 119 } 120 121 var prefix1 = new Prefix("abc"); 122 var prefix2 = new Prefix("def"); 123 124 "abc123".matchAll(prefix1) === true && "abc123".matchAll(prefix2) === false && 125 "def123".matchAll(prefix1) === false && "def123".matchAll(prefix2) === true; 126 ` 127 testScript(SCRIPT, valueTrue, t) 128 } 129 130 func TestGenericSplitter(t *testing.T) { 131 const SCRIPT = ` 132 function MyRegexp(pattern, flags) { 133 if (pattern instanceof MyRegexp) { 134 pattern = pattern.wrapped; 135 } 136 this.wrapped = new RegExp(pattern, flags); 137 } 138 139 MyRegexp.prototype.exec = function() { 140 return this.wrapped.exec.apply(this.wrapped, arguments); 141 } 142 143 Object.defineProperty(MyRegexp.prototype, "lastIndex", { 144 get: function() { 145 return this.wrapped.lastIndex; 146 }, 147 set: function(v) { 148 this.wrapped.lastIndex = v; 149 } 150 }); 151 152 Object.defineProperty(MyRegexp.prototype, "flags", { 153 get: function() { 154 return this.wrapped.flags; 155 } 156 }); 157 158 MyRegexp[Symbol.species] = MyRegexp; 159 MyRegexp.prototype[Symbol.split] = RegExp.prototype[Symbol.split]; 160 161 var r = new MyRegexp(/ /); 162 var res = "a b c".split(r); 163 res.length === 3 && res[0] === "a" && res[1] === "b" && res[2] === "c"; 164 ` 165 testScript(SCRIPT, valueTrue, t) 166 } 167 168 func TestStringIterSurrPair(t *testing.T) { 169 const SCRIPT = ` 170 var lo = '\uD834'; 171 var hi = '\uDF06'; 172 var pair = lo + hi; 173 var string = 'a' + pair + 'b' + lo + pair + hi + lo; 174 var iterator = string[Symbol.iterator](); 175 var result; 176 177 result = iterator.next(); 178 if (result.value !== 'a') { 179 throw new Error("at 0: " + result.value); 180 } 181 result = iterator.next(); 182 if (result.value !== pair) { 183 throw new Error("at 1: " + result.value); 184 } 185 186 ` 187 testScript(SCRIPT, _undefined, t) 188 } 189 190 func TestValueStringBuilder(t *testing.T) { 191 t.Run("substringASCII", func(t *testing.T) { 192 t.Parallel() 193 var sb StringBuilder 194 str := newStringValue("a\U00010000b") 195 sb.WriteSubstring(str, 0, 1) 196 res := sb.String() 197 if res != asciiString("a") { 198 t.Fatal(res) 199 } 200 }) 201 202 t.Run("substringASCIIPure", func(t *testing.T) { 203 t.Parallel() 204 var sb StringBuilder 205 str := newStringValue("ab") 206 sb.WriteSubstring(str, 0, 1) 207 res := sb.String() 208 if res != asciiString("a") { 209 t.Fatal(res) 210 } 211 }) 212 213 t.Run("substringUnicode", func(t *testing.T) { 214 t.Parallel() 215 var sb StringBuilder 216 str := newStringValue("a\U00010000b") 217 sb.WriteSubstring(str, 1, 3) 218 res := sb.String() 219 if !res.SameAs(unicodeStringFromRunes([]rune{0x10000})) { 220 t.Fatal(res) 221 } 222 }) 223 224 t.Run("substringASCIIUnicode", func(t *testing.T) { 225 t.Parallel() 226 var sb StringBuilder 227 str := newStringValue("a\U00010000b") 228 sb.WriteSubstring(str, 0, 2) 229 res := sb.String() 230 if !res.SameAs(unicodeStringFromRunes([]rune{'a', 0xD800})) { 231 t.Fatal(res) 232 } 233 }) 234 235 t.Run("substringUnicodeASCII", func(t *testing.T) { 236 t.Parallel() 237 var sb StringBuilder 238 str := newStringValue("a\U00010000b") 239 sb.WriteSubstring(str, 2, 4) 240 res := sb.String() 241 if !res.SameAs(unicodeStringFromRunes([]rune{0xDC00, 'b'})) { 242 t.Fatal(res) 243 } 244 }) 245 246 t.Run("concatSubstringUnicodeASCII", func(t *testing.T) { 247 t.Parallel() 248 var sb StringBuilder 249 sb.WriteString(newStringValue("юникод")) 250 sb.WriteSubstring(asciiString(" ascii"), 0, 6) 251 if res := sb.String(); !res.SameAs(newStringValue("юникод ascii")) { 252 t.Fatal(res) 253 } 254 }) 255 256 t.Run("concat_ASCII_importedASCII", func(t *testing.T) { 257 t.Parallel() 258 var sb StringBuilder 259 sb.WriteString(asciiString("ascii")) 260 sb.WriteString(&importedString{s: " imported_ascii1234567890"}) 261 s := sb.String() 262 if res, ok := s.(asciiString); !ok || res != "ascii imported_ascii1234567890" { 263 t.Fatal(s) 264 } 265 }) 266 267 t.Run("concat_ASCII_importedUnicode", func(t *testing.T) { 268 t.Parallel() 269 var sb StringBuilder 270 sb.WriteString(asciiString("ascii")) 271 sb.WriteString(&importedString{s: " imported_юникод"}) 272 s := sb.String() 273 if res, ok := s.(unicodeString); !ok || !res.SameAs(newStringValue("ascii imported_юникод")) { 274 t.Fatal(s) 275 } 276 }) 277 278 }