string-search-test262.test.ts 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811
  1. /*
  2. * Portions adapted from Test262 at revision 250f204f23a9249ff204be2baec29600faae7b75:
  3. * - test/built-ins/String/prototype/split/call-split-l-0-instance-is-string-hello.js
  4. * - test/built-ins/String/prototype/split/call-split-l-1-instance-is-string-hello.js
  5. * - test/built-ins/String/prototype/split/call-split-l-2-instance-is-string-hello.js
  6. * - test/built-ins/String/prototype/split/call-split-l-3-instance-is-string-hello.js
  7. * - test/built-ins/String/prototype/split/call-split-l-4-instance-is-string-hello.js
  8. * - test/built-ins/String/prototype/split/call-split-l-na-n-instance-is-string-hello.js
  9. * - test/built-ins/String/prototype/split/call-split-l-instance-is-string-hello.js
  10. * - test/built-ins/String/prototype/split/call-split-ll-instance-is-string-hello.js
  11. * - test/built-ins/String/prototype/split/call-split-h-instance-is-string-hello.js
  12. * - test/built-ins/String/prototype/split/call-split-hello-instance-is-string-hello.js
  13. * - test/built-ins/String/prototype/split/call-split-hellothere-instance-is-string-hello.js
  14. * - test/built-ins/String/prototype/split/call-split-o-instance-is-string-hello.js
  15. * - test/built-ins/String/prototype/split/call-split-x-instance-is-string-hello.js
  16. * - test/built-ins/String/prototype/split/call-split-x-instance-is-empty-string.js
  17. * - test/built-ins/String/prototype/split/call-split-4-instance-is-string-one-1-two-2-four-4.js
  18. * - test/built-ins/String/prototype/split/call-split-on-instance-is-string-one-1-two-2-four-4.js
  19. * - test/built-ins/String/prototype/split/call-split-instance-is-string-one-two-three-four-five.js
  20. * - test/built-ins/String/prototype/split/call-split-instance-is-string-one-two-three.js
  21. * - test/built-ins/String/prototype/split/call-split-instance-is-string.js
  22. * - test/built-ins/String/prototype/split/instance-is-string-one-two-three-four-five.js
  23. * - test/built-ins/String/prototype/split/instance-is-string.js
  24. * - test/built-ins/String/prototype/split/separator-colon-instance-is-string-one-1-two-2-four-4.js
  25. * - test/built-ins/String/prototype/split/separator-comma-instance-is-string-one-two-three-four-five.js
  26. * - test/built-ins/String/prototype/split/separator-empty-string-instance-is-string.js
  27. * - test/built-ins/String/prototype/split/call-split-without-arguments-and-instance-is-empty-string.js
  28. * - test/built-ins/String/prototype/split/separator-undef.js
  29. * - test/built-ins/String/prototype/slice/S15.5.4.13_A1_T6.js
  30. * - test/built-ins/String/prototype/slice/S15.5.4.13_A1_T14.js
  31. * - test/built-ins/String/prototype/slice/S15.5.4.13_A2_T1.js
  32. * - test/built-ins/String/prototype/slice/S15.5.4.13_A2_T2.js
  33. * - test/built-ins/String/prototype/slice/S15.5.4.13_A2_T3.js
  34. * - test/built-ins/String/prototype/slice/S15.5.4.13_A2_T4.js
  35. * - test/built-ins/String/prototype/slice/S15.5.4.13_A2_T5.js
  36. * - test/built-ins/String/prototype/slice/S15.5.4.13_A2_T6.js
  37. * - test/built-ins/String/prototype/slice/S15.5.4.13_A2_T7.js
  38. * - test/built-ins/String/prototype/slice/S15.5.4.13_A2_T8.js
  39. * - test/built-ins/String/prototype/slice/S15.5.4.13_A2_T9.js
  40. * - test/built-ins/String/prototype/substring/S15.5.4.15_A1_T6.js
  41. * - test/built-ins/String/prototype/substring/S15.5.4.15_A1_T14.js
  42. * - test/built-ins/String/prototype/substring/S15.5.4.15_A2_T1.js
  43. * - test/built-ins/String/prototype/substring/S15.5.4.15_A2_T2.js
  44. * - test/built-ins/String/prototype/substring/S15.5.4.15_A2_T3.js
  45. * - test/built-ins/String/prototype/substring/S15.5.4.15_A2_T4.js
  46. * - test/built-ins/String/prototype/substring/S15.5.4.15_A2_T5.js
  47. * - test/built-ins/String/prototype/substring/S15.5.4.15_A2_T6.js
  48. * - test/built-ins/String/prototype/substring/S15.5.4.15_A2_T7.js
  49. * - test/built-ins/String/prototype/substring/S15.5.4.15_A2_T8.js
  50. * - test/built-ins/String/prototype/substring/S15.5.4.15_A2_T9.js
  51. * - test/built-ins/String/prototype/substring/S15.5.4.15_A2_T10.js
  52. * - test/built-ins/String/prototype/includes/String.prototype.includes_FailMissingLetter.js
  53. * - test/built-ins/String/prototype/includes/String.prototype.includes_SuccessNoLocation.js
  54. * - test/built-ins/String/prototype/includes/String.prototype.includes_FailBadLocation.js
  55. * - test/built-ins/String/prototype/includes/String.prototype.includes_FailLocation.js
  56. * - test/built-ins/String/prototype/includes/String.prototype.includes_Success.js
  57. * - test/built-ins/String/prototype/includes/searchstring-found-with-position.js
  58. * - test/built-ins/String/prototype/includes/searchstring-found-without-position.js
  59. * - test/built-ins/String/prototype/includes/searchstring-not-found-with-position.js
  60. * - test/built-ins/String/prototype/includes/searchstring-not-found-without-position.js
  61. * - test/built-ins/String/prototype/includes/return-false-with-out-of-bounds-position.js
  62. * - test/built-ins/String/prototype/includes/return-true-if-searchstring-is-empty.js
  63. * - test/built-ins/String/prototype/includes/coerced-values-of-position.js
  64. * - test/built-ins/String/prototype/startsWith/searchstring-found-with-position.js
  65. * - test/built-ins/String/prototype/startsWith/searchstring-found-without-position.js
  66. * - test/built-ins/String/prototype/startsWith/searchstring-not-found-with-position.js
  67. * - test/built-ins/String/prototype/startsWith/searchstring-not-found-without-position.js
  68. * - test/built-ins/String/prototype/startsWith/out-of-bounds-position.js
  69. * - test/built-ins/String/prototype/startsWith/return-true-if-searchstring-is-empty.js
  70. * - test/built-ins/String/prototype/startsWith/coerced-values-of-position.js
  71. * - test/built-ins/String/prototype/endsWith/String.prototype.endsWith_Success.js
  72. * - test/built-ins/String/prototype/endsWith/String.prototype.endsWith_Success_2.js
  73. * - test/built-ins/String/prototype/endsWith/String.prototype.endsWith_Success_3.js
  74. * - test/built-ins/String/prototype/endsWith/String.prototype.endsWith_Success_4.js
  75. * - test/built-ins/String/prototype/endsWith/String.prototype.endsWith_Fail.js
  76. * - test/built-ins/String/prototype/endsWith/String.prototype.endsWith_Fail_2.js
  77. * - test/built-ins/String/prototype/endsWith/searchstring-found-with-position.js
  78. * - test/built-ins/String/prototype/endsWith/searchstring-found-without-position.js
  79. * - test/built-ins/String/prototype/endsWith/searchstring-not-found-with-position.js
  80. * - test/built-ins/String/prototype/endsWith/searchstring-not-found-without-position.js
  81. * - test/built-ins/String/prototype/endsWith/return-false-if-search-start-is-less-than-zero.js
  82. * - test/built-ins/String/prototype/endsWith/return-true-if-searchstring-is-empty.js
  83. * - test/built-ins/String/prototype/endsWith/coerced-values-of-position.js
  84. * - test/built-ins/String/prototype/indexOf/S15.5.4.7_A2_T1.js
  85. * - test/built-ins/String/prototype/indexOf/S15.5.4.7_A2_T2.js
  86. * - test/built-ins/String/prototype/indexOf/S15.5.4.7_A2_T3.js
  87. * - test/built-ins/String/prototype/indexOf/S15.5.4.7_A2_T4.js
  88. * - test/built-ins/String/prototype/indexOf/S15.5.4.7_A3_T1.js
  89. * - test/built-ins/String/prototype/indexOf/S15.5.4.7_A3_T3.js
  90. * - test/built-ins/String/prototype/indexOf/position-tointeger.js
  91. * - test/built-ins/String/prototype/indexOf/searchstring-tostring.js
  92. * - test/built-ins/String/prototype/lastIndexOf/not-a-substring.js
  93. *
  94. * Copyright 2009 the Sputnik authors. All rights reserved.
  95. * Copyright (c) 2014 Ryan Lewis. All rights reserved.
  96. * Copyright (C) 2015 the V8 project authors. All rights reserved.
  97. * Copyright (C) 2016 the V8 project authors. All rights reserved.
  98. * Copyright (C) 2017 Josh Wolfe. All rights reserved.
  99. * Copyright (C) 2020 Leo Balter. All rights reserved.
  100. * Copyright (C) 2026 Garham Lee. All rights reserved.
  101. * Test262 portions are governed by the BSD license in LICENSE.test262.
  102. */
  103. import { describe, expect, test } from "bun:test"
  104. import { Effect } from "effect"
  105. import { CodeMode } from "../src/index.js"
  106. const value = async (code: string) => {
  107. const result = await Effect.runPromise(CodeMode.execute({ code, tools: {} }))
  108. if (!result.ok) throw new Error(`expected success, got ${result.error.kind}: ${result.error.message}`)
  109. return result.value
  110. }
  111. const cases = [
  112. {
  113. path: "test/built-ins/String/prototype/split/call-split-l-0-instance-is-string-hello.js",
  114. code: `const result = "hello".split("l", 0); return [result.length, result[0] === undefined]`,
  115. expected: [0, true],
  116. labels: [
  117. "The value of __split.length is expected to equal the value of __expected.length",
  118. "The value of __split[0] is expected to equal the value of __expected[0]",
  119. ],
  120. },
  121. {
  122. path: "test/built-ins/String/prototype/split/call-split-l-1-instance-is-string-hello.js",
  123. code: `const result = "hello".split("l", 1); return [result.length, result[0]]`,
  124. expected: [1, "he"],
  125. labels: [
  126. "The value of __split.length is expected to equal the value of __expected.length",
  127. "The value of __split[0] is expected to equal the value of __expected[0]",
  128. ],
  129. },
  130. {
  131. path: "test/built-ins/String/prototype/split/call-split-l-2-instance-is-string-hello.js",
  132. code: `const result = "hello".split("l", 2); return [result.length, result[0], result[1]]`,
  133. expected: [2, "he", ""],
  134. labels: [
  135. "The value of __split.length is expected to equal the value of __expected.length",
  136. "The value of __split[index] is expected to equal the value of __expected[index]",
  137. "The value of __split[index] is expected to equal the value of __expected[index]",
  138. ],
  139. },
  140. {
  141. path: "test/built-ins/String/prototype/split/call-split-l-3-instance-is-string-hello.js",
  142. code: `const result = "hello".split("l", 3); return [result.length, result[0], result[1], result[2]]`,
  143. expected: [3, "he", "", "o"],
  144. labels: [
  145. "The value of __split.length is expected to equal the value of __expected.length",
  146. "The value of __split[index] is expected to equal the value of __expected[index]",
  147. "The value of __split[index] is expected to equal the value of __expected[index]",
  148. "The value of __split[index] is expected to equal the value of __expected[index]",
  149. ],
  150. },
  151. {
  152. path: "test/built-ins/String/prototype/split/call-split-l-4-instance-is-string-hello.js",
  153. code: `const result = "hello".split("l", 4); return [result.length, result[0], result[1], result[2]]`,
  154. expected: [3, "he", "", "o"],
  155. labels: [
  156. "The value of __split.length is expected to equal the value of __expected.length",
  157. "The value of __split[index] is expected to equal the value of __expected[index]",
  158. "The value of __split[index] is expected to equal the value of __expected[index]",
  159. "The value of __split[index] is expected to equal the value of __expected[index]",
  160. ],
  161. },
  162. {
  163. path: "test/built-ins/String/prototype/split/call-split-l-na-n-instance-is-string-hello.js",
  164. code: `const result = "hello".split("l", NaN); return [result.length, result[0] === undefined]`,
  165. expected: [0, true],
  166. labels: [
  167. "The value of __split.length is expected to equal the value of __expected.length",
  168. "The value of __split[0] is expected to equal the value of __expected[0]",
  169. ],
  170. },
  171. {
  172. path: "test/built-ins/String/prototype/split/call-split-l-instance-is-string-hello.js",
  173. code: `const result = "hello".split("l"); return [result.length, result[0], result[1], result[2]]`,
  174. expected: [3, "he", "", "o"],
  175. labels: [
  176. "The value of __split.length is 3",
  177. 'The value of __split[0] is "he"',
  178. 'The value of __split[1] is ""',
  179. 'The value of __split[2] is "o"',
  180. ],
  181. },
  182. {
  183. path: "test/built-ins/String/prototype/split/call-split-ll-instance-is-string-hello.js",
  184. code: `const result = "hello".split("ll"); return [result.length, result[0], result[1]]`,
  185. expected: [2, "he", "o"],
  186. labels: ["The value of __split.length is 2", 'The value of __split[0] is "he"', 'The value of __split[1] is "o"'],
  187. },
  188. {
  189. path: "test/built-ins/String/prototype/split/call-split-h-instance-is-string-hello.js",
  190. code: `const result = "hello".split("h"); return [result.length, result[0], result[1]]`,
  191. expected: [2, "", "ello"],
  192. labels: ["The value of __split.length is 2", 'The value of __split[0] is ""', 'The value of __split[1] is "ello"'],
  193. },
  194. {
  195. path: "test/built-ins/String/prototype/split/call-split-hello-instance-is-string-hello.js",
  196. code: `const result = "hello".split("hello"); return [result.length, result[0], result[1]]`,
  197. expected: [2, "", ""],
  198. labels: ["The value of __split.length is 2", 'The value of __split[0] is ""', 'The value of __split[1] is ""'],
  199. },
  200. {
  201. path: "test/built-ins/String/prototype/split/call-split-hellothere-instance-is-string-hello.js",
  202. code: `const result = "hello".split("hellothere"); return [result.length, result[0]]`,
  203. expected: [1, "hello"],
  204. labels: ["The value of __split.length is 1", 'The value of __split[0] is "hello"'],
  205. },
  206. {
  207. path: "test/built-ins/String/prototype/split/call-split-o-instance-is-string-hello.js",
  208. code: `const result = "hello".split("o"); return [result.length, result[0], result[1]]`,
  209. expected: [2, "hell", ""],
  210. labels: ["The value of __split.length is 2", 'The value of __split[0] is "hell"', 'The value of __split[1] is ""'],
  211. },
  212. {
  213. path: "test/built-ins/String/prototype/split/call-split-x-instance-is-string-hello.js",
  214. code: `const result = "hello".split("x"); return [result.length, result[0]]`,
  215. expected: [1, "hello"],
  216. labels: ["The value of __split.length is 1", 'The value of __split[0] is "hello"'],
  217. },
  218. {
  219. path: "test/built-ins/String/prototype/split/call-split-x-instance-is-empty-string.js",
  220. code: `const result = "".split("x"); return [result.length, result[0]]`,
  221. expected: [1, ""],
  222. labels: ["The value of __split.length is 1", 'The value of __split[0] is ""'],
  223. },
  224. {
  225. path: "test/built-ins/String/prototype/split/call-split-4-instance-is-string-one-1-two-2-four-4.js",
  226. code: `const result = "one-1 two-2 four-4".split("-4"); return [result.length, result[0], result[1]]`,
  227. expected: [2, "one-1 two-2 four", ""],
  228. labels: [
  229. "The value of __split.length is 2",
  230. 'The value of __split[0] is "one-1 two-2 four"',
  231. 'The value of __split[1] is ""',
  232. ],
  233. },
  234. {
  235. path: "test/built-ins/String/prototype/split/call-split-on-instance-is-string-one-1-two-2-four-4.js",
  236. code: `const result = "one-1 two-2 four-4".split("on"); return [result.length, result[0], result[1]]`,
  237. expected: [2, "", "e-1 two-2 four-4"],
  238. labels: [
  239. "The value of __split.length is 2",
  240. 'The value of __split[0] is ""',
  241. 'The value of __split[1] is "e-1 two-2 four-4"',
  242. ],
  243. },
  244. {
  245. path: "test/built-ins/String/prototype/split/call-split-instance-is-string-one-two-three-four-five.js",
  246. code: `const result = "one two three four five".split(" "); return [result.length, ...result]`,
  247. expected: [5, "one", "two", "three", "four", "five"],
  248. labels: [
  249. "The value of __split.length is 5",
  250. 'The value of __split[0] is "one"',
  251. 'The value of __split[1] is "two"',
  252. 'The value of __split[2] is "three"',
  253. 'The value of __split[3] is "four"',
  254. 'The value of __split[4] is "five"',
  255. ],
  256. },
  257. {
  258. path: "test/built-ins/String/prototype/split/call-split-instance-is-string-one-two-three.js",
  259. code: `const result = "one two three".split(""); return [result[0], result[1], result[11], result[12]]`,
  260. expected: ["o", "n", "e", "e"],
  261. labels: [
  262. 'The value of __split[0] is "o"',
  263. 'The value of __split[1] is "n"',
  264. 'The value of __split[11] is "e"',
  265. 'The value of __split[12] is "e"',
  266. ],
  267. },
  268. {
  269. path: "test/built-ins/String/prototype/split/call-split-instance-is-string.js",
  270. code: `const result = " ".split(" "); return [result.length, result[0], result[1]]`,
  271. expected: [2, "", ""],
  272. labels: ["The value of __split.length is 2", 'The value of __split[0] is ""', 'The value of __split[1] is ""'],
  273. },
  274. {
  275. path: "test/built-ins/String/prototype/split/instance-is-string-one-two-three-four-five.js",
  276. code: `const result = "one,two,three,four,five".split(); return [result.length, result[0]]`,
  277. expected: [1, "one,two,three,four,five"],
  278. labels: ["The value of __split.length is 1", 'The value of __split[0] is "one,two,three,four,five"'],
  279. },
  280. {
  281. path: "test/built-ins/String/prototype/split/instance-is-string.js",
  282. code: `const result = " ".split(); return [result.length, result[0]]`,
  283. expected: [1, " "],
  284. labels: ["The value of __split.length is 1", 'The value of __split[0] is " "'],
  285. },
  286. {
  287. path: "test/built-ins/String/prototype/split/separator-colon-instance-is-string-one-1-two-2-four-4.js",
  288. code: `const result = "one-1,two-2,four-4".split(":"); return [result.length, result[0]]`,
  289. expected: [1, "one-1,two-2,four-4"],
  290. labels: ["The value of __split.length is 1", 'The value of __split[0] is "one-1,two-2,four-4"'],
  291. },
  292. {
  293. path: "test/built-ins/String/prototype/split/separator-comma-instance-is-string-one-two-three-four-five.js",
  294. code: `const result = "one,two,three,four,five".split(","); return [result.length, ...result]`,
  295. expected: [5, "one", "two", "three", "four", "five"],
  296. labels: [
  297. "The value of __split.length is 5",
  298. 'The value of __split[0] is "one"',
  299. 'The value of __split[1] is "two"',
  300. 'The value of __split[2] is "three"',
  301. 'The value of __split[3] is "four"',
  302. 'The value of __split[4] is "five"',
  303. ],
  304. },
  305. {
  306. path: "test/built-ins/String/prototype/split/separator-empty-string-instance-is-string.js",
  307. code: `const result = " ".split(""); return [result.length, result[0]]`,
  308. expected: [1, " "],
  309. labels: ["The value of __split.length is 1", 'The value of __split[0] is " "'],
  310. },
  311. {
  312. path: "test/built-ins/String/prototype/split/call-split-without-arguments-and-instance-is-empty-string.js",
  313. code: `const result = "".split(); return [result.length, result[0]]`,
  314. expected: [1, ""],
  315. labels: ["The value of __split.length is 1", 'The value of __split[0] is ""'],
  316. },
  317. {
  318. path: "test/built-ins/String/prototype/split/separator-undef.js",
  319. code: `const result = "undefined is not a function".split(); return [Array.isArray(result), result.length, result[0]]`,
  320. expected: [true, 1, "undefined is not a function"],
  321. labels: [
  322. "implicit separator, result is array",
  323. "implicit separator, result.length",
  324. "implicit separator, [0] is the same string",
  325. ],
  326. },
  327. {
  328. path: "test/built-ins/String/prototype/slice/S15.5.4.13_A1_T6.js",
  329. code: `return ["undefined".slice(undefined, 3)]`,
  330. expected: ["und"],
  331. labels: ['#1: new String("undefined").slice(x,3) === "und"'],
  332. },
  333. {
  334. path: "test/built-ins/String/prototype/slice/S15.5.4.13_A1_T14.js",
  335. code: `return ["report".slice(undefined)]`,
  336. expected: ["report"],
  337. labels: ['#1: "report".slice(function(){}()) === "report"'],
  338. },
  339. {
  340. path: "test/built-ins/String/prototype/slice/S15.5.4.13_A2_T1.js",
  341. code: `return [typeof "this is a string object".slice()]`,
  342. expected: ["string"],
  343. labels: ['#1: typeof __string.slice() === "string"'],
  344. },
  345. {
  346. path: "test/built-ins/String/prototype/slice/S15.5.4.13_A2_T2.js",
  347. code: `return ["this is a string object".slice(NaN, Infinity)]`,
  348. expected: ["this is a string object"],
  349. labels: ['#1: __string.slice(NaN, Infinity) === "this is a string object"'],
  350. },
  351. {
  352. path: "test/built-ins/String/prototype/slice/S15.5.4.13_A2_T3.js",
  353. code: `return ["".slice(1, 0)]`,
  354. expected: [""],
  355. labels: ['#1: __string.slice(1,0) === ""'],
  356. },
  357. {
  358. path: "test/built-ins/String/prototype/slice/S15.5.4.13_A2_T4.js",
  359. code: `return ["this is a string object".slice(Infinity, NaN)]`,
  360. expected: [""],
  361. labels: ['#1: __string.slice(Infinity, NaN) === ""'],
  362. },
  363. {
  364. path: "test/built-ins/String/prototype/slice/S15.5.4.13_A2_T5.js",
  365. code: `return ["this is a string object".slice(Infinity, Infinity)]`,
  366. expected: [""],
  367. labels: ['#1: __string.slice(Infinity, Infinity) === ""'],
  368. },
  369. {
  370. path: "test/built-ins/String/prototype/slice/S15.5.4.13_A2_T6.js",
  371. code: `return ["this is a string object".slice(-0.01, 0)]`,
  372. expected: [""],
  373. labels: ['#1: __string.slice(-0.01,0) === ""'],
  374. },
  375. {
  376. path: "test/built-ins/String/prototype/slice/S15.5.4.13_A2_T7.js",
  377. code: `const text = "this is a string object"; return [text.slice(text.length, text.length)]`,
  378. expected: [""],
  379. labels: ['#1: __string.slice(__string.length, __string.length) === ""'],
  380. },
  381. {
  382. path: "test/built-ins/String/prototype/slice/S15.5.4.13_A2_T8.js",
  383. code: `const text = "this is a string object"; return [text.slice(text.length + 1, 0)]`,
  384. expected: [""],
  385. labels: ['#1: __string.slice(__string.length+1, 0) === ""'],
  386. },
  387. {
  388. path: "test/built-ins/String/prototype/slice/S15.5.4.13_A2_T9.js",
  389. code: `return ["this is a string object".slice(-Infinity, -Infinity)]`,
  390. expected: [""],
  391. labels: ['#1: __string.slice(-Infinity, -Infinity) === ""'],
  392. },
  393. {
  394. path: "test/built-ins/String/prototype/substring/S15.5.4.15_A1_T6.js",
  395. code: `return ["undefined".substring(undefined, 3)]`,
  396. expected: ["und"],
  397. labels: ['#1: new String("undefined").substring(x,3) === "und"'],
  398. },
  399. {
  400. path: "test/built-ins/String/prototype/substring/S15.5.4.15_A1_T14.js",
  401. code: `return ["report".substring(undefined)]`,
  402. expected: ["report"],
  403. labels: ['#1: "report".substring(function(){}()) === "report"'],
  404. },
  405. {
  406. path: "test/built-ins/String/prototype/substring/S15.5.4.15_A2_T1.js",
  407. code: `return [typeof "this is a string object".substring()]`,
  408. expected: ["string"],
  409. labels: ['#1: typeof __string.substring() === "string"'],
  410. },
  411. {
  412. path: "test/built-ins/String/prototype/substring/S15.5.4.15_A2_T2.js",
  413. code: `return ["this is a string object".substring(NaN, Infinity)]`,
  414. expected: ["this is a string object"],
  415. labels: ['#1: __string.substring(NaN, Infinity) === "this is a string object"'],
  416. },
  417. {
  418. path: "test/built-ins/String/prototype/substring/S15.5.4.15_A2_T3.js",
  419. code: `return ["".substring(1, 0)]`,
  420. expected: [""],
  421. labels: ['#1: __string.substring(1,0) === ""'],
  422. },
  423. {
  424. path: "test/built-ins/String/prototype/substring/S15.5.4.15_A2_T4.js",
  425. code: `return ["this is a string object".substring(Infinity, NaN)]`,
  426. expected: ["this is a string object"],
  427. labels: ['#1: __string.substring(Infinity, NaN) === "this is a string object"'],
  428. },
  429. {
  430. path: "test/built-ins/String/prototype/substring/S15.5.4.15_A2_T5.js",
  431. code: `return ["this is a string object".substring(Infinity, Infinity)]`,
  432. expected: [""],
  433. labels: ['#1: __string.substring(Infinity, Infinity) === ""'],
  434. },
  435. {
  436. path: "test/built-ins/String/prototype/substring/S15.5.4.15_A2_T6.js",
  437. code: `return ["this is a string object".substring(-0.01, 0)]`,
  438. expected: [""],
  439. labels: ['#1: __string.substring(-0.01,0) === ""'],
  440. },
  441. {
  442. path: "test/built-ins/String/prototype/substring/S15.5.4.15_A2_T7.js",
  443. code: `const text = "this is a string object"; return [text.substring(text.length, text.length)]`,
  444. expected: [""],
  445. labels: ['#1: __string.substring(__string.length, __string.length) === ""'],
  446. },
  447. {
  448. path: "test/built-ins/String/prototype/substring/S15.5.4.15_A2_T8.js",
  449. code: `const text = "this is a string object"; return [text.substring(text.length + 1, 0)]`,
  450. expected: ["this is a string object"],
  451. labels: ['#1: __string.substring(__string.length+1, 0) === "this is a string object"'],
  452. },
  453. {
  454. path: "test/built-ins/String/prototype/substring/S15.5.4.15_A2_T9.js",
  455. code: `return ["this is a string object".substring(-Infinity, -Infinity)]`,
  456. expected: [""],
  457. labels: ['#1: __string.substring(-Infinity, -Infinity) === ""'],
  458. },
  459. {
  460. path: "test/built-ins/String/prototype/substring/S15.5.4.15_A2_T10.js",
  461. code: `return ["this_is_a_string object".substring(0, 8)]`,
  462. expected: ["this_is_"],
  463. labels: ['#1: __string.substring(0,8) === "this_is_"'],
  464. },
  465. {
  466. path: "test/built-ins/String/prototype/includes/String.prototype.includes_FailMissingLetter.js",
  467. code: `return ["word".includes("a", 0)]`,
  468. expected: [false],
  469. labels: ['"word".includes("a", 0)'],
  470. },
  471. {
  472. path: "test/built-ins/String/prototype/includes/String.prototype.includes_SuccessNoLocation.js",
  473. code: `return ["word".includes("w")]`,
  474. expected: [true],
  475. labels: ['"word".includes("w")'],
  476. },
  477. {
  478. path: "test/built-ins/String/prototype/includes/String.prototype.includes_FailBadLocation.js",
  479. code: `return ["word".includes("w", 5)]`,
  480. expected: [false],
  481. labels: ['"word".includes("w", 5)'],
  482. },
  483. {
  484. path: "test/built-ins/String/prototype/includes/String.prototype.includes_FailLocation.js",
  485. code: `return ["word".includes("o", 3)]`,
  486. expected: [false],
  487. labels: ['"word".includes("o", 3)'],
  488. },
  489. {
  490. path: "test/built-ins/String/prototype/includes/String.prototype.includes_Success.js",
  491. code: `return ["word".includes("w", 0)]`,
  492. expected: [true],
  493. labels: ['"word".includes("w", 0)'],
  494. },
  495. {
  496. path: "test/built-ins/String/prototype/includes/searchstring-found-with-position.js",
  497. code: `const text = "The future is cool!"; return [text.includes("The future", 0), text.includes(" is ", 1), text.includes("cool!", 10)]`,
  498. expected: [true, true, true],
  499. labels: [
  500. 'Returns true for str.includes("The future", 0)',
  501. 'Returns true for str.includes(" is ", 1)',
  502. 'Returns true for str.includes("cool!", 10)',
  503. ],
  504. },
  505. {
  506. path: "test/built-ins/String/prototype/includes/searchstring-found-without-position.js",
  507. code: `const text = "The future is cool!"; return [text.includes("The future"), text.includes("is cool!"), text.includes(text)]`,
  508. expected: [true, true, true],
  509. labels: [
  510. 'Returns true for str.includes("The future")',
  511. 'Returns true for str.includes("is cool!")',
  512. "Returns true for str.includes(str)",
  513. ],
  514. },
  515. {
  516. path: "test/built-ins/String/prototype/includes/searchstring-not-found-with-position.js",
  517. code: `const text = "The future is cool!"; return [text.includes("The future", 1), text.includes(text, 1)]`,
  518. expected: [false, false],
  519. labels: ['Returns false on str.includes("The future", 1)', "Returns false on str.includes(str, 1)"],
  520. },
  521. {
  522. path: "test/built-ins/String/prototype/includes/searchstring-not-found-without-position.js",
  523. code: `const text = "The future is cool!"; return [text.includes("Flash"), text.includes("FUTURE")]`,
  524. expected: [false, false],
  525. labels: ["Flash if not included", "includes is case sensitive"],
  526. },
  527. {
  528. path: "test/built-ins/String/prototype/includes/return-false-with-out-of-bounds-position.js",
  529. code: `const text = "The future is cool!"; return [
  530. text.includes("!", text.length + 1), text.includes("!", 100), text.includes("!", Infinity), text.includes("!", text.length),
  531. ]`,
  532. expected: [false, false, false, false],
  533. labels: [
  534. 'str.includes("!", str.length + 1) returns false',
  535. 'str.includes("!", 100) returns false',
  536. 'str.includes("!", Infinity) returns false',
  537. 'str.includes("!", str.length) returns false',
  538. ],
  539. },
  540. {
  541. path: "test/built-ins/String/prototype/includes/return-true-if-searchstring-is-empty.js",
  542. code: `const text = "The future is cool!"; return [text.includes("", text.length), text.includes(""), text.includes("", Infinity)]`,
  543. expected: [true, true, true],
  544. labels: [
  545. 'str.includes("", str.length) returns true',
  546. 'str.includes("") returns true',
  547. 'str.includes("", Infinity) returns true',
  548. ],
  549. },
  550. {
  551. path: "test/built-ins/String/prototype/includes/coerced-values-of-position.js",
  552. code: `const text = "The future is cool!"; return [
  553. text.includes("The future", NaN), text.includes("The future", undefined), text.includes("The future", 0.4),
  554. text.includes("The future", -1), text.includes("The future", 1.4),
  555. ]`,
  556. expected: [true, true, true, true, false],
  557. labels: ["NaN coerced to 0", "undefined coerced to 0", "0.4 coerced to 0", "negative position", "1.4 coerced to 1"],
  558. },
  559. {
  560. path: "test/built-ins/String/prototype/startsWith/searchstring-found-with-position.js",
  561. code: `const text = "The future is cool!"; return [text.startsWith("The future", 0), text.startsWith("future", 4), text.startsWith(" is cool!", 10)]`,
  562. expected: [true, true, true],
  563. labels: [
  564. 'str.startsWith("The future", 0) === true',
  565. 'str.startsWith("future", 4) === true',
  566. 'str.startsWith(" is cool!", 10) === true',
  567. ],
  568. },
  569. {
  570. path: "test/built-ins/String/prototype/startsWith/searchstring-found-without-position.js",
  571. code: `const text = "The future is cool!"; return [text.startsWith("The "), text.startsWith("The future"), text.startsWith(text)]`,
  572. expected: [true, true, true],
  573. labels: [
  574. 'str.startsWith("The ") === true',
  575. 'str.startsWith("The future") === true',
  576. "str.startsWith(str) === true",
  577. ],
  578. },
  579. {
  580. path: "test/built-ins/String/prototype/startsWith/searchstring-not-found-with-position.js",
  581. code: `const text = "The future is cool!"; return [text.startsWith("The future", 1), text.startsWith(text, 1)]`,
  582. expected: [false, false],
  583. labels: ['str.startsWith("The future", 1) === false', "str.startsWith(str, 1) === false"],
  584. },
  585. {
  586. path: "test/built-ins/String/prototype/startsWith/searchstring-not-found-without-position.js",
  587. code: `const text = "The future is cool!"; return [text.startsWith("Flash"), text.startsWith("THE FUTURE"), text.startsWith("future is cool!")]`,
  588. expected: [false, false, false],
  589. labels: [
  590. 'str.startsWith("Flash") === false',
  591. "startsWith is case sensitive",
  592. 'str.startsWith("future is cool!") === false',
  593. ],
  594. },
  595. {
  596. path: "test/built-ins/String/prototype/startsWith/out-of-bounds-position.js",
  597. code: `const text = "The future is cool!"; return [
  598. text.startsWith("!", text.length), text.startsWith("!", 100), text.startsWith("!", Infinity),
  599. text.startsWith("The future", -1), text.startsWith("The future", -Infinity),
  600. ]`,
  601. expected: [false, false, false, true, true],
  602. labels: [
  603. 'str.startsWith("!", str.length) returns false',
  604. 'str.startsWith("!", 100) returns false',
  605. 'str.startsWith("!", Infinity) returns false',
  606. "position argument < 0 will search from the start of the string (-1)",
  607. "position argument < 0 will search from the start of the string (-Infinity)",
  608. ],
  609. },
  610. {
  611. path: "test/built-ins/String/prototype/startsWith/return-true-if-searchstring-is-empty.js",
  612. code: `const text = "The future is cool!"; return [text.startsWith(""), text.startsWith("", text.length), text.startsWith("", Infinity)]`,
  613. expected: [true, true, true],
  614. labels: [
  615. 'str.startsWith("") returns true',
  616. 'str.startsWith("", str.length) returns true',
  617. 'str.startsWith("", Infinity) returns true',
  618. ],
  619. },
  620. {
  621. path: "test/built-ins/String/prototype/startsWith/coerced-values-of-position.js",
  622. code: `const text = "The future is cool!"; return [
  623. text.startsWith("The future", NaN), text.startsWith("The future", undefined),
  624. text.startsWith("The future", 0.4), text.startsWith("The future", 1.4),
  625. ]`,
  626. expected: [true, true, true, false],
  627. labels: ["NaN coerced to 0", "undefined coerced to 0", "0.4 coerced to 0", "1.4 coerced to 1"],
  628. },
  629. {
  630. path: "test/built-ins/String/prototype/endsWith/String.prototype.endsWith_Success.js",
  631. code: `return ["word".endsWith("d")]`,
  632. expected: [true],
  633. labels: ['"word".endsWith("d")'],
  634. },
  635. {
  636. path: "test/built-ins/String/prototype/endsWith/String.prototype.endsWith_Success_2.js",
  637. code: `return ["word".endsWith("d", 4)]`,
  638. expected: [true],
  639. labels: ['"word".endsWith("d", 4)'],
  640. },
  641. {
  642. path: "test/built-ins/String/prototype/endsWith/String.prototype.endsWith_Success_3.js",
  643. code: `return ["word".endsWith("d", 25)]`,
  644. expected: [true],
  645. labels: ['"word".endsWith("d", 25)'],
  646. },
  647. {
  648. path: "test/built-ins/String/prototype/endsWith/String.prototype.endsWith_Success_4.js",
  649. code: `return ["word".endsWith("r", 3)]`,
  650. expected: [true],
  651. labels: ['"word".endsWith("r", 3)'],
  652. },
  653. {
  654. path: "test/built-ins/String/prototype/endsWith/String.prototype.endsWith_Fail.js",
  655. code: `return ["word".endsWith("r")]`,
  656. expected: [false],
  657. labels: ['"word".endsWith("r")'],
  658. },
  659. {
  660. path: "test/built-ins/String/prototype/endsWith/String.prototype.endsWith_Fail_2.js",
  661. code: `return ["word".endsWith("d", 3)]`,
  662. expected: [false],
  663. labels: ['"word".endsWith("d", 3)'],
  664. },
  665. {
  666. path: "test/built-ins/String/prototype/endsWith/searchstring-found-with-position.js",
  667. code: `const text = "The future is cool!"; return [text.endsWith("The future", 10), text.endsWith("future", 10), text.endsWith(" is cool!", text.length)]`,
  668. expected: [true, true, true],
  669. labels: [
  670. 'str.endsWith("The future", 10) === true',
  671. 'str.endsWith("future", 10) === true',
  672. 'str.endsWith(" is cool!", str.length) === true',
  673. ],
  674. },
  675. {
  676. path: "test/built-ins/String/prototype/endsWith/searchstring-found-without-position.js",
  677. code: `const text = "The future is cool!"; return [text.endsWith("cool!"), text.endsWith("!"), text.endsWith(text)]`,
  678. expected: [true, true, true],
  679. labels: ['str.endsWith("cool!") === true', 'str.endsWith("!") === true', "str.endsWith(str) === true"],
  680. },
  681. {
  682. path: "test/built-ins/String/prototype/endsWith/searchstring-not-found-with-position.js",
  683. code: `const text = "The future is cool!"; return [text.endsWith("is cool!", text.length - 1), text.endsWith("!", 1)]`,
  684. expected: [false, false],
  685. labels: ['str.endsWith("is cool!", str.length - 1) === false', 'str.endsWith("!", 1) === false'],
  686. },
  687. {
  688. path: "test/built-ins/String/prototype/endsWith/searchstring-not-found-without-position.js",
  689. code: `const text = "The future is cool!"; return [text.endsWith("is Flash!"), text.endsWith("IS COOL!"), text.endsWith("The future")]`,
  690. expected: [false, false, false],
  691. labels: [
  692. 'str.endsWith("is Flash!") === false',
  693. "endsWith is case sensitive",
  694. 'str.endsWith("The future") === false',
  695. ],
  696. },
  697. {
  698. path: "test/built-ins/String/prototype/endsWith/return-false-if-search-start-is-less-than-zero.js",
  699. code: `return ["web".endsWith("w", 0), "Bob".endsWith(" Bob")]`,
  700. expected: [false, false],
  701. labels: ['"web".endsWith("w", 0) returns false', '"Bob".endsWith(" Bob") returns false'],
  702. },
  703. {
  704. path: "test/built-ins/String/prototype/endsWith/return-true-if-searchstring-is-empty.js",
  705. code: `const text = "The future is cool!"; return [
  706. text.endsWith(""), text.endsWith("", text.length), text.endsWith("", Infinity),
  707. text.endsWith("", -1), text.endsWith("", -Infinity),
  708. ]`,
  709. expected: [true, true, true, true, true],
  710. labels: [
  711. 'str.endsWith("") returns true',
  712. 'str.endsWith("", str.length) returns true',
  713. 'str.endsWith("", Infinity) returns true',
  714. 'str.endsWith("", -1) returns true',
  715. 'str.endsWith("", -Infinity) returns true',
  716. ],
  717. },
  718. {
  719. path: "test/built-ins/String/prototype/endsWith/coerced-values-of-position.js",
  720. code: `const text = "The future is cool!"; return [
  721. text.endsWith("", NaN), text.endsWith("", undefined), text.endsWith("The future", 10.4),
  722. ]`,
  723. expected: [true, true, true],
  724. labels: ["NaN coerced to 0", "undefined coerced to 0", "10.4 coerced to 10"],
  725. },
  726. {
  727. path: "test/built-ins/String/prototype/indexOf/S15.5.4.7_A2_T1.js",
  728. code: `return ["abcd".indexOf("abcdab")]`,
  729. expected: [-1],
  730. labels: ['#1: "abcd".indexOf("abcdab")===-1'],
  731. },
  732. {
  733. path: "test/built-ins/String/prototype/indexOf/S15.5.4.7_A2_T2.js",
  734. code: `return ["abcd".indexOf("abcdab", 0)]`,
  735. expected: [-1],
  736. labels: ['#1: "abcd".indexOf("abcdab",0)===-1'],
  737. },
  738. {
  739. path: "test/built-ins/String/prototype/indexOf/S15.5.4.7_A2_T3.js",
  740. code: `return ["abcd".indexOf("abcdab", 99)]`,
  741. expected: [-1],
  742. labels: ['#1: "abcd".indexOf("abcdab",99)===-1'],
  743. },
  744. {
  745. path: "test/built-ins/String/prototype/indexOf/S15.5.4.7_A2_T4.js",
  746. code: `return ["abcd".indexOf("abcdab", NaN)]`,
  747. expected: [-1],
  748. labels: ['#1: "abcd".indexOf("abcdab",NaN)===-1'],
  749. },
  750. {
  751. path: "test/built-ins/String/prototype/indexOf/S15.5.4.7_A3_T1.js",
  752. code: `return ["$$abcdabcd".indexOf("ab", NaN)]`,
  753. expected: [2],
  754. labels: ['#1: "$$abcdabcd".indexOf("ab",NaN)===2'],
  755. },
  756. {
  757. path: "test/built-ins/String/prototype/indexOf/S15.5.4.7_A3_T3.js",
  758. code: `return ["$$abcdabcd".indexOf("ab", -Infinity)]`,
  759. expected: [2],
  760. labels: ['#1: "$$abcdabcd".indexOf("ab", function(){return -Infinity;}())===2'],
  761. },
  762. {
  763. path: "test/built-ins/String/prototype/indexOf/position-tointeger.js",
  764. code: `return [
  765. "aaaa".indexOf("aa", 0), "aaaa".indexOf("aa", 1), "aaaa".indexOf("aa", -0.9),
  766. "aaaa".indexOf("aa", 0.9), "aaaa".indexOf("aa", 1.9), "aaaa".indexOf("aa", NaN),
  767. "aaaa".indexOf("aa", Infinity), "aaaa".indexOf("aa", undefined),
  768. "aaaa".indexOf("aa", 2), "aaaa".indexOf("aa", 2.9),
  769. ]`,
  770. expected: [0, 1, 0, 0, 1, 0, -1, 0, 2, 2],
  771. labels: [
  772. "position 0",
  773. "position 1",
  774. "ToInteger: truncate towards 0 (-0.9)",
  775. "ToInteger: truncate towards 0 (0.9)",
  776. "ToInteger: truncate towards 0 (1.9)",
  777. "ToInteger: NaN => 0",
  778. "position Infinity",
  779. "ToInteger: undefined => NaN => 0",
  780. "position 2",
  781. "ToInteger: truncate towards 0 (2.9)",
  782. ],
  783. },
  784. {
  785. path: "test/built-ins/String/prototype/indexOf/searchstring-tostring.js",
  786. code: `return ["foo".indexOf(""), "__foo__".indexOf("foo")]`,
  787. expected: [0, 2],
  788. labels: ['"foo".indexOf("")', '"__foo__".indexOf("foo")'],
  789. },
  790. {
  791. path: "test/built-ins/String/prototype/lastIndexOf/not-a-substring.js",
  792. code: `return ["abc".lastIndexOf("d")]`,
  793. expected: [-1],
  794. labels: [
  795. "String.prototype.lastIndexOf returns -1 when searchString is shorter than this and searchString is not a substring of this.",
  796. ],
  797. },
  798. ] as const
  799. describe("Test262-adapted String search and extraction behavior", () => {
  800. for (const item of cases) {
  801. test(item.path, async () => {
  802. const actual = await value(item.code)
  803. if (!Array.isArray(actual)) throw new Error(`expected assertion values for ${item.path}`)
  804. expect(actual.length, "adapted assertion count").toBe(item.expected.length)
  805. item.expected.forEach((expected, index) => expect(actual[index], item.labels[index]!).toEqual(expected))
  806. })
  807. }
  808. })