string-regexp-test262.test.ts 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625
  1. /*
  2. * Portions adapted from Test262 at revision 250f204f23a9249ff204be2baec29600faae7b75:
  3. * - test/built-ins/String/prototype/split/separator-regexp.js
  4. * - test/built-ins/String/prototype/split/arguments-are-regexp-s-and-3-and-instance-is-string-a-b-c-de-f.js
  5. * - test/built-ins/String/prototype/split/argument-is-regexp-s-and-instance-is-string-a-b-c-de-f.js
  6. * - test/built-ins/String/prototype/split/argument-is-regexp-d-and-instance-is-string-dfe23iu-34-65.js
  7. * - test/built-ins/String/prototype/split/argument-is-regexp-reg-exp-d-and-instance-is-string-dfe23iu-34-65.js
  8. * - test/built-ins/String/prototype/split/argument-is-regexp-a-z-and-instance-is-string-abc.js
  9. * - test/built-ins/String/prototype/split/argument-is-reg-exp-a-z-and-instance-is-string-abc.js
  10. * - test/built-ins/String/prototype/split/arguments-are-regexp-l-and-undefined-and-instance-is-string-hello.js
  11. * - test/built-ins/String/prototype/split/arguments-are-regexp-l-and-0-and-instance-is-string-hello.js
  12. * - test/built-ins/String/prototype/split/arguments-are-regexp-l-and-1-and-instance-is-string-hello.js
  13. * - test/built-ins/String/prototype/split/arguments-are-regexp-l-and-2-and-instance-is-string-hello.js
  14. * - test/built-ins/String/prototype/split/arguments-are-regexp-l-and-3-and-instance-is-string-hello.js
  15. * - test/built-ins/String/prototype/split/arguments-are-regexp-l-and-4-and-instance-is-string-hello.js
  16. * - test/built-ins/String/prototype/split/argument-is-regexp-l-and-instance-is-string-hello.js
  17. * - test/built-ins/String/prototype/split/argument-is-new-reg-exp-and-instance-is-string-hello.js
  18. * - test/built-ins/String/prototype/split/arguments-are-new-reg-exp-and-0-and-instance-is-string-hello.js
  19. * - test/built-ins/String/prototype/split/arguments-are-new-reg-exp-and-1-and-instance-is-string-hello.js
  20. * - test/built-ins/String/prototype/split/arguments-are-new-reg-exp-and-2-and-instance-is-string-hello.js
  21. * - test/built-ins/String/prototype/split/arguments-are-new-reg-exp-and-3-and-instance-is-string-hello.js
  22. * - test/built-ins/String/prototype/split/arguments-are-new-reg-exp-and-4-and-instance-is-string-hello.js
  23. * - test/built-ins/String/prototype/split/arguments-are-new-reg-exp-and-undefined-and-instance-is-string-hello.js
  24. * - test/built-ins/String/prototype/split/call-split-2-instance-is-string-one-two-three-four-five.js
  25. * - test/built-ins/String/prototype/split/separator-regexp-comma-instance-is-string-one-1-two-2-four-4.js
  26. * - test/built-ins/String/prototype/split/argument-is-regexp-x-and-instance-is-string-a-b-c-de-f.js
  27. * - test/built-ins/String/prototype/replace/regexp-capture-by-index.js
  28. * - test/built-ins/String/prototype/replace/S15.5.4.11_A1_T17.js
  29. * - test/built-ins/String/prototype/replace/S15.5.4.11_A2_T1.js
  30. * - test/built-ins/String/prototype/replace/S15.5.4.11_A2_T2.js
  31. * - test/built-ins/String/prototype/replace/S15.5.4.11_A2_T3.js
  32. * - test/built-ins/String/prototype/replace/S15.5.4.11_A2_T4.js
  33. * - test/built-ins/String/prototype/replace/S15.5.4.11_A2_T5.js
  34. * - test/built-ins/String/prototype/replace/S15.5.4.11_A2_T6.js
  35. * - test/built-ins/String/prototype/replace/S15.5.4.11_A2_T7.js
  36. * - test/built-ins/String/prototype/replace/S15.5.4.11_A2_T8.js
  37. * - test/built-ins/String/prototype/replace/S15.5.4.11_A2_T9.js
  38. * - test/built-ins/String/prototype/replace/S15.5.4.11_A2_T10.js
  39. * - test/built-ins/String/prototype/replace/S15.5.4.11_A3_T1.js
  40. * - test/built-ins/String/prototype/replace/S15.5.4.11_A3_T2.js
  41. * - test/built-ins/String/prototype/replace/S15.5.4.11_A3_T3.js
  42. * - test/built-ins/String/prototype/replace/S15.5.4.11_A5_T1.js
  43. * - test/built-ins/String/prototype/replaceAll/searchValue-replacer-RegExp-call.js
  44. * - test/built-ins/String/prototype/replaceAll/searchValue-empty-string.js
  45. * - test/built-ins/String/prototype/replaceAll/searchValue-empty-string-this-empty-string.js
  46. * - test/built-ins/String/prototype/replaceAll/replaceValue-value-replaces-string.js
  47. * - test/built-ins/String/prototype/replaceAll/getSubstitution-0x0024.js
  48. * - test/built-ins/String/prototype/replaceAll/getSubstitution-0x0024-0x0024.js
  49. * - test/built-ins/String/prototype/replaceAll/getSubstitution-0x0024-0x0026.js
  50. * - test/built-ins/String/prototype/replaceAll/getSubstitution-0x0024-0x0060.js
  51. * - test/built-ins/String/prototype/replaceAll/getSubstitution-0x0024-0x0027.js
  52. * - test/built-ins/String/prototype/replaceAll/getSubstitution-0x0024N.js
  53. * - test/built-ins/String/prototype/replaceAll/getSubstitution-0x0024NN.js
  54. * - test/built-ins/String/prototype/replaceAll/getSubstitution-0x0024-0x003C.js
  55. * - test/built-ins/String/prototype/match/S15.5.4.10_A1_T14.js
  56. * - test/built-ins/String/prototype/match/S15.5.4.10_A2_T2.js
  57. * - test/built-ins/String/prototype/match/S15.5.4.10_A2_T3.js
  58. * - test/built-ins/String/prototype/match/S15.5.4.10_A2_T4.js
  59. * - test/built-ins/String/prototype/match/S15.5.4.10_A2_T5.js
  60. * - test/built-ins/String/prototype/match/S15.5.4.10_A2_T6.js
  61. * - test/built-ins/String/prototype/match/S15.5.4.10_A2_T7.js
  62. * - test/built-ins/String/prototype/match/S15.5.4.10_A2_T8.js
  63. * - test/built-ins/String/prototype/match/S15.5.4.10_A2_T12.js
  64. * - test/built-ins/String/prototype/matchAll/regexp-prototype-matchAll-v-u-flag.js
  65. * - test/built-ins/String/prototype/search/S15.5.4.12_A1_T14.js
  66. * - test/built-ins/String/prototype/search/S15.5.4.12_A2_T1.js
  67. * - test/built-ins/String/prototype/search/S15.5.4.12_A2_T2.js
  68. * - test/built-ins/String/prototype/search/S15.5.4.12_A2_T3.js
  69. * - test/built-ins/String/prototype/search/S15.5.4.12_A2_T4.js
  70. * - test/built-ins/String/prototype/search/S15.5.4.12_A2_T5.js
  71. * - test/built-ins/String/prototype/search/S15.5.4.12_A2_T6.js
  72. * - test/built-ins/String/prototype/search/S15.5.4.12_A2_T7.js
  73. * - test/built-ins/String/prototype/search/S15.5.4.12_A3_T1.js
  74. * - test/built-ins/String/prototype/search/S15.5.4.12_A3_T2.js
  75. *
  76. * Copyright 2009 the Sputnik authors. All rights reserved.
  77. * Copyright (C) 2019 Leo Balter. All rights reserved.
  78. * Copyright (C) 2020 Rick Waldron. All rights reserved.
  79. * Copyright (C) 2023 Richard Gibson. All rights reserved.
  80. * Copyright (C) 2024 Tan Meng. All rights reserved.
  81. * Test262 portions are governed by the BSD license in LICENSE.test262.
  82. */
  83. import { describe, expect, test } from "bun:test"
  84. import { Effect } from "effect"
  85. import { CodeMode } from "../src/index.js"
  86. type Vector = {
  87. readonly path: string
  88. readonly code: string
  89. readonly expected: CodeMode.DataValue
  90. }
  91. const value = async (code: string) => {
  92. const result = await Effect.runPromise(CodeMode.execute({ code, tools: {} }))
  93. if (!result.ok) throw new Error(`expected success, got ${result.error.kind}: ${result.error.message}`)
  94. return result.value
  95. }
  96. const run = (name: string, vectors: ReadonlyArray<Vector>) => {
  97. describe(name, () => {
  98. for (const vector of vectors) {
  99. test(vector.path, async () => {
  100. expect(await value(vector.code)).toEqual(vector.expected)
  101. })
  102. }
  103. })
  104. }
  105. run("Test262-adapted regexp split behavior", [
  106. {
  107. path: "test/built-ins/String/prototype/split/separator-regexp.js",
  108. code: `
  109. return [
  110. "x".split(/^/), "x".split(/$/), "x".split(/.?/), "x".split(/.*/), "x".split(/.+/),
  111. "x".split(/.*?/), "x".split(/.{1}/), "x".split(/.{1,}/), "x".split(/.{1,2}/),
  112. "x".split(/()/), "x".split(/./), "x".split(/(?:)/), "x".split(/(...)/),
  113. "x".split(/(|)/), "x".split(/[]/), "x".split(/[^]/), "x".split(/[.-.]/),
  114. "x".split(/\\0/), "x".split(/\\b/), "x".split(/\\B/), "x".split(/\\d/),
  115. "x".split(/\\D/), "x".split(/\\n/), "x".split(/\\r/), "x".split(/\\s/),
  116. "x".split(/\\S/), "x".split(/\\v/), "x".split(/\\w/), "x".split(/\\W/),
  117. ]
  118. `,
  119. expected: [
  120. ["x"], ["x"], ["", ""], ["", ""], ["", ""], ["x"], ["", ""], ["", ""], ["", ""],
  121. ["x"], ["", ""], ["x"], ["x"], ["x"], ["x"], ["", ""], ["x"], ["x"], ["x"],
  122. ["x"], ["x"], ["", ""], ["x"], ["x"], ["x"], ["", ""], ["x"], ["", ""], ["x"],
  123. ],
  124. },
  125. {
  126. path: "test/built-ins/String/prototype/split/arguments-are-regexp-s-and-3-and-instance-is-string-a-b-c-de-f.js",
  127. code: `return "a b c de f".split(/\\s/, 3)`,
  128. expected: ["a", "b", "c"],
  129. },
  130. {
  131. path: "test/built-ins/String/prototype/split/argument-is-regexp-s-and-instance-is-string-a-b-c-de-f.js",
  132. code: `return "a b c de f".split(/\\s/)`,
  133. expected: ["a", "b", "c", "de", "f"],
  134. },
  135. {
  136. path: "test/built-ins/String/prototype/split/argument-is-regexp-d-and-instance-is-string-dfe23iu-34-65.js",
  137. code: `return "dfe23iu 34 =+65--".split(/\\d+/)`,
  138. expected: ["dfe", "iu ", " =+", "--"],
  139. },
  140. {
  141. path: "test/built-ins/String/prototype/split/argument-is-regexp-reg-exp-d-and-instance-is-string-dfe23iu-34-65.js",
  142. code: `return "dfe23iu 34 =+65--".split(new RegExp("\\\\d+"))`,
  143. expected: ["dfe", "iu ", " =+", "--"],
  144. },
  145. {
  146. path: "test/built-ins/String/prototype/split/argument-is-regexp-a-z-and-instance-is-string-abc.js",
  147. code: `return "abc".split(/[a-z]/)`,
  148. expected: ["", "", "", ""],
  149. },
  150. {
  151. path: "test/built-ins/String/prototype/split/argument-is-reg-exp-a-z-and-instance-is-string-abc.js",
  152. code: `return "abc".split(new RegExp("[a-z]"))`,
  153. expected: ["", "", "", ""],
  154. },
  155. {
  156. path: "test/built-ins/String/prototype/split/arguments-are-regexp-l-and-undefined-and-instance-is-string-hello.js",
  157. code: `return "hello".split(/l/, undefined)`,
  158. expected: ["he", "", "o"],
  159. },
  160. {
  161. path: "test/built-ins/String/prototype/split/arguments-are-regexp-l-and-0-and-instance-is-string-hello.js",
  162. code: `return "hello".split(/l/, 0)`,
  163. expected: [],
  164. },
  165. {
  166. path: "test/built-ins/String/prototype/split/arguments-are-regexp-l-and-1-and-instance-is-string-hello.js",
  167. code: `return "hello".split(/l/, 1)`,
  168. expected: ["he"],
  169. },
  170. {
  171. path: "test/built-ins/String/prototype/split/arguments-are-regexp-l-and-2-and-instance-is-string-hello.js",
  172. code: `return "hello".split(/l/, 2)`,
  173. expected: ["he", ""],
  174. },
  175. {
  176. path: "test/built-ins/String/prototype/split/arguments-are-regexp-l-and-3-and-instance-is-string-hello.js",
  177. code: `return "hello".split(/l/, 3)`,
  178. expected: ["he", "", "o"],
  179. },
  180. {
  181. path: "test/built-ins/String/prototype/split/arguments-are-regexp-l-and-4-and-instance-is-string-hello.js",
  182. code: `return "hello".split(/l/, 4)`,
  183. expected: ["he", "", "o"],
  184. },
  185. {
  186. path: "test/built-ins/String/prototype/split/argument-is-regexp-l-and-instance-is-string-hello.js",
  187. code: `return "hello".split(/l/)`,
  188. expected: ["he", "", "o"],
  189. },
  190. {
  191. path: "test/built-ins/String/prototype/split/argument-is-new-reg-exp-and-instance-is-string-hello.js",
  192. code: `return "hello".split(new RegExp())`,
  193. expected: ["h", "e", "l", "l", "o"],
  194. },
  195. {
  196. path: "test/built-ins/String/prototype/split/arguments-are-new-reg-exp-and-0-and-instance-is-string-hello.js",
  197. code: `return "hello".split(new RegExp(), 0)`,
  198. expected: [],
  199. },
  200. {
  201. path: "test/built-ins/String/prototype/split/arguments-are-new-reg-exp-and-1-and-instance-is-string-hello.js",
  202. code: `return "hello".split(new RegExp(), 1)`,
  203. expected: ["h"],
  204. },
  205. {
  206. path: "test/built-ins/String/prototype/split/arguments-are-new-reg-exp-and-2-and-instance-is-string-hello.js",
  207. code: `return "hello".split(new RegExp(), 2)`,
  208. expected: ["h", "e"],
  209. },
  210. {
  211. path: "test/built-ins/String/prototype/split/arguments-are-new-reg-exp-and-3-and-instance-is-string-hello.js",
  212. code: `return "hello".split(new RegExp(), 3)`,
  213. expected: ["h", "e", "l"],
  214. },
  215. {
  216. path: "test/built-ins/String/prototype/split/arguments-are-new-reg-exp-and-4-and-instance-is-string-hello.js",
  217. code: `return "hello".split(new RegExp(), 4)`,
  218. expected: ["h", "e", "l", "l"],
  219. },
  220. {
  221. path: "test/built-ins/String/prototype/split/arguments-are-new-reg-exp-and-undefined-and-instance-is-string-hello.js",
  222. code: `return "hello".split(new RegExp(), undefined)`,
  223. expected: ["h", "e", "l", "l", "o"],
  224. },
  225. {
  226. path: "test/built-ins/String/prototype/split/call-split-2-instance-is-string-one-two-three-four-five.js",
  227. code: `return "one two three four five".split(/ /, 2)`,
  228. expected: ["one", "two"],
  229. },
  230. {
  231. path: "test/built-ins/String/prototype/split/separator-regexp-comma-instance-is-string-one-1-two-2-four-4.js",
  232. code: `return "one-1,two-2,four-4".split(/,/)`,
  233. expected: ["one-1", "two-2", "four-4"],
  234. },
  235. {
  236. path: "test/built-ins/String/prototype/split/argument-is-regexp-x-and-instance-is-string-a-b-c-de-f.js",
  237. code: `return "a b c de f".split(/X/)`,
  238. expected: ["a b c de f"],
  239. },
  240. ])
  241. run("Test262-adapted replace behavior", [
  242. {
  243. path: "test/built-ins/String/prototype/replace/regexp-capture-by-index.js",
  244. code: `
  245. const str = "foo-x-bar"
  246. const patterns = ["x", /x/, /(x)/, /(x)($^)?/, /((((((((((x))))))))))/]
  247. const replacements = ["|$0|", "|$00|", "|$000|", "|$1|", "|$01|", "|$010|", "|$2|", "|$02|", "|$020|", "|$10|", "|$100|", "|$20|", "|$200|"]
  248. return replacements.flatMap((replacement) => patterns.map((pattern) => str.replace(pattern, replacement)))
  249. `,
  250. expected: [
  251. "foo-|$0|-bar", "foo-|$0|-bar", "foo-|$0|-bar", "foo-|$0|-bar", "foo-|$0|-bar",
  252. "foo-|$00|-bar", "foo-|$00|-bar", "foo-|$00|-bar", "foo-|$00|-bar", "foo-|$00|-bar",
  253. "foo-|$000|-bar", "foo-|$000|-bar", "foo-|$000|-bar", "foo-|$000|-bar", "foo-|$000|-bar",
  254. "foo-|$1|-bar", "foo-|$1|-bar", "foo-|x|-bar", "foo-|x|-bar", "foo-|x|-bar",
  255. "foo-|$01|-bar", "foo-|$01|-bar", "foo-|x|-bar", "foo-|x|-bar", "foo-|x|-bar",
  256. "foo-|$010|-bar", "foo-|$010|-bar", "foo-|x0|-bar", "foo-|x0|-bar", "foo-|x0|-bar",
  257. "foo-|$2|-bar", "foo-|$2|-bar", "foo-|$2|-bar", "foo-||-bar", "foo-|x|-bar",
  258. "foo-|$02|-bar", "foo-|$02|-bar", "foo-|$02|-bar", "foo-||-bar", "foo-|x|-bar",
  259. "foo-|$020|-bar", "foo-|$020|-bar", "foo-|$020|-bar", "foo-|0|-bar", "foo-|x0|-bar",
  260. "foo-|$10|-bar", "foo-|$10|-bar", "foo-|x0|-bar", "foo-|x0|-bar", "foo-|x|-bar",
  261. "foo-|$100|-bar", "foo-|$100|-bar", "foo-|x00|-bar", "foo-|x00|-bar", "foo-|x0|-bar",
  262. "foo-|$20|-bar", "foo-|$20|-bar", "foo-|$20|-bar", "foo-|0|-bar", "foo-|x0|-bar",
  263. "foo-|$200|-bar", "foo-|$200|-bar", "foo-|$200|-bar", "foo-|00|-bar", "foo-|x00|-bar",
  264. ],
  265. },
  266. {
  267. path: "test/built-ins/String/prototype/replace/S15.5.4.11_A1_T17.js",
  268. code: `return "asdf".replace(new RegExp(undefined, "g"), "1")`,
  269. expected: "1a1s1d1f1",
  270. },
  271. {
  272. path: "test/built-ins/String/prototype/replace/S15.5.4.11_A2_T1.js",
  273. code: `return "She sells seashells by the seashore.".replace(/sh/g, "sch")`,
  274. expected: "She sells seaschells by the seaschore.",
  275. },
  276. {
  277. path: "test/built-ins/String/prototype/replace/S15.5.4.11_A2_T2.js",
  278. code: `return "She sells seashells by the seashore.".replace(/sh/g, "$$sch")`,
  279. expected: "She sells sea$schells by the sea$schore.",
  280. },
  281. {
  282. path: "test/built-ins/String/prototype/replace/S15.5.4.11_A2_T3.js",
  283. code: `return "She sells seashells by the seashore.".replace(/sh/g, "$&sch")`,
  284. expected: "She sells seashschells by the seashschore.",
  285. },
  286. {
  287. path: "test/built-ins/String/prototype/replace/S15.5.4.11_A2_T4.js",
  288. code: `return "She sells seashells by the seashore.".replace(/sh/g, "$\`sch")`,
  289. expected: "She sells seaShe sells seaschells by the seaShe sells seashells by the seaschore.",
  290. },
  291. {
  292. path: "test/built-ins/String/prototype/replace/S15.5.4.11_A2_T5.js",
  293. code: `return "She sells seashells by the seashore.".replace(/sh/g, "$'sch")`,
  294. expected: "She sells seaells by the seashore.schells by the seaore.schore.",
  295. },
  296. {
  297. path: "test/built-ins/String/prototype/replace/S15.5.4.11_A2_T6.js",
  298. code: `return "She sells seashells by the seashore.".replace(/sh/, "sch")`,
  299. expected: "She sells seaschells by the seashore.",
  300. },
  301. {
  302. path: "test/built-ins/String/prototype/replace/S15.5.4.11_A2_T7.js",
  303. code: `return "She sells seashells by the seashore.".replace(/sh/, "$$sch")`,
  304. expected: "She sells sea$schells by the seashore.",
  305. },
  306. {
  307. path: "test/built-ins/String/prototype/replace/S15.5.4.11_A2_T8.js",
  308. code: `return "She sells seashells by the seashore.".replace(/sh/, "$&sch")`,
  309. expected: "She sells seashschells by the seashore.",
  310. },
  311. {
  312. path: "test/built-ins/String/prototype/replace/S15.5.4.11_A2_T9.js",
  313. code: `return "She sells seashells by the seashore.".replace(/sh/, "$\`sch")`,
  314. expected: "She sells seaShe sells seaschells by the seashore.",
  315. },
  316. {
  317. path: "test/built-ins/String/prototype/replace/S15.5.4.11_A2_T10.js",
  318. code: `return "She sells seashells by the seashore.".replace(/sh/, "$'sch")`,
  319. expected: "She sells seaells by the seashore.schells by the seashore.",
  320. },
  321. {
  322. path: "test/built-ins/String/prototype/replace/S15.5.4.11_A3_T1.js",
  323. code: `return "uid=31".replace(/(uid=)(\\d+)/, "$1115")`,
  324. expected: "uid=115",
  325. },
  326. {
  327. path: "test/built-ins/String/prototype/replace/S15.5.4.11_A3_T2.js",
  328. code: `return "uid=31".replace(/(uid=)(\\d+)/, "$1115")`,
  329. expected: "uid=115",
  330. },
  331. {
  332. path: "test/built-ins/String/prototype/replace/S15.5.4.11_A3_T3.js",
  333. code: `return "uid=31".replace(/(uid=)(\\d+)/, "$11A15")`,
  334. expected: "uid=1A15",
  335. },
  336. {
  337. path: "test/built-ins/String/prototype/replace/S15.5.4.11_A5_T1.js",
  338. code: `return "aaaaaaaaaa,aaaaaaaaaaaaaaa".replace(/^(a+)\\1*,\\1+$/, "$1")`,
  339. expected: "aaaaa",
  340. },
  341. ])
  342. run("Test262-adapted replaceAll behavior", [
  343. {
  344. path: "test/built-ins/String/prototype/replaceAll/searchValue-replacer-RegExp-call.js",
  345. code: `
  346. return [
  347. "abc abc abc".replaceAll(new RegExp("b", "g"), "z"),
  348. "abc abc abc".replaceAll(new RegExp("b", "gy"), "z"),
  349. "abc abc abc".replaceAll(new RegExp("b", "giy"), "z"),
  350. "No Uppercase!".replaceAll(new RegExp("[A-Z]", "g"), ""),
  351. "No Uppercase?".replaceAll(new RegExp("[A-Z]", "gy"), ""),
  352. "NO UPPERCASE!".replaceAll(new RegExp("[A-Z]", "gy"), ""),
  353. "abcabcabcabc".replaceAll(new RegExp("a(b)(ca)", "g"), "$2-$1"),
  354. "abcabcabcabc".replaceAll(new RegExp("(a(.))", "g"), "$1$2$3"),
  355. "aabacadaeafagahaiajakalamano a azaya".replaceAll(new RegExp("(((((((((((((a(.).).).).).).).).))))))", "g"), "($10)-($12)-($1)"),
  356. "abcba".replaceAll(new RegExp("b", "g"), "$'"),
  357. "abcba".replaceAll(new RegExp("b", "g"), "$\`"),
  358. "abcba".replaceAll(new RegExp("(?<named>b)", "g"), "($<named>)"),
  359. "abcba".replaceAll(new RegExp("(?<named>b)", "g"), "($<named)"),
  360. "abcba".replaceAll(new RegExp("(?<named>b)", "g"), "($<unnamed>)"),
  361. "abcabcabcabc".replaceAll(new RegExp("a(b)(ca)", "g"), "($$)"),
  362. "abcabcabcabc".replaceAll(new RegExp("a(b)(ca)", "g"), "($)"),
  363. "abcabcabcabc".replaceAll(new RegExp("a(b)(ca)", "g"), "($$$$)"),
  364. "abcabcabcabc".replaceAll(new RegExp("a(b)(ca)", "g"), "($$$)"),
  365. "abcabcabcabc".replaceAll(new RegExp("a(b)(ca)", "g"), "($$&)"),
  366. "abcabcabcabc".replaceAll(new RegExp("a(b)(ca)", "g"), "($$1)"),
  367. "abcabcabcabc".replaceAll(new RegExp("a(b)(ca)", "g"), "($$\`)"),
  368. "abcabcabcabc".replaceAll(new RegExp("a(b)(ca)", "g"), "($$')"),
  369. "abcabcabcabc".replaceAll(new RegExp("a(?<z>b)(ca)", "g"), "($$<z>)"),
  370. "abcabcabcabc".replaceAll(new RegExp("a(b)(ca)", "g"), "($&)"),
  371. ]
  372. `,
  373. expected: [
  374. "azc azc azc", "abc abc abc", "abc abc abc", "o ppercase!", "o Uppercase?", " UPPERCASE!",
  375. "ca-bbcca-bbc", "abb$3cabb$3cabb$3cabb$3c",
  376. "(aabaca)-(aaba)-(aabacadaea)f(agahai)-(agah)-(agahaiajak)(alaman)-(alam)-(alamano a )azaya",
  377. "acbacaa", "aacabca", "a(b)c(b)a", "a($<named)c($<named)a", "a()c()a", "($)bc($)bc",
  378. "($)bc($)bc", "($$)bc($$)bc", "($$)bc($$)bc", "($&)bc($&)bc", "($1)bc($1)bc",
  379. "($`)bc($`)bc", "($')bc($')bc", "($<z>)bc($<z>)bc", "(abca)bc(abca)bc",
  380. ],
  381. },
  382. {
  383. path: "test/built-ins/String/prototype/replaceAll/searchValue-empty-string.js",
  384. code: `return ["aab c \\nx".replaceAll("", "_"), "a".replaceAll("", "_")]`,
  385. expected: ["_a_a_b_ _c_ _ _\n_x_", "_a_"],
  386. },
  387. {
  388. path: "test/built-ins/String/prototype/replaceAll/searchValue-empty-string-this-empty-string.js",
  389. code: `return "".replaceAll("", "abc")`,
  390. expected: "abc",
  391. },
  392. {
  393. path: "test/built-ins/String/prototype/replaceAll/replaceValue-value-replaces-string.js",
  394. code: `return ["aaab a a aac".replaceAll("aa", "z"), "aaab a a aac".replaceAll("aa", "a"), "aaab a a aac".replaceAll("a", "a"), "aaab a a aac".replaceAll("a", "z")]`,
  395. expected: ["zab a a zc", "aab a a ac", "aaab a a aac", "zzzb z z zzc"],
  396. },
  397. {
  398. path: "test/built-ins/String/prototype/replaceAll/getSubstitution-0x0024.js",
  399. code: `
  400. const str = "Ninguém é igual a ninguém. Todo o ser humano é um estranho ímpar."
  401. return [str.replaceAll("ninguém", "$"), str.replaceAll("é", "$"), str.replaceAll("é", "$ -"), str.replaceAll("é", "$$$")]
  402. `,
  403. expected: [
  404. "Ninguém é igual a $. Todo o ser humano é um estranho ímpar.",
  405. "Ningu$m $ igual a ningu$m. Todo o ser humano $ um estranho ímpar.",
  406. "Ningu$ -m $ - igual a ningu$ -m. Todo o ser humano $ - um estranho ímpar.",
  407. "Ningu$$m $$ igual a ningu$$m. Todo o ser humano $$ um estranho ímpar.",
  408. ],
  409. },
  410. {
  411. path: "test/built-ins/String/prototype/replaceAll/getSubstitution-0x0024-0x0024.js",
  412. code: `
  413. const str = "Ninguém é igual a ninguém. Todo o ser humano é um estranho ímpar."
  414. return [str.replaceAll("ninguém", "$$"), str.replaceAll("é", "$$"), str.replaceAll("é", "$$ -"), str.replaceAll("é", "$$&"), str.replaceAll("é", "$$$"), str.replaceAll("é", "$$$$")]
  415. `,
  416. expected: [
  417. "Ninguém é igual a $. Todo o ser humano é um estranho ímpar.",
  418. "Ningu$m $ igual a ningu$m. Todo o ser humano $ um estranho ímpar.",
  419. "Ningu$ -m $ - igual a ningu$ -m. Todo o ser humano $ - um estranho ímpar.",
  420. "Ningu$&m $& igual a ningu$&m. Todo o ser humano $& um estranho ímpar.",
  421. "Ningu$$m $$ igual a ningu$$m. Todo o ser humano $$ um estranho ímpar.",
  422. "Ningu$$m $$ igual a ningu$$m. Todo o ser humano $$ um estranho ímpar.",
  423. ],
  424. },
  425. {
  426. path: "test/built-ins/String/prototype/replaceAll/getSubstitution-0x0024-0x0026.js",
  427. code: `
  428. const str = "Ninguém é igual a ninguém. Todo o ser humano é um estranho ímpar."
  429. return [str.replaceAll("ninguém", "$&"), str.replaceAll("ninguém", "($&)"), str.replaceAll("é", "($&)"), str.replaceAll("é", "($&) $&")]
  430. `,
  431. expected: [
  432. "Ninguém é igual a ninguém. Todo o ser humano é um estranho ímpar.",
  433. "Ninguém é igual a (ninguém). Todo o ser humano é um estranho ímpar.",
  434. "Ningu(é)m (é) igual a ningu(é)m. Todo o ser humano (é) um estranho ímpar.",
  435. "Ningu(é) ém (é) é igual a ningu(é) ém. Todo o ser humano (é) é um estranho ímpar.",
  436. ],
  437. },
  438. {
  439. path: "test/built-ins/String/prototype/replaceAll/getSubstitution-0x0024-0x0060.js",
  440. code: `
  441. const str = "Ninguém é igual a ninguém. Todo o ser humano é um estranho ímpar."
  442. return [str.replaceAll("ninguém", "$\`"), str.replaceAll("Ninguém", "$\`"), str.replaceAll("ninguém", "($\`)"), str.replaceAll("é", "($\`)")]
  443. `,
  444. expected: [
  445. "Ninguém é igual a Ninguém é igual a . Todo o ser humano é um estranho ímpar.",
  446. " é igual a ninguém. Todo o ser humano é um estranho ímpar.",
  447. "Ninguém é igual a (Ninguém é igual a ). Todo o ser humano é um estranho ímpar.",
  448. "Ningu(Ningu)m (Ninguém ) igual a ningu(Ninguém é igual a ningu)m. Todo o ser humano (Ninguém é igual a ninguém. Todo o ser humano ) um estranho ímpar.",
  449. ],
  450. },
  451. {
  452. path: "test/built-ins/String/prototype/replaceAll/getSubstitution-0x0024-0x0027.js",
  453. code: `
  454. const str = "Ninguém é igual a ninguém. Todo o ser humano é um estranho ímpar."
  455. return [str.replaceAll("ninguém", "$'"), str.replaceAll(".", "--- $'"), str.replaceAll("é", "($')")]
  456. `,
  457. expected: [
  458. "Ninguém é igual a . Todo o ser humano é um estranho ímpar.. Todo o ser humano é um estranho ímpar.",
  459. "Ninguém é igual a ninguém--- Todo o ser humano é um estranho ímpar. Todo o ser humano é um estranho ímpar--- ",
  460. "Ningu(m é igual a ninguém. Todo o ser humano é um estranho ímpar.)m ( igual a ninguém. Todo o ser humano é um estranho ímpar.) igual a ningu(m. Todo o ser humano é um estranho ímpar.)m. Todo o ser humano ( um estranho ímpar.) um estranho ímpar.",
  461. ],
  462. },
  463. {
  464. path: "test/built-ins/String/prototype/replaceAll/getSubstitution-0x0024N.js",
  465. code: `
  466. const str = "ABC AAA ABC AAA"
  467. return ["$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9"].map((replacement) => str.replaceAll("ABC", replacement))
  468. `,
  469. expected: ["$1 AAA $1 AAA", "$2 AAA $2 AAA", "$3 AAA $3 AAA", "$4 AAA $4 AAA", "$5 AAA $5 AAA", "$6 AAA $6 AAA", "$7 AAA $7 AAA", "$8 AAA $8 AAA", "$9 AAA $9 AAA"],
  470. },
  471. {
  472. path: "test/built-ins/String/prototype/replaceAll/getSubstitution-0x0024NN.js",
  473. code: `
  474. const str = "aaaaaaaaaaaaaaaa aaaaaaaa aaaaaaaaaaaaaaaa"
  475. return [str.replaceAll("a", "$11"), str.replaceAll("a", "$29")]
  476. `,
  477. expected: [
  478. "$11$11$11$11$11$11$11$11$11$11$11$11$11$11$11$11 $11$11$11$11$11$11$11$11 $11$11$11$11$11$11$11$11$11$11$11$11$11$11$11$11",
  479. "$29$29$29$29$29$29$29$29$29$29$29$29$29$29$29$29 $29$29$29$29$29$29$29$29 $29$29$29$29$29$29$29$29$29$29$29$29$29$29$29$29",
  480. ],
  481. },
  482. {
  483. path: "test/built-ins/String/prototype/replaceAll/getSubstitution-0x0024-0x003C.js",
  484. code: `return "aaaaaaaaaaaaaaaa aaaaaaaa aaaaaaaaaaaaaaaa".replaceAll("a", "$<")`,
  485. expected: "$<$<$<$<$<$<$<$<$<$<$<$<$<$<$<$< $<$<$<$<$<$<$<$< $<$<$<$<$<$<$<$<$<$<$<$<$<$<$<$<",
  486. },
  487. ])
  488. run("Test262-adapted match behavior", [
  489. {
  490. path: "test/built-ins/String/prototype/match/S15.5.4.10_A1_T14.js",
  491. code: `const match = "ABBABABAB77BBAA".match(new RegExp("77")); return [match[0], match.index]`,
  492. expected: ["77", 9],
  493. },
  494. {
  495. path: "test/built-ins/String/prototype/match/S15.5.4.10_A2_T2.js",
  496. code: `return "343443444".match(/34/g)`,
  497. expected: ["34", "34", "34"],
  498. },
  499. {
  500. path: "test/built-ins/String/prototype/match/S15.5.4.10_A2_T3.js",
  501. code: `return "123456abcde7890".match(/\\d{1}/g)`,
  502. expected: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"],
  503. },
  504. {
  505. path: "test/built-ins/String/prototype/match/S15.5.4.10_A2_T4.js",
  506. code: `return "123456abcde7890".match(/\\d{2}/g)`,
  507. expected: ["12", "34", "56", "78", "90"],
  508. },
  509. {
  510. path: "test/built-ins/String/prototype/match/S15.5.4.10_A2_T5.js",
  511. code: `return "123456abcde7890".match(/\\D{2}/g)`,
  512. expected: ["ab", "cd"],
  513. },
  514. {
  515. path: "test/built-ins/String/prototype/match/S15.5.4.10_A2_T6.js",
  516. code: `const match = "Boston, Mass. 02134".match(/([\\d]{5})([- ]?[\\d]{4})?$/); return [match[0], match[1], match[2] === undefined, match.length, match.index]`,
  517. expected: ["02134", "02134", true, 3, 14],
  518. },
  519. {
  520. path: "test/built-ins/String/prototype/match/S15.5.4.10_A2_T7.js",
  521. code: `return "Boston, Mass. 02134".match(/([\\d]{5})([- ]?[\\d]{4})?$/g)`,
  522. expected: ["02134"],
  523. },
  524. {
  525. path: "test/built-ins/String/prototype/match/S15.5.4.10_A2_T8.js",
  526. code: `const match = "Boston, MA 02134".match(/([\\d]{5})([- ]?[\\d]{4})?$/); return [match[0], match[1], match[2] === undefined, match.length, match.index]`,
  527. expected: ["02134", "02134", true, 3, 11],
  528. },
  529. {
  530. path: "test/built-ins/String/prototype/match/S15.5.4.10_A2_T12.js",
  531. code: `return "Boston, MA 02134".match(/([\\d]{5})([- ]?[\\d]{4})?$/g)`,
  532. expected: ["02134"],
  533. },
  534. ])
  535. run("Test262-adapted matchAll behavior", [
  536. {
  537. path: "test/built-ins/String/prototype/matchAll/regexp-prototype-matchAll-v-u-flag.js",
  538. code: `
  539. const text = "𠮷a𠮷b𠮷"
  540. const collect = (regex) => {
  541. const matches = text.matchAll(regex)
  542. return matches.map((match) => match[0]).concat(matches.map((match) => match.index))
  543. }
  544. const empty = text.matchAll(/(?:)/gu)
  545. const complex = "a𠮷b􏿿c".matchAll(/\\P{ASCII}/gu)
  546. return [
  547. collect(/𠮷/g),
  548. collect(/𠮷/gu),
  549. collect(/\\p{Script=Han}/gu),
  550. collect(/./gu),
  551. empty.map((match) => match[0]).concat(empty.map((match) => match.index)).length,
  552. complex.map((match) => match[0]),
  553. ]
  554. `,
  555. expected: [
  556. ["𠮷", "𠮷", "𠮷", 0, 3, 6],
  557. ["𠮷", "𠮷", "𠮷", 0, 3, 6],
  558. ["𠮷", "𠮷", "𠮷", 0, 3, 6],
  559. ["𠮷", "a", "𠮷", "b", "𠮷", 0, 2, 3, 5, 6],
  560. 12,
  561. ["𠮷", "􏿿"],
  562. ],
  563. },
  564. ])
  565. run("Test262-adapted search behavior", [
  566. {
  567. path: "test/built-ins/String/prototype/search/S15.5.4.12_A1_T14.js",
  568. code: `return "ABBABABAB77BBAA".search(new RegExp("77"))`,
  569. expected: 9,
  570. },
  571. {
  572. path: "test/built-ins/String/prototype/search/S15.5.4.12_A2_T1.js",
  573. code: `return "test string".search("string")`,
  574. expected: 5,
  575. },
  576. {
  577. path: "test/built-ins/String/prototype/search/S15.5.4.12_A2_T2.js",
  578. code: `return "test string".search("String")`,
  579. expected: -1,
  580. },
  581. {
  582. path: "test/built-ins/String/prototype/search/S15.5.4.12_A2_T3.js",
  583. code: `return "test string".search(/String/i)`,
  584. expected: 5,
  585. },
  586. {
  587. path: "test/built-ins/String/prototype/search/S15.5.4.12_A2_T4.js",
  588. code: `return "one two three four five".search(/Four/)`,
  589. expected: -1,
  590. },
  591. {
  592. path: "test/built-ins/String/prototype/search/S15.5.4.12_A2_T5.js",
  593. code: `return "one two three four five".search(/four/)`,
  594. expected: 14,
  595. },
  596. {
  597. path: "test/built-ins/String/prototype/search/S15.5.4.12_A2_T6.js",
  598. code: `return "test string".search("notexist")`,
  599. expected: -1,
  600. },
  601. {
  602. path: "test/built-ins/String/prototype/search/S15.5.4.12_A2_T7.js",
  603. code: `return "test string probe".search("string pro")`,
  604. expected: 5,
  605. },
  606. {
  607. path: "test/built-ins/String/prototype/search/S15.5.4.12_A3_T1.js",
  608. code: `const text = "power of the power of the power of the great sword"; return [text.search(/the/), text.search(/the/g)]`,
  609. expected: [9, 9],
  610. },
  611. {
  612. path: "test/built-ins/String/prototype/search/S15.5.4.12_A3_T2.js",
  613. code: `const text = "power of the power of the power of the great sword"; return [text.search(/of/), text.search(/of/g)]`,
  614. expected: [6, 6],
  615. },
  616. ])