import { OnigurumaRegExp } from "bun"; import { expect, it, test } from "bun:test"; import { gc as gcTrace } from "./gc"; it("repeated match and exec calls", () => { for (let i = 0; i < 20000; i++) { let r1 = new OnigurumaRegExp("//.+?/[^?]+", "sg"); let r2 = new RegExp("//.+?/[^?]+", "sg"); let s1 = "https://dylan-conway.com/profile"; expect(s1.match(r1)[0] === s1.match(r2)[0]).toBe(true); expect(r1.exec(s1)[0] === r2.exec(s1)[0]).toBe(true); } }); it("repeated match and exec calls no global flag", () => { for (let i = 0; i < 20000; i++) { let r1 = new OnigurumaRegExp("//.+?/[^?]+", "s"); let r2 = new RegExp("//.+?/[^?]+", "s"); let s1 = "https://dylan-conway.com/profile"; expect(r1.exec(s1)[0] === r2.exec(s1)[0]).toBe(true); expect(s1.match(r1)[0] === s1.match(r2)[0]).toBe(true); } }); const rb1 = new OnigurumaRegExp("//.+?/[^?]+", "s"); const rb2 = new RegExp("//.+?/[^?]+", "s"); it("repeated match calls with global regex without global flag", () => { for (let i = 0; i < 20000; i++) { let s1 = "https://dylan-conway.com/profile"; expect(rb1.exec(s1)[0] === rb2.exec(s1)[0]).toBe(true); expect(s1.match(rb1)[0] === s1.match(rb2)[0]).toBe(true); } }); it("escaped characters in character classes", () => { expect( new RegExp("[a-z]").exec("a")[0] === new OnigurumaRegExp("[a-z]").exec("a")[0] ).toBe(true); Bun.gc(true); expect( new RegExp("[a-z]").exec("b")[0] === new OnigurumaRegExp("[a-z]").exec("b")[0] ).toBe(true); Bun.gc(true); expect(new RegExp("[a-zA-Z0-9_]+").exec("B9")[0]).toBe( new OnigurumaRegExp("[a-zA-Z0-9_]+").exec("B9")[0] ); Bun.gc(true); expect(new RegExp("[a-z]").exec("-")).toBe(null); Bun.gc(true); expect(new OnigurumaRegExp("[a-z]").exec("-")).toBe(null); Bun.gc(true); expect(new RegExp("[a\\-z]").exec("-")[0]).toBe("-"); Bun.gc(true); expect(new OnigurumaRegExp("[a\\-z]").exec("-")[0]).toBe("-"); Bun.gc(true); expect(new RegExp("[a\\-z]").exec("a")[0]).toBe("a"); Bun.gc(true); expect(new OnigurumaRegExp("[a\\-z]").exec("a")[0]).toBe("a"); Bun.gc(true); expect(new RegExp("[a\\-z]").exec("z")[0]).toBe("z"); Bun.gc(true); expect(new OnigurumaRegExp("[a\\-z]").exec("z")[0]).toBe("z"); Bun.gc(true); expect(new RegExp("[a\\-z]").exec("b")).toBe(null); Bun.gc(true); expect(new OnigurumaRegExp("[a\\-z]").exec("b")).toBe(null); Bun.gc(true); expect(new RegExp("[^b-c]").exec("a")[0]).toBe( new OnigurumaRegExp("[^b-c]").exec("a")[0] ); Bun.gc(true); expect(new RegExp("[\\^b-c]").exec("a")).toBe(null); expect(new OnigurumaRegExp("[\\^b-c]").exec("a")).toBe(null); Bun.gc(true); expect(new RegExp("[\\^b-c]").exec("^c")[0]).toBe("^"); expect(new OnigurumaRegExp("[\\^b-c]").exec("^c")[0]).toBe("^"); Bun.gc(true); expect(new RegExp("[a^b-c]").exec("a^")[0]).toBe("a"); expect(new OnigurumaRegExp("[a^b-c]").exec("a^")[0]).toBe("a"); Bun.gc(true); expect(new RegExp("[\\\\]").exec("\\")[0]).toBe("\\"); expect(new OnigurumaRegExp("[\\\\]").exec("\\")[0]).toBe("\\"); Bun.gc(true); let p = "//.+?[^?]+"; let s = "https://dylan-conway.com/profile"; const b1 = new RegExp(p, "gs"); const b2 = new OnigurumaRegExp(p, "gs"); Bun.gc(true); expect(s.match(b1)[0] === s.match(b2)[0]).toBe(true); Bun.gc(true); const b3 = new RegExp("[\\^]"); const b4 = new OnigurumaRegExp("[\\^]"); Bun.gc(true); expect( "https://dylan-co^nway.com/profile".match(b3)[0] === "https://dylan-co^nway.com/profile".match(b4)[0] ).toBe(true); Bun.gc(true); // prettier-ignore p = "\/\/.+?\/[^?]+"; s = "https://dylan-conway.com/profile"; Bun.gc(true); expect(s.match(new OnigurumaRegExp(p, "gs"))[0]).toBe( new RegExp(p, "gs").exec(s)[0] ); Bun.gc(true); // middle no escape p = "[.i^e]+"; s = "https://dylan-co^nway.com/profile"; expect(new OnigurumaRegExp(p).exec(s)[0]).toBe(new RegExp(p).exec(s)[0]); // middle with escape p = "[.i\\^e]+"; s = "https://dylan-co^nway.com/profile"; expect(new OnigurumaRegExp(p).exec(s)[0]).toBe(new RegExp(p).exec(s)[0]); // end with escape p = "[.ie\\^]+"; s = "https://dylan-co^nway.com/profile"; expect(new OnigurumaRegExp(p).exec(s)[0]).toBe(new RegExp(p).exec(s)[0]); // end no escape p = "[.ie^]+"; s = "https://dylan-co^nway.com/profile"; expect(new OnigurumaRegExp(p).exec(s)[0]).toBe(new RegExp(p).exec(s)[0]); // start no escape p = "[^.ie]+"; s = "https://dylan-co^nway.com/profile"; expect(new OnigurumaRegExp(p).exec(s)[0]).toBe(new RegExp(p).exec(s)[0]); // start with escape p = "[\\^.ie]+"; s = "https://dylan-co^nway.com/profile"; expect(new OnigurumaRegExp(p).exec(s)[0]).toBe(new RegExp(p).exec(s)[0]); // middle with escape p = "[.i\\-e]+"; s = "https://dylan-conway.com/profile"; expect(new OnigurumaRegExp(p).exec(s)[0]).toBe(new RegExp(p).exec(s)[0]); // end with escape p = "[.ie\\-]+"; s = "https://dylan-conway.com/profile"; expect(new OnigurumaRegExp(p).exec(s)[0]).toBe(new RegExp(p).exec(s)[0]); // end no escape p = "[.ie-]+"; s = "https://dylan-conway.com/profile"; expect(new OnigurumaRegExp(p).exec(s)[0]).toBe(new RegExp(p).exec(s)[0]); // start no escape p = "[-.ie]+"; s = "https://dylan-conway.com/profile"; expect(new OnigurumaRegExp(p).exec(s)[0]).toBe(new RegExp(p).exec(s)[0]); // start with escape p = "[\\-.ie]+"; s = "https://dylan-conway.com/profile"; expect(new OnigurumaRegExp(p).exec(s)[0]).toBe(new RegExp(p).exec(s)[0]); let r1 = new RegExp("^([[(]-?[\\d]+)?,?(-?[\\d]+[\\])])?$").exec("(1,1]"); Bun.gc(true); let r2 = new OnigurumaRegExp("^([[(]-?[\\d]+)?,?(-?[\\d]+[\\])])?$").exec( "(1,1]" ); Bun.gc(true); expect(r1[0]).toBe(r2[0]); Bun.gc(true); let r3 = new RegExp("[\\d],[\\d]").exec("1,2"); let r4 = new OnigurumaRegExp("[\\d],[\\d]").exec("1,2"); expect(r3[0]).toBe(r4[0]); let r5 = new RegExp("^[(],[)]?$").exec("(,"); let r6 = new OnigurumaRegExp("^[(],[)]?$").exec("(,"); expect(r5[0]).toBe(r6[0]); let r9 = new RegExp("[([],[)\\]]").exec("[,]"); let r10 = new OnigurumaRegExp("[([],[)\\]]").exec("[,]"); expect(r9[0]).toBe(r10[0]); let r13 = new RegExp("\\[").exec("["); let r14 = new OnigurumaRegExp("\\[").exec("["); expect(r13[0]).toBe(r14[0]); let r15 = new RegExp("\\]").exec("]"); let r16 = new OnigurumaRegExp("\\]").exec("]"); expect(r15[0]).toBe(r16[0]); let r17 = new RegExp("]").exec("]"); let r18 = new OnigurumaRegExp("]").exec("]"); expect(r17[0]).toBe(r18[0]); let r21 = new RegExp("[\\]]").exec("]"); let r22 = new OnigurumaRegExp("[\\]]").exec("]"); expect(r21[0]).toBe(r22[0]); let r23 = new RegExp("[\\[]").exec("["); let r24 = new OnigurumaRegExp("[\\[]").exec("["); expect(r23[0]).toBe(r24[0]); let r25 = new RegExp("[[][[]").exec("[["); let r26 = new OnigurumaRegExp("[[][[]").exec("[["); expect(r25[0]).toBe(r26[0]); let r27 = new RegExp("[[\\]][[\\]]").exec("[]"); let r28 = new OnigurumaRegExp("[[\\]][[\\]]").exec("[]"); expect(r27[0]).toBe(r28[0]); let r29 = new RegExp("[[\\]][[\\]]").exec("]["); let r30 = new OnigurumaRegExp("[[\\]][[\\]]").exec("]["); expect(r29[0]).toBe(r30[0]); let r31 = new RegExp("[[\\]][[\\]]").exec("]]"); let r32 = new OnigurumaRegExp("[[\\]][[\\]]").exec("]]"); expect(r31[0]).toBe(r32[0]); let r33 = new RegExp("[\\]][\\]]").exec("]]"); let r34 = new OnigurumaRegExp("[\\]][\\]]").exec("]]"); expect(r33[0]).toBe(r34[0]); let r35 = new RegExp("[a-z&&[^aeiou]").exec("a"); let r36 = new OnigurumaRegExp("[a-z&&[^aeiou]").exec("a"); expect(r35[0]).toBe(r36[0]); let r37 = new RegExp("[a-z&&[^aeiou]]").exec("a]"); let r38 = new OnigurumaRegExp("[a-z&&[^aeiou]]").exec("a]"); expect(r37[0]).toBe(r38[0]); }); it("OnigurumaRegExp.prototype.exec()", () => { let a1 = new OnigurumaRegExp("\x3e", "gd"); let a1_1 = a1.exec("table fo\x3eotball, fo\x3eosball"); a1_1 = a1.exec("table fo\x3eotball, fo\x3eosball"); let a2 = new RegExp("\x3e", "gd"); let a2_1 = a2.exec("table fo\x3eotball, fo\x3eosball"); a2_1 = a2.exec("table fo\x3eotball, fo\x3eosball"); expect(a1_1[0]).toBe(a2_1[0]); expect(a1_1[1]).toBe(a2_1[1]); expect(a1_1.index).toBe(a2_1.index); expect(a1_1.input).toBe(a2_1.input); expect(a1.lastIndex).toBe(a2.lastIndex); expect(a1_1.groups).toBe(a2_1.groups); expect(a1_1.indices[0][0]).toBe(a2_1.indices[0][0]); expect(a1_1.indices[0][1]).toBe(a2_1.indices[0][1]); }); test("OnigurumaRegExp.prototype.exec() 2", () => { let a1 = new OnigurumaRegExp("\x3e\\x5e", "gd"); let a1_1 = a1.exec("table fo\x3e\x5eotball, fo\x3e\x5eosball"); a1_1 = a1.exec("table fo\x3e\x5eotball, fo\x3e\x5eosball"); let a2 = new RegExp("\x3e\\x5e", "gd"); let a2_1 = a2.exec("table fo\x3e\x5eotball, fo\x3e\x5eosball"); a2_1 = a2.exec("table fo\x3e\x5eotball, fo\x3e\x5eosball"); expect(a1_1[0]).toBe(a2_1[0]); expect(a1_1[1]).toBe(a2_1[1]); expect(a1_1.index).toBe(a2_1.index); expect(a1_1.input).toBe(a2_1.input); expect(a1.lastIndex).toBe(a2.lastIndex); expect(a1_1.groups).toBe(a2_1.groups); expect(a1_1.indices[0][0]).toBe(a2_1.indices[0][0]); expect(a1_1.indices[0][1]).toBe(a2_1.indices[0][1]); }); test("OnigurumaRegExp.prototype.exec() 3", () => { let a22 = new OnigurumaRegExp("\\x9\\x5e", "gd"); let a22_1 = a22.exec("table fox9^otball, fox9^osball"); expect(a22_1[0]).toBe("x9^"); let a1 = new OnigurumaRegExp("x3\\x5e", "gd"); let a1_1 = a1.exec("table fo\\x3\x5eotball, fo\\x3\x5eosball"); let a2 = new RegExp("\\x3\\x5e", "gd"); let a2_1 = a2.exec("table fo\\x3\x5eotball, fo\\x3\x5eosball"); expect(a1_1[0]).toBe(a2_1[0]); expect(a1_1[1]).toBe(a2_1[1]); expect(a1_1.index).toBe(a2_1.index); expect(a1_1.input).toBe(a2_1.input); expect(a1.lastIndex).toBe(a2.lastIndex); expect(a1_1.groups).toBe(a2_1.groups); expect(a1_1.indices[0][0]).toBe(a2_1.indices[0][0]); expect(a1_1.indices[0][1]).toBe(a2_1.indices[0][1]); }); test("OnigurumaRegExp.prototype.exec() 4", () => { let a2 = new RegExp("\\x3\\x5e", "gd"); let a2_1 = a2.exec("table fox3^otball, fox3^osball"); a2_1 = a2.exec("table fox3^otball, fox3^osball"); for (const RegExpConstructor of [OnigurumaRegExp, RegExp]) { let a2 = new RegExpConstructor("\\x3\\x5e", "gd"); let a2_1 = a2.exec("table fox3^otball, fox3^osball"); expect(a2_1[0]).toBe("x3^"); expect(new RegExpConstructor("\\x3").source).toBe("\\x3"); expect(new RegExpConstructor("\\x").source).toBe("\\x"); expect(new RegExpConstructor("\\a").source).toBe("\\a"); expect(new RegExpConstructor("j\\x3\\x2").source).toBe("j\\x3\\x2"); expect(new RegExpConstructor("\\x3\\x5\\j").source).toBe("\\x3\\x5\\j"); expect(new RegExpConstructor("\\x3\\x7\\xa").source).toBe("\\x3\\x7\\xa"); expect(new RegExpConstructor("\\j323\\x7\\xa").source).toBe( "\\j323\\x7\\xa" ); expect(new RegExpConstructor("\\x56").test("V")).toBe(true); } }); test("OnigurumaRegExp.prototype.test()", () => { expect(new RegExp("\\\\(?![*+?^${}(|)[\\]])", "g").test("\\")).toBe(true); expect(new OnigurumaRegExp("\\\\(?![*+?^${}(|)[\\]])", "g").test("\\")).toBe( true ); expect(new RegExp("\\x56").test("V")).toBe(true); expect(new OnigurumaRegExp("\\x56").test("V")).toBe(true); expect( new RegExp("//").compile("\\\\(?![*+?^${}(|)[\\]])", "g").test("\\") ).toBe(true); let r = new OnigurumaRegExp("//"); expect(r.compile("\\\\(?![*+?^${}(|)[\\]])", "g").test("\\")).toBe(true); expect( new OnigurumaRegExp("").compile("\\\\(?![*+?^${}(|)[\\]])", "g").test("\\") ).toBe(true); }); test("OnigurumaRegExp flag order", () => { expect(new OnigurumaRegExp("a", "gd").toString()).toBe("/a/dg"); expect(new OnigurumaRegExp("a", "ydmg").toString()).toBe("/a/dgmy"); }); test("OnigurumaRegExp.prototype.source", () => { let a1 = new OnigurumaRegExp("(foo)", "gd"); let a2 = new RegExp("(foo)", "dg"); expect(a1.source).toBe(a2.source); expect(new OnigurumaRegExp("/").source).toBe("\\/"); expect(new RegExp("/").source).toBe("\\/"); expect(new OnigurumaRegExp().source).toBe(new RegExp().source); expect(new OnigurumaRegExp("").source).toBe(new RegExp("").source); expect(new OnigurumaRegExp("a").source).toBe(new RegExp("a").source); expect(new OnigurumaRegExp("a", "g").source).toBe( new RegExp("a", "g").source ); expect(new OnigurumaRegExp("/").source).toBe(new RegExp("/").source); expect(new OnigurumaRegExp("\n").source).toBe(new RegExp("\n").source); expect(new OnigurumaRegExp("\r").source).toBe(new RegExp("\r").source); }); test("OnigurumaRegExp.prototype.toString()", () => { expect(new OnigurumaRegExp().toString()).toBe(new RegExp().toString()); expect(new OnigurumaRegExp("").toString()).toBe(new RegExp("").toString()); expect(new OnigurumaRegExp("a").toString()).toBe(new RegExp("a").toString()); expect(new OnigurumaRegExp("a", "g").toString()).toBe( new RegExp("a", "g").toString() ); expect(new OnigurumaRegExp("/").toString()).toBe(new RegExp("/").toString()); expect(new OnigurumaRegExp("\n").toString()).toBe( new RegExp("\n").toString() ); expect(new OnigurumaRegExp("\r").toString()).toBe( new RegExp("\r").toString() ); expect( new OnigurumaRegExp( "jf/.a.,voejpjoajglz;/qwjopeiv\\//\\/jpoqaj/Zdkj" ).toString() ).toBe( new RegExp("jf/.a.,voejpjoajglz;/qwjopeiv\\//\\/jpoqaj/Zdkj").toString() ); }); test("OnigurumaRegExp flags", () => { // multiline option for (const RegExpConstructor of [OnigurumaRegExp, RegExp]) { expect(new RegExpConstructor("boat").test("sailor\nboat")).toBe(true); expect(new RegExpConstructor("^boat").test("sailor\nboat")).toBe(false); expect(new RegExpConstructor("^boat", "m").test("sailor\nboat")).toBe(true); } // sticky option for (const RegExpConstructor of [RegExp]) { let str2 = "sailor"; let h3 = new RegExpConstructor("or"); let h4 = new RegExpConstructor("or", "y"); expect(h3.test(str2)).toBe(true); expect(h4.test(str2)).toBe(false); let g1 = new RegExpConstructor("sail"); let g2 = new RegExpConstructor("sail", "y"); expect(g1.test(str2)).toBe(true); expect(g2.test(str2)).toBe(true); } expect(/a/s.toString()).toBe("/a/s"); expect(/a/g.toString()).toBe("/a/g"); expect(/a/y.toString()).toBe("/a/y"); expect(/a/m.toString()).toBe("/a/m"); expect(/a/gs.toString()).toBe("/a/gs"); expect(/a/sy.toString()).toBe("/a/sy"); expect(/a/gm.toString()).toBe("/a/gm"); expect(/a/gsy.toString()).toBe("/a/gsy"); expect(/a/gms.toString()).toBe("/a/gms"); expect(/a/gmy.toString()).toBe("/a/gmy"); // expect(/a/d.toString()).toBe("/a/d"); // expect(/a/dgimsuy.toString()).toBe("/a/dgimsuy"); // case insensitive option for (const RegExpConstructor of [OnigurumaRegExp, RegExp]) { expect(new RegExpConstructor("Is ThIs SqL?").test("IS THIS SQL?")).toBe( false ); expect( new RegExpConstructor("Is ThIs SqL?", "i").test("IS THIS SQL?") ).toBe(true); } // dotall option for (const RegExpConstructor of [OnigurumaRegExp, RegExp]) { expect(new RegExpConstructor("a.b").test("a\nb")).toBe(false); expect(new RegExpConstructor("a.b", "s").test("a\nb")).toBe(true); } // indices option for (const RegExpConstructor of [OnigurumaRegExp, RegExp]) { expect(new RegExpConstructor("a", "g").exec("a").indices).toBe(undefined); expect(new RegExpConstructor("a", "gd").exec("a").index).toBe(0); expect(new RegExpConstructor("a", "dg").exec("a").index).toBe(0); } }); test("OnigurumaRegExp.lastIndex", () => { for (const RegExpConstructor of [RegExp, OnigurumaRegExp]) { let a = new RegExpConstructor("foo", "g"); expect(a.lastIndex).toBe(0); a.lastIndex = 1; expect(a.lastIndex).toBe(1); a.lastIndex = 0; expect(a.lastIndex).toBe(0); a.lastIndex = 1; expect(a.lastIndex).toBe(1); a.test("kfjekf"); expect(a.lastIndex).toBe(0); a.test("o"); expect(a.lastIndex).toBe(0); } let p1 = new OnigurumaRegExp("a"); expect(p1.lastIndex).toBe(0); p1.lastIndex = 2; expect(p1.lastIndex).toBe(2); let p2 = new OnigurumaRegExp("b"); expect(p2.lastIndex).toBe(0); p2.lastIndex = 2348; expect(p2.lastIndex).toBe(2348); expect(p1.lastIndex).toBe(2); for (const RegExpConstructor of [RegExp, OnigurumaRegExp]) { let a = new RegExpConstructor("foo", "g"); a.lastIndex = 33; expect(a.lastIndex).toBe(33); a.compile("bar"); expect(a.lastIndex).toBe(0); a.lastIndex = 44; expect(a.lastIndex).toBe(44); } for (const RegExpConstructor of [OnigurumaRegExp]) { let a = new RegExpConstructor("foo", "g"); expect(a.lastIndex).toBe(0); a.test("kfjekfoofjekf"); expect(a.lastIndex).toBe(8); a.test("kejfkjs"); expect(a.lastIndex).toBe(0); a.exec("kfjekfoofjekf"); expect(a.lastIndex).toBe(8); a.exec("kejfkjs"); expect(a.lastIndex).toBe(0); } }); test("OnigurumaRegExp errors", () => { let r = new OnigurumaRegExp("a", "igsym"); let b = new OnigurumaRegExp("l", "m"); try { r.compile(b, "g"); } catch (e) { expect(e.message).toBe( "Cannot supply flags when constructing one RegExp from another." ); } try { r.compile("ll", "a"); } catch (e) { expect(e.message).toBe("Invalid flags supplied to RegExp constructor."); } try { new OnigurumaRegExp("c", "a"); } catch (e) { expect(e.message).toBe("Invalid flags supplied to RegExp constructor."); } const invalidRegExpError = "Invalid regular expression: "; try { new OnigurumaRegExp("?", "g"); } catch (e) { expect(e.message.substring(0, invalidRegExpError.length)).toBe( invalidRegExpError ); } try { new OnigurumaRegExp("?"); } catch (e) { expect(e.message.substring(0, invalidRegExpError.length)).toBe( invalidRegExpError ); } try { r.compile("?", "g"); } catch (e) { expect(e.message.substring(0, invalidRegExpError.length)).toBe( invalidRegExpError ); } try { r.compile("?"); } catch (e) { expect(e.message.substring(0, invalidRegExpError.length)).toBe( invalidRegExpError ); } try { new OnigurumaRegExp("\\"); } catch (e) { expect(e.message.substring(0, invalidRegExpError.length)).toBe( invalidRegExpError ); } }); test("OnigurumaRegExp random", () => { expect(new OnigurumaRegExp("love").test("I love JavaScript")).toBe(true); expect(new RegExp("love").test("I love JavaScript")).toBe(true); expect(new OnigurumaRegExp("a").test("sailor")).toBe(true); expect(new OnigurumaRegExp("or").test("sailor")).toBe(true); expect(new RegExp("a").test("sailor")).toBe(true); expect(new RegExp("or").test("sailor")).toBe(true); expect(new OnigurumaRegExp("a").test("a")).toBe(true); expect(new OnigurumaRegExp("a").test("b")).toBe(false); expect(new OnigurumaRegExp("a", "i").test("a")).toBe(true); expect(new OnigurumaRegExp("a", "i").test("A")).toBe(true); expect(new OnigurumaRegExp("a", "g").test("A")).toBe(false); expect(new OnigurumaRegExp("A", "i").test("a")).toBe(true); expect(new OnigurumaRegExp("A", "g").test("a")).toBe(false); expect(new OnigurumaRegExp("afasdfebadf", "i").test("b")).toBe(false); let r = new OnigurumaRegExp("a", "g"); expect(r.source).toBe("a"); expect(r.flags).toBe("g"); expect(r.toString()).toBe("/a/g"); r.compile("b", "i"); expect(r.source).toBe("b"); expect(r.flags).toBe("i"); expect(r.toString()).toBe("/b/i"); let b = new OnigurumaRegExp("l", "m"); expect(r.compile(b) instanceof OnigurumaRegExp).toBe(true); expect(r.source).toBe("l"); expect(r.flags).toBe("m"); expect(r.toString()).toBe("/l/m"); expect(new OnigurumaRegExp("a", "d").hasIndices).toBe(true); expect(new OnigurumaRegExp("a", "i").hasIndices).toBe(false); expect(new OnigurumaRegExp("a", "s").dotAll).toBe(true); expect(new OnigurumaRegExp("a", "i").dotAll).toBe(false); expect(new OnigurumaRegExp("a", "i").ignoreCase).toBe(true); expect(new OnigurumaRegExp("a", "s").ignoreCase).toBe(false); expect(new OnigurumaRegExp("a", "g").global).toBe(true); expect(new OnigurumaRegExp("a", "s").global).toBe(false); expect(new OnigurumaRegExp("a", "m").multiline).toBe(true); expect(new OnigurumaRegExp("a", "s").multiline).toBe(false); expect(new OnigurumaRegExp("a", "y").sticky).toBe(true); expect(new OnigurumaRegExp("a", "i").sticky).toBe(false); expect(new OnigurumaRegExp("a", "u").unicode).toBe(true); expect(new OnigurumaRegExp("a", "d").unicode).toBe(false); expect(new RegExp("a", "d").hasIndices).toBe(true); expect(new RegExp("a", "i").hasIndices).toBe(false); expect(new RegExp("a", "s").dotAll).toBe(true); expect(new RegExp("a", "i").dotAll).toBe(false); expect(new RegExp("a", "i").ignoreCase).toBe(true); expect(new RegExp("a", "s").ignoreCase).toBe(false); expect(new RegExp("a", "g").global).toBe(true); expect(new RegExp("a", "s").global).toBe(false); expect(new RegExp("a", "m").multiline).toBe(true); expect(new RegExp("a", "s").multiline).toBe(false); expect(new RegExp("a", "y").sticky).toBe(true); expect(new RegExp("a", "i").sticky).toBe(false); expect(new RegExp("a", "u").unicode).toBe(true); expect(new RegExp("a", "d").unicode).toBe(false); }); it("String.prototype.replace", () => { for (let RegExpConstructor of [OnigurumaRegExp, RegExp]) { const r = new RegExpConstructor("a", "g"); expect("a".replace(r, "b")).toBe("b"); expect("a".replace(r, () => "b")).toBe("b"); expect( "a".replace(r, (match, offset, string) => { expect(match).toBe("a"); expect(offset).toBe(0); expect(string).toBe("a"); return "b"; }) ).toBe("b"); } expect("aaaaaa".replace(new OnigurumaRegExp("a", "g"), "b")).toBe("bbbbbb"); expect("aaaaaa".replace(new OnigurumaRegExp("a"), "b")).toBe("baaaaa"); // case sensitive expect("aaaaaa".replace(new OnigurumaRegExp("A", "i"), "b")).toBe("baaaaa"); expect("aaaaaa".replace(new OnigurumaRegExp("A"), "b")).toBe("aaaaaa"); expect("aaaaaa".replace(new RegExp("a", "g"), "b")).toBe("bbbbbb"); expect("aaaaaa".replace(new RegExp("a"), "b")).toBe("baaaaa"); }); it("Strings.prototype.match", () => { let str = "The rain in SPAIN stays mainly in the plain"; for (let RegExpConstructor of [OnigurumaRegExp, RegExp]) { let r1 = new RegExpConstructor("ain", "g"); let m1 = str.match(r1); expect(m1[0]).toBe("ain"); expect(m1[1]).toBe("ain"); expect(m1[2]).toBe("ain"); r1.compile("ain", "ig"); m1 = str.match(r1); expect(m1[0]).toBe("ain"); expect(m1[1]).toBe("AIN"); expect(m1[2]).toBe("ain"); expect(m1[3]).toBe("ain"); } }); it("String.prototype.matchAll", () => { let str = "test1test2"; for (let RegExpConstructor of [RegExp, OnigurumaRegExp]) { const regexp = new RegExpConstructor("t(e)(st(d?))", "g"); const array = [...str.matchAll(regexp)]; expect(array[0][0]).toBe("test"); expect(array[0][1]).toBe("e"); expect(array[0][2]).toBe("st"); expect(array[0][3]).toBe(""); expect(array[1][0]).toBe("test"); expect(array[1][1]).toBe("e"); expect(array[1][2]).toBe("st"); expect(array[1][3]).toBe(""); } }); it("String.prototype.search", () => { let str = "The rain in SPAIN stays mainly in the plain"; for (let RegExpConstructor of [OnigurumaRegExp, RegExp]) { let r1 = new RegExpConstructor("ain", "g"); expect(str.search(r1)).toBe(5); r1.compile("ain", "ig"); expect(str.search(r1)).toBe(5); } }); it("String.prototype.split", () => { let str = "Hello World. How are you doing?"; for (let RegExpConstructor of [RegExp, OnigurumaRegExp]) { let r1 = new RegExpConstructor("\\s", "g"); let m1 = str.split(r1); expect(m1[0]).toBe("Hello"); expect(m1[1]).toBe("World."); expect(m1[2]).toBe("How"); expect(m1[3]).toBe("are"); expect(m1[4]).toBe("you"); expect(m1[5]).toBe("doing?"); } }); it("escapes characters, unicode, and hex", () => { for (const RegExpConstructor of [OnigurumaRegExp, RegExp]) { expect(new RegExpConstructor("[\\x00-\\x1F]").toString()).toBe( "/[\\x00-\\x1F]/" ); expect(new RegExpConstructor("[\\u0000-\\u001F]").toString()).toBe( "/[\\u0000-\\u001F]/" ); var s = /\\x{7HHHHHHH}(?=\\u{1233})/; let a = new RegExpConstructor("\u{0001F46E}"); expect(a.exec("👮")[0]).toBe("👮"); } let y = new OnigurumaRegExp("[👮\\x7F](?<=👮)"); expect(y.exec("👮\\x{7F}")[0]).toBe("👮"); let by = new OnigurumaRegExp("[👮\\cx7f](?<=👮)"); expect(y.exec("👮\\x{7F}")[0]).toBe("👮"); let bz = new OnigurumaRegExp("[👮\\x7](?<=👮)"); let d = new OnigurumaRegExp("[\u{0001F46E}\x7F](?<=\u{0001F46E})"); expect(d.exec("👮\x7F")[0]).toBe("👮"); let y_2 = /[[👮\x7F](?<=👮)]/; expect(y_2.exec("👮]")[0]).toBe("👮]"); let a1 = new OnigurumaRegExp("(f\xf3oo)", "gd"); let a1_1 = a1.exec("table f\xf3ootball, f\xf3oosball"); a1_1 = a1.exec("table f\xf3ootball, f\xf3oosball"); let a2 = new RegExp("(f\xf3oo)", "dg"); let a2_1 = a2.exec("table f\xf3ootball, f\xf3oosball"); a2_1 = a2.exec("table f\xf3ootball, f\xf3oosball"); expect(a1_1[0]).toBe(a2_1[0]); expect(a1_1[1]).toBe(a2_1[1]); expect(a1_1.index).toBe(a2_1.index); expect(a1_1.input).toBe(a2_1.input); expect(a1.lastIndex).toBe(a2.lastIndex); expect(a1_1.groups).toBe(a2_1.groups); expect(a1_1.indices[0][0]).toBe(a2_1.indices[0][0]); expect(a1_1.indices[0][1]).toBe(a2_1.indices[0][1]); expect(a1_1.indices[1][0]).toBe(a2_1.indices[1][0]); expect(a1_1.indices[1][1]).toBe(a2_1.indices[1][1]); }); it("lookbehinds", () => { expect(/\d+(?=%)/.source).toBe("\\d+(?=%)"); expect(/\d+(?!%)/.source).toBe("\\d+(?!%)"); expect(/(?<=\$)\d+/.source).toBe("(?<=\\$)\\d+"); expect(/(?