builtin_string_test.go 8.2 KB

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