string-regexp-test262.test.ts 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731
  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"],
  121. ["x"],
  122. ["", ""],
  123. ["", ""],
  124. ["", ""],
  125. ["x"],
  126. ["", ""],
  127. ["", ""],
  128. ["", ""],
  129. ["x"],
  130. ["", ""],
  131. ["x"],
  132. ["x"],
  133. ["x"],
  134. ["x"],
  135. ["", ""],
  136. ["x"],
  137. ["x"],
  138. ["x"],
  139. ["x"],
  140. ["x"],
  141. ["", ""],
  142. ["x"],
  143. ["x"],
  144. ["x"],
  145. ["", ""],
  146. ["x"],
  147. ["", ""],
  148. ["x"],
  149. ],
  150. },
  151. {
  152. path: "test/built-ins/String/prototype/split/arguments-are-regexp-s-and-3-and-instance-is-string-a-b-c-de-f.js",
  153. code: `return "a b c de f".split(/\\s/, 3)`,
  154. expected: ["a", "b", "c"],
  155. },
  156. {
  157. path: "test/built-ins/String/prototype/split/argument-is-regexp-s-and-instance-is-string-a-b-c-de-f.js",
  158. code: `return "a b c de f".split(/\\s/)`,
  159. expected: ["a", "b", "c", "de", "f"],
  160. },
  161. {
  162. path: "test/built-ins/String/prototype/split/argument-is-regexp-d-and-instance-is-string-dfe23iu-34-65.js",
  163. code: `return "dfe23iu 34 =+65--".split(/\\d+/)`,
  164. expected: ["dfe", "iu ", " =+", "--"],
  165. },
  166. {
  167. path: "test/built-ins/String/prototype/split/argument-is-regexp-reg-exp-d-and-instance-is-string-dfe23iu-34-65.js",
  168. code: `return "dfe23iu 34 =+65--".split(new RegExp("\\\\d+"))`,
  169. expected: ["dfe", "iu ", " =+", "--"],
  170. },
  171. {
  172. path: "test/built-ins/String/prototype/split/argument-is-regexp-a-z-and-instance-is-string-abc.js",
  173. code: `return "abc".split(/[a-z]/)`,
  174. expected: ["", "", "", ""],
  175. },
  176. {
  177. path: "test/built-ins/String/prototype/split/argument-is-reg-exp-a-z-and-instance-is-string-abc.js",
  178. code: `return "abc".split(new RegExp("[a-z]"))`,
  179. expected: ["", "", "", ""],
  180. },
  181. {
  182. path: "test/built-ins/String/prototype/split/arguments-are-regexp-l-and-undefined-and-instance-is-string-hello.js",
  183. code: `return "hello".split(/l/, undefined)`,
  184. expected: ["he", "", "o"],
  185. },
  186. {
  187. path: "test/built-ins/String/prototype/split/arguments-are-regexp-l-and-0-and-instance-is-string-hello.js",
  188. code: `return "hello".split(/l/, 0)`,
  189. expected: [],
  190. },
  191. {
  192. path: "test/built-ins/String/prototype/split/arguments-are-regexp-l-and-1-and-instance-is-string-hello.js",
  193. code: `return "hello".split(/l/, 1)`,
  194. expected: ["he"],
  195. },
  196. {
  197. path: "test/built-ins/String/prototype/split/arguments-are-regexp-l-and-2-and-instance-is-string-hello.js",
  198. code: `return "hello".split(/l/, 2)`,
  199. expected: ["he", ""],
  200. },
  201. {
  202. path: "test/built-ins/String/prototype/split/arguments-are-regexp-l-and-3-and-instance-is-string-hello.js",
  203. code: `return "hello".split(/l/, 3)`,
  204. expected: ["he", "", "o"],
  205. },
  206. {
  207. path: "test/built-ins/String/prototype/split/arguments-are-regexp-l-and-4-and-instance-is-string-hello.js",
  208. code: `return "hello".split(/l/, 4)`,
  209. expected: ["he", "", "o"],
  210. },
  211. {
  212. path: "test/built-ins/String/prototype/split/argument-is-regexp-l-and-instance-is-string-hello.js",
  213. code: `return "hello".split(/l/)`,
  214. expected: ["he", "", "o"],
  215. },
  216. {
  217. path: "test/built-ins/String/prototype/split/argument-is-new-reg-exp-and-instance-is-string-hello.js",
  218. code: `return "hello".split(new RegExp())`,
  219. expected: ["h", "e", "l", "l", "o"],
  220. },
  221. {
  222. path: "test/built-ins/String/prototype/split/arguments-are-new-reg-exp-and-0-and-instance-is-string-hello.js",
  223. code: `return "hello".split(new RegExp(), 0)`,
  224. expected: [],
  225. },
  226. {
  227. path: "test/built-ins/String/prototype/split/arguments-are-new-reg-exp-and-1-and-instance-is-string-hello.js",
  228. code: `return "hello".split(new RegExp(), 1)`,
  229. expected: ["h"],
  230. },
  231. {
  232. path: "test/built-ins/String/prototype/split/arguments-are-new-reg-exp-and-2-and-instance-is-string-hello.js",
  233. code: `return "hello".split(new RegExp(), 2)`,
  234. expected: ["h", "e"],
  235. },
  236. {
  237. path: "test/built-ins/String/prototype/split/arguments-are-new-reg-exp-and-3-and-instance-is-string-hello.js",
  238. code: `return "hello".split(new RegExp(), 3)`,
  239. expected: ["h", "e", "l"],
  240. },
  241. {
  242. path: "test/built-ins/String/prototype/split/arguments-are-new-reg-exp-and-4-and-instance-is-string-hello.js",
  243. code: `return "hello".split(new RegExp(), 4)`,
  244. expected: ["h", "e", "l", "l"],
  245. },
  246. {
  247. path: "test/built-ins/String/prototype/split/arguments-are-new-reg-exp-and-undefined-and-instance-is-string-hello.js",
  248. code: `return "hello".split(new RegExp(), undefined)`,
  249. expected: ["h", "e", "l", "l", "o"],
  250. },
  251. {
  252. path: "test/built-ins/String/prototype/split/call-split-2-instance-is-string-one-two-three-four-five.js",
  253. code: `return "one two three four five".split(/ /, 2)`,
  254. expected: ["one", "two"],
  255. },
  256. {
  257. path: "test/built-ins/String/prototype/split/separator-regexp-comma-instance-is-string-one-1-two-2-four-4.js",
  258. code: `return "one-1,two-2,four-4".split(/,/)`,
  259. expected: ["one-1", "two-2", "four-4"],
  260. },
  261. {
  262. path: "test/built-ins/String/prototype/split/argument-is-regexp-x-and-instance-is-string-a-b-c-de-f.js",
  263. code: `return "a b c de f".split(/X/)`,
  264. expected: ["a b c de f"],
  265. },
  266. ])
  267. run("Test262-adapted replace behavior", [
  268. {
  269. path: "test/built-ins/String/prototype/replace/regexp-capture-by-index.js",
  270. code: `
  271. const str = "foo-x-bar"
  272. const patterns = ["x", /x/, /(x)/, /(x)($^)?/, /((((((((((x))))))))))/]
  273. const replacements = ["|$0|", "|$00|", "|$000|", "|$1|", "|$01|", "|$010|", "|$2|", "|$02|", "|$020|", "|$10|", "|$100|", "|$20|", "|$200|"]
  274. return replacements.flatMap((replacement) => patterns.map((pattern) => str.replace(pattern, replacement)))
  275. `,
  276. expected: [
  277. "foo-|$0|-bar",
  278. "foo-|$0|-bar",
  279. "foo-|$0|-bar",
  280. "foo-|$0|-bar",
  281. "foo-|$0|-bar",
  282. "foo-|$00|-bar",
  283. "foo-|$00|-bar",
  284. "foo-|$00|-bar",
  285. "foo-|$00|-bar",
  286. "foo-|$00|-bar",
  287. "foo-|$000|-bar",
  288. "foo-|$000|-bar",
  289. "foo-|$000|-bar",
  290. "foo-|$000|-bar",
  291. "foo-|$000|-bar",
  292. "foo-|$1|-bar",
  293. "foo-|$1|-bar",
  294. "foo-|x|-bar",
  295. "foo-|x|-bar",
  296. "foo-|x|-bar",
  297. "foo-|$01|-bar",
  298. "foo-|$01|-bar",
  299. "foo-|x|-bar",
  300. "foo-|x|-bar",
  301. "foo-|x|-bar",
  302. "foo-|$010|-bar",
  303. "foo-|$010|-bar",
  304. "foo-|x0|-bar",
  305. "foo-|x0|-bar",
  306. "foo-|x0|-bar",
  307. "foo-|$2|-bar",
  308. "foo-|$2|-bar",
  309. "foo-|$2|-bar",
  310. "foo-||-bar",
  311. "foo-|x|-bar",
  312. "foo-|$02|-bar",
  313. "foo-|$02|-bar",
  314. "foo-|$02|-bar",
  315. "foo-||-bar",
  316. "foo-|x|-bar",
  317. "foo-|$020|-bar",
  318. "foo-|$020|-bar",
  319. "foo-|$020|-bar",
  320. "foo-|0|-bar",
  321. "foo-|x0|-bar",
  322. "foo-|$10|-bar",
  323. "foo-|$10|-bar",
  324. "foo-|x0|-bar",
  325. "foo-|x0|-bar",
  326. "foo-|x|-bar",
  327. "foo-|$100|-bar",
  328. "foo-|$100|-bar",
  329. "foo-|x00|-bar",
  330. "foo-|x00|-bar",
  331. "foo-|x0|-bar",
  332. "foo-|$20|-bar",
  333. "foo-|$20|-bar",
  334. "foo-|$20|-bar",
  335. "foo-|0|-bar",
  336. "foo-|x0|-bar",
  337. "foo-|$200|-bar",
  338. "foo-|$200|-bar",
  339. "foo-|$200|-bar",
  340. "foo-|00|-bar",
  341. "foo-|x00|-bar",
  342. ],
  343. },
  344. {
  345. path: "test/built-ins/String/prototype/replace/S15.5.4.11_A1_T17.js",
  346. code: `return "asdf".replace(new RegExp(undefined, "g"), "1")`,
  347. expected: "1a1s1d1f1",
  348. },
  349. {
  350. path: "test/built-ins/String/prototype/replace/S15.5.4.11_A2_T1.js",
  351. code: `return "She sells seashells by the seashore.".replace(/sh/g, "sch")`,
  352. expected: "She sells seaschells by the seaschore.",
  353. },
  354. {
  355. path: "test/built-ins/String/prototype/replace/S15.5.4.11_A2_T2.js",
  356. code: `return "She sells seashells by the seashore.".replace(/sh/g, "$$sch")`,
  357. expected: "She sells sea$schells by the sea$schore.",
  358. },
  359. {
  360. path: "test/built-ins/String/prototype/replace/S15.5.4.11_A2_T3.js",
  361. code: `return "She sells seashells by the seashore.".replace(/sh/g, "$&sch")`,
  362. expected: "She sells seashschells by the seashschore.",
  363. },
  364. {
  365. path: "test/built-ins/String/prototype/replace/S15.5.4.11_A2_T4.js",
  366. code: `return "She sells seashells by the seashore.".replace(/sh/g, "$\`sch")`,
  367. expected: "She sells seaShe sells seaschells by the seaShe sells seashells by the seaschore.",
  368. },
  369. {
  370. path: "test/built-ins/String/prototype/replace/S15.5.4.11_A2_T5.js",
  371. code: `return "She sells seashells by the seashore.".replace(/sh/g, "$'sch")`,
  372. expected: "She sells seaells by the seashore.schells by the seaore.schore.",
  373. },
  374. {
  375. path: "test/built-ins/String/prototype/replace/S15.5.4.11_A2_T6.js",
  376. code: `return "She sells seashells by the seashore.".replace(/sh/, "sch")`,
  377. expected: "She sells seaschells by the seashore.",
  378. },
  379. {
  380. path: "test/built-ins/String/prototype/replace/S15.5.4.11_A2_T7.js",
  381. code: `return "She sells seashells by the seashore.".replace(/sh/, "$$sch")`,
  382. expected: "She sells sea$schells by the seashore.",
  383. },
  384. {
  385. path: "test/built-ins/String/prototype/replace/S15.5.4.11_A2_T8.js",
  386. code: `return "She sells seashells by the seashore.".replace(/sh/, "$&sch")`,
  387. expected: "She sells seashschells by the seashore.",
  388. },
  389. {
  390. path: "test/built-ins/String/prototype/replace/S15.5.4.11_A2_T9.js",
  391. code: `return "She sells seashells by the seashore.".replace(/sh/, "$\`sch")`,
  392. expected: "She sells seaShe sells seaschells by the seashore.",
  393. },
  394. {
  395. path: "test/built-ins/String/prototype/replace/S15.5.4.11_A2_T10.js",
  396. code: `return "She sells seashells by the seashore.".replace(/sh/, "$'sch")`,
  397. expected: "She sells seaells by the seashore.schells by the seashore.",
  398. },
  399. {
  400. path: "test/built-ins/String/prototype/replace/S15.5.4.11_A3_T1.js",
  401. code: `return "uid=31".replace(/(uid=)(\\d+)/, "$1115")`,
  402. expected: "uid=115",
  403. },
  404. {
  405. path: "test/built-ins/String/prototype/replace/S15.5.4.11_A3_T2.js",
  406. code: `return "uid=31".replace(/(uid=)(\\d+)/, "$1115")`,
  407. expected: "uid=115",
  408. },
  409. {
  410. path: "test/built-ins/String/prototype/replace/S15.5.4.11_A3_T3.js",
  411. code: `return "uid=31".replace(/(uid=)(\\d+)/, "$11A15")`,
  412. expected: "uid=1A15",
  413. },
  414. {
  415. path: "test/built-ins/String/prototype/replace/S15.5.4.11_A5_T1.js",
  416. code: `return "aaaaaaaaaa,aaaaaaaaaaaaaaa".replace(/^(a+)\\1*,\\1+$/, "$1")`,
  417. expected: "aaaaa",
  418. },
  419. ])
  420. run("Test262-adapted replaceAll behavior", [
  421. {
  422. path: "test/built-ins/String/prototype/replaceAll/searchValue-replacer-RegExp-call.js",
  423. code: `
  424. return [
  425. "abc abc abc".replaceAll(new RegExp("b", "g"), "z"),
  426. "abc abc abc".replaceAll(new RegExp("b", "gy"), "z"),
  427. "abc abc abc".replaceAll(new RegExp("b", "giy"), "z"),
  428. "No Uppercase!".replaceAll(new RegExp("[A-Z]", "g"), ""),
  429. "No Uppercase?".replaceAll(new RegExp("[A-Z]", "gy"), ""),
  430. "NO UPPERCASE!".replaceAll(new RegExp("[A-Z]", "gy"), ""),
  431. "abcabcabcabc".replaceAll(new RegExp("a(b)(ca)", "g"), "$2-$1"),
  432. "abcabcabcabc".replaceAll(new RegExp("(a(.))", "g"), "$1$2$3"),
  433. "aabacadaeafagahaiajakalamano a azaya".replaceAll(new RegExp("(((((((((((((a(.).).).).).).).).))))))", "g"), "($10)-($12)-($1)"),
  434. "abcba".replaceAll(new RegExp("b", "g"), "$'"),
  435. "abcba".replaceAll(new RegExp("b", "g"), "$\`"),
  436. "abcba".replaceAll(new RegExp("(?<named>b)", "g"), "($<named>)"),
  437. "abcba".replaceAll(new RegExp("(?<named>b)", "g"), "($<named)"),
  438. "abcba".replaceAll(new RegExp("(?<named>b)", "g"), "($<unnamed>)"),
  439. "abcabcabcabc".replaceAll(new RegExp("a(b)(ca)", "g"), "($$)"),
  440. "abcabcabcabc".replaceAll(new RegExp("a(b)(ca)", "g"), "($)"),
  441. "abcabcabcabc".replaceAll(new RegExp("a(b)(ca)", "g"), "($$$$)"),
  442. "abcabcabcabc".replaceAll(new RegExp("a(b)(ca)", "g"), "($$$)"),
  443. "abcabcabcabc".replaceAll(new RegExp("a(b)(ca)", "g"), "($$&)"),
  444. "abcabcabcabc".replaceAll(new RegExp("a(b)(ca)", "g"), "($$1)"),
  445. "abcabcabcabc".replaceAll(new RegExp("a(b)(ca)", "g"), "($$\`)"),
  446. "abcabcabcabc".replaceAll(new RegExp("a(b)(ca)", "g"), "($$')"),
  447. "abcabcabcabc".replaceAll(new RegExp("a(?<z>b)(ca)", "g"), "($$<z>)"),
  448. "abcabcabcabc".replaceAll(new RegExp("a(b)(ca)", "g"), "($&)"),
  449. ]
  450. `,
  451. expected: [
  452. "azc azc azc",
  453. "abc abc abc",
  454. "abc abc abc",
  455. "o ppercase!",
  456. "o Uppercase?",
  457. " UPPERCASE!",
  458. "ca-bbcca-bbc",
  459. "abb$3cabb$3cabb$3cabb$3c",
  460. "(aabaca)-(aaba)-(aabacadaea)f(agahai)-(agah)-(agahaiajak)(alaman)-(alam)-(alamano a )azaya",
  461. "acbacaa",
  462. "aacabca",
  463. "a(b)c(b)a",
  464. "a($<named)c($<named)a",
  465. "a()c()a",
  466. "($)bc($)bc",
  467. "($)bc($)bc",
  468. "($$)bc($$)bc",
  469. "($$)bc($$)bc",
  470. "($&)bc($&)bc",
  471. "($1)bc($1)bc",
  472. "($`)bc($`)bc",
  473. "($')bc($')bc",
  474. "($<z>)bc($<z>)bc",
  475. "(abca)bc(abca)bc",
  476. ],
  477. },
  478. {
  479. path: "test/built-ins/String/prototype/replaceAll/searchValue-empty-string.js",
  480. code: `return ["aab c \\nx".replaceAll("", "_"), "a".replaceAll("", "_")]`,
  481. expected: ["_a_a_b_ _c_ _ _\n_x_", "_a_"],
  482. },
  483. {
  484. path: "test/built-ins/String/prototype/replaceAll/searchValue-empty-string-this-empty-string.js",
  485. code: `return "".replaceAll("", "abc")`,
  486. expected: "abc",
  487. },
  488. {
  489. path: "test/built-ins/String/prototype/replaceAll/replaceValue-value-replaces-string.js",
  490. 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")]`,
  491. expected: ["zab a a zc", "aab a a ac", "aaab a a aac", "zzzb z z zzc"],
  492. },
  493. {
  494. path: "test/built-ins/String/prototype/replaceAll/getSubstitution-0x0024.js",
  495. code: `
  496. const str = "Ninguém é igual a ninguém. Todo o ser humano é um estranho ímpar."
  497. return [str.replaceAll("ninguém", "$"), str.replaceAll("é", "$"), str.replaceAll("é", "$ -"), str.replaceAll("é", "$$$")]
  498. `,
  499. expected: [
  500. "Ninguém é igual a $. Todo o ser humano é um estranho ímpar.",
  501. "Ningu$m $ igual a ningu$m. Todo o ser humano $ um estranho ímpar.",
  502. "Ningu$ -m $ - igual a ningu$ -m. Todo o ser humano $ - um estranho ímpar.",
  503. "Ningu$$m $$ igual a ningu$$m. Todo o ser humano $$ um estranho ímpar.",
  504. ],
  505. },
  506. {
  507. path: "test/built-ins/String/prototype/replaceAll/getSubstitution-0x0024-0x0024.js",
  508. code: `
  509. const str = "Ninguém é igual a ninguém. Todo o ser humano é um estranho ímpar."
  510. return [str.replaceAll("ninguém", "$$"), str.replaceAll("é", "$$"), str.replaceAll("é", "$$ -"), str.replaceAll("é", "$$&"), str.replaceAll("é", "$$$"), str.replaceAll("é", "$$$$")]
  511. `,
  512. expected: [
  513. "Ninguém é igual a $. Todo o ser humano é um estranho ímpar.",
  514. "Ningu$m $ igual a ningu$m. Todo o ser humano $ um estranho ímpar.",
  515. "Ningu$ -m $ - igual a ningu$ -m. Todo o ser humano $ - um estranho ímpar.",
  516. "Ningu$&m $& igual a ningu$&m. Todo o ser humano $& um estranho ímpar.",
  517. "Ningu$$m $$ igual a ningu$$m. Todo o ser humano $$ um estranho ímpar.",
  518. "Ningu$$m $$ igual a ningu$$m. Todo o ser humano $$ um estranho ímpar.",
  519. ],
  520. },
  521. {
  522. path: "test/built-ins/String/prototype/replaceAll/getSubstitution-0x0024-0x0026.js",
  523. code: `
  524. const str = "Ninguém é igual a ninguém. Todo o ser humano é um estranho ímpar."
  525. return [str.replaceAll("ninguém", "$&"), str.replaceAll("ninguém", "($&)"), str.replaceAll("é", "($&)"), str.replaceAll("é", "($&) $&")]
  526. `,
  527. expected: [
  528. "Ninguém é igual a ninguém. Todo o ser humano é um estranho ímpar.",
  529. "Ninguém é igual a (ninguém). Todo o ser humano é um estranho ímpar.",
  530. "Ningu(é)m (é) igual a ningu(é)m. Todo o ser humano (é) um estranho ímpar.",
  531. "Ningu(é) ém (é) é igual a ningu(é) ém. Todo o ser humano (é) é um estranho ímpar.",
  532. ],
  533. },
  534. {
  535. path: "test/built-ins/String/prototype/replaceAll/getSubstitution-0x0024-0x0060.js",
  536. code: `
  537. const str = "Ninguém é igual a ninguém. Todo o ser humano é um estranho ímpar."
  538. return [str.replaceAll("ninguém", "$\`"), str.replaceAll("Ninguém", "$\`"), str.replaceAll("ninguém", "($\`)"), str.replaceAll("é", "($\`)")]
  539. `,
  540. expected: [
  541. "Ninguém é igual a Ninguém é igual a . Todo o ser humano é um estranho ímpar.",
  542. " é igual a ninguém. Todo o ser humano é um estranho ímpar.",
  543. "Ninguém é igual a (Ninguém é igual a ). Todo o ser humano é um estranho ímpar.",
  544. "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.",
  545. ],
  546. },
  547. {
  548. path: "test/built-ins/String/prototype/replaceAll/getSubstitution-0x0024-0x0027.js",
  549. code: `
  550. const str = "Ninguém é igual a ninguém. Todo o ser humano é um estranho ímpar."
  551. return [str.replaceAll("ninguém", "$'"), str.replaceAll(".", "--- $'"), str.replaceAll("é", "($')")]
  552. `,
  553. expected: [
  554. "Ninguém é igual a . Todo o ser humano é um estranho ímpar.. Todo o ser humano é um estranho ímpar.",
  555. "Ninguém é igual a ninguém--- Todo o ser humano é um estranho ímpar. Todo o ser humano é um estranho ímpar--- ",
  556. "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.",
  557. ],
  558. },
  559. {
  560. path: "test/built-ins/String/prototype/replaceAll/getSubstitution-0x0024N.js",
  561. code: `
  562. const str = "ABC AAA ABC AAA"
  563. return ["$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9"].map((replacement) => str.replaceAll("ABC", replacement))
  564. `,
  565. expected: [
  566. "$1 AAA $1 AAA",
  567. "$2 AAA $2 AAA",
  568. "$3 AAA $3 AAA",
  569. "$4 AAA $4 AAA",
  570. "$5 AAA $5 AAA",
  571. "$6 AAA $6 AAA",
  572. "$7 AAA $7 AAA",
  573. "$8 AAA $8 AAA",
  574. "$9 AAA $9 AAA",
  575. ],
  576. },
  577. {
  578. path: "test/built-ins/String/prototype/replaceAll/getSubstitution-0x0024NN.js",
  579. code: `
  580. const str = "aaaaaaaaaaaaaaaa aaaaaaaa aaaaaaaaaaaaaaaa"
  581. return [str.replaceAll("a", "$11"), str.replaceAll("a", "$29")]
  582. `,
  583. expected: [
  584. "$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",
  585. "$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",
  586. ],
  587. },
  588. {
  589. path: "test/built-ins/String/prototype/replaceAll/getSubstitution-0x0024-0x003C.js",
  590. code: `return "aaaaaaaaaaaaaaaa aaaaaaaa aaaaaaaaaaaaaaaa".replaceAll("a", "$<")`,
  591. expected: "$<$<$<$<$<$<$<$<$<$<$<$<$<$<$<$< $<$<$<$<$<$<$<$< $<$<$<$<$<$<$<$<$<$<$<$<$<$<$<$<",
  592. },
  593. ])
  594. run("Test262-adapted match behavior", [
  595. {
  596. path: "test/built-ins/String/prototype/match/S15.5.4.10_A1_T14.js",
  597. code: `const match = "ABBABABAB77BBAA".match(new RegExp("77")); return [match[0], match.index]`,
  598. expected: ["77", 9],
  599. },
  600. {
  601. path: "test/built-ins/String/prototype/match/S15.5.4.10_A2_T2.js",
  602. code: `return "343443444".match(/34/g)`,
  603. expected: ["34", "34", "34"],
  604. },
  605. {
  606. path: "test/built-ins/String/prototype/match/S15.5.4.10_A2_T3.js",
  607. code: `return "123456abcde7890".match(/\\d{1}/g)`,
  608. expected: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"],
  609. },
  610. {
  611. path: "test/built-ins/String/prototype/match/S15.5.4.10_A2_T4.js",
  612. code: `return "123456abcde7890".match(/\\d{2}/g)`,
  613. expected: ["12", "34", "56", "78", "90"],
  614. },
  615. {
  616. path: "test/built-ins/String/prototype/match/S15.5.4.10_A2_T5.js",
  617. code: `return "123456abcde7890".match(/\\D{2}/g)`,
  618. expected: ["ab", "cd"],
  619. },
  620. {
  621. path: "test/built-ins/String/prototype/match/S15.5.4.10_A2_T6.js",
  622. code: `const match = "Boston, Mass. 02134".match(/([\\d]{5})([- ]?[\\d]{4})?$/); return [match[0], match[1], match[2] === undefined, match.length, match.index]`,
  623. expected: ["02134", "02134", true, 3, 14],
  624. },
  625. {
  626. path: "test/built-ins/String/prototype/match/S15.5.4.10_A2_T7.js",
  627. code: `return "Boston, Mass. 02134".match(/([\\d]{5})([- ]?[\\d]{4})?$/g)`,
  628. expected: ["02134"],
  629. },
  630. {
  631. path: "test/built-ins/String/prototype/match/S15.5.4.10_A2_T8.js",
  632. code: `const match = "Boston, MA 02134".match(/([\\d]{5})([- ]?[\\d]{4})?$/); return [match[0], match[1], match[2] === undefined, match.length, match.index]`,
  633. expected: ["02134", "02134", true, 3, 11],
  634. },
  635. {
  636. path: "test/built-ins/String/prototype/match/S15.5.4.10_A2_T12.js",
  637. code: `return "Boston, MA 02134".match(/([\\d]{5})([- ]?[\\d]{4})?$/g)`,
  638. expected: ["02134"],
  639. },
  640. ])
  641. run("Test262-adapted matchAll behavior", [
  642. {
  643. path: "test/built-ins/String/prototype/matchAll/regexp-prototype-matchAll-v-u-flag.js",
  644. code: `
  645. const text = "𠮷a𠮷b𠮷"
  646. const collect = (regex) => {
  647. const matches = text.matchAll(regex)
  648. return matches.map((match) => match[0]).concat(matches.map((match) => match.index))
  649. }
  650. const empty = text.matchAll(/(?:)/gu)
  651. const complex = "a𠮷b􏿿c".matchAll(/\\P{ASCII}/gu)
  652. return [
  653. collect(/𠮷/g),
  654. collect(/𠮷/gu),
  655. collect(/\\p{Script=Han}/gu),
  656. collect(/./gu),
  657. empty.map((match) => match[0]).concat(empty.map((match) => match.index)).length,
  658. complex.map((match) => match[0]),
  659. ]
  660. `,
  661. expected: [
  662. ["𠮷", "𠮷", "𠮷", 0, 3, 6],
  663. ["𠮷", "𠮷", "𠮷", 0, 3, 6],
  664. ["𠮷", "𠮷", "𠮷", 0, 3, 6],
  665. ["𠮷", "a", "𠮷", "b", "𠮷", 0, 2, 3, 5, 6],
  666. 12,
  667. ["𠮷", "􏿿"],
  668. ],
  669. },
  670. ])
  671. run("Test262-adapted search behavior", [
  672. {
  673. path: "test/built-ins/String/prototype/search/S15.5.4.12_A1_T14.js",
  674. code: `return "ABBABABAB77BBAA".search(new RegExp("77"))`,
  675. expected: 9,
  676. },
  677. {
  678. path: "test/built-ins/String/prototype/search/S15.5.4.12_A2_T1.js",
  679. code: `return "test string".search("string")`,
  680. expected: 5,
  681. },
  682. {
  683. path: "test/built-ins/String/prototype/search/S15.5.4.12_A2_T2.js",
  684. code: `return "test string".search("String")`,
  685. expected: -1,
  686. },
  687. {
  688. path: "test/built-ins/String/prototype/search/S15.5.4.12_A2_T3.js",
  689. code: `return "test string".search(/String/i)`,
  690. expected: 5,
  691. },
  692. {
  693. path: "test/built-ins/String/prototype/search/S15.5.4.12_A2_T4.js",
  694. code: `return "one two three four five".search(/Four/)`,
  695. expected: -1,
  696. },
  697. {
  698. path: "test/built-ins/String/prototype/search/S15.5.4.12_A2_T5.js",
  699. code: `return "one two three four five".search(/four/)`,
  700. expected: 14,
  701. },
  702. {
  703. path: "test/built-ins/String/prototype/search/S15.5.4.12_A2_T6.js",
  704. code: `return "test string".search("notexist")`,
  705. expected: -1,
  706. },
  707. {
  708. path: "test/built-ins/String/prototype/search/S15.5.4.12_A2_T7.js",
  709. code: `return "test string probe".search("string pro")`,
  710. expected: 5,
  711. },
  712. {
  713. path: "test/built-ins/String/prototype/search/S15.5.4.12_A3_T1.js",
  714. code: `const text = "power of the power of the power of the great sword"; return [text.search(/the/), text.search(/the/g)]`,
  715. expected: [9, 9],
  716. },
  717. {
  718. path: "test/built-ins/String/prototype/search/S15.5.4.12_A3_T2.js",
  719. code: `const text = "power of the power of the power of the great sword"; return [text.search(/of/), text.search(/of/g)]`,
  720. expected: [6, 6],
  721. },
  722. ])