diff --git a/Meta/import-v8-regexp-tests.py b/Meta/import-v8-regexp-tests.py new file mode 100644 index 00000000000..f01f16ba1c2 --- /dev/null +++ b/Meta/import-v8-regexp-tests.py @@ -0,0 +1,310 @@ +#!/usr/bin/env python3 +"""Import V8 mjsunit regexp tests into Ladybird's test-js format. + +Usage: python3 Meta/import-v8-regexp-tests.py /path/to/v8 + +This script imports V8's regexp test files that don't depend on V8-specific +native builtins, wrapping them in Ladybird's test()/expect() harness format +with a compatibility shim for V8's assertion functions. +""" + +import os +import re +import shutil +import sys + +V8_COMPAT_SHIM = """\ +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} +""" + +DEST_DIR = "Tests/LibJS/Runtime/3rdparty/v8" + +# Files that use V8-specific native syntax (%Foo, --allow-natives-syntax) +# and cannot be imported as-is. +SKIP_PATTERNS = [ + r"allow-natives-syntax", + r"%[A-Z]", +] + +# Files to skip entirely (not importable at all). +SKIP_FILES = { + # Performance benchmarks, not correctness tests. + "ascii-regexp-subject.js", + "string-slices-regexp.js", + # Uses V8's non-standard /l (linear) flag in regex literals, which causes + # parse errors in other engines. + "regexp-14098.js", + "regexp-444637793.js", + # Uses regex literal syntax that triggers parse errors in our engine. + "regexp-unicode-sets.js", + # Multi-file dependency (lu-ui0..9 depend on testCodePointRange from lu-ui). + "harmony/regexp-property-lu-ui0.js", + "harmony/regexp-property-lu-ui1.js", + "harmony/regexp-property-lu-ui2.js", + "harmony/regexp-property-lu-ui3.js", + "harmony/regexp-property-lu-ui4.js", + "harmony/regexp-property-lu-ui5.js", + "harmony/regexp-property-lu-ui6.js", + "harmony/regexp-property-lu-ui7.js", + "harmony/regexp-property-lu-ui8.js", + "harmony/regexp-property-lu-ui9.js", +} + +# Tests that crash or hang -- use test.skip() so they don't block the suite. +SKIP_TESTS = { + # Hangs: catastrophic backtracking tests that rely on V8-specific + # optimizations to terminate in reasonable time. + "regexp-capture-3", + # Crashes (SIGSEGV). + "regexp-capture", +} + +# Tests that fail but should be tracked -- use test.xfail() so we notice +# when they start passing. +XFAIL_TESTS = { + "es6/regexp-constructor", + "es6/regexp-tostring", + "es6/unicode-escapes-in-regexps", + "es6/unicode-regexp-backrefs", + "es6/unicode-regexp-ignore-case-noi18n", + "es6/unicode-regexp-restricted-syntax", + "es6/unicode-regexp-zero-length", + "regexp-duplicate-named-groups", + "regexp-lookahead", + "regexp-multiline", + "regexp-sort", + "regexp-UC16", + "harmony/regexp-property-binary", + "harmony/regexp-property-char-class", + "harmony/regexp-property-enumerated", + "harmony/regexp-property-exact-match", + "harmony/regexp-property-general-category", + "harmony/regexp-property-invalid", + "harmony/regexp-property-special", +} + + +def should_skip(content): + for pattern in SKIP_PATTERNS: + if re.search(pattern, content): + return True + return False + + +def file_key(subdir, filename): + """Get the key used in SKIP_FILES.""" + if subdir: + return f"{subdir}/{filename}" + return filename + + +def test_name(subdir, filename): + """Get the test name (no .js extension).""" + name = filename.replace(".js", "") + if subdir: + return f"{subdir}/{name}" + return name + + +def find_regexp_tests(v8_dir): + """Find all regexp-related test files in V8's mjsunit directory.""" + mjsunit = os.path.join(v8_dir, "test", "mjsunit") + files = [] + + # Top-level regexp files + for f in sorted(os.listdir(mjsunit)): + if f.endswith(".js") and "regexp" in f.lower(): + files.append(("", os.path.join(mjsunit, f))) + + # es6/ subdirectory + es6_dir = os.path.join(mjsunit, "es6") + if os.path.isdir(es6_dir): + for f in sorted(os.listdir(es6_dir)): + if f.endswith(".js") and ("regexp" in f.lower() or "unicode-regexp" in f.lower()): + files.append(("es6", os.path.join(es6_dir, f))) + + # harmony/ subdirectory + harmony_dir = os.path.join(mjsunit, "harmony") + if os.path.isdir(harmony_dir): + for f in sorted(os.listdir(harmony_dir)): + if f.endswith(".js") and "regexp" in f.lower(): + files.append(("harmony", os.path.join(harmony_dir, f))) + + return files + + +def extract_copyright_header(content): + """Extract the BSD copyright header from the file.""" + lines = content.split("\n") + header_lines = [] + for line in lines: + if line.startswith("//"): + header_lines.append(line) + else: + break + return "\n".join(header_lines) + + +def extract_body(content): + """Extract the test body (everything after the copyright header and flags comment).""" + lines = content.split("\n") + body_start = 0 + for i, line in enumerate(lines): + if line.startswith("//"): + continue + if line.strip() == "": + body_start = i + 1 + continue + body_start = i + break + return "\n".join(lines[body_start:]) + + +def convert_file(subdir, src_path): + """Convert a V8 test file to Ladybird format.""" + with open(src_path) as f: + content = f.read() + + filename = os.path.basename(src_path) + + if file_key(subdir, filename) in SKIP_FILES: + return None, "skip-file" + + if should_skip(content): + return None, "v8-natives" + + name = test_name(subdir, filename) + header = extract_copyright_header(content) + body = extract_body(content) + + # Determine test wrapper + if name in SKIP_TESTS: + wrapper = "test.skip" + elif name in XFAIL_TESTS: + wrapper = "test.xfail" + else: + wrapper = "test" + + # Build the converted file + result = header + "\n\n" + result += V8_COMPAT_SHIM + "\n" + result += f'{wrapper}("{name}", () => {{\n' + + # Indent the body + for line in body.split("\n"): + if line.strip(): + result += " " + line + "\n" + else: + result += "\n" + + result += "});\n" + return result, wrapper + + +def main(): + if len(sys.argv) < 2: + print(f"Usage: {sys.argv[0]} /path/to/v8", file=sys.stderr) + sys.exit(1) + + v8_dir = sys.argv[1] + if not os.path.isdir(os.path.join(v8_dir, "test", "mjsunit")): + print(f"Error: {v8_dir}/test/mjsunit not found", file=sys.stderr) + sys.exit(1) + + # Clean destination + if os.path.exists(DEST_DIR): + shutil.rmtree(DEST_DIR) + + os.makedirs(DEST_DIR, exist_ok=True) + os.makedirs(os.path.join(DEST_DIR, "es6"), exist_ok=True) + os.makedirs(os.path.join(DEST_DIR, "harmony"), exist_ok=True) + + files = find_regexp_tests(v8_dir) + counts = {"test": 0, "test.skip": 0, "test.xfail": 0, "skipped": 0} + + for subdir, src_path in files: + converted, status = convert_file(subdir, src_path) + filename = os.path.basename(src_path) + key = file_key(subdir, filename) + + if converted is None: + counts["skipped"] += 1 + print(f" SKIP ({status}): {key}") + continue + + if subdir: + dest_path = os.path.join(DEST_DIR, subdir, filename) + else: + dest_path = os.path.join(DEST_DIR, filename) + + with open(dest_path, "w") as f: + f.write(converted) + + counts[status] += 1 + tag = "" if status == "test" else f" [{status}]" + rel = os.path.relpath(dest_path) + print(f" OK: {rel}{tag}") + + print( + f"\nImported: {counts['test']} pass, {counts['test.xfail']} xfail, " + f"{counts['test.skip']} skip, {counts['skipped']} not imported" + ) + + +if __name__ == "__main__": + main() diff --git a/Meta/import-webkit-regexp-tests.py b/Meta/import-webkit-regexp-tests.py new file mode 100644 index 00000000000..80d21136cf0 --- /dev/null +++ b/Meta/import-webkit-regexp-tests.py @@ -0,0 +1,220 @@ +#!/usr/bin/env python3 +"""Import WebKit LayoutTests regex tests into Ladybird's test-js format. + +Usage: python3 Meta/import-webkit-regexp-tests.py /path/to/WebKit + +This script imports WebKit's LayoutTests/fast/regex/ test files, wrapping +them in Ladybird's test()/expect() harness format with a compatibility +shim for WebKit's shouldBe/shouldBeTrue/etc assertion functions. +""" + +import os +import shutil +import sys + +WEBKIT_COMPAT_SHIM = """\ +// WebKit assertion compatibility shim for Ladybird's test-js harness + +function description(msg) { + // No-op, just used for test documentation in WebKit. +} + +function shouldBe(actual_code, expected_code) { + let actual = eval(actual_code); + let expected = eval(expected_code); + if (typeof actual === "string" && typeof expected === "string") { + expect(actual).toBe(expected); + } else if (Array.isArray(actual) && Array.isArray(expected)) { + expect(actual).toEqual(expected); + } else if ( + actual !== null && + typeof actual === "object" && + expected !== null && + typeof expected === "object" + ) { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function shouldBeTrue(code) { + expect(eval(code)).toBeTrue(); +} + +function shouldBeFalse(code) { + expect(eval(code)).toBeFalse(); +} + +function shouldBeNull(code) { + expect(eval(code)).toBeNull(); +} + +function shouldBeUndefined(code) { + expect(eval(code)).toBeUndefined(); +} + +function shouldThrow(code, expected_error) { + expect(() => eval(code)).toThrow(); +} + +function shouldNotThrow(code) { + eval(code); +} +""" + +SRC_DIR = "LayoutTests/fast/regex/script-tests" +DEST_DIR = "Tests/LibJS/Runtime/3rdparty/webkit" + +# Files to skip entirely. +SKIP_FILES = { + "TEMPLATE.html", +} + +# Tests that crash or hang -- use test.skip(). +SKIP_TESTS = { + # Crashes (SIGSEGV). + "pcre-test-1", +} + +# Tests that fail -- use test.xfail(). +XFAIL_TESTS = { + "backreferences", + "dotstar", + "malformed-escapes", + "non-pattern-characters", + "overflow", + "quantified-assertions", + "repeat-match-waldemar", + "slow", +} + + +def find_tests(webkit_dir): + """Find all regex test JS files in WebKit's LayoutTests.""" + src = os.path.join(webkit_dir, SRC_DIR) + files = [] + for f in sorted(os.listdir(src)): + if f.endswith(".js") and f not in SKIP_FILES: + files.append(os.path.join(src, f)) + return files + + +def extract_copyright_header(content): + """Extract any copyright/license header.""" + lines = content.split("\n") + header_lines = [] + for line in lines: + if line.startswith("//"): + header_lines.append(line) + elif line.strip() == "": + if header_lines: + header_lines.append(line) + else: + break + # Remove trailing empty lines + while header_lines and header_lines[-1].strip() == "": + header_lines.pop() + return "\n".join(header_lines) + + +def extract_body(content): + """Extract the test body after any header.""" + lines = content.split("\n") + body_start = 0 + in_header = True + for i, line in enumerate(lines): + if in_header: + if line.startswith("//") or line.strip() == "": + continue + else: + in_header = False + body_start = i + break + return "\n".join(lines[body_start:]) + + +def convert_file(src_path): + """Convert a WebKit test file to Ladybird format.""" + with open(src_path) as f: + content = f.read() + + filename = os.path.basename(src_path) + name = filename.replace(".js", "") + + header = extract_copyright_header(content) + body = extract_body(content) + + # Determine test wrapper + if name in SKIP_TESTS: + wrapper = "test.skip" + elif name in XFAIL_TESTS: + wrapper = "test.xfail" + else: + wrapper = "test" + + # Build the converted file. + # The shim MUST be inside the test() callback so that eval() in + # shouldBe/shouldBeTrue can access variables defined in the test body. + result = "" + if header: + result += header + "\n\n" + result += f'{wrapper}("{name}", () => {{\n' + + # Indent and insert shim + body inside the test callback + for line in WEBKIT_COMPAT_SHIM.split("\n"): + if line.strip(): + result += " " + line + "\n" + else: + result += "\n" + + result += "\n" + + for line in body.split("\n"): + if line.strip(): + result += " " + line + "\n" + else: + result += "\n" + + result += "});\n" + return result, wrapper + + +def main(): + if len(sys.argv) < 2: + print(f"Usage: {sys.argv[0]} /path/to/WebKit", file=sys.stderr) + sys.exit(1) + + webkit_dir = sys.argv[1] + src = os.path.join(webkit_dir, SRC_DIR) + if not os.path.isdir(src): + print(f"Error: {src} not found", file=sys.stderr) + sys.exit(1) + + # Clean destination + if os.path.exists(DEST_DIR): + shutil.rmtree(DEST_DIR) + + os.makedirs(DEST_DIR, exist_ok=True) + + files = find_tests(webkit_dir) + counts = {"test": 0, "test.skip": 0, "test.xfail": 0} + + for src_path in files: + converted, status = convert_file(src_path) + filename = os.path.basename(src_path) + dest_path = os.path.join(DEST_DIR, filename) + + with open(dest_path, "w") as f: + f.write(converted) + + counts[status] += 1 + tag = "" if status == "test" else f" [{status}]" + rel = os.path.relpath(dest_path) + print(f" OK: {rel}{tag}") + + print(f"\nImported: {counts['test']} pass, {counts['test.xfail']} xfail, {counts['test.skip']} skip") + + +if __name__ == "__main__": + main() diff --git a/Tests/LibJS/Runtime/3rdparty/v8/es6/array-concat-spreadable-regexp.js b/Tests/LibJS/Runtime/3rdparty/v8/es6/array-concat-spreadable-regexp.js new file mode 100644 index 00000000000..39688bcd920 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/es6/array-concat-spreadable-regexp.js @@ -0,0 +1,92 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("es6/array-concat-spreadable-regexp", () => { + "use strict"; + var re = /abc/; + // RegExps are not concat-spreadable by default + assertEquals([re], [].concat(re)); + + // RegExps may be individually concat-spreadable + re[Symbol.isConcatSpreadable] = true; + ((re[0] = 1), (re[1] = 2), (re[2] = 3), (re.length = 3)); + assertEquals([1, 2, 3], [].concat(re)); + + // RegExps may be concat-spreadable + RegExp.prototype[Symbol.isConcatSpreadable] = true; + RegExp.prototype.length = 3; + + assertEquals(new Array(3), [].concat(/abc/)); + RegExp.prototype[0] = 1; + RegExp.prototype[1] = 2; + RegExp.prototype[2] = 3; + assertEquals([1, 2, 3], [].concat(/abc/)); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/es6/regexp-constructor.js b/Tests/LibJS/Runtime/3rdparty/v8/es6/regexp-constructor.js new file mode 100644 index 00000000000..c588cb74ed2 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/es6/regexp-constructor.js @@ -0,0 +1,204 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test.xfail("es6/regexp-constructor", () => { + "use strict"; + + function should_not_be_called() { + throw new Error("should not be called"); + } + + (function () { + var r = new RegExp("biep"); + assertTrue(r === RegExp(r)); + assertFalse(r === new RegExp(r)); + r[Symbol.match] = false; + Object.defineProperty(r, "source", { get: should_not_be_called }); + Object.defineProperty(r, "flags", { get: should_not_be_called }); + assertFalse(r === RegExp(r)); + })(); + + (function () { + let allow = false; + class A extends RegExp { + get source() { + if (!allow) throw new Error("should not be called"); + return super.source; + } + get flags() { + if (!allow) throw new Error("should not be called"); + return super.flags; + } + } + + var r = new A("biep"); + var r2 = RegExp(r); + + assertFalse(r === r2); + allow = true; + assertEquals(r, r2); + allow = false; + assertTrue(A.prototype === r.__proto__); + assertTrue(RegExp.prototype === r2.__proto__); + + var r3 = RegExp(r); + assertFalse(r3 === r); + allow = true; + assertEquals(r3, r); + allow = false; + + var r4 = new A(r2); + assertFalse(r4 === r2); + allow = true; + assertEquals(r4, r2); + allow = false; + assertTrue(A.prototype === r4.__proto__); + + r[Symbol.match] = false; + var r5 = new A(r); + assertFalse(r5 === r); + allow = true; + assertEquals(r5, r); + allow = false; + assertTrue(A.prototype === r5.__proto__); + })(); + + (function () { + var log = []; + var match = { + get source() { + log.push("source"); + return "biep"; + }, + get flags() { + log.push("flags"); + return "i"; + }, + }; + Object.defineProperty(match, Symbol.match, { + get() { + log.push("match"); + return true; + }, + }); + var r = RegExp(match); + assertEquals(["match", "source", "flags"], log); + assertFalse(r === match); + assertEquals(/biep/i, r); + })(); + + (function () { + var log = []; + var match = { + get source() { + log.push("source"); + return "biep"; + }, + get flags() { + log.push("flags"); + return "i"; + }, + }; + Object.defineProperty(match, Symbol.match, { + get() { + log.push("match"); + return true; + }, + }); + match.constructor = RegExp; + var r = RegExp(match); + assertEquals(["match"], log); + assertTrue(r === match); + })(); + + (function () { + var r = RegExp("biep", "i"); + r[Symbol.match] = false; + var r2 = RegExp(r, "g"); + assertFalse(r === r2); + assertEquals(/biep/i, r); + assertEquals(/biep/g, r2); + })(); + + (function () { + class A extends RegExp { + get ["constructor"]() { + log.push("constructor"); + return RegExp; + } + } + var r = new A("biep"); + var log = []; + var r2 = RegExp(r); + assertEquals(["constructor"], log); + assertTrue(r === r2); + })(); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/es6/regexp-flags.js b/Tests/LibJS/Runtime/3rdparty/v8/es6/regexp-flags.js new file mode 100644 index 00000000000..d143871b496 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/es6/regexp-flags.js @@ -0,0 +1,219 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("es6/regexp-flags", () => { + var r1 = /abc/gi; + assertEquals("abc", r1.source); + assertTrue(r1.global); + assertTrue(r1.ignoreCase); + assertFalse(r1.multiline); + assertFalse(r1.sticky); + assertFalse(r1.unicode); + + // Internal slot of prototype is not read. + var r2 = { __proto__: r1 }; + assertThrows(function () { + r2.source; + }, TypeError); + assertThrows(function () { + r2.global; + }, TypeError); + assertThrows(function () { + r2.ignoreCase; + }, TypeError); + assertThrows(function () { + r2.multiline; + }, TypeError); + assertThrows(function () { + r2.sticky; + }, TypeError); + assertThrows(function () { + r2.unicode; + }, TypeError); + + var r3 = /I/; + var string = "iIiIi"; + var expected = "iXiIi"; + assertFalse(r3.global); + assertFalse(r3.ignoreCase); + assertEquals("", r3.flags); + assertEquals(expected, string.replace(r3, "X")); + + var get_count = 0; + Object.defineProperty(r3, "global", { + get: function () { + get_count++; + return true; + }, + }); + Object.defineProperty(r3, "ignoreCase", { + get: function () { + get_count++; + return true; + }, + }); + + assertTrue(r3.global); + assertEquals(1, get_count); + assertTrue(r3.ignoreCase); + assertEquals(2, get_count); + // Overridden flag getters affects the flags getter. + assertEquals("gi", r3.flags); + assertEquals(4, get_count); + // Overridden flag getters affect string.replace + // TODO(adamk): Add more tests here once we've switched + // to use [[OriginalFlags]] in more cases. + // TODO(jgruber): This exact case actually causes an infinite loop in the spec + // (@@replace sees global = true while BuiltinExec sees global = false). + // Comment the test for now and remove / fix once this has been resolved on + // the spec side. + //assertEquals(expected, string.replace(r3, "X")); + //assertEquals(5, get_count); + + function testName(name) { + // Test for ES2017 RegExp web compatibility semantics + // https://github.com/tc39/ecma262/pull/511 + assertEquals(name === "source" ? "(?:)" : undefined, RegExp.prototype[name]); + assertEquals("get " + name, Object.getOwnPropertyDescriptor(RegExp.prototype, name).get.name); + } + + testName("global"); + testName("ignoreCase"); + testName("multiline"); + testName("source"); + testName("sticky"); + testName("unicode"); + + RegExp.prototype.flags = "setter should be undefined"; + + assertEquals("", RegExp("").flags); + assertEquals("", /./.flags); + assertEquals("gimuy", RegExp("", "yugmi").flags); + assertEquals("gimuy", /foo/gimuy.flags); + + var descriptor = Object.getOwnPropertyDescriptor(RegExp.prototype, "flags"); + assertTrue(descriptor.configurable); + assertFalse(descriptor.enumerable); + assertInstanceof(descriptor.get, Function); + assertEquals(undefined, descriptor.set); + + function testGenericFlags(object) { + return descriptor.get.call(object); + } + + assertEquals("", testGenericFlags({})); + assertEquals("i", testGenericFlags({ ignoreCase: true })); + assertEquals("uy", testGenericFlags({ global: 0, sticky: 1, unicode: 1 })); + assertEquals("m", testGenericFlags({ __proto__: { multiline: true } })); + assertThrows(function () { + testGenericFlags(); + }, TypeError); + assertThrows(function () { + testGenericFlags(undefined); + }, TypeError); + assertThrows(function () { + testGenericFlags(null); + }, TypeError); + assertThrows(function () { + testGenericFlags(true); + }, TypeError); + assertThrows(function () { + testGenericFlags(false); + }, TypeError); + assertThrows(function () { + testGenericFlags(""); + }, TypeError); + assertThrows(function () { + testGenericFlags(42); + }, TypeError); + + var counter = 0; + var map = {}; + var object = { + get global() { + map.g = counter++; + }, + get ignoreCase() { + map.i = counter++; + }, + get multiline() { + map.m = counter++; + }, + get unicode() { + map.u = counter++; + }, + get sticky() { + map.y = counter++; + }, + }; + testGenericFlags(object); + assertEquals({ g: 0, i: 1, m: 2, u: 3, y: 4 }, map); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/es6/regexp-match-lastindex.js b/Tests/LibJS/Runtime/3rdparty/v8/es6/regexp-match-lastindex.js new file mode 100644 index 00000000000..3fe08ce9675 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/es6/regexp-match-lastindex.js @@ -0,0 +1,81 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("es6/regexp-match-lastindex", () => { + var global = /./g; + global.lastIndex = { + valueOf: function () { + assertUnreachable(); + }, + }; + "x".match(global); + assertEquals(0, global.lastIndex); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/es6/regexp-prototype.js b/Tests/LibJS/Runtime/3rdparty/v8/es6/regexp-prototype.js new file mode 100644 index 00000000000..f7b49ef014e --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/es6/regexp-prototype.js @@ -0,0 +1,85 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("es6/regexp-prototype", () => { + var proto_desc = Object.getOwnPropertyDescriptor(RegExp, "prototype"); + assertFalse(proto_desc.writable); + assertFalse(proto_desc.enumerable); + assertFalse(proto_desc.configurable); + + // ES6 21.2.5.1 + var proto = proto_desc.value; + assertFalse(proto instanceof RegExp); + assertEquals(undefined, Object.getOwnPropertyDescriptor(proto, "valueOf")); + assertEquals(proto.valueOf, Object.prototype.valueOf); + var proto_constr = Object.getOwnPropertyDescriptor(proto, "constructor"); + assertEquals(RegExp, proto_constr.value); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/es6/regexp-replace-lastindex.js b/Tests/LibJS/Runtime/3rdparty/v8/es6/regexp-replace-lastindex.js new file mode 100644 index 00000000000..df0b20933b9 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/es6/regexp-replace-lastindex.js @@ -0,0 +1,86 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("es6/regexp-replace-lastindex", () => { + var global = /./g; + global.lastIndex = { + valueOf: function () { + assertUnreachable(); + }, + }; + assertEquals( + "X", + "x".replace(global, function (a) { + return "X"; + }) + ); + assertEquals(0, global.lastIndex); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/es6/regexp-sticky.js b/Tests/LibJS/Runtime/3rdparty/v8/es6/regexp-sticky.js new file mode 100644 index 00000000000..ab4a03258fd --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/es6/regexp-sticky.js @@ -0,0 +1,208 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("es6/regexp-sticky", () => { + var re = /foo.bar/; + + assertTrue(!!"foo*bar".match(re)); + assertTrue(!!"..foo*bar".match(re)); + + var plain = /foobar/; + + assertTrue(!!"foobar".match(plain)); + assertTrue(!!"..foobar".match(plain)); + + var sticky = /foo.bar/y; + + assertTrue(!!"foo*bar".match(sticky)); + assertEquals(7, sticky.lastIndex); + assertFalse(!!"..foo*bar".match(sticky)); + + var stickyplain = /foobar/y; + + assertTrue(!!"foobarfoobar".match(stickyplain)); + assertEquals(6, stickyplain.lastIndex); + assertTrue(!!"foobarfoobar".match(stickyplain)); + assertEquals(12, stickyplain.lastIndex); + assertFalse(!!"..foobarfoobar".match(stickyplain)); + + var global = /foo.bar/g; + + assertTrue(global.test("foo*bar")); + assertFalse(global.test("..foo*bar")); + global.lastIndex = 0; + assertTrue(global.test("..foo*bar")); + + var plainglobal = /foobar/g; + + assertTrue(plainglobal.test("foobar")); + assertFalse(plainglobal.test("foobar")); + plainglobal.lastIndex = 0; + assertTrue(plainglobal.test("foobar")); + + var stickyglobal = /foo.bar/gy; + + assertTrue(stickyglobal.test("foo*bar")); + assertEquals(7, stickyglobal.lastIndex); + assertFalse(stickyglobal.test("..foo*bar")); + stickyglobal.lastIndex = 0; + assertFalse(stickyglobal.test("..foo*bar")); + stickyglobal.lastIndex = 2; + assertTrue(stickyglobal.test("..foo*bar")); + assertEquals(9, stickyglobal.lastIndex); + + var stickyplainglobal = /foobar/gy; + assertTrue(stickyplainglobal.sticky); + stickyplainglobal.sticky = false; + + assertTrue(stickyplainglobal.test("foobar")); + assertEquals(6, stickyplainglobal.lastIndex); + assertFalse(stickyplainglobal.test("..foobar")); + stickyplainglobal.lastIndex = 0; + assertFalse(stickyplainglobal.test("..foobar")); + stickyplainglobal.lastIndex = 2; + assertTrue(stickyplainglobal.test("..foobar")); + assertEquals(8, stickyplainglobal.lastIndex); + + assertEquals("/foo.bar/gy", "" + stickyglobal); + assertEquals("/foo.bar/g", "" + global); + + assertTrue(stickyglobal.sticky); + stickyglobal.sticky = false; + assertTrue(stickyglobal.sticky); + + var stickyglobal2 = new RegExp("foo.bar", "gy"); + assertTrue(stickyglobal2.test("foo*bar")); + assertEquals(7, stickyglobal2.lastIndex); + assertFalse(stickyglobal2.test("..foo*bar")); + stickyglobal2.lastIndex = 0; + assertFalse(stickyglobal2.test("..foo*bar")); + stickyglobal2.lastIndex = 2; + assertTrue(stickyglobal2.test("..foo*bar")); + assertEquals(9, stickyglobal2.lastIndex); + + assertEquals("/foo.bar/gy", "" + stickyglobal2); + + assertTrue(stickyglobal2.sticky); + stickyglobal2.sticky = false; + assertTrue(stickyglobal2.sticky); + + sticky.lastIndex = -1; // Causes sticky regexp to fail fast + assertFalse(sticky.test("..foo.bar")); + assertEquals(0, sticky.lastIndex); + + sticky.lastIndex = -1; // Causes sticky regexp to fail fast + assertFalse(!!sticky.exec("..foo.bar")); + assertEquals(0, sticky.lastIndex); + + // ES6 draft says: Even when the y flag is used with a pattern, ^ always + // matches only at the beginning of Input, or (if Multiline is true) at the + // beginning of a line. + var hat = /^foo/y; + hat.lastIndex = 2; + assertFalse(hat.test("..foo")); + + var mhat = /^foo/my; + mhat.lastIndex = 2; + assertFalse(mhat.test("..foo")); + mhat.lastIndex = 2; + assertTrue(mhat.test(".\nfoo")); + + // Check that we don't apply incorrect optimization to sticky regexps that + // are anchored at end. + var stickyanchored = /bar$/y; + assertFalse(stickyanchored.test("foobar")); + stickyanchored.lastIndex = 3; + assertTrue(stickyanchored.test("foobar")); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/es6/regexp-tolength.js b/Tests/LibJS/Runtime/3rdparty/v8/es6/regexp-tolength.js new file mode 100644 index 00000000000..1d53754f943 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/es6/regexp-tolength.js @@ -0,0 +1,86 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("es6/regexp-tolength", () => { + "use strict"; + + let regexp = /x/g; + + regexp.lastIndex = -1; + + assertTrue(regexp.test("axb")); + assertEquals(2, regexp.lastIndex); + + regexp.lastIndex = -1; + + assertEquals("x", regexp.exec("axb")[0]); + assertEquals(2, regexp.lastIndex); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/es6/regexp-tostring.js b/Tests/LibJS/Runtime/3rdparty/v8/es6/regexp-tostring.js new file mode 100644 index 00000000000..19fb6bf73d8 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/es6/regexp-tostring.js @@ -0,0 +1,125 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test.xfail("es6/regexp-tostring", () => { + var log = []; + + var fake = { + get source() { + log.push("p"); + return { + toString: function () { + log.push("ps"); + return "pattern"; + }, + }; + }, + get flags() { + log.push("f"); + return { + toString: function () { + log.push("fs"); + return "flags"; + }, + }; + }, + }; + + function testThrows(x) { + try { + RegExp.prototype.toString.call(x); + } catch (e) { + assertTrue(/incompatible receiver/.test(e.message)); + return; + } + assertUnreachable(); + } + + testThrows(1); + testThrows(null); + Number.prototype.source = "a"; + Number.prototype.flags = "b"; + testThrows(1); + + assertEquals("/pattern/flags", RegExp.prototype.toString.call(fake)); + assertEquals(["p", "ps", "f", "fs"], log); + + // Monkey-patching is also possible on RegExp instances + + let weird = /foo/; + Object.defineProperty(weird, "flags", { value: "bar" }); + Object.defineProperty(weird, "source", { value: "baz" }); + assertEquals("/baz/bar", weird.toString()); + + assertEquals("/(?:)/", RegExp.prototype.toString()); + assertEquals("(?:)", RegExp.prototype.source); + assertEquals("", RegExp.prototype.flags); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/es6/unicode-escapes-in-regexps.js b/Tests/LibJS/Runtime/3rdparty/v8/es6/unicode-escapes-in-regexps.js new file mode 100644 index 00000000000..d048376c8df --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/es6/unicode-escapes-in-regexps.js @@ -0,0 +1,335 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test.xfail("es6/unicode-escapes-in-regexps", () => { + function testRegexpHelper(r) { + assertTrue(r.test("foo")); + assertTrue(r.test("boo")); + assertFalse(r.test("moo")); + } + + (function TestUnicodeEscapes() { + testRegexpHelper(/(\u0066|\u0062)oo/); + testRegexpHelper(/(\u0066|\u0062)oo/u); + testRegexpHelper(/(\u{0066}|\u{0062})oo/u); + testRegexpHelper(/(\u{66}|\u{000062})oo/u); + + // Note that we need \\ inside a string, otherwise it's interpreted as a + // unicode escape inside a string. + testRegexpHelper(new RegExp("(\\u0066|\\u0062)oo")); + testRegexpHelper(new RegExp("(\\u0066|\\u0062)oo", "u")); + testRegexpHelper(new RegExp("(\\u{0066}|\\u{0062})oo", "u")); + testRegexpHelper(new RegExp("(\\u{66}|\\u{000062})oo", "u")); + + // Though, unicode escapes via strings should work too. + testRegexpHelper(new RegExp("(\u0066|\u0062)oo")); + testRegexpHelper(new RegExp("(\u0066|\u0062)oo", "u")); + testRegexpHelper(new RegExp("(\u{0066}|\u{0062})oo", "u")); + testRegexpHelper(new RegExp("(\u{66}|\u{000062})oo", "u")); + })(); + + (function TestUnicodeEscapesInCharacterClasses() { + testRegexpHelper(/[\u0062-\u0066]oo/); + testRegexpHelper(/[\u0062-\u0066]oo/u); + testRegexpHelper(/[\u{0062}-\u{0066}]oo/u); + testRegexpHelper(/[\u{62}-\u{00000066}]oo/u); + + // Note that we need \\ inside a string, otherwise it's interpreted as a + // unicode escape inside a string. + testRegexpHelper(new RegExp("[\\u0062-\\u0066]oo")); + testRegexpHelper(new RegExp("[\\u0062-\\u0066]oo", "u")); + testRegexpHelper(new RegExp("[\\u{0062}-\\u{0066}]oo", "u")); + testRegexpHelper(new RegExp("[\\u{62}-\\u{00000066}]oo", "u")); + + // Though, unicode escapes via strings should work too. + testRegexpHelper(new RegExp("[\u0062-\u0066]oo")); + testRegexpHelper(new RegExp("[\u0062-\u0066]oo", "u")); + testRegexpHelper(new RegExp("[\u{0062}-\u{0066}]oo", "u")); + testRegexpHelper(new RegExp("[\u{62}-\u{00000066}]oo", "u")); + })(); + + (function TestBraceEscapesWithoutUnicodeFlag() { + // \u followed by illegal escape will be parsed as u. {x} will be the + // character count. + function helper1(r) { + assertFalse(r.test("fbar")); + assertFalse(r.test("fubar")); + assertTrue(r.test("fuubar")); + assertFalse(r.test("fuuubar")); + } + helper1(/f\u{2}bar/); + helper1(new RegExp("f\\u{2}bar")); + + function helper2(r) { + assertFalse(r.test("fbar")); + assertTrue(r.test("fubar")); + assertTrue(r.test("fuubar")); + assertFalse(r.test("fuuubar")); + } + + helper2(/f\u{1,2}bar/); + helper2(new RegExp("f\\u{1,2}bar")); + + function helper3(r) { + assertTrue(r.test("u")); + assertTrue(r.test("{")); + assertTrue(r.test("2")); + assertTrue(r.test("}")); + assertFalse(r.test("q")); + assertFalse(r.test("(")); + assertFalse(r.test(")")); + } + helper3(/[\u{2}]/); + helper3(new RegExp("[\\u{2}]")); + })(); + + (function TestInvalidEscapes() { + // Without the u flag, invalid unicode escapes and other invalid escapes are + // treated as identity escapes. + function helper1(r) { + assertTrue(r.test("firstuxz89second")); + } + helper1(/first\u\x\z\8\9second/); + helper1(new RegExp("first\\u\\x\\z\\8\\9second")); + + function helper2(r) { + assertTrue(r.test("u")); + assertTrue(r.test("x")); + assertTrue(r.test("z")); + assertTrue(r.test("8")); + assertTrue(r.test("9")); + assertFalse(r.test("q")); + assertFalse(r.test("7")); + } + helper2(/[\u\x\z\8\9]/); + helper2(new RegExp("[\\u\\x\\z\\8\\9]")); + + // However, with the u flag, these are treated as invalid escapes. + assertThrows("/\\u/u", SyntaxError); + assertThrows("/\\u12/u", SyntaxError); + assertThrows("/\\ufoo/u", SyntaxError); + assertThrows("/\\x/u", SyntaxError); + assertThrows("/\\xfoo/u", SyntaxError); + assertThrows("/\\z/u", SyntaxError); + assertThrows("/\\8/u", SyntaxError); + assertThrows("/\\9/u", SyntaxError); + + assertThrows("new RegExp('\\\\u', 'u')", SyntaxError); + assertThrows("new RegExp('\\\\u12', 'u')", SyntaxError); + assertThrows("new RegExp('\\\\ufoo', 'u')", SyntaxError); + assertThrows("new RegExp('\\\\x', 'u')", SyntaxError); + assertThrows("new RegExp('\\\\xfoo', 'u')", SyntaxError); + assertThrows("new RegExp('\\\\z', 'u')", SyntaxError); + assertThrows("new RegExp('\\\\8', 'u')", SyntaxError); + assertThrows("new RegExp('\\\\9', 'u')", SyntaxError); + })(); + + (function TestTooBigHexEscape() { + // The hex number inside \u{} has a maximum value. + /\u{10ffff}/u; + new RegExp("\\u{10ffff}", "u"); + assertThrows("/\\u{110000}/u", SyntaxError); + assertThrows("new RegExp('\\\\u{110000}', 'u')", SyntaxError); + + // Without the u flag, they're of course fine ({x} is the count). + /\u{110000}/; + new RegExp("\\u{110000}"); + })(); + + (function TestSyntaxEscapes() { + // Syntax escapes work the same with or without the u flag. + function helper(r) { + assertTrue(r.test("foo[bar")); + assertFalse(r.test("foo]bar")); + } + helper(/foo\[bar/); + helper(new RegExp("foo\\[bar")); + helper(/foo\[bar/u); + helper(new RegExp("foo\\[bar", "u")); + })(); + + (function TestUnicodeSurrogates() { + // U+10E6D corresponds to the surrogate pair [U+D803, U+DE6D]. + function helper(r) { + assertTrue(r.test("foo\u{10e6d}bar")); + } + helper(/foo\ud803\ude6dbar/u); + helper(new RegExp("foo\\ud803\\ude6dbar", "u")); + })(); + + (function AllFlags() { + // Test that we can pass all possible regexp flags and they work properly. + function helper1(r) { + assertTrue(r.global); + assertTrue(r.ignoreCase); + assertTrue(r.multiline); + assertTrue(r.sticky); + assertTrue(r.unicode); + } + + helper1(/foo/gimuy); + helper1(new RegExp("foo", "gimyu")); + + function helper2(r) { + assertFalse(r.global); + assertFalse(r.ignoreCase); + assertFalse(r.multiline); + assertFalse(r.sticky); + assertFalse(r.unicode); + } + + helper2(/foo/); + helper2(new RegExp("foo")); + })(); + + (function DuplicatedFlags() { + // Test that duplicating the u flag is not allowed. + assertThrows("/foo/ugu"); + assertThrows("new RegExp('foo', 'ugu')"); + })(); + + (function ToString() { + // Test that the u flag is included in the string representation of regexps. + function helper(r) { + assertEquals(r.toString(), "/foo/u"); + } + helper(/foo/u); + helper(new RegExp("foo", "u")); + })(); + + // Non-BMP patterns. + // Single character atom. + assertTrue(new RegExp("\u{12345}", "u").test("\u{12345}")); + assertTrue(/\u{12345}/u.test("\u{12345}")); + assertTrue(new RegExp("\u{12345}", "u").test("\ud808\udf45")); + assertTrue(/\u{12345}/u.test("\ud808\udf45")); + assertFalse(new RegExp("\u{12345}", "u").test("\udf45")); + assertFalse(/\u{12345}/u.test("\udf45")); + + // Multi-character atom. + assertTrue(new RegExp("\u{12345}\u{23456}", "u").test("a\u{12345}\u{23456}b")); + assertTrue(/\u{12345}\u{23456}/u.test("b\u{12345}\u{23456}c")); + assertFalse(new RegExp("\u{12345}\u{23456}", "u").test("a\udf45\u{23456}b")); + assertFalse(/\u{12345}\u{23456}/u.test("b\udf45\u{23456}c")); + + // Disjunction. + assertTrue(new RegExp("\u{12345}(?:\u{23456})", "u").test("a\u{12345}\u{23456}b")); + assertTrue(/\u{12345}(?:\u{23456})/u.test("b\u{12345}\u{23456}c")); + assertFalse(new RegExp("\u{12345}(?:\u{23456})", "u").test("a\udf45\u{23456}b")); + assertFalse(/\u{12345}(?:\u{23456})/u.test("b\udf45\u{23456}c")); + + // Alternative. + assertTrue(new RegExp("\u{12345}|\u{23456}", "u").test("a\u{12345}b")); + assertTrue(/\u{12345}|\u{23456}/u.test("b\u{23456}c")); + assertFalse(new RegExp("\u{12345}|\u{23456}", "u").test("a\udf45\ud84db")); + assertFalse(/\u{12345}|\u{23456}/u.test("b\udf45\ud808c")); + + // Capture. + assertTrue(new RegExp("(\u{12345}|\u{23456}).\\1", "u").test("\u{12345}b\u{12345}")); + assertTrue(/(\u{12345}|\u{23456}).\1/u.test("\u{12345}b\u{12345}")); + assertFalse(new RegExp("(\u{12345}|\u{23456}).\\1", "u").test("\u{12345}b\u{23456}")); + assertFalse(/(\u{12345}|\u{23456}).\1/u.test("\u{12345}b\u{23456}")); + + // Quantifier. + assertTrue(new RegExp("\u{12345}{3}", "u").test("\u{12345}\u{12345}\u{12345}")); + assertTrue(/\u{12345}{3}/u.test("\u{12345}\u{12345}\u{12345}")); + assertTrue(new RegExp("\u{12345}{3}").test("\u{12345}\udf45\udf45")); + assertFalse(/\ud808\udf45{3}/u.test("\u{12345}\udf45\udf45")); + assertTrue(/\ud808\udf45{3}/u.test("\u{12345}\u{12345}\u{12345}")); + assertFalse(new RegExp("\u{12345}{3}", "u").test("\u{12345}\udf45\udf45")); + assertFalse(/\u{12345}{3}/u.test("\u{12345}\udf45\udf45")); + + // Literal surrogates. + assertEquals(["\u{10000}\u{10000}"], new RegExp("\ud800\udc00+", "u").exec("\u{10000}\u{10000}")); + assertEquals(["\u{10000}\u{10000}"], new RegExp("\\ud800\\udc00+", "u").exec("\u{10000}\u{10000}")); + + assertEquals( + ["\u{10003}\u{50001}"], + new RegExp("[\\ud800\\udc03-\\ud900\\udc01\]+", "u").exec("\u{10003}\u{50001}") + ); + assertEquals(["\u{10003}\u{50001}"], new RegExp("[\ud800\udc03-\u{50001}\]+", "u").exec("\u{10003}\u{50001}")); + + // Unicode escape sequences to represent a non-BMP character cannot have + // mixed notation, and must follow the rules for RegExpUnicodeEscapeSequence. + assertThrows(() => new RegExp("[\\ud800\udc03-\ud900\\udc01\]+", "u")); + assertThrows(() => new RegExp("[\\ud800\udc03-\ud900\\udc01\]+", "u")); + assertNull(new RegExp("\\ud800\udc00+", "u").exec("\u{10000}\u{10000}")); + assertNull(new RegExp("\ud800\\udc00+", "u").exec("\u{10000}\u{10000}")); + + assertNull(new RegExp("[\\ud800\udc00]", "u").exec("\u{10000}")); + assertNull(new RegExp("[\\{ud800}\udc00]", "u").exec("\u{10000}")); + assertNull(new RegExp("[\ud800\\udc00]", "u").exec("\u{10000}")); + assertNull(new RegExp("[\ud800\\{udc00}]", "u").exec("\u{10000}")); + + assertNull(/\u{d800}\u{dc00}+/u.exec("\ud800\udc00\udc00")); + assertNull(/\ud800\u{dc00}+/u.exec("\ud800\udc00\udc00")); + assertNull(/\u{d800}\udc00+/u.exec("\ud800\udc00\udc00")); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/es6/unicode-regexp-backrefs.js b/Tests/LibJS/Runtime/3rdparty/v8/es6/unicode-regexp-backrefs.js new file mode 100644 index 00000000000..516829aeb65 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/es6/unicode-regexp-backrefs.js @@ -0,0 +1,115 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test.xfail("es6/unicode-regexp-backrefs", () => { + function replace(string) { + return string.replace(/L/g, "\ud800").replace(/l/g, "\ud801").replace(/T/g, "\udc00").replace(/\./g, "[^]"); + } + + function test(expectation, regexp_source, subject) { + if (expectation !== null) expectation = expectation.map(replace); + subject = replace(subject); + regexp_source = replace(regexp_source); + assertEquals(expectation, new RegExp(regexp_source, "u").exec(subject)); + } + + // Back reference does not end in the middle of a surrogate pair. + test(null, "(L)\\1", "LLT"); + test(["LLTLl", "L", "l"], "(L).*\\1(.)", "LLTLl"); + test(null, "(aL).*\\1", "aLaLT"); + test(["aLaLTaLl", "aL", "l"], "(aL).*\\1(.)", "aLaLTaLl"); + + var s = "TabcLxLTabcLxTabcLTyTabcLz"; + test([s, "TabcL", "z"], "([^x]+).*\\1(.)", s); + + // Back reference does not start in the middle of a surrogate pair. + test(["TLTabTc", "T", "c"], "(T).*\\1(.)", "TLTabTc"); + + // Lookbehinds. + test(null, "(?<=\\1(T)x)", "LTTx"); + test(["", "b", "T"], "(?<=(.)\\2.*(T)x)", "bTaLTTx"); + test(null, "(?<=\\1.*(L)x)", "LTLx"); + test(["", "b", "L"], "(?<=(.)\\2.*(L)x)", "bLaLTLx"); + + test(null, "([^x]+)x*\\1", "LxLT"); + test(null, "([^x]+)x*\\1", "TxLT"); + test(null, "([^x]+)x*\\1", "LTxL"); + test(null, "([^x]+)x*\\1", "LTxT"); + test(null, "([^x]+)x*\\1", "xLxLT"); + test(null, "([^x]+)x*\\1", "xTxLT"); + test(null, "([^x]+)x*\\1", "xLTxL"); + test(null, "([^x]+)x*\\1", "xLTxT"); + test(null, "([^x]+)x*\\1", "xxxLxxLTxx"); + test(null, "([^x]+)x*\\1", "xxxTxxLTxx"); + test(null, "([^x]+)x*\\1", "xxxLTxxLxx"); + test(null, "([^x]+)x*\\1", "xxxLTxxTxx"); + test(["LTTxxLTT", "LTT"], "([^x]+)x*\\1", "xxxLTTxxLTTxx"); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/es6/unicode-regexp-ignore-case-noi18n.js b/Tests/LibJS/Runtime/3rdparty/v8/es6/unicode-regexp-ignore-case-noi18n.js new file mode 100644 index 00000000000..f1bc82fe515 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/es6/unicode-regexp-ignore-case-noi18n.js @@ -0,0 +1,137 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test.xfail("es6/unicode-regexp-ignore-case-noi18n", () => { + assertTrue(/[a]/iu.test("\u{20a0}a")); + assertTrue(/[a]/iu.test("\u{20a0}A")); + assertTrue(/[A]/iu.test("\u{20a0}a")); + assertTrue(/[A]/iu.test("\u{20a0}A")); + + // Non-unicode use toUpperCase mappings. + assertFalse(/[\u00e5]/i.test("\u212b")); + assertFalse(/[\u212b]/i.test("\u00e5\u1234")); + assertFalse(/[\u212b]/i.test("\u00e5")); + + assertTrue("\u212b".toLowerCase() == "\u00e5"); + assertTrue("\u00c5".toLowerCase() == "\u00e5"); + assertTrue("\u00e5".toUpperCase() == "\u00c5"); + + // Unicode uses case folding mappings. + assertFalse(/\u00e5/iu.test("\u212b")); + assertTrue(/\u00e5/iu.test("\u00c5")); + assertTrue(/\u00e5/iu.test("\u00e5")); + assertFalse(/\u00e5/iu.test("\u212b")); + assertTrue(/\u00c5/iu.test("\u00e5")); + assertFalse(/\u00c5/iu.test("\u212b")); + assertTrue(/\u00c5/iu.test("\u00c5")); + assertFalse(/\u212b/iu.test("\u00c5")); + assertFalse(/\u212b/iu.test("\u00e5")); + assertTrue(/\u212b/iu.test("\u212b")); + + // Non-BMP. + assertFalse(/\u{10400}/i.test("\u{10428}")); + assertFalse(/\u{10400}/iu.test("\u{10428}")); + assertFalse(/\ud801\udc00/iu.test("\u{10428}")); + assertFalse(/[\u{10428}]/iu.test("\u{10400}")); + assertFalse(/[\ud801\udc28]/iu.test("\u{10400}")); + assertEquals(["\uff21\u{10400}"], /[\uff40-\u{10428}]+/iu.exec("\uff21\u{10400}abc")); + + // TODO(v8:10120): Investigate why these don't behave as expected. + { + // Should be: + // assertEquals(["abc"], /[^\uff40-\u{10428}]+/ui.exec("\uff21\u{10400}abc\uff23")); + // + // But is: + assertEquals(["\u{ff21}"], /[^\uff40-\u{10428}]+/iu.exec("\uff21\u{10400}abc\uff23")); + } + + assertEquals(["\uff53\u24bb"], /[\u24d5-\uff33]+/iu.exec("\uff54\uff53\u24bb\u24ba")); + + // Full mappings are ignored. + assertFalse(/\u00df/iu.test("SS")); + assertFalse(/\u1f8d/iu.test("\u1f05\u03b9")); + + // Simple mappings. + assertFalse(/\u1f8d/iu.test("\u1f85")); + + // Common mappings. + assertTrue(/\u1f6b/iu.test("\u1f63")); + + // Back references. + assertNull(/(.)\1\1/iu.exec("\u00e5\u212b\u00c5")); + assertNull(/(.)\1/iu.exec("\u{118aa}\u{118ca}")); + + // Non-Latin1 maps to Latin1. + assertNull(/^\u017F/iu.exec("s")); + assertNull(/^\u017F/iu.exec("s\u1234")); + assertNull(/^a[\u017F]/iu.exec("as")); + assertNull(/^a[\u017F]/iu.exec("as\u1234")); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/es6/unicode-regexp-ignore-case.js b/Tests/LibJS/Runtime/3rdparty/v8/es6/unicode-regexp-ignore-case.js new file mode 100644 index 00000000000..37efb2b6113 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/es6/unicode-regexp-ignore-case.js @@ -0,0 +1,135 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("es6/unicode-regexp-ignore-case", () => { + assertFalse(/[\u00e5]/i.test("\u212b")); + assertFalse(/[\u212b]/i.test("\u00e5\u1234")); + assertFalse(/[\u212b]/i.test("\u00e5")); + + assertTrue("\u212b".toLowerCase() == "\u00e5"); + assertTrue("\u00c5".toLowerCase() == "\u00e5"); + assertTrue("\u00e5".toUpperCase() == "\u00c5"); + + // Unicode uses case folding mappings. + assertTrue(/\u00e5/iu.test("\u212b")); + assertTrue(/\u00e5/iu.test("\u00c5")); + assertTrue(/\u00e5/iu.test("\u00e5")); + assertTrue(/\u00e5/iu.test("\u212b")); + assertTrue(/\u00c5/iu.test("\u00e5")); + assertTrue(/\u00c5/iu.test("\u212b")); + assertTrue(/\u00c5/iu.test("\u00c5")); + assertTrue(/\u212b/iu.test("\u00c5")); + assertTrue(/\u212b/iu.test("\u00e5")); + assertTrue(/\u212b/iu.test("\u212b")); + + // Non-BMP. + assertFalse(/\u{10400}/i.test("\u{10428}")); + assertTrue(/\u{10400}/iu.test("\u{10428}")); + assertTrue(/\ud801\udc00/iu.test("\u{10428}")); + assertTrue(/[\u{10428}]/iu.test("\u{10400}")); + assertTrue(/[\ud801\udc28]/iu.test("\u{10400}")); + assertEquals(["\uff21\u{10400}"], /[\uff40-\u{10428}]+/iu.exec("\uff21\u{10400}abc")); + assertEquals(["abc"], /[^\uff40-\u{10428}]+/iu.exec("\uff21\u{10400}abc\uff23")); + assertTrue(/\u{10c80}/iu.test("\u{10cc0}")); + assertTrue(/\u{10c80}/iv.test("\u{10cc0}")); + assertFalse(/\u{10c80}/u.test("\u{10cc0}")); + assertFalse(/\u{10c80}/v.test("\u{10cc0}")); + assertTrue(/\u{10cc0}/iu.test("\u{10c80}")); + assertTrue(/\u{10cc0}/iv.test("\u{10c80}")); + assertFalse(/\u{10cc0}/u.test("\u{10c80}")); + assertFalse(/\u{10cc0}/v.test("\u{10c80}")); + + assertEquals(["\uff53\u24bb"], /[\u24d5-\uff33]+/iu.exec("\uff54\uff53\u24bb\u24ba")); + + // Full mappings are ignored. + assertFalse(/\u00df/iu.test("SS")); + assertFalse(/\u1f8d/iu.test("\u1f05\u03b9")); + + // Simple mappings work. + assertTrue(/\u1f8d/iu.test("\u1f85")); + + // Common mappings work. + assertTrue(/\u1f6b/iu.test("\u1f63")); + + // Back references. + assertEquals(["\u00e5\u212b\u00c5", "\u00e5"], /(.)\1\1/iu.exec("\u00e5\u212b\u00c5")); + assertEquals(["\u{118aa}\u{118ca}", "\u{118aa}"], /(.)\1/iu.exec("\u{118aa}\u{118ca}")); + + // Misc. + assertTrue(/\u00e5\u00e5\u00e5/iu.test("\u212b\u00e5\u00c5")); + assertTrue(/AB\u{10400}/iu.test("ab\u{10428}")); + + // Non-Latin1 maps to Latin1. + assertEquals(["s"], /^\u017F/iu.exec("s")); + assertEquals(["s"], /^\u017F/iu.exec("s\u1234")); + assertEquals(["as"], /^a[\u017F]/iu.exec("as")); + assertEquals(["as"], /^a[\u017F]/iu.exec("as\u1234")); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/es6/unicode-regexp-last-index.js b/Tests/LibJS/Runtime/3rdparty/v8/es6/unicode-regexp-last-index.js new file mode 100644 index 00000000000..ab32a100b40 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/es6/unicode-regexp-last-index.js @@ -0,0 +1,168 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("es6/unicode-regexp-last-index", () => { + var r = /./gu; + assertEquals(["\ud800\udc00"], r.exec("\ud800\udc00\ud801\udc01")); + assertEquals(2, r.lastIndex); + r.lastIndex = 1; + assertEquals(["\ud800\udc00"], r.exec("\ud800\udc00\ud801\udc01")); + assertEquals(2, r.lastIndex); + assertEquals(["\ud801\udc01"], r.exec("\ud800\udc00\ud801\udc01")); + r.lastIndex = 3; + assertEquals(["\ud801\udc01"], r.exec("\ud800\udc00\ud801\udc01")); + assertEquals(4, r.lastIndex); + r.lastIndex = 4; + assertNull(r.exec("\ud800\udc00\ud801\udc01")); + assertEquals(0, r.lastIndex); + r.lastIndex = 5; + assertNull(r.exec("\ud800\udc00\ud801\udc01")); + assertEquals(0, r.lastIndex); + + r.lastIndex = 3; + assertEquals(["\ud802"], r.exec("\ud800\udc00\ud801\ud802")); + r.lastIndex = 4; + assertNull(r.exec("\ud800\udc00\ud801\ud802")); + + r = /./g; + assertEquals(["\ud800"], r.exec("\ud800\udc00\ud801\udc01")); + assertEquals(1, r.lastIndex); + assertEquals(["\udc00"], r.exec("\ud800\udc00\ud801\udc01")); + assertEquals(2, r.lastIndex); + assertEquals(["\ud801"], r.exec("\ud800\udc00\ud801\udc01")); + assertEquals(3, r.lastIndex); + assertEquals(["\udc01"], r.exec("\ud800\udc00\ud801\udc01")); + assertEquals(4, r.lastIndex); + assertNull(r.exec("\ud800\udc00\ud801\udc01")); + assertEquals(0, r.lastIndex); + r.lastIndex = 1; + assertEquals(["\udc00"], r.exec("\ud800\udc00\ud801\udc01")); + assertEquals(2, r.lastIndex); + + // ------------------------ + + r = /^./gu; + assertEquals(["\ud800\udc00"], r.exec("\ud800\udc00\ud801\udc01")); + assertEquals(2, r.lastIndex); + r.lastIndex = 1; + assertEquals(["\ud800\udc00"], r.exec("\ud800\udc00\ud801\udc01")); + assertEquals(2, r.lastIndex); + assertNull(r.exec("\ud800\udc00\ud801\udc01")); + assertEquals(0, r.lastIndex); + r.lastIndex = 3; + assertNull(r.exec("\ud800\udc00\ud801\udc01")); + assertEquals(0, r.lastIndex); + r.lastIndex = 4; + assertNull(r.exec("\ud800\udc00\ud801\udc01")); + assertEquals(0, r.lastIndex); + r.lastIndex = 5; + assertNull(r.exec("\ud800\udc00\ud801\udc01")); + assertEquals(0, r.lastIndex); + + r = /^./g; + assertEquals(["\ud800"], r.exec("\ud800\udc00\ud801\udc01")); + assertEquals(1, r.lastIndex); + assertNull(r.exec("\ud800\udc00\ud801\udc01")); + assertEquals(0, r.lastIndex); + r.lastIndex = 3; + assertNull(r.exec("\ud800\udc00\ud801\udc01")); + assertEquals(0, r.lastIndex); + + //------------------------ + + r = /(?:(^.)|.)/gu; + assertEquals(["\ud800\udc00", "\ud800\udc00"], r.exec("\ud800\udc00\ud801\udc01")); + assertEquals(2, r.lastIndex); + r.lastIndex = 1; + assertEquals(["\ud800\udc00", "\ud800\udc00"], r.exec("\ud800\udc00\ud801\udc01")); + assertEquals(2, r.lastIndex); + assertEquals(["\ud801\udc01", undefined], r.exec("\ud800\udc00\ud801\udc01")); + r.lastIndex = 3; + assertEquals(["\ud801\udc01", undefined], r.exec("\ud800\udc00\ud801\udc01")); + r.lastIndex = 4; + assertNull(r.exec("\ud800\udc00\ud801\udc01")); + r.lastIndex = 5; + assertNull(r.exec("\ud800\udc00\ud801\udc01")); + + r.lastIndex = 3; + assertEquals(["\ud802", undefined], r.exec("\ud800\udc00\ud801\ud802")); + r.lastIndex = 4; + assertNull(r.exec("\ud800\udc00\ud801\ud802")); + + r = /(?:(^.)|.)/g; + assertEquals(["\ud800", "\ud800"], r.exec("\ud800\udc00\ud801\udc01")); + assertEquals(1, r.lastIndex); + assertEquals(["\udc00", undefined], r.exec("\ud800\udc00\ud801\udc01")); + assertEquals(2, r.lastIndex); + r.lastIndex = 3; + assertEquals(["\udc01", undefined], r.exec("\ud800\udc00\ud801\udc01")); + assertEquals(4, r.lastIndex); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/es6/unicode-regexp-restricted-syntax.js b/Tests/LibJS/Runtime/3rdparty/v8/es6/unicode-regexp-restricted-syntax.js new file mode 100644 index 00000000000..b969569fe87 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/es6/unicode-regexp-restricted-syntax.js @@ -0,0 +1,111 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test.xfail("es6/unicode-regexp-restricted-syntax", () => { + assertThrows("/\\1/u", SyntaxError); + // test262/language/literals/regexp/u-invalid-char-range-a + assertThrows("/[\\w-a]/u", SyntaxError); + // test262/language/literals/regexp/u-invalid-char-range-b + assertThrows("/[a-\\w]/u", SyntaxError); + // test262/language/literals/regexp/u-invalid-char-esc + assertThrows("/\\c/u", SyntaxError); + assertThrows("/\\c0/u", SyntaxError); + // test262/built-ins/RegExp/unicode_restricted_quantifiable_assertion + assertThrows("/(?=.)*/u", SyntaxError); + assertThrows("/(?=.){1,2}/u", SyntaxError); + // test262/built-ins/RegExp/unicode_restricted_octal_escape + assertThrows("/[\\1]/u", SyntaxError); + assertThrows("/\\00/u", SyntaxError); + assertThrows("/\\09/u", SyntaxError); + // test262/built-ins/RegExp/unicode_restricted_identity_escape_alpha + assertThrows("/[\\c]/u", SyntaxError); + // test262/built-ins/RegExp/unicode_restricted_identity_escape_c + assertThrows("/[\\c0]/u", SyntaxError); + // test262/built-ins/RegExp/unicode_restricted_incomple_quantifier + assertThrows("/a{/u", SyntaxError); + assertThrows("/a{1,/u", SyntaxError); + assertThrows("/{/u", SyntaxError); + assertThrows("/}/u", SyntaxError); + // test262/data/test/built-ins/RegExp/unicode_restricted_brackets + assertThrows("/]/u", SyntaxError); + // test262/built-ins/RegExp/unicode_identity_escape + /\//u; + + // escaped \0 is allowed inside a character class. + assertEquals(["\0"], /[\0]/u.exec("\0")); + // unless it is followed by another digit. + assertThrows("/[\\00]/u", SyntaxError); + assertThrows("/[\\01]/u", SyntaxError); + assertThrows("/[\\09]/u", SyntaxError); + assertEquals(["\u{0}1\u{0}a\u{0}"], /[1\0a]+/u.exec("b\u{0}1\u{0}a\u{0}2")); + // escaped \- is allowed inside a character class. + assertEquals(["-"], /[a\-z]/u.exec("12-34")); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/es6/unicode-regexp-unanchored-advance.js b/Tests/LibJS/Runtime/3rdparty/v8/es6/unicode-regexp-unanchored-advance.js new file mode 100644 index 00000000000..10537e48020 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/es6/unicode-regexp-unanchored-advance.js @@ -0,0 +1,75 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("es6/unicode-regexp-unanchored-advance", () => { + var s = "a".repeat(1e7) + "\u1234"; + assertEquals(["\u1234", "\u1234"], /(\u1234)/u.exec(s)); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/es6/unicode-regexp-zero-length.js b/Tests/LibJS/Runtime/3rdparty/v8/es6/unicode-regexp-zero-length.js new file mode 100644 index 00000000000..57b9532c3b6 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/es6/unicode-regexp-zero-length.js @@ -0,0 +1,122 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test.xfail("es6/unicode-regexp-zero-length", () => { + var L = "\ud800"; + var T = "\udc00"; + var x = "x"; + + var r = /()/g; // Global, but not unicode. + // Zero-length matches do not advance lastIndex. + assertEquals(["", ""], r.exec(L + T + L + T)); + assertEquals(0, r.lastIndex); + r.lastIndex = 1; + assertEquals(["", ""], r.exec(L + T + L + T)); + assertEquals(1, r.lastIndex); + + var u = /()/gu; // Global and unicode. + // Zero-length matches do not advance lastIndex. + assertEquals(["", ""], u.exec(L + T + L + T)); + assertEquals(0, u.lastIndex); + u.lastIndex = 1; + assertEquals(["", ""], u.exec(L + T + L + T)); + assertEquals(0, u.lastIndex); + + // However, with repeating matches, lastIndex does not matter. + // We do advance from match to match. + r.lastIndex = 2; + assertEquals(x + L + x + T + x + L + x + T + x, (L + T + L + T).replace(r, "x")); + + // With unicode flag, we advance code point by code point. + u.lastIndex = 3; + assertEquals(x + L + T + x + L + T + x, (L + T + L + T).replace(u, "x")); + + // Test that exhausting the global match cache is fine. + assertEquals((x + L + T).repeat(1000) + x, (L + T).repeat(1000).replace(u, "x")); + + // Same thing for RegExp.prototype.match. + r.lastIndex = 1; + assertEquals(["", "", "", "", ""], (L + T + L + T).match(r)); + r.lastIndex = 2; + assertEquals(["", "", "", "", ""], (L + T + L + T).match(r)); + + u.lastIndex = 1; + assertEquals(["", "", ""], (L + T + L + T).match(u)); + u.lastIndex = 2; + assertEquals(["", "", ""], (L + T + L + T).match(u)); + + var expected = []; + for (var i = 0; i <= 1000; i++) expected.push(""); + assertEquals(expected, (L + T).repeat(1000).match(u)); + + // Also test RegExp.prototype.@@split. + assertEquals(["\u{12345}"], "\u{12345}".split(/(?:)/u)); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-change-exec.js b/Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-change-exec.js new file mode 100644 index 00000000000..da11cd5f2f5 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-change-exec.js @@ -0,0 +1,78 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("harmony/regexp-change-exec", () => { + class MyError extends Error {} + RegExp.prototype.exec = () => { + throw new MyError(); + }; + assertThrows(() => "foo".match(/bar/), MyError); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-dotall.js b/Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-dotall.js new file mode 100644 index 00000000000..8b0653351cd --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-dotall.js @@ -0,0 +1,202 @@ +// Copyright 2017 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("harmony/regexp-dotall", () => { + function toSlowMode(re) { + re.exec = str => RegExp.prototype.exec.call(re, str); + return re; + } + + // Construction does not throw. + { + let re = /./s; + re = RegExp(".", "s"); + re = new RegExp(".", "s"); + assertThrows(() => new RegExp(".", "wtf"), SyntaxError); + } + + // The flags accessors. + { + let re = /./s; + assertEquals("s", re.flags); + assertFalse(re.global); + assertFalse(re.ignoreCase); + assertFalse(re.multiline); + assertFalse(re.sticky); + assertFalse(re.unicode); + assertTrue(re.dotAll); + + re = toSlowMode(/./s); + assertEquals("s", re.flags); + assertFalse(re.global); + assertFalse(re.ignoreCase); + assertFalse(re.multiline); + assertFalse(re.sticky); + assertFalse(re.unicode); + assertTrue(re.dotAll); + + re = /./gimsuy; + assertEquals("gimsuy", re.flags); + assertTrue(re.global); + assertTrue(re.ignoreCase); + assertTrue(re.multiline); + assertTrue(re.sticky); + assertTrue(re.unicode); + assertTrue(re.dotAll); + + re = /./gimuy; + assertEquals("gimuy", re.flags); + assertTrue(re.global); + assertTrue(re.ignoreCase); + assertTrue(re.multiline); + assertTrue(re.sticky); + assertTrue(re.unicode); + assertFalse(re.dotAll); + } + + // Different construction variants with all flags. + { + assertEquals("gimsuy", new RegExp("", "yusmig").flags); + assertEquals("gimsuy", new RegExp().compile("", "yusmig").flags); + } + + // Default '.' behavior. + { + let re = /^.$/; + assertTrue(re.test("a")); + assertTrue(re.test("3")); + assertTrue(re.test("π")); + assertTrue(re.test("\u2027")); + assertTrue(re.test("\u0085")); + assertTrue(re.test("\v")); + assertTrue(re.test("\f")); + assertTrue(re.test("\u180E")); + assertFalse(re.test("\u{10300}")); // Supplementary plane. + assertFalse(re.test("\n")); + assertFalse(re.test("\r")); + assertFalse(re.test("\u2028")); + assertFalse(re.test("\u2029")); + } + + // Default '.' behavior (unicode). + { + let re = /^.$/u; + assertTrue(re.test("a")); + assertTrue(re.test("3")); + assertTrue(re.test("π")); + assertTrue(re.test("\u2027")); + assertTrue(re.test("\u0085")); + assertTrue(re.test("\v")); + assertTrue(re.test("\f")); + assertTrue(re.test("\u180E")); + assertTrue(re.test("\u{10300}")); // Supplementary plane. + assertFalse(re.test("\n")); + assertFalse(re.test("\r")); + assertFalse(re.test("\u2028")); + assertFalse(re.test("\u2029")); + } + + // DotAll '.' behavior. + { + let re = /^.$/s; + assertTrue(re.test("a")); + assertTrue(re.test("3")); + assertTrue(re.test("π")); + assertTrue(re.test("\u2027")); + assertTrue(re.test("\u0085")); + assertTrue(re.test("\v")); + assertTrue(re.test("\f")); + assertTrue(re.test("\u180E")); + assertFalse(re.test("\u{10300}")); // Supplementary plane. + assertTrue(re.test("\n")); + assertTrue(re.test("\r")); + assertTrue(re.test("\u2028")); + assertTrue(re.test("\u2029")); + } + + // DotAll '.' behavior (unicode). + { + let re = /^.$/su; + assertTrue(re.test("a")); + assertTrue(re.test("3")); + assertTrue(re.test("π")); + assertTrue(re.test("\u2027")); + assertTrue(re.test("\u0085")); + assertTrue(re.test("\v")); + assertTrue(re.test("\f")); + assertTrue(re.test("\u180E")); + assertTrue(re.test("\u{10300}")); // Supplementary plane. + assertTrue(re.test("\n")); + assertTrue(re.test("\r")); + assertTrue(re.test("\u2028")); + assertTrue(re.test("\u2029")); + } +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-property-binary.js b/Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-property-binary.js new file mode 100644 index 00000000000..c0137e4f33f --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-property-binary.js @@ -0,0 +1,239 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("harmony/regexp-property-binary", () => { + function t(re, s) { + assertTrue(re.test(s)); + } + function f(re, s) { + assertFalse(re.test(s)); + } + + assertThrows("/\\p{Hiragana}/u"); + assertThrows("/\\p{Bidi_Class}/u"); + assertThrows("/\\p{Bidi_C=False}/u"); + assertThrows("/\\P{Bidi_Control=Y}/u"); + assertThrows("/\\p{AHex=Yes}/u"); + + assertThrows("/\\p{Composition_Exclusion}/u"); + assertThrows("/\\p{CE}/u"); + assertThrows("/\\p{Full_Composition_Exclusion}/u"); + assertThrows("/\\p{Comp_Ex}/u"); + assertThrows("/\\p{Grapheme_Link}/u"); + assertThrows("/\\p{Gr_Link}/u"); + assertThrows("/\\p{Hyphen}/u"); + assertThrows("/\\p{NFD_Inert}/u"); + assertThrows("/\\p{NFDK_Inert}/u"); + assertThrows("/\\p{NFC_Inert}/u"); + assertThrows("/\\p{NFKC_Inert}/u"); + assertThrows("/\\p{Segment_Starter}/u"); + + t(/\p{Alphabetic}/u, "æ"); + f(/\p{Alpha}/u, "1"); + + t(/\p{ASCII_Hex_Digit}/u, "f"); + f(/\p{AHex}/u, "g"); + + t(/\p{Bidi_Control}/u, "\u200e"); + f(/\p{Bidi_C}/u, "g"); + + t(/\p{Bidi_Mirrored}/u, "("); + f(/\p{Bidi_M}/u, "-"); + + t(/\p{Case_Ignorable}/u, "\u02b0"); + f(/\p{CI}/u, "a"); + + t(/\p{Changes_When_Casefolded}/u, "B"); + f(/\p{CWCF}/u, "1"); + + t(/\p{Changes_When_Casemapped}/u, "b"); + f(/\p{CWCM}/u, "1"); + + t(/\p{Changes_When_Lowercased}/u, "B"); + f(/\p{CWL}/u, "1"); + + t(/\p{Changes_When_Titlecased}/u, "b"); + f(/\p{CWT}/u, "1"); + + t(/\p{Changes_When_Uppercased}/u, "b"); + f(/\p{CWU}/u, "1"); + + t(/\p{Dash}/u, "-"); + f(/\p{Dash}/u, "1"); + + t(/\p{Default_Ignorable_Code_Point}/u, "\u00ad"); + f(/\p{DI}/u, "1"); + + t(/\p{Deprecated}/u, "\u17a3"); + f(/\p{Dep}/u, "1"); + + t(/\p{Diacritic}/u, "\u0301"); + f(/\p{Dia}/u, "1"); + + t(/\p{Emoji}/u, "\u2603"); + f(/\p{Emoji}/u, "x"); + + t(/\p{Emoji_Component}/u, "\u{1F1E6}"); + f(/\p{Emoji_Component}/u, "x"); + + t(/\p{Emoji_Modifier_Base}/u, "\u{1F6CC}"); + f(/\p{Emoji_Modifier_Base}/u, "x"); + + t(/\p{Emoji_Modifier}/u, "\u{1F3FE}"); + f(/\p{Emoji_Modifier}/u, "x"); + + t(/\p{Emoji_Presentation}/u, "\u{1F308}"); + f(/\p{Emoji_Presentation}/u, "x"); + + t(/\p{Extender}/u, "\u3005"); + f(/\p{Ext}/u, "x"); + + t(/\p{Grapheme_Base}/u, " "); + f(/\p{Gr_Base}/u, "\u0010"); + + t(/\p{Grapheme_Extend}/u, "\u0300"); + f(/\p{Gr_Ext}/u, "x"); + + t(/\p{Hex_Digit}/u, "a"); + f(/\p{Hex}/u, "g"); + + t(/\p{ID_Continue}/u, "1"); + f(/\p{IDC}/u, "."); + + t(/\p{ID_Start}/u, "a"); + f(/\p{IDS}/u, "1"); + + t(/\p{Ideographic}/u, "漢"); + f(/\p{Ideo}/u, "H"); + + t(/\p{IDS_Binary_Operator}/u, "\u2FF0"); + f(/\p{IDSB}/u, "a"); + + t(/\p{IDS_Trinary_Operator}/u, "\u2FF2"); + f(/\p{IDST}/u, "a"); + + t(/\p{Join_Control}/u, "\u200c"); + f(/\p{Join_C}/u, "a"); + + t(/\p{Logical_Order_Exception}/u, "\u0e40"); + f(/\p{LOE}/u, "a"); + + t(/\p{Lowercase}/u, "a"); + f(/\p{Lower}/u, "A"); + + t(/\p{Math}/u, "="); + f(/\p{Math}/u, "A"); + + t(/\p{Noncharacter_Code_Point}/u, "\uFDD0"); + f(/\p{NChar}/u, "A"); + + t(/\p{Pattern_Syntax}/u, "\u0021"); + f(/\p{NChar}/u, "A"); + + t(/\p{Pattern_White_Space}/u, "\u0009"); + f(/\p{Pat_Syn}/u, "A"); + + t(/\p{Quotation_Mark}/u, "'"); + f(/\p{QMark}/u, "A"); + + t(/\p{Radical}/u, "\u2FAD"); + f(/\p{Radical}/u, "A"); + + t(/\p{Regional_Indicator}/u, "\u{1F1E6}"); + f(/\p{Regional_Indicator}/u, "A"); + + t(/\p{Sentence_Terminal}/u, "!"); + f(/\p{STerm}/u, "A"); + + t(/\p{Soft_Dotted}/u, "i"); + f(/\p{SD}/u, "A"); + + t(/\p{Terminal_Punctuation}/u, "."); + f(/\p{Term}/u, "A"); + + t(/\p{Unified_Ideograph}/u, "\u4e00"); + f(/\p{UIdeo}/u, "A"); + + t(/\p{Uppercase}/u, "A"); + f(/\p{Upper}/u, "a"); + + t(/\p{Variation_Selector}/u, "\uFE00"); + f(/\p{VS}/u, "A"); + + t(/\p{White_Space}/u, " "); + f(/\p{WSpace}/u, "A"); + + t(/\p{XID_Continue}/u, "1"); + f(/\p{XIDC}/u, " "); + + t(/\p{XID_Start}/u, "A"); + f(/\p{XIDS}/u, " "); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-property-char-class.js b/Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-property-char-class.js new file mode 100644 index 00000000000..ac3b5dd4fa9 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-property-char-class.js @@ -0,0 +1,95 @@ +// Copyright 2011 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("harmony/regexp-property-char-class", () => { + assertThrows("/[\\p]/u"); + assertThrows("/[\\p{garbage}]/u"); + assertThrows("/[\\p{}]/u"); + assertThrows("/[\\p{]/u"); + assertThrows("/[\\p}]/u"); + assertThrows("/^[\\p{Lu}-\\p{Ll}]+$/u"); + + assertTrue(/^[\p{Lu}\p{Ll}]+$/u.test("ABCabc")); + assertTrue(/^[\p{Lu}-]+$/u.test("ABC-")); + assertFalse(/^[\P{Lu}\p{Ll}]+$/u.test("ABCabc")); + assertTrue(/^[\P{Lu}\p{Ll}]+$/u.test("abc")); + assertTrue(/^[\P{Lu}]+$/u.test("abc123")); + assertFalse(/^[\P{Lu}]+$/u.test("XYZ")); + assertTrue(/[\p{Math}]/u.test("+")); + assertTrue(/[\P{Bidi_M}]/u.test(" ")); + assertTrue(/[\p{Hex}]/u.test("A")); + + assertTrue(/^[^\P{Lu}]+$/u.test("XYZ")); + assertFalse(/^[^\p{Lu}\p{Ll}]+$/u.test("abc")); + assertFalse(/^[^\p{Lu}\p{Ll}]+$/u.test("ABC")); + assertTrue(/^[^\p{Lu}\p{Ll}]+$/u.test("123")); + assertTrue(/^[^\p{Lu}\P{Ll}]+$/u.test("abc")); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-property-enumerated.js b/Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-property-enumerated.js new file mode 100644 index 00000000000..a28e48cefd7 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-property-enumerated.js @@ -0,0 +1,92 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test.xfail("harmony/regexp-property-enumerated", () => { + assertThrows("/\\p{Bidi_Class=L}+/u"); + assertThrows("/\\p{bc=Left_To_Right}+/u"); + assertThrows("/\\p{bc=AL}+/u"); + assertThrows("/\\p{bc=Arabic_Letter}+/u"); + + assertThrows("/\\p{Line_Break=Glue}/u"); + assertThrows("/\\p{lb=AL}/u"); + + assertThrows("/\\p{Block=}/u"); + assertThrows("/\\p{=}/u"); + assertThrows("/\\p{=L}/u"); + assertThrows("/\\p{=Hiragana}/u"); + assertThrows("/\\p{Block=CJK=}/u"); + + assertThrows("/\\p{Age=V8_0}/u"); + assertDoesNotThrow("/\\p{General_Category=Letter}/u"); + assertDoesNotThrow("/\\p{gc=L}/u"); + assertThrows("/\\p{General_Category_Mask=Letter}/u"); + assertThrows("/\\p{gcm=L}/u"); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-property-exact-match.js b/Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-property-exact-match.js new file mode 100644 index 00000000000..9b826f97524 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-property-exact-match.js @@ -0,0 +1,109 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test.xfail("harmony/regexp-property-exact-match", () => { + assertThrows("/\\p{In CJK}/u"); + assertThrows("/\\p{InCJKUnifiedIdeographs}/u"); + assertThrows("/\\p{InCJK}/u"); + assertThrows("/\\p{InCJK_Unified_Ideographs}/u"); + + assertThrows("/\\p{InCyrillic_Sup}/u"); + assertThrows("/\\p{InCyrillic_Supplement}/u"); + assertThrows("/\\p{InCyrillic_Supplementary}/u"); + assertThrows("/\\p{InCyrillicSupplementary}/u"); + assertThrows("/\\p{InCyrillic_supplementary}/u"); + + assertDoesNotThrow("/\\p{C}/u"); + assertDoesNotThrow("/\\p{Other}/u"); + assertDoesNotThrow("/\\p{Cc}/u"); + assertDoesNotThrow("/\\p{Control}/u"); + assertDoesNotThrow("/\\p{cntrl}/u"); + assertDoesNotThrow("/\\p{M}/u"); + assertDoesNotThrow("/\\p{Mark}/u"); + assertDoesNotThrow("/\\p{Combining_Mark}/u"); + assertThrows("/\\p{Combining Mark}/u"); + + assertDoesNotThrow("/\\p{Script=Copt}/u"); + assertThrows("/\\p{Coptic}/u"); + assertThrows("/\\p{Qaac}/u"); + assertThrows("/\\p{Egyp}/u"); + assertDoesNotThrow("/\\p{Script=Egyptian_Hieroglyphs}/u"); + assertThrows("/\\p{EgyptianHieroglyphs}/u"); + + assertThrows("/\\p{BidiClass=LeftToRight}/u"); + assertThrows("/\\p{BidiC=LeftToRight}/u"); + assertThrows("/\\p{bidi_c=Left_To_Right}/u"); + + assertThrows("/\\p{Block=CJK}/u"); + assertThrows("/\\p{Block = CJK}/u"); + assertThrows("/\\p{Block=cjk}/u"); + assertThrows("/\\p{BLK=CJK}/u"); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-property-general-category.js b/Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-property-general-category.js new file mode 100644 index 00000000000..7101051ffbc --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-property-general-category.js @@ -0,0 +1,136 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("harmony/regexp-property-general-category", () => { + assertThrows("/\\p/u"); + assertThrows("/\\p{garbage}/u"); + assertThrows("/\\p{}/u"); + assertThrows("/\\p{/u"); + assertThrows("/\\p}/u"); + assertThrows("/\\pL/u"); + assertThrows("/\\P/u"); + assertThrows("/\\P{garbage}/u"); + assertThrows("/\\P{}/u"); + assertThrows("/\\P{/u"); + assertThrows("/\\P}/u"); + assertThrows("/\\PL/u"); + + assertTrue(/\p{Ll}/u.test("a")); + assertFalse(/\P{Ll}/u.test("a")); + assertTrue(/\P{Ll}/u.test("A")); + assertFalse(/\p{Ll}/u.test("A")); + assertTrue(/\p{Ll}/u.test("\u{1D7BE}")); + assertFalse(/\P{Ll}/u.test("\u{1D7BE}")); + assertFalse(/\p{Ll}/u.test("\u{1D5E3}")); + assertTrue(/\P{Ll}/u.test("\u{1D5E3}")); + + assertTrue(/\p{Ll}/iu.test("a")); + assertTrue(/\p{Ll}/iu.test("\u{118D4}")); + assertTrue(/\p{Ll}/iu.test("A")); + assertTrue(/\p{Ll}/iu.test("\u{118B4}")); + assertTrue(/\P{Ll}/iu.test("a")); + assertTrue(/\P{Ll}/iu.test("\u{118D4}")); + assertTrue(/\P{Ll}/iu.test("A")); + assertTrue(/\P{Ll}/iu.test("\u{118B4}")); + + assertTrue(/\p{Lu}/u.test("A")); + assertFalse(/\P{Lu}/u.test("A")); + assertTrue(/\P{Lu}/u.test("a")); + assertFalse(/\p{Lu}/u.test("a")); + assertTrue(/\p{Lu}/u.test("\u{1D5E3}")); + assertFalse(/\P{Lu}/u.test("\u{1D5E3}")); + assertFalse(/\p{Lu}/u.test("\u{1D7BE}")); + assertTrue(/\P{Lu}/u.test("\u{1D7BE}")); + + assertTrue(/\p{Lu}/iu.test("a")); + assertTrue(/\p{Lu}/iu.test("\u{118D4}")); + assertTrue(/\p{Lu}/iu.test("A")); + assertTrue(/\p{Lu}/iu.test("\u{118B4}")); + assertTrue(/\P{Lu}/iu.test("a")); + assertTrue(/\P{Lu}/iu.test("\u{118D4}")); + assertTrue(/\P{Lu}/iu.test("A")); + assertTrue(/\P{Lu}/iu.test("\u{118B4}")); + + assertTrue(/\p{Sm}/u.test("+")); + assertFalse(/\P{Sm}/u.test("+")); + assertTrue(/\p{Sm}/u.test("\u{1D6C1}")); + assertFalse(/\P{Sm}/u.test("\u{1D6C1}")); + + assertFalse(/\p{L}/u.test("\uA6EE")); + assertTrue(/\P{L}/u.test("\uA6EE")); + + assertTrue(/\p{Lowercase_Letter}/u.test("a")); + assertTrue(/\p{Math_Symbol}/u.test("+")); + + assertTrue(/\p{gc=Ll}/u.test("a")); + assertTrue(/\p{General_Category=Math_Symbol}/u.test("+")); + assertTrue(/\p{General_Category=L}/u.test("X")); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-property-invalid.js b/Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-property-invalid.js new file mode 100644 index 00000000000..48389dde832 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-property-invalid.js @@ -0,0 +1,107 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("harmony/regexp-property-invalid", () => { + assertThrows("/\p{Block=ASCII}+/u"); + assertThrows("/\p{Block=ASCII}+/u"); + assertThrows("/\p{Block=Basic_Latin}+/u"); + assertThrows("/\p{Block=Basic_Latin}+/u"); + + assertThrows("/\p{blk=CJK}+/u"); + assertThrows("/\p{blk=CJK_Unified_Ideographs}+/u"); + assertThrows("/\p{blk=CJK}+/u"); + assertThrows("/\p{blk=CJK_Unified_Ideographs}+/u"); + + assertThrows("/\p{Block=ASCII}+/u"); + assertThrows("/\p{Block=ASCII}+/u"); + assertThrows("/\p{Block=Basic_Latin}+/u"); + assertThrows("/\p{Block=Basic_Latin}+/u"); + + assertThrows("/\p{NFKD_Quick_Check=Y}+/u"); + assertThrows("/\p{NFKD_QC=Yes}+/u"); + + assertThrows("/\p{Numeric_Type=Decimal}+/u"); + assertThrows("/\p{nt=De}+/u"); + + assertThrows("/\p{Bidi_Class=Arabic_Letter}+/u"); + assertThrows("/\p{Bidi_Class=AN}+/u"); + + assertThrows("/\p{ccc=OV}+/u"); + + assertThrows("/\p{Sentence_Break=Format}+/u"); + + assertThrows("/\\p{In}/u"); + assertThrows("/\\pI/u"); + assertThrows("/\\p{I}/u"); + assertThrows("/\\p{CJK}/u"); + + assertThrows("/\\p{}/u"); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-property-lu-ui.js b/Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-property-lu-ui.js new file mode 100644 index 00000000000..f96f1c7a893 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-property-lu-ui.js @@ -0,0 +1,96 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("harmony/regexp-property-lu-ui", () => { + const regexp = /\P{Lu}/iu; + const regexpu = + /[\0-@\[-\xBF\xD7\xDF-\xFF\u0101\u0103\u0105\u0107\u0109\u010B\u010D\u010F\u0111\u0113\u0115\u0117\u0119\u011B\u011D\u011F\u0121\u0123\u0125\u0127\u0129\u012B\u012D\u012F\u0131\u0133\u0135\u0137\u0138\u013A\u013C\u013E\u0140\u0142\u0144\u0146\u0148\u0149\u014B\u014D\u014F\u0151\u0153\u0155\u0157\u0159\u015B\u015D\u015F\u0161\u0163\u0165\u0167\u0169\u016B\u016D\u016F\u0171\u0173\u0175\u0177\u017A\u017C\u017E-\u0180\u0183\u0185\u0188\u018C\u018D\u0192\u0195\u0199-\u019B\u019E\u01A1\u01A3\u01A5\u01A8\u01AA\u01AB\u01AD\u01B0\u01B4\u01B6\u01B9-\u01BB\u01BD-\u01C3\u01C5\u01C6\u01C8\u01C9\u01CB\u01CC\u01CE\u01D0\u01D2\u01D4\u01D6\u01D8\u01DA\u01DC\u01DD\u01DF\u01E1\u01E3\u01E5\u01E7\u01E9\u01EB\u01ED\u01EF\u01F0\u01F2\u01F3\u01F5\u01F9\u01FB\u01FD\u01FF\u0201\u0203\u0205\u0207\u0209\u020B\u020D\u020F\u0211\u0213\u0215\u0217\u0219\u021B\u021D\u021F\u0221\u0223\u0225\u0227\u0229\u022B\u022D\u022F\u0231\u0233-\u0239\u023C\u023F\u0240\u0242\u0247\u0249\u024B\u024D\u024F-\u036F\u0371\u0373-\u0375\u0377-\u037E\u0380-\u0385\u0387\u038B\u038D\u0390\u03A2\u03AC-\u03CE\u03D0\u03D1\u03D5-\u03D7\u03D9\u03DB\u03DD\u03DF\u03E1\u03E3\u03E5\u03E7\u03E9\u03EB\u03ED\u03EF-\u03F3\u03F5\u03F6\u03F8\u03FB\u03FC\u0430-\u045F\u0461\u0463\u0465\u0467\u0469\u046B\u046D\u046F\u0471\u0473\u0475\u0477\u0479\u047B\u047D\u047F\u0481-\u0489\u048B\u048D\u048F\u0491\u0493\u0495\u0497\u0499\u049B\u049D\u049F\u04A1\u04A3\u04A5\u04A7\u04A9\u04AB\u04AD\u04AF\u04B1\u04B3\u04B5\u04B7\u04B9\u04BB\u04BD\u04BF\u04C2\u04C4\u04C6\u04C8\u04CA\u04CC\u04CE\u04CF\u04D1\u04D3\u04D5\u04D7\u04D9\u04DB\u04DD\u04DF\u04E1\u04E3\u04E5\u04E7\u04E9\u04EB\u04ED\u04EF\u04F1\u04F3\u04F5\u04F7\u04F9\u04FB\u04FD\u04FF\u0501\u0503\u0505\u0507\u0509\u050B\u050D\u050F\u0511\u0513\u0515\u0517\u0519\u051B\u051D\u051F\u0521\u0523\u0525\u0527\u0529\u052B\u052D\u052F\u0530\u0557-\u109F\u10C6\u10C8-\u10CC\u10CE-\u139F\u13F6-\u1DFF\u1E01\u1E03\u1E05\u1E07\u1E09\u1E0B\u1E0D\u1E0F\u1E11\u1E13\u1E15\u1E17\u1E19\u1E1B\u1E1D\u1E1F\u1E21\u1E23\u1E25\u1E27\u1E29\u1E2B\u1E2D\u1E2F\u1E31\u1E33\u1E35\u1E37\u1E39\u1E3B\u1E3D\u1E3F\u1E41\u1E43\u1E45\u1E47\u1E49\u1E4B\u1E4D\u1E4F\u1E51\u1E53\u1E55\u1E57\u1E59\u1E5B\u1E5D\u1E5F\u1E61\u1E63\u1E65\u1E67\u1E69\u1E6B\u1E6D\u1E6F\u1E71\u1E73\u1E75\u1E77\u1E79\u1E7B\u1E7D\u1E7F\u1E81\u1E83\u1E85\u1E87\u1E89\u1E8B\u1E8D\u1E8F\u1E91\u1E93\u1E95-\u1E9D\u1E9F\u1EA1\u1EA3\u1EA5\u1EA7\u1EA9\u1EAB\u1EAD\u1EAF\u1EB1\u1EB3\u1EB5\u1EB7\u1EB9\u1EBB\u1EBD\u1EBF\u1EC1\u1EC3\u1EC5\u1EC7\u1EC9\u1ECB\u1ECD\u1ECF\u1ED1\u1ED3\u1ED5\u1ED7\u1ED9\u1EDB\u1EDD\u1EDF\u1EE1\u1EE3\u1EE5\u1EE7\u1EE9\u1EEB\u1EED\u1EEF\u1EF1\u1EF3\u1EF5\u1EF7\u1EF9\u1EFB\u1EFD\u1EFF-\u1F07\u1F10-\u1F17\u1F1E-\u1F27\u1F30-\u1F37\u1F40-\u1F47\u1F4E-\u1F58\u1F5A\u1F5C\u1F5E\u1F60-\u1F67\u1F70-\u1FB7\u1FBC-\u1FC7\u1FCC-\u1FD7\u1FDC-\u1FE7\u1FED-\u1FF7\u1FFC-\u2101\u2103-\u2106\u2108-\u210A\u210E\u210F\u2113\u2114\u2116-\u2118\u211E-\u2123\u2125\u2127\u2129\u212E\u212F\u2134-\u213D\u2140-\u2144\u2146-\u2182\u2184-\u2BFF\u2C2F-\u2C5F\u2C61\u2C65\u2C66\u2C68\u2C6A\u2C6C\u2C71\u2C73\u2C74\u2C76-\u2C7D\u2C81\u2C83\u2C85\u2C87\u2C89\u2C8B\u2C8D\u2C8F\u2C91\u2C93\u2C95\u2C97\u2C99\u2C9B\u2C9D\u2C9F\u2CA1\u2CA3\u2CA5\u2CA7\u2CA9\u2CAB\u2CAD\u2CAF\u2CB1\u2CB3\u2CB5\u2CB7\u2CB9\u2CBB\u2CBD\u2CBF\u2CC1\u2CC3\u2CC5\u2CC7\u2CC9\u2CCB\u2CCD\u2CCF\u2CD1\u2CD3\u2CD5\u2CD7\u2CD9\u2CDB\u2CDD\u2CDF\u2CE1\u2CE3-\u2CEA\u2CEC\u2CEE-\u2CF1\u2CF3-\uA63F\uA641\uA643\uA645\uA647\uA649\uA64B\uA64D\uA64F\uA651\uA653\uA655\uA657\uA659\uA65B\uA65D\uA65F\uA661\uA663\uA665\uA667\uA669\uA66B\uA66D-\uA67F\uA681\uA683\uA685\uA687\uA689\uA68B\uA68D\uA68F\uA691\uA693\uA695\uA697\uA699\uA69B-\uA721\uA723\uA725\uA727\uA729\uA72B\uA72D\uA72F-\uA731\uA733\uA735\uA737\uA739\uA73B\uA73D\uA73F\uA741\uA743\uA745\uA747\uA749\uA74B\uA74D\uA74F\uA751\uA753\uA755\uA757\uA759\uA75B\uA75D\uA75F\uA761\uA763\uA765\uA767\uA769\uA76B\uA76D\uA76F-\uA778\uA77A\uA77C\uA77F\uA781\uA783\uA785\uA787-\uA78A\uA78C\uA78E\uA78F\uA791\uA793-\uA795\uA797\uA799\uA79B\uA79D\uA79F\uA7A1\uA7A3\uA7A5\uA7A7\uA7A9\uA7AE\uA7AF\uA7B5\uA7B7-\uFF20\uFF3B-\u{103FF}\u{10428}-\u{10C7F}\u{10CB3}-\u{1189F}\u{118C0}-\u{1D3FF}\u{1D41A}-\u{1D433}\u{1D44E}-\u{1D467}\u{1D482}-\u{1D49B}\u{1D49D}\u{1D4A0}\u{1D4A1}\u{1D4A3}\u{1D4A4}\u{1D4A7}\u{1D4A8}\u{1D4AD}\u{1D4B6}-\u{1D4CF}\u{1D4EA}-\u{1D503}\u{1D506}\u{1D50B}\u{1D50C}\u{1D515}\u{1D51D}-\u{1D537}\u{1D53A}\u{1D53F}\u{1D545}\u{1D547}-\u{1D549}\u{1D551}-\u{1D56B}\u{1D586}-\u{1D59F}\u{1D5BA}-\u{1D5D3}\u{1D5EE}-\u{1D607}\u{1D622}-\u{1D63B}\u{1D656}-\u{1D66F}\u{1D68A}-\u{1D6A7}\u{1D6C1}-\u{1D6E1}\u{1D6FB}-\u{1D71B}\u{1D735}-\u{1D755}\u{1D76F}-\u{1D78F}\u{1D7A9}-\u{1D7C9}\u{1D7CB}-\u{10FFFF}]/iu; + + // Test is split into parts to increase parallelism. + const number_of_tests = 10; + const max_codepoint = 0x10ffff; + + function firstCodePointOfRange(i) { + return Math.floor(i * (max_codepoint / number_of_tests)); + } + + function testCodePointRange(i) { + assertTrue(i >= 0 && i < number_of_tests); + + const from = firstCodePointOfRange(i); + const to = i == number_of_tests - 1 ? max_codepoint + 1 : firstCodePointOfRange(i + 1); + + for (let codePoint = from; codePoint < to; codePoint++) { + const string = String.fromCodePoint(codePoint); + assertEquals(regexp.test(string), regexpu.test(string)); + } + } +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-property-script-extensions.js b/Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-property-script-extensions.js new file mode 100644 index 00000000000..8a235ddf85d --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-property-script-extensions.js @@ -0,0 +1,508 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("harmony/regexp-property-script-extensions", () => { + function t(re, s) { + assertTrue(re.test(s)); + } + function f(re, s) { + assertFalse(re.test(s)); + } + + t(/\p{Script_Extensions=Bopo}+/u, "\u300A"); + t(/\p{Script_Extensions=Hang}+/u, "\u300A"); + t(/\p{Script_Extensions=Hani}+/u, "\u300A"); + t(/\p{Script_Extensions=Hira}+/u, "\u300A"); + t(/\p{Script_Extensions=Kana}+/u, "\u300A"); + t(/\p{Script_Extensions=Yiii}+/u, "\u300A"); + + t(/\p{scx=Bopomofo}+/u, "\u3003"); + t(/\p{scx=Hangul}+/u, "\u3003"); + t(/\p{scx=Han}+/u, "\u3003"); + t(/\p{scx=Hiragana}+/u, "\u3003"); + t(/\p{scx=Katakana}+/u, "\u3003"); + f(/\p{scx=Yi}+/u, "\u3003"); + + t(/\p{Script_Extensions=Cypriot}+/u, "\u{10107}"); + f(/\p{Script=Cypriot}+/u, "\u{10107}"); + f(/\p{scx=Cprt}+/u, "\u3003"); + + /* Auto-generated from Unicode data file using following script + let data = read("ScriptExtensions.txt"); + let map = new Map(); + for (let line of data.split("\n")) { + let match = /^(\p{Hex}{4,6})(..(\p{Hex}{4,6}))?\s+; ([\w\s]+) #/u.exec(line); + if (!match) continue; + let [,start,,end,scripts] = match; + if (!end) end = start; + start = parseInt(start, 16); + end = parseInt(end, 16); + for (let script of scripts.split(" ")) { + let codepoints = map.get(script) || new Set(); + for (let c = start; c <= end; c++) codepoints.add(c); + map.set(script, codepoints); + } + } + + for (let s of map.keys()){ + let codepoints = map.get(s); + print(`// Script_Extension=${s}`); + for (let i = 0; i < 5;) { + let c = (Math.random() * 0x110000) | 0; + if (codepoints.has(c)) continue; + print(`f(/(?=\\P{sc=${s}})\\p{scx=${s}}/u, "\\u{${c.toString(16)}}");`); + i++; + } + } + */ + + // Unicode version 11.0.0 + // https://unicode.org/Public/10.0.0/ucd/ScriptExtensions.txt + + // Script_Extension=Beng + f(/(?=\P{sc=Beng})\p{scx=Beng}/u, "\u{e52ee}"); + f(/(?=\P{sc=Beng})\p{scx=Beng}/u, "\u{78b48}"); + f(/(?=\P{sc=Beng})\p{scx=Beng}/u, "\u{59987}"); + f(/(?=\P{sc=Beng})\p{scx=Beng}/u, "\u{d18a8}"); + f(/(?=\P{sc=Beng})\p{scx=Beng}/u, "\u{2b84e}"); + // Script_Extension=Deva + f(/(?=\P{sc=Deva})\p{scx=Deva}/u, "\u{757f8}"); + f(/(?=\P{sc=Deva})\p{scx=Deva}/u, "\u{2cb44}"); + f(/(?=\P{sc=Deva})\p{scx=Deva}/u, "\u{7624d}"); + f(/(?=\P{sc=Deva})\p{scx=Deva}/u, "\u{9a219}"); + f(/(?=\P{sc=Deva})\p{scx=Deva}/u, "\u{e41a8}"); + // Script_Extension=Dupl + f(/(?=\P{sc=Dupl})\p{scx=Dupl}/u, "\u{4ae62}"); + f(/(?=\P{sc=Dupl})\p{scx=Dupl}/u, "\u{b80a}"); + f(/(?=\P{sc=Dupl})\p{scx=Dupl}/u, "\u{c856c}"); + f(/(?=\P{sc=Dupl})\p{scx=Dupl}/u, "\u{36c5f}"); + f(/(?=\P{sc=Dupl})\p{scx=Dupl}/u, "\u{42ef3}"); + // Script_Extension=Grek + f(/(?=\P{sc=Grek})\p{scx=Grek}/u, "\u{85c59}"); + f(/(?=\P{sc=Grek})\p{scx=Grek}/u, "\u{bd40}"); + f(/(?=\P{sc=Grek})\p{scx=Grek}/u, "\u{7ffef}"); + f(/(?=\P{sc=Grek})\p{scx=Grek}/u, "\u{b4a21}"); + f(/(?=\P{sc=Grek})\p{scx=Grek}/u, "\u{b97b3}"); + // Script_Extension=Hani + f(/(?=\P{sc=Hani})\p{scx=Hani}/u, "\u{d59d4}"); + f(/(?=\P{sc=Hani})\p{scx=Hani}/u, "\u{8da54}"); + f(/(?=\P{sc=Hani})\p{scx=Hani}/u, "\u{77a36}"); + f(/(?=\P{sc=Hani})\p{scx=Hani}/u, "\u{8d66b}"); + f(/(?=\P{sc=Hani})\p{scx=Hani}/u, "\u{b2371}"); + // Script_Extension=Latn + f(/(?=\P{sc=Latn})\p{scx=Latn}/u, "\u{10d47b}"); + f(/(?=\P{sc=Latn})\p{scx=Latn}/u, "\u{7a184}"); + f(/(?=\P{sc=Latn})\p{scx=Latn}/u, "\u{a64ac}"); + f(/(?=\P{sc=Latn})\p{scx=Latn}/u, "\u{ea450}"); + f(/(?=\P{sc=Latn})\p{scx=Latn}/u, "\u{ab23e}"); + // Script_Extension=Arab + f(/(?=\P{sc=Arab})\p{scx=Arab}/u, "\u{43609}"); + f(/(?=\P{sc=Arab})\p{scx=Arab}/u, "\u{bea28}"); + f(/(?=\P{sc=Arab})\p{scx=Arab}/u, "\u{f9ef}"); + f(/(?=\P{sc=Arab})\p{scx=Arab}/u, "\u{7b3fc}"); + f(/(?=\P{sc=Arab})\p{scx=Arab}/u, "\u{3a64a}"); + // Script_Extension=Copt + f(/(?=\P{sc=Copt})\p{scx=Copt}/u, "\u{a7927}"); + f(/(?=\P{sc=Copt})\p{scx=Copt}/u, "\u{e11a5}"); + f(/(?=\P{sc=Copt})\p{scx=Copt}/u, "\u{a7afe}"); + f(/(?=\P{sc=Copt})\p{scx=Copt}/u, "\u{68bd4}"); + f(/(?=\P{sc=Copt})\p{scx=Copt}/u, "\u{4c963}"); + // Script_Extension=Rohg + f(/(?=\P{sc=Rohg})\p{scx=Rohg}/u, "\u{cd74e}"); + f(/(?=\P{sc=Rohg})\p{scx=Rohg}/u, "\u{c4e3c}"); + f(/(?=\P{sc=Rohg})\p{scx=Rohg}/u, "\u{1f2de}"); + f(/(?=\P{sc=Rohg})\p{scx=Rohg}/u, "\u{999ca}"); + f(/(?=\P{sc=Rohg})\p{scx=Rohg}/u, "\u{f25d9}"); + // Script_Extension=Syrc + f(/(?=\P{sc=Syrc})\p{scx=Syrc}/u, "\u{dd913}"); + f(/(?=\P{sc=Syrc})\p{scx=Syrc}/u, "\u{81cdc}"); + f(/(?=\P{sc=Syrc})\p{scx=Syrc}/u, "\u{32fb2}"); + f(/(?=\P{sc=Syrc})\p{scx=Syrc}/u, "\u{cc6ec}"); + f(/(?=\P{sc=Syrc})\p{scx=Syrc}/u, "\u{adba2}"); + // Script_Extension=Thaa + f(/(?=\P{sc=Thaa})\p{scx=Thaa}/u, "\u{782b1}"); + f(/(?=\P{sc=Thaa})\p{scx=Thaa}/u, "\u{ca567}"); + f(/(?=\P{sc=Thaa})\p{scx=Thaa}/u, "\u{c1506}"); + f(/(?=\P{sc=Thaa})\p{scx=Thaa}/u, "\u{e783}"); + f(/(?=\P{sc=Thaa})\p{scx=Thaa}/u, "\u{fc8e1}"); + // Script_Extension=Armn + f(/(?=\P{sc=Armn})\p{scx=Armn}/u, "\u{36a6d}"); + f(/(?=\P{sc=Armn})\p{scx=Armn}/u, "\u{6c98}"); + f(/(?=\P{sc=Armn})\p{scx=Armn}/u, "\u{c4326}"); + f(/(?=\P{sc=Armn})\p{scx=Armn}/u, "\u{25eb6}"); + f(/(?=\P{sc=Armn})\p{scx=Armn}/u, "\u{db9d9}"); + // Script_Extension=Geor + f(/(?=\P{sc=Geor})\p{scx=Geor}/u, "\u{e48f5}"); + f(/(?=\P{sc=Geor})\p{scx=Geor}/u, "\u{9914e}"); + f(/(?=\P{sc=Geor})\p{scx=Geor}/u, "\u{49dad}"); + f(/(?=\P{sc=Geor})\p{scx=Geor}/u, "\u{9d193}"); + f(/(?=\P{sc=Geor})\p{scx=Geor}/u, "\u{10ce35}"); + // Script_Extension=Bopo + f(/(?=\P{sc=Bopo})\p{scx=Bopo}/u, "\u{36ac1}"); + f(/(?=\P{sc=Bopo})\p{scx=Bopo}/u, "\u{73ae5}"); + f(/(?=\P{sc=Bopo})\p{scx=Bopo}/u, "\u{cd0a}"); + f(/(?=\P{sc=Bopo})\p{scx=Bopo}/u, "\u{bd8bd}"); + f(/(?=\P{sc=Bopo})\p{scx=Bopo}/u, "\u{eb174}"); + // Script_Extension=Bugi + f(/(?=\P{sc=Bugi})\p{scx=Bugi}/u, "\u{7dcfc}"); + f(/(?=\P{sc=Bugi})\p{scx=Bugi}/u, "\u{b17d1}"); + f(/(?=\P{sc=Bugi})\p{scx=Bugi}/u, "\u{15cb5}"); + f(/(?=\P{sc=Bugi})\p{scx=Bugi}/u, "\u{10d4f6}"); + f(/(?=\P{sc=Bugi})\p{scx=Bugi}/u, "\u{12bbe}"); + // Script_Extension=Java + f(/(?=\P{sc=Java})\p{scx=Java}/u, "\u{10f6f3}"); + f(/(?=\P{sc=Java})\p{scx=Java}/u, "\u{75579}"); + f(/(?=\P{sc=Java})\p{scx=Java}/u, "\u{b39e4}"); + f(/(?=\P{sc=Java})\p{scx=Java}/u, "\u{104b64}"); + f(/(?=\P{sc=Java})\p{scx=Java}/u, "\u{102995}"); + // Script_Extension=Cprt + f(/(?=\P{sc=Cprt})\p{scx=Cprt}/u, "\u{46b94}"); + f(/(?=\P{sc=Cprt})\p{scx=Cprt}/u, "\u{3eaa1}"); + f(/(?=\P{sc=Cprt})\p{scx=Cprt}/u, "\u{3dd9a}"); + f(/(?=\P{sc=Cprt})\p{scx=Cprt}/u, "\u{c3e90}"); + f(/(?=\P{sc=Cprt})\p{scx=Cprt}/u, "\u{75301}"); + // Script_Extension=Linb + f(/(?=\P{sc=Linb})\p{scx=Linb}/u, "\u{b0cc}"); + f(/(?=\P{sc=Linb})\p{scx=Linb}/u, "\u{2759a}"); + f(/(?=\P{sc=Linb})\p{scx=Linb}/u, "\u{a6482}"); + f(/(?=\P{sc=Linb})\p{scx=Linb}/u, "\u{11c84}"); + f(/(?=\P{sc=Linb})\p{scx=Linb}/u, "\u{a3931}"); + // Script_Extension=Cyrl + f(/(?=\P{sc=Cyrl})\p{scx=Cyrl}/u, "\u{2d4a3}"); + f(/(?=\P{sc=Cyrl})\p{scx=Cyrl}/u, "\u{394c9}"); + f(/(?=\P{sc=Cyrl})\p{scx=Cyrl}/u, "\u{aa2e7}"); + f(/(?=\P{sc=Cyrl})\p{scx=Cyrl}/u, "\u{823e3}"); + f(/(?=\P{sc=Cyrl})\p{scx=Cyrl}/u, "\u{f753e}"); + // Script_Extension=Glag + f(/(?=\P{sc=Glag})\p{scx=Glag}/u, "\u{f060c}"); + f(/(?=\P{sc=Glag})\p{scx=Glag}/u, "\u{f4430}"); + f(/(?=\P{sc=Glag})\p{scx=Glag}/u, "\u{89208}"); + f(/(?=\P{sc=Glag})\p{scx=Glag}/u, "\u{3b2fa}"); + f(/(?=\P{sc=Glag})\p{scx=Glag}/u, "\u{5a463}"); + // Script_Extension=Perm + f(/(?=\P{sc=Perm})\p{scx=Perm}/u, "\u{f4f29}"); + f(/(?=\P{sc=Perm})\p{scx=Perm}/u, "\u{154a1}"); + f(/(?=\P{sc=Perm})\p{scx=Perm}/u, "\u{8d2e1}"); + f(/(?=\P{sc=Perm})\p{scx=Perm}/u, "\u{6ddec}"); + f(/(?=\P{sc=Perm})\p{scx=Perm}/u, "\u{2859e}"); + // Script_Extension=Gran + f(/(?=\P{sc=Gran})\p{scx=Gran}/u, "\u{dcc3b}"); + f(/(?=\P{sc=Gran})\p{scx=Gran}/u, "\u{240a1}"); + f(/(?=\P{sc=Gran})\p{scx=Gran}/u, "\u{d94fd}"); + f(/(?=\P{sc=Gran})\p{scx=Gran}/u, "\u{3e537}"); + f(/(?=\P{sc=Gran})\p{scx=Gran}/u, "\u{ddf65}"); + // Script_Extension=Shrd + f(/(?=\P{sc=Shrd})\p{scx=Shrd}/u, "\u{c17cc}"); + f(/(?=\P{sc=Shrd})\p{scx=Shrd}/u, "\u{2d717}"); + f(/(?=\P{sc=Shrd})\p{scx=Shrd}/u, "\u{93c84}"); + f(/(?=\P{sc=Shrd})\p{scx=Shrd}/u, "\u{e4d57}"); + f(/(?=\P{sc=Shrd})\p{scx=Shrd}/u, "\u{4449a}"); + // Script_Extension=Taml + f(/(?=\P{sc=Taml})\p{scx=Taml}/u, "\u{fb7ab}"); + f(/(?=\P{sc=Taml})\p{scx=Taml}/u, "\u{d687c}"); + f(/(?=\P{sc=Taml})\p{scx=Taml}/u, "\u{b6aea}"); + f(/(?=\P{sc=Taml})\p{scx=Taml}/u, "\u{e42bc}"); + f(/(?=\P{sc=Taml})\p{scx=Taml}/u, "\u{77534}"); + // Script_Extension=Gujr + f(/(?=\P{sc=Gujr})\p{scx=Gujr}/u, "\u{4b35c}"); + f(/(?=\P{sc=Gujr})\p{scx=Gujr}/u, "\u{889e5}"); + f(/(?=\P{sc=Gujr})\p{scx=Gujr}/u, "\u{107d78}"); + f(/(?=\P{sc=Gujr})\p{scx=Gujr}/u, "\u{c68d8}"); + f(/(?=\P{sc=Gujr})\p{scx=Gujr}/u, "\u{a5b0a}"); + // Script_Extension=Khoj + f(/(?=\P{sc=Khoj})\p{scx=Khoj}/u, "\u{2da77}"); + f(/(?=\P{sc=Khoj})\p{scx=Khoj}/u, "\u{9fb5}"); + f(/(?=\P{sc=Khoj})\p{scx=Khoj}/u, "\u{a0268}"); + f(/(?=\P{sc=Khoj})\p{scx=Khoj}/u, "\u{10d835}"); + f(/(?=\P{sc=Khoj})\p{scx=Khoj}/u, "\u{49e92}"); + // Script_Extension=Guru + f(/(?=\P{sc=Guru})\p{scx=Guru}/u, "\u{54186}"); + f(/(?=\P{sc=Guru})\p{scx=Guru}/u, "\u{a2fff}"); + f(/(?=\P{sc=Guru})\p{scx=Guru}/u, "\u{e25c3}"); + f(/(?=\P{sc=Guru})\p{scx=Guru}/u, "\u{10496}"); + f(/(?=\P{sc=Guru})\p{scx=Guru}/u, "\u{10ad15}"); + // Script_Extension=Mult + f(/(?=\P{sc=Mult})\p{scx=Mult}/u, "\u{2794e}"); + f(/(?=\P{sc=Mult})\p{scx=Mult}/u, "\u{2f6b4}"); + f(/(?=\P{sc=Mult})\p{scx=Mult}/u, "\u{d50f2}"); + f(/(?=\P{sc=Mult})\p{scx=Mult}/u, "\u{62dac}"); + f(/(?=\P{sc=Mult})\p{scx=Mult}/u, "\u{ad0b2}"); + // Script_Extension=Hira + f(/(?=\P{sc=Hira})\p{scx=Hira}/u, "\u{be070}"); + f(/(?=\P{sc=Hira})\p{scx=Hira}/u, "\u{d2d48}"); + f(/(?=\P{sc=Hira})\p{scx=Hira}/u, "\u{ec3a2}"); + f(/(?=\P{sc=Hira})\p{scx=Hira}/u, "\u{b2f9d}"); + f(/(?=\P{sc=Hira})\p{scx=Hira}/u, "\u{4b539}"); + // Script_Extension=Kana + f(/(?=\P{sc=Kana})\p{scx=Kana}/u, "\u{545d5}"); + f(/(?=\P{sc=Kana})\p{scx=Kana}/u, "\u{23e9d}"); + f(/(?=\P{sc=Kana})\p{scx=Kana}/u, "\u{104ba8}"); + f(/(?=\P{sc=Kana})\p{scx=Kana}/u, "\u{dc9d5}"); + f(/(?=\P{sc=Kana})\p{scx=Kana}/u, "\u{8229c}"); + // Script_Extension=Mong + f(/(?=\P{sc=Mong})\p{scx=Mong}/u, "\u{3b0ad}"); + f(/(?=\P{sc=Mong})\p{scx=Mong}/u, "\u{d9402}"); + f(/(?=\P{sc=Mong})\p{scx=Mong}/u, "\u{8f4ae}"); + f(/(?=\P{sc=Mong})\p{scx=Mong}/u, "\u{18b7d}"); + f(/(?=\P{sc=Mong})\p{scx=Mong}/u, "\u{e0393}"); + // Script_Extension=Phag + f(/(?=\P{sc=Phag})\p{scx=Phag}/u, "\u{3eb13}"); + f(/(?=\P{sc=Phag})\p{scx=Phag}/u, "\u{273e7}"); + f(/(?=\P{sc=Phag})\p{scx=Phag}/u, "\u{d7ad4}"); + f(/(?=\P{sc=Phag})\p{scx=Phag}/u, "\u{80daf}"); + f(/(?=\P{sc=Phag})\p{scx=Phag}/u, "\u{bd1ad}"); + // Script_Extension=Cakm + f(/(?=\P{sc=Cakm})\p{scx=Cakm}/u, "\u{19eeb}"); + f(/(?=\P{sc=Cakm})\p{scx=Cakm}/u, "\u{19dab}"); + f(/(?=\P{sc=Cakm})\p{scx=Cakm}/u, "\u{f3a42}"); + f(/(?=\P{sc=Cakm})\p{scx=Cakm}/u, "\u{455c7}"); + f(/(?=\P{sc=Cakm})\p{scx=Cakm}/u, "\u{baa96}"); + // Script_Extension=Sylo + f(/(?=\P{sc=Sylo})\p{scx=Sylo}/u, "\u{54d3}"); + f(/(?=\P{sc=Sylo})\p{scx=Sylo}/u, "\u{283e9}"); + f(/(?=\P{sc=Sylo})\p{scx=Sylo}/u, "\u{edab9}"); + f(/(?=\P{sc=Sylo})\p{scx=Sylo}/u, "\u{e135d}"); + f(/(?=\P{sc=Sylo})\p{scx=Sylo}/u, "\u{31bc2}"); + // Script_Extension=Mymr + f(/(?=\P{sc=Mymr})\p{scx=Mymr}/u, "\u{9d605}"); + f(/(?=\P{sc=Mymr})\p{scx=Mymr}/u, "\u{109cae}"); + f(/(?=\P{sc=Mymr})\p{scx=Mymr}/u, "\u{cc2dd}"); + f(/(?=\P{sc=Mymr})\p{scx=Mymr}/u, "\u{d1757}"); + f(/(?=\P{sc=Mymr})\p{scx=Mymr}/u, "\u{baaff}"); + // Script_Extension=Tale + f(/(?=\P{sc=Tale})\p{scx=Tale}/u, "\u{81845}"); + f(/(?=\P{sc=Tale})\p{scx=Tale}/u, "\u{fe9d6}"); + f(/(?=\P{sc=Tale})\p{scx=Tale}/u, "\u{8c1a0}"); + f(/(?=\P{sc=Tale})\p{scx=Tale}/u, "\u{f1a55}"); + f(/(?=\P{sc=Tale})\p{scx=Tale}/u, "\u{a8f6}"); + // Script_Extension=Lina + f(/(?=\P{sc=Lina})\p{scx=Lina}/u, "\u{e3554}"); + f(/(?=\P{sc=Lina})\p{scx=Lina}/u, "\u{e7555}"); + f(/(?=\P{sc=Lina})\p{scx=Lina}/u, "\u{29fc1}"); + f(/(?=\P{sc=Lina})\p{scx=Lina}/u, "\u{3fe04}"); + f(/(?=\P{sc=Lina})\p{scx=Lina}/u, "\u{df6e2}"); + // Script_Extension=Knda + f(/(?=\P{sc=Knda})\p{scx=Knda}/u, "\u{36afd}"); + f(/(?=\P{sc=Knda})\p{scx=Knda}/u, "\u{72966}"); + f(/(?=\P{sc=Knda})\p{scx=Knda}/u, "\u{531de}"); + f(/(?=\P{sc=Knda})\p{scx=Knda}/u, "\u{cd350}"); + f(/(?=\P{sc=Knda})\p{scx=Knda}/u, "\u{4081f}"); + // Script_Extension=Kali + f(/(?=\P{sc=Kali})\p{scx=Kali}/u, "\u{2cc77}"); + f(/(?=\P{sc=Kali})\p{scx=Kali}/u, "\u{7973a}"); + f(/(?=\P{sc=Kali})\p{scx=Kali}/u, "\u{d67e0}"); + f(/(?=\P{sc=Kali})\p{scx=Kali}/u, "\u{6f0a6}"); + f(/(?=\P{sc=Kali})\p{scx=Kali}/u, "\u{130b7}"); + // Script_Extension=Buhd + f(/(?=\P{sc=Buhd})\p{scx=Buhd}/u, "\u{91a77}"); + f(/(?=\P{sc=Buhd})\p{scx=Buhd}/u, "\u{dad60}"); + f(/(?=\P{sc=Buhd})\p{scx=Buhd}/u, "\u{10577d}"); + f(/(?=\P{sc=Buhd})\p{scx=Buhd}/u, "\u{107c7d}"); + f(/(?=\P{sc=Buhd})\p{scx=Buhd}/u, "\u{6d43d}"); + // Script_Extension=Hano + f(/(?=\P{sc=Hano})\p{scx=Hano}/u, "\u{7e942}"); + f(/(?=\P{sc=Hano})\p{scx=Hano}/u, "\u{b0a24}"); + f(/(?=\P{sc=Hano})\p{scx=Hano}/u, "\u{106205}"); + f(/(?=\P{sc=Hano})\p{scx=Hano}/u, "\u{4ac72}"); + f(/(?=\P{sc=Hano})\p{scx=Hano}/u, "\u{e6681}"); + // Script_Extension=Tagb + f(/(?=\P{sc=Tagb})\p{scx=Tagb}/u, "\u{dd8fa}"); + f(/(?=\P{sc=Tagb})\p{scx=Tagb}/u, "\u{e622d}"); + f(/(?=\P{sc=Tagb})\p{scx=Tagb}/u, "\u{d43fb}"); + f(/(?=\P{sc=Tagb})\p{scx=Tagb}/u, "\u{10ba23}"); + f(/(?=\P{sc=Tagb})\p{scx=Tagb}/u, "\u{bfbce}"); + // Script_Extension=Tglg + f(/(?=\P{sc=Tglg})\p{scx=Tglg}/u, "\u{bb9f4}"); + f(/(?=\P{sc=Tglg})\p{scx=Tglg}/u, "\u{cb69f}"); + f(/(?=\P{sc=Tglg})\p{scx=Tglg}/u, "\u{5bb3f}"); + f(/(?=\P{sc=Tglg})\p{scx=Tglg}/u, "\u{b6f43}"); + f(/(?=\P{sc=Tglg})\p{scx=Tglg}/u, "\u{d013b}"); + // Script_Extension=Dogr + f(/(?=\P{sc=Dogr})\p{scx=Dogr}/u, "\u{2d845}"); + f(/(?=\P{sc=Dogr})\p{scx=Dogr}/u, "\u{1a910}"); + f(/(?=\P{sc=Dogr})\p{scx=Dogr}/u, "\u{3ba2a}"); + f(/(?=\P{sc=Dogr})\p{scx=Dogr}/u, "\u{bde46}"); + f(/(?=\P{sc=Dogr})\p{scx=Dogr}/u, "\u{108e84}"); + // Script_Extension=Kthi + f(/(?=\P{sc=Kthi})\p{scx=Kthi}/u, "\u{10dd0}"); + f(/(?=\P{sc=Kthi})\p{scx=Kthi}/u, "\u{5484b}"); + f(/(?=\P{sc=Kthi})\p{scx=Kthi}/u, "\u{3aed6}"); + f(/(?=\P{sc=Kthi})\p{scx=Kthi}/u, "\u{1e733}"); + f(/(?=\P{sc=Kthi})\p{scx=Kthi}/u, "\u{9448f}"); + // Script_Extension=Mahj + f(/(?=\P{sc=Mahj})\p{scx=Mahj}/u, "\u{a2006}"); + f(/(?=\P{sc=Mahj})\p{scx=Mahj}/u, "\u{184cd}"); + f(/(?=\P{sc=Mahj})\p{scx=Mahj}/u, "\u{575ba}"); + f(/(?=\P{sc=Mahj})\p{scx=Mahj}/u, "\u{1005cb}"); + f(/(?=\P{sc=Mahj})\p{scx=Mahj}/u, "\u{c2d02}"); + // Script_Extension=Hang + f(/(?=\P{sc=Hang})\p{scx=Hang}/u, "\u{b42fb}"); + f(/(?=\P{sc=Hang})\p{scx=Hang}/u, "\u{15eff}"); + f(/(?=\P{sc=Hang})\p{scx=Hang}/u, "\u{cc05b}"); + f(/(?=\P{sc=Hang})\p{scx=Hang}/u, "\u{85919}"); + f(/(?=\P{sc=Hang})\p{scx=Hang}/u, "\u{c27ea}"); + // Script_Extension=Yiii + f(/(?=\P{sc=Yiii})\p{scx=Yiii}/u, "\u{b9c10}"); + f(/(?=\P{sc=Yiii})\p{scx=Yiii}/u, "\u{55fef}"); + f(/(?=\P{sc=Yiii})\p{scx=Yiii}/u, "\u{fe59b}"); + f(/(?=\P{sc=Yiii})\p{scx=Yiii}/u, "\u{ffd82}"); + f(/(?=\P{sc=Yiii})\p{scx=Yiii}/u, "\u{7df88}"); + // Script_Extension=Mlym + f(/(?=\P{sc=Mlym})\p{scx=Mlym}/u, "\u{38ca6}"); + f(/(?=\P{sc=Mlym})\p{scx=Mlym}/u, "\u{b536b}"); + f(/(?=\P{sc=Mlym})\p{scx=Mlym}/u, "\u{d73c3}"); + f(/(?=\P{sc=Mlym})\p{scx=Mlym}/u, "\u{ef7c}"); + f(/(?=\P{sc=Mlym})\p{scx=Mlym}/u, "\u{54f11}"); + // Script_Extension=Orya + f(/(?=\P{sc=Orya})\p{scx=Orya}/u, "\u{103437}"); + f(/(?=\P{sc=Orya})\p{scx=Orya}/u, "\u{6db9f}"); + f(/(?=\P{sc=Orya})\p{scx=Orya}/u, "\u{c0cbf}"); + f(/(?=\P{sc=Orya})\p{scx=Orya}/u, "\u{693e6}"); + f(/(?=\P{sc=Orya})\p{scx=Orya}/u, "\u{107f31}"); + // Script_Extension=Telu + f(/(?=\P{sc=Telu})\p{scx=Telu}/u, "\u{4565}"); + f(/(?=\P{sc=Telu})\p{scx=Telu}/u, "\u{92ad2}"); + f(/(?=\P{sc=Telu})\p{scx=Telu}/u, "\u{7de0b}"); + f(/(?=\P{sc=Telu})\p{scx=Telu}/u, "\u{bc7b2}"); + f(/(?=\P{sc=Telu})\p{scx=Telu}/u, "\u{9edd7}"); + // Script_Extension=Adlm + f(/(?=\P{sc=Adlm})\p{scx=Adlm}/u, "\u{8be77}"); + f(/(?=\P{sc=Adlm})\p{scx=Adlm}/u, "\u{31dbb}"); + f(/(?=\P{sc=Adlm})\p{scx=Adlm}/u, "\u{f2854}"); + f(/(?=\P{sc=Adlm})\p{scx=Adlm}/u, "\u{10a682}"); + f(/(?=\P{sc=Adlm})\p{scx=Adlm}/u, "\u{eba94}"); + // Script_Extension=Mand + f(/(?=\P{sc=Mand})\p{scx=Mand}/u, "\u{180bd}"); + f(/(?=\P{sc=Mand})\p{scx=Mand}/u, "\u{98fb9}"); + f(/(?=\P{sc=Mand})\p{scx=Mand}/u, "\u{aaa0c}"); + f(/(?=\P{sc=Mand})\p{scx=Mand}/u, "\u{de7c8}"); + f(/(?=\P{sc=Mand})\p{scx=Mand}/u, "\u{e27ed}"); + // Script_Extension=Mani + f(/(?=\P{sc=Mani})\p{scx=Mani}/u, "\u{88d89}"); + f(/(?=\P{sc=Mani})\p{scx=Mani}/u, "\u{2102d}"); + f(/(?=\P{sc=Mani})\p{scx=Mani}/u, "\u{35a92}"); + f(/(?=\P{sc=Mani})\p{scx=Mani}/u, "\u{1e78e}"); + f(/(?=\P{sc=Mani})\p{scx=Mani}/u, "\u{6afba}"); + // Script_Extension=Phlp + f(/(?=\P{sc=Phlp})\p{scx=Phlp}/u, "\u{10677d}"); + f(/(?=\P{sc=Phlp})\p{scx=Phlp}/u, "\u{31238}"); + f(/(?=\P{sc=Phlp})\p{scx=Phlp}/u, "\u{62ae}"); + f(/(?=\P{sc=Phlp})\p{scx=Phlp}/u, "\u{88872}"); + f(/(?=\P{sc=Phlp})\p{scx=Phlp}/u, "\u{9720e}"); + // Script_Extension=Sogd + f(/(?=\P{sc=Sogd})\p{scx=Sogd}/u, "\u{4c593}"); + f(/(?=\P{sc=Sogd})\p{scx=Sogd}/u, "\u{74ba6}"); + f(/(?=\P{sc=Sogd})\p{scx=Sogd}/u, "\u{f97a0}"); + f(/(?=\P{sc=Sogd})\p{scx=Sogd}/u, "\u{62e97}"); + f(/(?=\P{sc=Sogd})\p{scx=Sogd}/u, "\u{d2895}"); + // Script_Extension=Modi + f(/(?=\P{sc=Modi})\p{scx=Modi}/u, "\u{107b3}"); + f(/(?=\P{sc=Modi})\p{scx=Modi}/u, "\u{c6ffe}"); + f(/(?=\P{sc=Modi})\p{scx=Modi}/u, "\u{57254}"); + f(/(?=\P{sc=Modi})\p{scx=Modi}/u, "\u{3a9de}"); + f(/(?=\P{sc=Modi})\p{scx=Modi}/u, "\u{bb58d}"); + // Script_Extension=Sind + f(/(?=\P{sc=Sind})\p{scx=Sind}/u, "\u{b2f72}"); + f(/(?=\P{sc=Sind})\p{scx=Sind}/u, "\u{f7673}"); + f(/(?=\P{sc=Sind})\p{scx=Sind}/u, "\u{b2066}"); + f(/(?=\P{sc=Sind})\p{scx=Sind}/u, "\u{22ea9}"); + f(/(?=\P{sc=Sind})\p{scx=Sind}/u, "\u{492a}"); + // Script_Extension=Takr + f(/(?=\P{sc=Takr})\p{scx=Takr}/u, "\u{89a3a}"); + f(/(?=\P{sc=Takr})\p{scx=Takr}/u, "\u{2c9bb}"); + f(/(?=\P{sc=Takr})\p{scx=Takr}/u, "\u{60523}"); + f(/(?=\P{sc=Takr})\p{scx=Takr}/u, "\u{86916}"); + f(/(?=\P{sc=Takr})\p{scx=Takr}/u, "\u{ce4af}"); + // Script_Extension=Tirh + f(/(?=\P{sc=Tirh})\p{scx=Tirh}/u, "\u{2905}"); + f(/(?=\P{sc=Tirh})\p{scx=Tirh}/u, "\u{900cf}"); + f(/(?=\P{sc=Tirh})\p{scx=Tirh}/u, "\u{4b07a}"); + f(/(?=\P{sc=Tirh})\p{scx=Tirh}/u, "\u{2319}"); + f(/(?=\P{sc=Tirh})\p{scx=Tirh}/u, "\u{69d82}"); + // Script_Extension=Gong + f(/(?=\P{sc=Gong})\p{scx=Gong}/u, "\u{3ce05}"); + f(/(?=\P{sc=Gong})\p{scx=Gong}/u, "\u{362e8}"); + f(/(?=\P{sc=Gong})\p{scx=Gong}/u, "\u{fe0b9}"); + f(/(?=\P{sc=Gong})\p{scx=Gong}/u, "\u{99c0c}"); + f(/(?=\P{sc=Gong})\p{scx=Gong}/u, "\u{10a9c2}"); + // Script_Extension=Sinh + f(/(?=\P{sc=Sinh})\p{scx=Sinh}/u, "\u{8ac14}"); + f(/(?=\P{sc=Sinh})\p{scx=Sinh}/u, "\u{fea84}"); + f(/(?=\P{sc=Sinh})\p{scx=Sinh}/u, "\u{5f107}"); + f(/(?=\P{sc=Sinh})\p{scx=Sinh}/u, "\u{7ed82}"); + f(/(?=\P{sc=Sinh})\p{scx=Sinh}/u, "\u{1b5b4}"); + // Script_Extension=Limb + f(/(?=\P{sc=Limb})\p{scx=Limb}/u, "\u{36208}"); + f(/(?=\P{sc=Limb})\p{scx=Limb}/u, "\u{dff4e}"); + f(/(?=\P{sc=Limb})\p{scx=Limb}/u, "\u{fb421}"); + f(/(?=\P{sc=Limb})\p{scx=Limb}/u, "\u{5e20e}"); + f(/(?=\P{sc=Limb})\p{scx=Limb}/u, "\u{b6402}"); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-property-scripts.js b/Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-property-scripts.js new file mode 100644 index 00000000000..69bf60f4c86 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-property-scripts.js @@ -0,0 +1,107 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("harmony/regexp-property-scripts", () => { + function t(re, s) { + assertTrue(re.test(s)); + } + function f(re, s) { + assertFalse(re.test(s)); + } + + t(/\p{Script=Common}+/u, "."); + f(/\p{Script=Common}+/u, "supercalifragilisticexpialidocious"); + + t(/\p{Script=Han}+/u, "话说天下大势,分久必合,合久必分"); + t(/\p{Script=Hani}+/u, "吾庄后有一桃园,花开正盛"); + f(/\p{Script=Han}+/u, "おはようございます"); + f(/\p{Script=Hani}+/u, "Something is rotten in the state of Denmark"); + + t(/\p{Script=Latin}+/u, "Wie froh bin ich, daß ich weg bin!"); + t(/\p{Script=Latn}+/u, "It was a bright day in April, and the clocks were striking thirteen"); + f(/\p{Script=Latin}+/u, "奔腾千里荡尘埃,渡水登山紫雾开"); + f(/\p{Script=Latn}+/u, "いただきます"); + + t(/\p{sc=Hiragana}/u, "いただきます"); + t(/\p{sc=Hira}/u, "ありがとうございました"); + f(/\p{sc=Hiragana}/u, "Als Gregor Samsa eines Morgens aus unruhigen Träumen erwachte"); + f(/\p{sc=Hira}/u, "Call me Ishmael"); + + t(/\p{sc=Phoenician}/u, "\u{10900}\u{1091a}"); + t(/\p{sc=Phnx}/u, "\u{1091f}\u{10916}"); + f(/\p{sc=Phoenician}/u, "Arthur est un perroquet"); + f(/\p{sc=Phnx}/u, "设心狠毒非良士,操卓原来一路人"); + + t(/\p{sc=Grek}/u, "ἄνδρα μοι ἔννεπε, μοῦσα, πολύτροπον, ὃς μάλα πολλὰ"); + t(/\p{sc=Greek}/u, "μῆνιν ἄειδε θεὰ Πηληϊάδεω Ἀχιλῆος"); + f(/\p{sc=Greek}/u, "高贤未服英雄志,屈节偏生杰士疑"); + f(/\p{sc=Greek}/u, "Mr. Jones, of the Manor Farm, had locked the hen-houses for the night"); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-property-special.js b/Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-property-special.js new file mode 100644 index 00000000000..e70c0516a78 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-property-special.js @@ -0,0 +1,144 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("harmony/regexp-property-special", () => { + function t(re, s) { + assertTrue(re.test(s)); + } + function f(re, s) { + assertFalse(re.test(s)); + } + + t(/\p{ASCII}+/u, "abc123"); + f(/\p{ASCII}+/u, "ⓐⓑⓒ①②③"); + f(/\p{ASCII}+/u, "🄰🄱🄲①②③"); + f(/\P{ASCII}+/u, "abcd123"); + t(/\P{ASCII}+/u, "ⓐⓑⓒ①②③"); + t(/\P{ASCII}+/u, "🄰🄱🄲①②③"); + + f(/[^\p{ASCII}]+/u, "abc123"); + f(/[\p{ASCII}]+/u, "ⓐⓑⓒ①②③"); + f(/[\p{ASCII}]+/u, "🄰🄱🄲①②③"); + t(/[^\P{ASCII}]+/u, "abcd123"); + t(/[\P{ASCII}]+/u, "ⓐⓑⓒ①②③"); + f(/[^\P{ASCII}]+/u, "🄰🄱🄲①②③"); + + t(/\p{Any}+/u, "🄰🄱🄲①②③"); + + assertEquals(["\ud800"], /\p{Any}/u.exec("\ud800\ud801")); + assertEquals(["\udc00"], /\p{Any}/u.exec("\udc00\udc01")); + assertEquals(["\ud800\udc01"], /\p{Any}/u.exec("\ud800\udc01")); + assertEquals(["\udc01"], /\p{Any}/u.exec("\udc01")); + + f(/\P{Any}+/u, "123"); + f(/[\P{Any}]+/u, "123"); + t(/[\P{Any}\d]+/u, "123"); + t(/[^\P{Any}]+/u, "123"); + + t(/\p{Assigned}+/u, "123"); + t(/\p{Assigned}+/u, "🄰🄱🄲"); + f(/\p{Assigned}+/u, "\ufdd0"); + f(/\p{Assigned}+/u, "\u{fffff}"); + + f(/\P{Assigned}+/u, "123"); + f(/\P{Assigned}+/u, "🄰🄱🄲"); + t(/\P{Assigned}+/u, "\ufdd0"); + t(/\P{Assigned}+/u, "\u{fffff}"); + f(/\P{Assigned}/u, ""); + + t(/[^\P{Assigned}]+/u, "123"); + f(/[\P{Assigned}]+/u, "🄰🄱🄲"); + f(/[^\P{Assigned}]+/u, "\ufdd0"); + t(/[\P{Assigned}]+/u, "\u{fffff}"); + f(/[\P{Assigned}]/u, ""); + + f(/[^\u1234\p{ASCII}]+/u, "\u1234"); + t(/[x\P{ASCII}]+/u, "x"); + t(/[\u1234\p{ASCII}]+/u, "\u1234"); + + // Contributory binary properties are not supported. + assertThrows("/\\p{Other_Alphabetic}/u"); + assertThrows("/\\P{OAlpha}/u"); + assertThrows("/\\p{Other_Default_Ignorable_Code_Point}/u"); + assertThrows("/\\P{ODI}/u"); + assertThrows("/\\p{Other_Grapheme_Extend}/u"); + assertThrows("/\\P{OGr_Ext}/u"); + assertThrows("/\\p{Other_ID_Continue}/u"); + assertThrows("/\\P{OIDC}/u"); + assertThrows("/\\p{Other_ID_Start}/u"); + assertThrows("/\\P{OIDS}/u"); + assertThrows("/\\p{Other_Lowercase}/u"); + assertThrows("/\\P{OLower}/u"); + assertThrows("/\\p{Other_Math}/u"); + assertThrows("/\\P{OMath}/u"); + assertThrows("/\\p{Other_Uppercase}/u"); + assertThrows("/\\P{OUpper}/u"); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/regexp-UC16.js b/Tests/LibJS/Runtime/3rdparty/v8/regexp-UC16.js new file mode 100644 index 00000000000..6c4326d9a13 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/regexp-UC16.js @@ -0,0 +1,126 @@ +// Copyright 2008 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test.xfail("regexp-UC16", () => { + assertEquals("x\u03a3\u03c3x,\u03a3", String(/x(.)\1x/i.exec("x\u03a3\u03c3x")), "backref-UC16"); + assertFalse(/x(...)\1/i.test("x\u03a3\u03c2\u03c3\u03c2\u03c3"), "\\1 ASCII, string short"); + assertTrue(/\u03a3((?:))\1\1x/i.test("\u03c2x"), "backref-UC16-empty"); + assertTrue(/x(?:...|(...))\1x/i.test("x\u03a3\u03c2\u03c3x"), "backref-UC16-uncaptured"); + assertTrue(/x(?:...|(...))\1x/i.test("x\u03c2\u03c3\u039b\u03a3\u03c2\u03bbx"), "backref-UC16-backtrack"); + var longUC16String = "x\u03a3\u03c2\u039b\u03c2\u03c3\u03bb\u03c3\u03a3\u03bb"; + assertEquals( + longUC16String + "," + longUC16String.substring(1, 4), + String(/x(...)\1\1/i.exec(longUC16String)), + "backref-UC16-twice" + ); + + assertFalse(/\xc1/i.test("fooA"), "quickcheck-uc16-pattern-ascii-subject"); + assertFalse(/[\xe9]/.test("i"), "charclass-uc16-pattern-ascii-subject"); + assertFalse(/\u5e74|\u6708/.test("t"), "alternation-uc16-pattern-ascii-subject"); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/regexp-boyer-moore.js b/Tests/LibJS/Runtime/3rdparty/v8/regexp-boyer-moore.js new file mode 100644 index 00000000000..5f4fbdf262e --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/regexp-boyer-moore.js @@ -0,0 +1,99 @@ +// Copyright 2025 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("regexp-boyer-moore", () => { + function UseSpecialBytecode() { + // Trigger the single-position Boyer-Moore optimization. + var re = /.......a[^l]/; + subject = "Now is the time for all good men"; + for (var i = 0; i < 5; i++) subject += subject; + for (var i = 0; i < 5; i++) { + re.test(subject); + } + } + + UseSpecialBytecode(); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/regexp-cache-replace.js b/Tests/LibJS/Runtime/3rdparty/v8/regexp-cache-replace.js new file mode 100644 index 00000000000..e326d95577a --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/regexp-cache-replace.js @@ -0,0 +1,118 @@ +// Copyright 2010 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("regexp-cache-replace", () => { + var re1 = /(o)/g; + assertEquals("FxxBar", "FooBar".replace(re1, "x")); + assertEquals("o", RegExp.$1); + assertTrue(/(x)/.test("abcxdef")); + assertEquals("x", RegExp.$1); + assertEquals("FxxBar", "FooBar".replace(re1, "x")); + assertEquals("o", RegExp.$1); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/regexp-call-as-function.js b/Tests/LibJS/Runtime/3rdparty/v8/regexp-call-as-function.js new file mode 100644 index 00000000000..34991b93cd0 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/regexp-call-as-function.js @@ -0,0 +1,118 @@ +// Copyright 2009 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("regexp-call-as-function", () => { + var regexp = /a(b)(c)/; + var subject = "xyzabcde"; + var expected = "abc,b,c"; + assertEquals(expected, String(regexp.exec(subject))); + assertThrows(function () { + regexp(subject); + }); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/regexp-capture-3.js b/Tests/LibJS/Runtime/3rdparty/v8/regexp-capture-3.js new file mode 100644 index 00000000000..667199f4706 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/regexp-capture-3.js @@ -0,0 +1,339 @@ +// Copyright 2012 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test.skip("regexp-capture-3", () => { + function oneMatch(re) { + "abcd".replace(re, function () {}); + assertEquals("abcd", RegExp.input); + assertEquals("a", RegExp.leftContext); + assertEquals("b", RegExp.lastMatch); + assertEquals("", RegExp.lastParen); + assertEquals(undefined, RegExp.lastIndex); + assertEquals(undefined, RegExp.index); + assertEquals("cd", RegExp.rightContext); + for (var i = 1; i < 10; i++) { + assertEquals("", RegExp["$" + i]); + } + } + + oneMatch(/b/); + oneMatch(/b/g); + + "abcdabcd".replace(/b/g, function () {}); + assertEquals("abcdabcd", RegExp.input); + assertEquals("abcda", RegExp.leftContext); + assertEquals("b", RegExp.lastMatch); + assertEquals("", RegExp.lastParen); + assertEquals(undefined, RegExp.lastIndex); + assertEquals(undefined, RegExp.index); + assertEquals("cd", RegExp.rightContext); + for (var i = 1; i < 10; i++) { + assertEquals("", RegExp["$" + i]); + } + + function captureMatch(re) { + "abcd".replace(re, function () {}); + assertEquals("abcd", RegExp.input); + assertEquals("a", RegExp.leftContext); + assertEquals("bc", RegExp.lastMatch); + assertEquals("c", RegExp.lastParen); + assertEquals(undefined, RegExp.lastIndex); + assertEquals(undefined, RegExp.index); + assertEquals("d", RegExp.rightContext); + assertEquals("b", RegExp.$1); + assertEquals("c", RegExp.$2); + for (var i = 3; i < 10; i++) { + assertEquals("", RegExp["$" + i]); + } + } + + captureMatch(/(b)(c)/); + captureMatch(/(b)(c)/g); + + "abcdabcd".replace(/(b)(c)/g, function () {}); + assertEquals("abcdabcd", RegExp.input); + assertEquals("abcda", RegExp.leftContext); + assertEquals("bc", RegExp.lastMatch); + assertEquals("c", RegExp.lastParen); + assertEquals(undefined, RegExp.lastIndex); + assertEquals(undefined, RegExp.index); + assertEquals("d", RegExp.rightContext); + assertEquals("b", RegExp.$1); + assertEquals("c", RegExp.$2); + for (var i = 3; i < 10; i++) { + assertEquals("", RegExp["$" + i]); + } + + function Override() { + // Set the internal lastMatchInfoOverride. After calling this we do a normal + // match and verify the override was cleared and that we record the new + // captures. + "abcdabcd".replace(/(b)(c)/g, function () {}); + } + + function TestOverride(input, expect, property, re_src) { + var re = new RegExp(re_src); + var re_g = new RegExp(re_src, "g"); + + function OverrideCase(fn) { + Override(); + fn(); + assertEquals(expect, RegExp[property]); + } + + OverrideCase(function () { + return input.replace(re, "x"); + }); + OverrideCase(function () { + return input.replace(re_g, "x"); + }); + OverrideCase(function () { + return input.replace(re, ""); + }); + OverrideCase(function () { + return input.replace(re_g, ""); + }); + OverrideCase(function () { + return input.match(re); + }); + OverrideCase(function () { + return input.match(re_g); + }); + OverrideCase(function () { + return re.test(input); + }); + OverrideCase(function () { + return re_g.test(input); + }); + } + + var input = "bar.foo baz......"; + var re_str = "(ba.).*?f"; + TestOverride(input, "bar", "$1", re_str); + + input = "foo bar baz"; + var re_str = "bar"; + TestOverride(input, "bar", "$&", re_str); + + function no_last_match(fn) { + fn(); + assertEquals("hestfisk", RegExp.$1); + } + + /(hestfisk)/.test("There's no such thing as a hestfisk!"); + + no_last_match(function () { + "foo".replace("f", ""); + }); + no_last_match(function () { + "foo".replace("f", "f"); + }); + no_last_match(function () { + "foo".split("o"); + }); + + var base = "In the music. In the music. "; + var cons = base + base + base + base; + no_last_match(function () { + cons.replace("x", "y"); + }); + no_last_match(function () { + cons.replace("e", "E"); + }); + + // Here's one that matches once, then tries to match again, but fails. + // Verify that the last match info is from the last match, not from the + // failure that came after. + "bar.foo baz......".replace(/(ba.).*?f/g, function () { + return "x"; + }); + assertEquals("bar", RegExp.$1); + + // A test that initially does a zero width match, but later does a non-zero + // width match. + var a = "foo bar baz".replace(/^|bar/g, ""); + assertEquals("foo baz", a); + + a = "foo bar baz".replace(/^|bar/g, "*"); + assertEquals("*foo * baz", a); + + // We test ToNode's filtering of nodes that can't match in one-byte mode, using + // regexps that will backtrack forever. Since a regexp with a non-Latin1 + // character in it can never match an Latin1 string we can test that the + // relevant node is removed by verifying that there is no hang. + function NoHang(re) { + "This is an ASCII string that could take forever".match(re); + } + + NoHang(/(((.*)*)*x)Ā/); // Continuation after loop is filtered, so is loop. + NoHang(/(((.*)*)*Ā)foo/); // Body of loop filtered. + NoHang(/Ā(((.*)*)*x)/); // Everything after a filtered character is filtered. + NoHang(/(((.*)*)*x)Ā/); // Everything before a filtered character is filtered. + NoHang(/[ćăĀ](((.*)*)*x)/); // Everything after a filtered class is filtered. + NoHang(/(((.*)*)*x)[ćăĀ]/); // Everything before a filtered class is filtered. + NoHang(/[^\x00-\xff](((.*)*)*x)/); // After negated class. + NoHang(/(((.*)*)*x)[^\x00-\xff]/); // Before negated class. + NoHang(/(?!(((.*)*)*x)Ā)foo/); // Negative lookahead is filtered. + NoHang(/(?!(((.*)*)*x))Ā/); // Continuation branch of negative lookahead. + NoHang(/(?=(((.*)*)*x)Ā)foo/); // Positive lookahead is filtered. + NoHang(/(?=(((.*)*)*x))Ā/); // Continuation branch of positive lookahead. + NoHang(/(?=Ā)(((.*)*)*x)/); // Positive lookahead also prunes continuation. + NoHang(/(æ|ø|Ā)(((.*)*)*x)/); // All branches of alternation are filtered. + NoHang(/(a|b|(((.*)*)*x))Ā/); // 1 out of 3 branches pruned. + NoHang(/(a|(((.*)*)*x)ă|(((.*)*)*x)Ā)/); // 2 out of 3 branches pruned. + NoHang(/(((.*)*)*x)Ā{2}/); // Unrolled loop. + NoHang(/(((.*)*)*x)Ā{2,}/); // Unrolled min. + NoHang(/(((.*)*)*x)Ā{5,10}/); // Loop with high min and max. + NoHang(/(((.*)*)*x)Ā{5,}/); // Loop with high min and infinite max. + NoHang(/(((.*)*)*x).{2}Ā/); // Successor of unrolled loop. + NoHang(/(((.*)*)*x).{2,}Ā/); // Successor of unrolled loop. + NoHang(/(((.*)*)*x).{2,10}Ā/); // Successor of unrolled loop. + NoHang(/(((.*)*)*x).{0,2}Ā/); // Successor of unrolled loop. + NoHang(/(((.*)*)*x).{5,10}Ā/); // Successor of loop with guards. + NoHang(/(((.*)*)*x)(.?){5,10}Ā/); // Successor of loop with zero length test. + + // Another test of ToNode - the body of the ? quantifier can't match on a + // Latin1 input, but the quantifier still matches. + assertTrue(/\u0100?/.test("abcd")); + + var s = "Don't prune based on a repetition of length 0"; + assertEquals(null, s.match(/å{1,1}prune/)); + assertEquals("prune", s.match(/å{0,0}prune/)[0]); + + // Some very deep regexps where CanMatchLatin1 used to give up in order not to + // make the stack overflow. + var regex6 = /a*\u0100*\w/; + var input0 = "a"; + regex6.exec(input0); + + var re = "\u0100*\\w"; + + for (var i = 0; i < 200; i++) re = "a*" + re; + + var regex7 = new RegExp(re); + regex7.exec(input0); + + var regex8 = new RegExp(re, "i"); + regex8.exec(input0); + + re = "[\u0100]*\\w"; + for (var i = 0; i < 200; i++) re = "a*" + re; + + var regex9 = new RegExp(re); + regex9.exec(input0); + + var regex10 = new RegExp(re, "i"); + regex10.exec(input0); + + var regex11 = /^(?:[^\u0000-\u0080]|[0-9a-z?,.!&\s#()])+$/i; + regex11.exec(input0); + + var regex12 = /u(\xf0{8}?\D*?|( ? !)$h??(|)*?(||)+?\6((?:\W\B|--\d-*-|)?$){0, }?|^Y( ? !1)\d+)+a/; + regex12.exec(""); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/regexp-capture-4.js b/Tests/LibJS/Runtime/3rdparty/v8/regexp-capture-4.js new file mode 100644 index 00000000000..055cb7cf812 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/regexp-capture-4.js @@ -0,0 +1,101 @@ +// Copyright 2025 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("regexp-capture-4", () => { + assertEquals(["xxy", "x"], /^(x)?\1y$/.exec("xxy")); + assertEquals(null, /^(x)?\1y$/.exec("xy")); + assertEquals(["y", undefined], /^(x)?\1y$/.exec("y")); + assertEquals(null, /^(x)?y$/.exec("xxy")); + assertEquals(["xy", "x"], /^(x)?y$/.exec("xy")); + assertEquals(["y", undefined], /^(x)?y$/.exec("y")); + assertEquals(["xyzxyz", "xyz", "y"], /^(x(y)?z){1,2}$/.exec("xyzxyz")); + assertEquals(["xyzxz", "xz", undefined], /^(x(y)?z){1,2}$/.exec("xyzxz")); + assertEquals(["xyz", "xyz", "y"], /^(x(y)?z){1,2}$/.exec("xyz")); + assertEquals(["xX", "x"], /(?:(.)\1)?/i.exec("xX")); + assertEquals(["xzxyz", "xyz", "y"], /^(\2x(y)?z){1,2}$/.exec("xzxyz")); + assertEquals(["xyzxz", "xz", undefined], /^(\2x(y)?z){1,2}$/.exec("xyzxz")); + assertEquals(["xyzxyz", "xyz", "y"], /^(\2x(y)?z){1,2}$/.exec("xyzxyz")); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/regexp-capture.js b/Tests/LibJS/Runtime/3rdparty/v8/regexp-capture.js new file mode 100644 index 00000000000..150be4499de --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/regexp-capture.js @@ -0,0 +1,149 @@ +// Copyright 2009 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test.skip("regexp-capture", () => { + assertEquals(true, /(x)?\1y/.test("y")); + assertEquals(["y", undefined], /(x)?\1y/.exec("y")); + assertEquals(["y", undefined], /(x)?y/.exec("y")); + assertEquals(["y", undefined], "y".match(/(x)?\1y/)); + assertEquals(["y", undefined], "y".match(/(x)?y/)); + assertEquals(["y"], "y".match(/(x)?\1y/g)); + assertEquals(["", undefined, ""], "y".split(/(x)?\1y/)); + assertEquals(["", undefined, ""], "y".split(/(x)?y/)); + assertEquals(0, "y".search(/(x)?\1y/)); + assertEquals("z", "y".replace(/(x)?\1y/, "z")); + assertEquals("", "y".replace(/(x)?y/, "$1")); + assertEquals( + "undefined", + "y".replace(/(x)?\1y/, function ($0, $1) { + return String($1); + }) + ); + assertEquals( + "undefined", + "y".replace(/(x)?y/, function ($0, $1) { + return String($1); + }) + ); + assertEquals( + "undefined", + "y".replace(/(x)?y/, function ($0, $1) { + return $1; + }) + ); + + // See https://bugzilla.mozilla.org/show_bug.cgi?id=476146 + assertEquals(["bbc", "b"], /^(b+|a){1,2}?bc/.exec("bbc")); + assertEquals(["bbaa", "a", "", "a"], /((\3|b)\2(a)){2,}/.exec("bbaababbabaaaaabbaaaabba")); + + // From crbug.com/128821 - don't hang: + "".match( + /((a|i|A|I|u|o|U|O)(s|c|b|c|d|f|g|h|j|k|l|m|n|p|q|r|s|t|v|w|x|y|z|B|C|D|F|G|H|J|K|L|M|N|P|Q|R|S|T|V|W|X|Y|Z)*) de\/da([.,!?\s]|$)/ + ); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/regexp-captures.js b/Tests/LibJS/Runtime/3rdparty/v8/regexp-captures.js new file mode 100644 index 00000000000..e5ea61648f0 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/regexp-captures.js @@ -0,0 +1,116 @@ +// Copyright 2009 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("regexp-captures", () => { + var re = + /^(((N({)?)|(R)|(U)|(V)|(B)|(H)|(n((n)|(r)|(v)|(h))?)|(r(r)?)|(v)|(b((n)|(b))?)|(h))|((Y)|(A)|(E)|(o(u)?)|(p(u)?)|(q(u)?)|(s)|(t)|(u)|(w)|(x(u)?)|(y)|(z)|(a((T)|(A)|(L))?)|(c)|(e)|(f(u)?)|(g(u)?)|(i)|(j)|(l)|(m(u)?)))+/; + var r = new RegExp(re); + var str = "Avtnennan gunzvmu pubExnY nEvln vaTxh rmuhguhaTxnY"; + assertTrue(r.test(str)); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/regexp-compile.js b/Tests/LibJS/Runtime/3rdparty/v8/regexp-compile.js new file mode 100644 index 00000000000..19e51d51338 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/regexp-compile.js @@ -0,0 +1,133 @@ +// Copyright 2008 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("regexp-compile", () => { + var re = /x/; + assertEquals("a.yb", "axyb".replace(re, ".")); + + re.compile("y"); + assertEquals("ax.b", "axyb".replace(re, ".")); + + re.compile("(x)"); + + assertEquals(["x", "x"], re.exec("axyb")); + + re.compile("(y)"); + + assertEquals(["y", "y"], re.exec("axyb")); + + assertEquals(2, re.compile.length); + + // If RegExp parsing fails, the RegExp is not modified + var r = /./; + try { + r.compile("? invalid"); + } catch (err) {} + assertEquals("/./", r.toString()); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/regexp-duplicate-named-groups.js b/Tests/LibJS/Runtime/3rdparty/v8/regexp-duplicate-named-groups.js new file mode 100644 index 00000000000..57bb9c8b45a --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/regexp-duplicate-named-groups.js @@ -0,0 +1,268 @@ +// Copyright 2024 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test.xfail("regexp-duplicate-named-groups", () => { + assertEarlyError("/(?.)(?.)/"); + assertEarlyError("/((?.)(?.))/"); + assertEarlyError("/(?.)((?.))/"); + assertEarlyError("/((?.))(?.)/"); + assertEarlyError("/(?(?.)|.)/"); + assertEarlyError("/(?.|(?.(?.)|.))/"); + assertEarlyError("/(?.)(?:.|(?.)/"); + assertEarlyError("/(?.)(?:.|(?.)/"); + assertEarlyError("/(?.)(?:(.)|(?.)/"); + assertEarlyError("/(?.)(?:(?:.)|(?.)/"); + assertEarlyError("/(?.)((?.)|(?.))/"); + assertEarlyError("/(?.)((?.)|(?.))/"); + assertEarlyError("/((?.)|(?.))(?.)/"); + assertEarlyError("/((?.)|(?.))(?.)/"); + assertEarlyError("/((?.)|((?.)|(?.))(?.)/"); + assertEarlyError("/((?.)|((?.)|(?.))(?.)/"); + assertEarlyError("/x(?.)((((?.)|(?.))|(?.)|(?.))|(?.))|(?.)y/"); + assertEarlyError("/x((?.)(((?.)|(?.))|(?.)|(?.))|(?.))|(?.)y/"); + assertEarlyError("/x(((?.)((?.)|(?.))|(?.)|(?.))|(?.))|(?.)y/"); + assertEarlyError("/x((((?.)(?.)|(?.))|(?.)|(?.))|(?.))|(?.)y/"); + assertEarlyError("/x(?.)|((?.)|(?.)|((?.)|((?.)|(?.)(?.))))y/"); + assertEarlyError("/x(?.)|((?.)|(?.)|((?.)|((?.)|(?.))(?.)|((?.)|(?.)|((?.)|((?.)|(?.)))(?.))y/"); + assertEarlyError("/x(?.)|((?.)|(?.)|((?.)|((?.)|(?.))))(?.)y/"); + + assertEarlyError("/(?.)|(?.)(?:(?.)|(?.)(?:(?.)|(?.)))/"); + assertEarlyError("/(?.)|(?.)(?:(?.)|(?.)(?:(?.)|(?.)))/"); + assertEarlyError("/(?.)|(?.)(?:(?.)|(?.)(?:(?.)|(?.)))/"); + assertEarlyError("/(?.)|(?.)(?:(?.)|(?.)(?:(?.)|(?.)))/"); + assertEarlyError("/(?.)|(?.)(?:(?.)|(?.)(?:(?.)|(?.)))/"); + assertEarlyError("/(?.)|(?.)(?:(?.)|(?.)(?:(?.)|(?.)))/"); + + // Cases with valid duplicate names. + new RegExp("(?.)|(?.)"); + new RegExp("(?.)|(?.)|(?.)|(?.)"); + new RegExp("(?.)|(.)|(?.)"); + new RegExp("(?.(?.))|(?.)"); + new RegExp("(?.)|(?.(?.)|.)"); + new RegExp("(?.)|(?.(?.)|.)"); + new RegExp("(?.(?.))|(?.)|(?.)"); + new RegExp("((?.)|((?.)|(?.))(?.))"); + new RegExp("((?.)|(?.))|(?.)(?.)"); + new RegExp("((?.)|(?.))|(?.)(?.)"); + new RegExp("(?:(?.)|(?.))|(?.)"); + new RegExp("(?.)|(?:(?.)|(?.))"); + new RegExp("x((((?.)|(?.))|(?.)|(?.))|(?.))|(?.)y"); + new RegExp("x(?.)|((?.)|(?.)|((?.)|((?.)|(?.))))y"); + + new RegExp("(?.)|(?.)(?:(?.)|(?.)(?:(?.)|(?.)))"); + new RegExp("(?.)|(?.)(?:(?.)|(?.)(?:(?.)|(?.)))"); + new RegExp("(?.)|(?.)(?:(?.)|(?.)(?:(?.)|(?.)))"); + new RegExp("(?.)|(?.)(?:(?.)|(?.)(?:(?.)|(?.)))"); + new RegExp("(?.)|(?.)(?:(?.)|(?.)(?:(?.)|(?.)))"); + new RegExp("(?.)|(?.)(?:(?.)|(?.)(?:(?.)|(?.)))"); + new RegExp("(?.)|(?.)(?:(?.)|(?.)(?:(?.)|(?.)))"); + new RegExp("(?.)|(?.)(?:(?.)|(?.)(?:(?.)|(?.)))"); + new RegExp("(?.)|(?.)(?:(?.)|(?.)(?:(?.)|(?.)))"); + new RegExp("(?.)|(?.)(?:(?.)|(?.)(?:(?.)|(?.)))"); + new RegExp("(?.)|(?.)(?:(?.)|(?.)(?:(?.)|(?.)))"); + new RegExp("(?.)|(?.)(?:(?.)|(?.)(?:(?.)|(?.)))"); + new RegExp("(?.)|(?.)(?:(?.)|(?.)(?:(?.)|(?.)))"); + + // Test different functions with duplicate names in alteration. + assertEquals(["xxyy", undefined, "y"], /(?:(?:(?x)|(?y))\k){2}/.exec("xxyy")); + assertEquals( + ["zzyyxx", "x", undefined, undefined, undefined, undefined], + /(?:(?:(?x)|(?y)|(a)|(?b)|(?z))\k){3}/.exec("xzzyyxxy") + ); + assertEquals(["xxyy", undefined, "y"], "xxyy".match(/(?:(?:(?x)|(?y))\k){2}/)); + assertEquals( + ["zzyyxx", "x", undefined, undefined, undefined, undefined], + "xzzyyxxy".match(/(?:(?:(?x)|(?y)|(a)|(?b)|(?z))\k){3}/) + ); + assertTrue(/(?:(?:(?x)|(?y))\k){2}/.test("xxyy")); + assertTrue(/(?:(?:(?x)|(?y)|(a)|(?b)|(?z))\k){3}/.test("xzzyyxxy")); + assertFalse(/(?:(?:(?x)|(?y))\k){2}/.test("xyxy")); + assertFalse(/(?:(?:(?x)|(?y)|(a)|(?b)|(?z))\k){3}/.test("xyzxyzxyz")); + assertEquals(3, "abcxyz".search(/(?x)|(?y)/)); + assertEquals(3, "abcxyz".search(/(?y)|(?x)/)); + assertEquals(1, "aybcxyz".search(/(?x)|(?y)/)); + assertEquals(1, "aybcxyz".search(/(?y)|(?x)/)); + assertEquals("2xyy", "xxyy".replace(/(?:(?:(?x)|(?y))\k)/, "2$")); + assertEquals("x2zyyxxy", "xzzyyxxy".replace(/(?:(?:(?x)|(?y)|(a)|(?b)|(?z))\k)/, "2$")); + assertEquals("2x(x,)yy", "xxyy".replace(/(?:(?:(?x)|(?y))\k)/, "2$($1,$2)")); + assertEquals( + "x2z(,,,,z)yyxxy", + "xzzyyxxy".replace(/(?:(?:(?x)|(?y)|(a)|(?b)|(?z))\k)/, "2$($1,$2,$3,$4,$5)") + ); + assertEquals("2x2y", "xxyy".replace(/(?:(?:(?x)|(?y))\k)/g, "2$")); + assertEquals("x2z2y2xy", "xzzyyxxy".replace(/(?:(?:(?x)|(?y)|(a)|(?b)|(?z))\k)/g, "2$")); + assertEquals("2x&2y", "xx&yy".replaceAll(/(?:(?:(?x)|(?y))\k)/g, "2$")); + assertEquals( + "x&2z&2y&2x&y", + "x&zz&yy&xx&y".replaceAll(/(?:(?:(?x)|(?y)|(a)|(?b)|(?z))\k)/g, "2$") + ); + assertEquals(["", "x", undefined, "", undefined, "y", ""], "xxyy".split(/(?:(?:(?x)|(?y))\k)/)); + assertEquals( + [ + "x", + undefined, + undefined, + undefined, + undefined, + "z", + "", + undefined, + "y", + undefined, + undefined, + undefined, + "", + "x", + undefined, + undefined, + undefined, + undefined, + "y", + ], + "xzzyyxxy".split(/(?:(?:(?x)|(?y)|(a)|(?b)|(?z))\k)/) + ); + + function assertMatchAll(matches, expected) { + let i = 0; + for (match of matches) { + assertEquals(expected[i], match); + i++; + } + } + assertMatchAll("xyx".matchAll(/(?x)|(?y)/g), [ + ["x", "x", undefined], + ["y", undefined, "y"], + ["x", "x", undefined], + ]); + assertMatchAll("xyx".matchAll(/(?y)|(?x)/g), [ + ["x", undefined, "x"], + ["y", "y", undefined], + ["x", undefined, "x"], + ]); + + // Property enumeration order of the groups object is based on source order, not + // match order. + assertEquals(["b", "a"], Object.keys(/(?x)(?x)|(?y)(?y)/.exec("xx").groups)); + assertEquals(["b", "a"], Object.keys(/(?x)(?x)|(?y)(?y)/.exec("yy").groups)); + + // Test match indices with duplicate groups. + assertEquals([2, 3], "abxy".match(/(?x)|(?y)/d).indices.groups.a); + assertEquals([2, 3], "bayx".match(/(?x)|(?y)/d).indices.groups.a); + + // Replace with function as replacement. + function testReplaceWithCallback(global) { + let replace_callback_cnt = 0; + + function checkReplace(match, c1, c2, offset, string, groups) { + replace_callback_cnt++; + if (offset == 0) { + // First callback for match 'xx'. + assertEquals("xx", match); + assertEquals("x", c1); + assertEquals(undefined, c2); + assertEquals("xxyy", string); + } else { + // Second callback for match 'yy'. + assertTrue(global); + assertEquals(2, offset); + assertEquals("yy", match); + assertEquals(undefined, c1); + assertEquals("y", c2); + assertEquals("xxyy", string); + } + return "2" + groups.a; + } + + let re = new RegExp("(?:(?:(?x)|(?y))\\k)", global ? "g" : ""); + let expected = global ? "2x2y" : "2xyy"; + assertEquals(expected, "xxyy".replace(re, checkReplace)); + assertEquals(global ? 2 : 1, replace_callback_cnt); + } + + testReplaceWithCallback(false); + testReplaceWithCallback(true); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/regexp-global.js b/Tests/LibJS/Runtime/3rdparty/v8/regexp-global.js new file mode 100644 index 00000000000..f67dbdae4c7 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/regexp-global.js @@ -0,0 +1,351 @@ +// Copyright 2012 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("regexp-global", () => { + var str = "ABX X"; + str = str.replace(/(\w)?X/g, function (match, capture) { + assertTrue(match.indexOf(capture) >= 0 || capture === undefined); + return capture ? capture.toLowerCase() : "-"; + }); + assertEquals("Ab -", str); + + // Test zero-length matches. + str = "Als Gregor Samsa eines Morgens"; + str = str.replace(/\b/g, function (match, capture) { + return "/"; + }); + assertEquals("/Als/ /Gregor/ /Samsa/ /eines/ /Morgens/", str); + + // Test zero-length matches that have non-zero-length sub-captures. + str = "It was a pleasure to burn."; + str = str.replace(/(?=(\w+))\b/g, function (match, capture) { + return capture.length; + }); + assertEquals("2It 3was 1a 8pleasure 2to 4burn.", str); + + // Test multiple captures. + str = "Try not. Do, or do not. There is no try."; + str = str.replace(/(not?)|(do)|(try)/gi, function (match, c1, c2, c3) { + assertTrue( + (c1 === undefined && c2 === undefined) || + (c2 === undefined && c3 === undefined) || + (c1 === undefined && c3 === undefined) + ); + if (c1) return "-"; + if (c2) return "+"; + if (c3) return "="; + }); + assertEquals("= -. +, or + -. There is - =.", str); + + // Test multiple alternate captures. + str = "FOUR LEGS GOOD, TWO LEGS BAD!"; + str = str.replace(/(FOUR|TWO) LEGS (GOOD|BAD)/g, function (match, num_legs, likeability) { + assertTrue(num_legs !== undefined); + assertTrue(likeability !== undefined); + if (num_legs == "FOUR") assertTrue(likeability == "GOOD"); + if (num_legs == "TWO") assertTrue(likeability == "BAD"); + return match.length - 10; + }); + assertEquals("4, 2!", str); + + // The same tests with UC16. + + //Test that an optional capture is cleared between two matches. + str = "AB\u1234 \u1234"; + str = str.replace(/(\w)?\u1234/g, function (match, capture) { + assertTrue(match.indexOf(capture) >= 0 || capture === undefined); + return capture ? capture.toLowerCase() : "-"; + }); + assertEquals("Ab -", str); + + // Test zero-length matches. + str = "Als \u2623\u2642 eines Morgens"; + str = str.replace(/\b/g, function (match, capture) { + return "/"; + }); + assertEquals("/Als/ \u2623\u2642 /eines/ /Morgens/", str); + + // Test zero-length matches that have non-zero-length sub-captures. + str = "It was a pleasure to \u70e7."; + str = str.replace(/(?=(\w+))\b/g, function (match, capture) { + return capture.length; + }); + assertEquals("2It 3was 1a 8pleasure 2to \u70e7.", str); + + // Test multiple captures. + str = "Try not. D\u26aa, or d\u26aa not. There is no try."; + str = str.replace(/(not?)|(d\u26aa)|(try)/gi, function (match, c1, c2, c3) { + assertTrue( + (c1 === undefined && c2 === undefined) || + (c2 === undefined && c3 === undefined) || + (c1 === undefined && c3 === undefined) + ); + if (c1) return "-"; + if (c2) return "+"; + if (c3) return "="; + }); + assertEquals("= -. +, or + -. There is - =.", str); + + // Test multiple alternate captures. + str = "FOUR \u817f GOOD, TWO \u817f BAD!"; + str = str.replace(/(FOUR|TWO) \u817f (GOOD|BAD)/g, function (match, num_legs, likeability) { + assertTrue(num_legs !== undefined); + assertTrue(likeability !== undefined); + if (num_legs == "FOUR") assertTrue(likeability == "GOOD"); + if (num_legs == "TWO") assertTrue(likeability == "BAD"); + return match.length - 7; + }); + assertEquals("4, 2!", str); + + // Test capture that is a real substring. + var str = "Beasts of England, beasts of Ireland"; + str = str.replace(/(.*)/g, function (match) { + return "~"; + }); + assertEquals("~~", str); + + // Test zero-length matches that have non-zero-length sub-captures that do not + // start at the match start position. + str = "up up up up"; + str = str.replace(/\b(?=u(p))/g, function (match, capture) { + return capture.length; + }); + + assertEquals("1up 1up 1up 1up", str); + + // Create regexp that has a *lot* of captures. + var re_string = "(a)"; + for (var i = 0; i < 500; i++) { + re_string = "(" + re_string + ")"; + } + re_string = re_string + "1"; + // re_string = "(((...((a))...)))1" + + var regexps = new Array(); + var last_match_expectations = new Array(); + var first_capture_expectations = new Array(); + + // Atomic regexp. + regexps.push(/a1/g); + last_match_expectations.push("a1"); + first_capture_expectations.push(""); + // Small regexp (no capture); + regexps.push(/\w1/g); + last_match_expectations.push("a1"); + first_capture_expectations.push(""); + // Small regexp (one capture). + regexps.push(/(a)1/g); + last_match_expectations.push("a1"); + first_capture_expectations.push("a"); + // Large regexp (a lot of captures). + regexps.push(new RegExp(re_string, "g")); + last_match_expectations.push("a1"); + first_capture_expectations.push("a"); + + function test_replace(result_expectation, subject, regexp, replacement) { + for (var i = 0; i < regexps.length; i++) { + // Overwrite last match info. + "deadbeef".replace(/(dead)beef/, "$1holeycow"); + // Conduct tests. + assertEquals(result_expectation, subject.replace(regexps[i], replacement)); + if (subject.length == 0) { + assertEquals("deadbeef", RegExp.lastMatch); + assertEquals("dead", RegExp["$1"]); + } else { + assertEquals(last_match_expectations[i], RegExp.lastMatch); + assertEquals(first_capture_expectations[i], RegExp["$1"]); + } + } + } + + function test_match(result_expectation, subject, regexp) { + for (var i = 0; i < regexps.length; i++) { + // Overwrite last match info. + "deadbeef".replace(/(dead)beef/, "$1holeycow"); + // Conduct tests. + if (result_expectation == null) { + assertNull(subject.match(regexps[i])); + } else { + assertArrayEquals(result_expectation, subject.match(regexps[i])); + } + if (subject.length == 0) { + assertEquals("deadbeef", RegExp.lastMatch); + assertEquals("dead", RegExp["$1"]); + } else { + assertEquals(last_match_expectations[i], RegExp.lastMatch); + assertEquals(first_capture_expectations[i], RegExp["$1"]); + } + } + } + + // Test for different number of matches. + for (var m = 0; m < 33; m++) { + // Create string that matches m times. + var subject = ""; + var test_1_expectation = ""; + var test_2_expectation = ""; + var test_3_expectation = m == 0 ? null : new Array(); + for (var i = 0; i < m; i++) { + subject += "a11"; + test_1_expectation += "x1"; + test_2_expectation += "1"; + test_3_expectation.push("a1"); + } + + // Test 1a: String.replace with string. + test_replace(test_1_expectation, subject, /a1/g, "x"); + + // Test 1b: String.replace with function. + function f() { + return "x"; + } + test_replace(test_1_expectation, subject, /a1/g, f); + + // Test 2a: String.replace with empty string. + test_replace(test_2_expectation, subject, /a1/g, ""); + + // Test 3a: String.match. + test_match(test_3_expectation, subject, /a1/g); + } + + // Test String hashing (compiling regular expression includes hashing). + var crosscheck = "\x80"; + for (var i = 0; i < 12; i++) crosscheck += crosscheck; + new RegExp(crosscheck); + + var subject = "ascii~only~string~here~"; + var replacement = "\x80"; + var result = subject.replace(/~/g, replacement); + for (var i = 0; i < 5; i++) result += result; + new RegExp(result); + + // Global Atom RegExp with a single char pattern. + // We chose a match count greater then 255*16, as this is the maximum count + // we can keep in a vector register before it overflows. + // In addition the string length shouldn't be a multiple of 16 to also test + // the scalar part. + // See RegExpMatchGlobalAtom_OneCharPattern() for details. + let text = "a".repeat(255 * 17 + 5); + assertEquals(4340, text.match(/a/g).length); + + // Two-byte. + const smiley = "\u{D83D}\u{DE0A}"; + text = smiley.repeat(255 * 17 + 5); + assertEquals(4340, text.match(new RegExp(smiley, "g")).length); + + // Two-byte subject with one-byte pattern. + text = smiley + "a".repeat(255 * 17 + 5); + assertEquals(4340, text.match(/a/g).length); + + // Test the cache with a slice. + text = "a".repeat(255 * 17 + 5).substring(1); + assertEquals(4339, text.match(/a/g).length); + assertEquals(4339, text.match(/a/g).length); + assertEquals(4339, text.match(/a/g).length); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/regexp-indexof.js b/Tests/LibJS/Runtime/3rdparty/v8/regexp-indexof.js new file mode 100644 index 00000000000..3fc2adcd3a6 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/regexp-indexof.js @@ -0,0 +1,196 @@ +// Copyright 2008 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("regexp-indexof", () => { + function CheckMatch(re, str, matches) { + assertEquals(matches.length > 0, re.test(str)); + var result = str.match(re); + if (matches.length > 0) { + assertEquals(matches.length, result.length); + var lastExpected; + var lastFrom; + var lastLength; + for (var idx = 0; idx < matches.length; idx++) { + var from = matches[idx][0]; + var length = matches[idx][1]; + var expected = str.substr(from, length); + var name = str + "[" + from + ".." + (from + length) + "]"; + assertEquals(expected, result[idx], name); + if (re.global || idx == 0) { + lastExpected = expected; + lastFrom = from; + lastLength = length; + } + } + assertEquals(lastExpected, RegExp.lastMatch, "lastMatch"); + assertEquals(str.substr(0, lastFrom), RegExp.leftContext, "leftContext"); + assertEquals(str.substr(lastFrom + lastLength), RegExp.rightContext, "rightContext"); + } else { + assertTrue(result === null); + } + } + + CheckMatch(/abc/, "xxxabcxxxabcxxx", [[3, 3]]); + CheckMatch(/abc/g, "xxxabcxxxabcxxx", [ + [3, 3], + [9, 3], + ]); + CheckMatch(/abc/, "xxxabababcxxxabcxxx", [[7, 3]]); + CheckMatch(/abc/g, "abcabcabc", [ + [0, 3], + [3, 3], + [6, 3], + ]); + CheckMatch(/aba/g, "ababababa", [ + [0, 3], + [4, 3], + ]); + CheckMatch(/foo/g, "ofooofoooofofooofo", [ + [1, 3], + [5, 3], + [12, 3], + ]); + CheckMatch(/foobarbaz/, "xx", []); + CheckMatch(new RegExp(""), "xxx", [[0, 0]]); + CheckMatch(/abc/, "abababa", []); + + assertEquals("xxxdefxxxdefxxx", "xxxabcxxxabcxxx".replace(/abc/g, "def")); + assertEquals("o-o-oofo-ofo", "ofooofoooofofooofo".replace(/foo/g, "-")); + assertEquals("deded", "deded".replace(/x/g, "-")); + assertEquals("-a-b-c-d-e-f-", "abcdef".replace(new RegExp("", "g"), "-")); + + CheckMatch(/a(.)/, "xyzzyabxyzzzyacxyzzy", [ + [5, 2], + [6, 1], + ]); + CheckMatch(/a(.)/g, "xyzzyabxyzzyacxyzzy", [ + [5, 2], + [12, 2], + ]); + + CheckMatch(/a|(?:)/g, "aba", [ + [0, 1], + [1, 0], + [2, 1], + [3, 0], + ]); + CheckMatch(/a|(?:)/g, "baba", [ + [0, 0], + [1, 1], + [2, 0], + [3, 1], + [4, 0], + ]); + CheckMatch(/a|(?:)/g, "bab", [ + [0, 0], + [1, 1], + [2, 0], + [3, 0], + ]); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/regexp-lastIndex.js b/Tests/LibJS/Runtime/3rdparty/v8/regexp-lastIndex.js new file mode 100644 index 00000000000..35d8e790907 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/regexp-lastIndex.js @@ -0,0 +1,102 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("regexp-lastIndex", () => { + var re = /x/g; + Object.defineProperty(re, "lastIndex", { writable: false }); + assertThrows(() => re.exec(""), TypeError); + assertThrows(() => re.exec("x"), TypeError); + + var re = /x/y; + Object.defineProperty(re, "lastIndex", { writable: false }); + assertThrows(() => re.exec(""), TypeError); + assertThrows(() => re.exec("x"), TypeError); + + var re = /x/; + Object.defineProperty(re, "lastIndex", { writable: false }); + assertEquals(null, re.exec("")); + assertEquals(["x"], re.exec("x")); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/regexp-lookahead.js b/Tests/LibJS/Runtime/3rdparty/v8/regexp-lookahead.js new file mode 100644 index 00000000000..e6cfc31a1a4 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/regexp-lookahead.js @@ -0,0 +1,249 @@ +// Copyright 2009 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test.xfail("regexp-lookahead", () => { + function stringEscape(string) { + // Converts string to source literal. + return '"' + string.replace(/["\\]/g, "\\$1") + '"'; + } + + function testRE(re, input, expected_result) { + var testName = re + ".test(" + stringEscape(input) + ")"; + if (expected_result) { + assertTrue(re.test(input), testName); + } else { + assertFalse(re.test(input), testName); + } + } + + function execRE(re, input, expected_result) { + var testName = re + ".exec('" + stringEscape(input) + "')"; + assertEquals(expected_result, re.exec(input), testName); + } + + // Test of simple positive lookahead. + + var re = /^(?=a)/; + testRE(re, "a", true); + testRE(re, "b", false); + execRE(re, "a", [""]); + + re = /^(?=\woo)f\w/; + testRE(re, "foo", true); + testRE(re, "boo", false); + testRE(re, "fao", false); + testRE(re, "foa", false); + execRE(re, "foo", ["fo"]); + + re = /(?=\w).(?=\W)/; + testRE(re, ".a! ", true); + testRE(re, ".! ", false); + testRE(re, ".ab! ", true); + execRE(re, ".ab! ", ["b"]); + + re = /(?=f(?=[^f]o))../; + testRE(re, ", foo!", true); + testRE(re, ", fo!", false); + testRE(re, ", ffo", false); + execRE(re, ", foo!", ["fo"]); + + // Positive lookahead with captures. + re = /^[^\'\"]*(?=([\'\"])).*\1(\w+)\1/; + testRE(re, " 'foo' ", true); + testRE(re, ' "foo" ', true); + testRE(re, " \" 'foo' ", false); + testRE(re, ' \' "foo" ', false); + testRE(re, " 'foo\" ", false); + testRE(re, " \"foo' ", false); + execRE(re, " 'foo' ", [" 'foo'", "'", "foo"]); + execRE(re, ' "foo" ', [' "foo"', '"', "foo"]); + + // Captures are cleared on backtrack past the look-ahead. + re = /^(?:(?=(.))a|b)\1$/; + testRE(re, "aa", true); + testRE(re, "b", true); + testRE(re, "bb", false); + testRE(re, "a", false); + execRE(re, "aa", ["aa", "a"]); + execRE(re, "b", ["b", undefined]); + + re = /^(?=(.)(?=(.)\1\2)\2\1)\1\2/; + testRE(re, "abab", true); + testRE(re, "ababxxxxxxxx", true); + testRE(re, "aba", false); + execRE(re, "abab", ["ab", "a", "b"]); + + re = /^(?:(?=(.))a|b|c)$/; + testRE(re, "a", true); + testRE(re, "b", true); + testRE(re, "c", true); + testRE(re, "d", false); + execRE(re, "a", ["a", "a"]); + execRE(re, "b", ["b", undefined]); + execRE(re, "c", ["c", undefined]); + + execRE(/^(?=(b))b/, "b", ["b", "b"]); + execRE(/^(?:(?=(b))|a)b/, "ab", ["ab", undefined]); + execRE(/^(?:(?=(b)(?:(?=(c))|d))|)bd/, "bd", ["bd", "b", undefined]); + + // Test of Negative Look-Ahead. + + re = /(?!x)./; + testRE(re, "y", true); + testRE(re, "x", false); + execRE(re, "y", ["y"]); + + re = /(?!(\d))|\d/; + testRE(re, "4", true); + execRE(re, "4", ["4", undefined]); + execRE(re, "x", ["", undefined]); + + // Test mixed nested look-ahead with captures. + + re = /^(?=(x)(?=(y)))/; + testRE(re, "xy", true); + testRE(re, "xz", false); + execRE(re, "xy", ["", "x", "y"]); + + re = /^(?!(x)(?!(y)))/; + testRE(re, "xy", true); + testRE(re, "xz", false); + execRE(re, "xy", ["", undefined, undefined]); + + re = /^(?=(x)(?!(y)))/; + testRE(re, "xz", true); + testRE(re, "xy", false); + execRE(re, "xz", ["", "x", undefined]); + + re = /^(?!(x)(?=(y)))/; + testRE(re, "xz", true); + testRE(re, "xy", false); + execRE(re, "xz", ["", undefined, undefined]); + + re = /^(?=(x)(?!(y)(?=(z))))/; + testRE(re, "xaz", true); + testRE(re, "xya", true); + testRE(re, "xyz", false); + testRE(re, "a", false); + execRE(re, "xaz", ["", "x", undefined, undefined]); + execRE(re, "xya", ["", "x", undefined, undefined]); + + re = /^(?!(x)(?=(y)(?!(z))))/; + testRE(re, "a", true); + testRE(re, "xa", true); + testRE(re, "xyz", true); + testRE(re, "xya", false); + execRE(re, "a", ["", undefined, undefined, undefined]); + execRE(re, "xa", ["", undefined, undefined, undefined]); + execRE(re, "xyz", ["", undefined, undefined, undefined]); + + // Be sure the quick check is working right for lookahead. + re = /(?=..)abcd/; + testRE(re, "----abcd", true); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/regexp-loop-capture.js b/Tests/LibJS/Runtime/3rdparty/v8/regexp-loop-capture.js new file mode 100644 index 00000000000..c28bdcc1110 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/regexp-loop-capture.js @@ -0,0 +1,113 @@ +// Copyright 2009 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("regexp-loop-capture", () => { + assertEquals(["abc", undefined, undefined, "c"], /(?:(a)|(b)|(c))+/.exec("abc")); + assertEquals(["ab", undefined], /(?:(a)|b)*/.exec("ab")); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/regexp-modifiers.js b/Tests/LibJS/Runtime/3rdparty/v8/regexp-modifiers.js new file mode 100644 index 00000000000..6177f8f3181 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/regexp-modifiers.js @@ -0,0 +1,147 @@ +// Copyright 2023 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("regexp-modifiers", () => { + function test_invalid(re) { + assertEarlyError(`/${re}/`); + assertThrowsAtRuntime(`new RegExp('${re}')`, SyntaxError); + } + + test_invalid("(?-:.)"); + test_invalid("(?--:.)"); + test_invalid("(?mm:.)"); + test_invalid("(?ii:.)"); + test_invalid("(?ss:.)"); + test_invalid("(?-mm:.)"); + test_invalid("(?-ii:.)"); + test_invalid("(?-ss:.)"); + test_invalid("(?g-:.)"); + test_invalid("(?-u:.)"); + test_invalid("(?m-m:.)"); + test_invalid("(?i-i:.)"); + test_invalid("(?s-s:.)"); + test_invalid("(?msi-ims:.)"); + test_invalid("(?i--m:.)"); + test_invalid("(?i<)"); + test_invalid("(?i=)"); + test_invalid("(?i!)"); + test_invalid("(?m<)"); + test_invalid("(?m=)"); + test_invalid("(?m!)"); + test_invalid("(?s<)"); + test_invalid("(?s=)"); + test_invalid("(?s!)"); + test_invalid("(?-<)"); + test_invalid("(?-=)"); + test_invalid("(?-!)"); + + function test(re, expectedMatch, expectedNoMatch = []) { + for (const match of expectedMatch) { + assertTrue(re.test(match), `${re}.test(${match})`); + } + for (const match of expectedNoMatch) { + assertFalse(re.test(match), `${re}.test(${match})`); + } + } + + test(/(?i:ba)r/, ["bar", "Bar", "BAr"], ["BAR", "BaR"]); + test(/(?-i:ba)r/i, ["bar", "baR"], ["Bar", "BAR"]); + test(/F(?i:oo(?-i:b)a)r/, ["Foobar", "FoObAr"], ["FooBar", "FoobaR"]); + test(/F(?i:oo(?i:b)a)r/, ["Foobar", "FoObAr", "FOOBAr"], ["FoobaR"]); + test(/^[a-z](?-i:[a-z])$/i, ["ab", "Ab"], ["aB"]); + test(/^(?i:[a-z])[a-z]$/, ["ab", "Ab"], ["aB"]); + test(/(?i:foo|bar)/, ["FOO", "FOo", "Foo", "fOO", "BAR", "BAr", "Bar", "bAR"]); + test(/(?i:foo|bar|baz)/, ["FOO", "FOo", "Foo", "fOO", "BAR", "BAr", "Bar", "bAR", "BAZ", "BAz", "Baz", "bAZ"]); + test(/Foo(?i:B[\q{ĀĂĄ|AaA}--\q{āăą}])r/v, ["FooBaaar", "FoobAAAr"], ["FooBĀĂĄr", "FooBaaaR"]); + + test(/(?m:^foo$)/, ["foo", "\nfoo", "foo\n", "\nfoo\n"], ["xfoo", "foox"]); + + test(/(?s:^.$)/, ["a", "A", "0", "\n", "\r", "\u2028", "\u2029", "π"], ["\u{10300}"]); + + test(/(?ms-i:^f.o$)/i, ["foo", "\nf\ro", "f\no\n", "\nfπo\n"], ["Foo", "\nf\nO", "foO\n", "\nFOO\n"]); + test(/(?m:^f(?si:.o)$)/, ["foo", "\nfoO", "f\no\n", "\nf\rO\n"], ["Foo", "F\no\n"]); + test(/(?i:.oo)/, ["Foo", "FOO", "fOo", "foO"]); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/regexp-multiline.js b/Tests/LibJS/Runtime/3rdparty/v8/regexp-multiline.js new file mode 100644 index 00000000000..baa20c72409 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/regexp-multiline.js @@ -0,0 +1,192 @@ +// Copyright 2008 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("regexp-multiline", () => { + /** + * @fileoverview Check that various regexp constructs work as intended. + * Particularly those regexps that use ^ and $. + */ + + assertTrue(/^bar/.test("bar")); + assertTrue(/^bar/.test("bar\nfoo")); + assertFalse(/^bar/.test("foo\nbar")); + assertTrue(/^bar/m.test("bar")); + assertTrue(/^bar/m.test("bar\nfoo")); + assertTrue(/^bar/m.test("foo\nbar")); + + assertTrue(/bar$/.test("bar")); + assertFalse(/bar$/.test("bar\nfoo")); + assertTrue(/bar$/.test("foo\nbar")); + assertTrue(/bar$/m.test("bar")); + assertTrue(/bar$/m.test("bar\nfoo")); + assertTrue(/bar$/m.test("foo\nbar")); + + assertFalse(/^bxr/.test("bar")); + assertFalse(/^bxr/.test("bar\nfoo")); + assertFalse(/^bxr/m.test("bar")); + assertFalse(/^bxr/m.test("bar\nfoo")); + assertFalse(/^bxr/m.test("foo\nbar")); + + assertFalse(/bxr$/.test("bar")); + assertFalse(/bxr$/.test("foo\nbar")); + assertFalse(/bxr$/m.test("bar")); + assertFalse(/bxr$/m.test("bar\nfoo")); + assertFalse(/bxr$/m.test("foo\nbar")); + + assertTrue(/^.*$/.test("")); + assertTrue(/^.*$/.test("foo")); + assertFalse(/^.*$/.test("\n")); + assertTrue(/^.*$/m.test("\n")); + + assertTrue(/^[\s]*$/.test(" ")); + assertTrue(/^[\s]*$/.test("\n")); + + assertTrue(/^[^]*$/.test("")); + assertTrue(/^[^]*$/.test("foo")); + assertTrue(/^[^]*$/.test("\n")); + + assertTrue(/^([()\s]|.)*$/.test("()\n()")); + assertTrue(/^([()\n]|.)*$/.test("()\n()")); + assertFalse(/^([()]|.)*$/.test("()\n()")); + assertTrue(/^([()]|.)*$/m.test("()\n()")); + assertTrue(/^([()]|.)*$/m.test("()\n")); + assertTrue(/^[()]*$/m.test("()\n.")); + + assertTrue(/^[\].]*$/.test("...]...")); + + function check_case(lc, uc) { + var a = new RegExp("^" + lc + "$"); + assertFalse(a.test(uc)); + a = new RegExp("^" + lc + "$", "i"); + assertTrue(a.test(uc)); + + var A = new RegExp("^" + uc + "$"); + assertFalse(A.test(lc)); + A = new RegExp("^" + uc + "$", "i"); + assertTrue(A.test(lc)); + + a = new RegExp("^[" + lc + "]$"); + assertFalse(a.test(uc)); + a = new RegExp("^[" + lc + "]$", "i"); + assertTrue(a.test(uc)); + + A = new RegExp("^[" + uc + "]$"); + assertFalse(A.test(lc)); + A = new RegExp("^[" + uc + "]$", "i"); + assertTrue(A.test(lc)); + } + + check_case("a", "A"); + // Aring + check_case(String.fromCharCode(229), String.fromCharCode(197)); + // Russian G + check_case(String.fromCharCode(0x413), String.fromCharCode(0x433)); + + assertThrows("a = new RegExp('[z-a]');"); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/regexp-override-exec.js b/Tests/LibJS/Runtime/3rdparty/v8/regexp-override-exec.js new file mode 100644 index 00000000000..0b9d3639df4 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/regexp-override-exec.js @@ -0,0 +1,107 @@ +// Copyright 2018 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("regexp-override-exec", () => { + var s = "baa"; + + assertEquals(1, s.search(/a/)); + assertEquals(["aa"], s.match(/a./)); + assertEquals(["b", "", ""], s.split(/a/)); + + let o = { index: 3, 0: "x" }; + + RegExp.prototype.exec = () => { + return o; + }; + assertEquals(3, s.search(/a/)); + assertEquals(o, s.match(/a./)); + assertEquals("baar", s.replace(/a./, "r")); + + RegExp.prototype.exec = () => { + return null; + }; + assertEquals(["baa"], s.split(/a/)); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/regexp-override-symbol-match-all.js b/Tests/LibJS/Runtime/3rdparty/v8/regexp-override-symbol-match-all.js new file mode 100644 index 00000000000..de51a3c2b0a --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/regexp-override-symbol-match-all.js @@ -0,0 +1,94 @@ +// Copyright 2018 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("regexp-override-symbol-match-all", () => { + var s = "baa"; + + assertEquals([["b"], ["a"], ["a"]], [...s.matchAll(/./g)]); + + RegExp.prototype[Symbol.matchAll] = () => 42; + assertEquals(42, s.matchAll(/a./g)); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/regexp-override-symbol-match.js b/Tests/LibJS/Runtime/3rdparty/v8/regexp-override-symbol-match.js new file mode 100644 index 00000000000..b2de6af740c --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/regexp-override-symbol-match.js @@ -0,0 +1,94 @@ +// Copyright 2018 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("regexp-override-symbol-match", () => { + var s = "baa"; + + assertEquals(["aa"], s.match(/a./)); + + RegExp.prototype[Symbol.match] = () => 42; + assertEquals(42, s.match(/a./)); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/regexp-override-symbol-replace.js b/Tests/LibJS/Runtime/3rdparty/v8/regexp-override-symbol-replace.js new file mode 100644 index 00000000000..ddd443bf9d9 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/regexp-override-symbol-replace.js @@ -0,0 +1,94 @@ +// Copyright 2018 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("regexp-override-symbol-replace", () => { + var s = "baa"; + + assertEquals("bca", s.replace(/a/, "c")); + + RegExp.prototype[Symbol.replace] = () => 42; + assertEquals(42, s.replace(/a./)); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/regexp-override-symbol-search.js b/Tests/LibJS/Runtime/3rdparty/v8/regexp-override-symbol-search.js new file mode 100644 index 00000000000..00154b15b22 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/regexp-override-symbol-search.js @@ -0,0 +1,94 @@ +// Copyright 2018 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("regexp-override-symbol-search", () => { + var s = "baa"; + + assertEquals(1, s.search(/a/)); + + RegExp.prototype[Symbol.search] = () => 42; + assertEquals(42, s.search(/a/)); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/regexp-override-symbol-split.js b/Tests/LibJS/Runtime/3rdparty/v8/regexp-override-symbol-split.js new file mode 100644 index 00000000000..634f85d478f --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/regexp-override-symbol-split.js @@ -0,0 +1,94 @@ +// Copyright 2018 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("regexp-override-symbol-split", () => { + var s = "baa"; + + assertEquals(["b", "", ""], s.split(/a/)); + + RegExp.prototype[Symbol.split] = () => 42; + assertEquals(42, s.split(/a./)); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/regexp-peephole.js b/Tests/LibJS/Runtime/3rdparty/v8/regexp-peephole.js new file mode 100644 index 00000000000..15254ba8299 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/regexp-peephole.js @@ -0,0 +1,99 @@ +// Copyright 2025 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("regexp-peephole", () => { + function test(re, expectMatch, expectNoMatch = []) { + for (const match of expectMatch) { + assertTrue(re.test(match), `${re}.test(${match})`); + } + for (const noMatch of expectNoMatch) { + assertFalse(re.test(noMatch), `${re}.test(${noMatch})`); + } + } + + // Test SkipUntilMatchInAlternativeWithFewChars + test(/[ab]bbbc|[de]eeef/, ["abbbcccc", "bbbbcccc", "deeeffff", "eeeeffff"], ["aeeef", "beeef", "dbbbc", "ebbbc"]); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/regexp-regexpexec.js b/Tests/LibJS/Runtime/3rdparty/v8/regexp-regexpexec.js new file mode 100644 index 00000000000..ba2ea980488 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/regexp-regexpexec.js @@ -0,0 +1,90 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("regexp-regexpexec", () => { + delete RegExp.prototype.exec; + assertEquals("b", "aba".replace(/a/g, "")); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/regexp-results-cache.js b/Tests/LibJS/Runtime/3rdparty/v8/regexp-results-cache.js new file mode 100644 index 00000000000..d406920a8c1 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/regexp-results-cache.js @@ -0,0 +1,166 @@ +// Copyright 2012 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("regexp-results-cache", () => { + var string = + "Friends, Romans, countrymen, lend me your ears! \ + I come to bury Caesar, not to praise him. \ + The evil that men do lives after them, \ + The good is oft interred with their bones; \ + So let it be with Caesar. The noble Brutus \ + Hath told you Caesar was ambitious; \ + If it were so, it was a grievous fault, \ + And grievously hath Caesar answer'd it. \ + Here, under leave of Brutus and the rest- \ + For Brutus is an honorable man; \ + So are they all, all honorable men- \ + Come I to speak in Caesar's funeral. \ + He was my friend, faithful and just to me; \ + But Brutus says he was ambitious, \ + And Brutus is an honorable man. \ + He hath brought many captives home to Rome, \ + Whose ransoms did the general coffers fill. \ + Did this in Caesar seem ambitious? \ + When that the poor have cried, Caesar hath wept; \ + Ambition should be made of sterner stuff: \ + Yet Brutus says he was ambitious, \ + And Brutus is an honorable man. \ + You all did see that on the Lupercal \ + I thrice presented him a kingly crown, \ + Which he did thrice refuse. Was this ambition? \ + Yet Brutus says he was ambitious, \ + And sure he is an honorable man. \ + I speak not to disprove what Brutus spoke, \ + But here I am to speak what I do know. \ + You all did love him once, not without cause; \ + What cause withholds you then to mourn for him? \ + O judgement, thou art fled to brutish beasts, \ + And men have lost their reason. Bear with me; \ + My heart is in the coffin there with Caesar, \ + And I must pause till it come back to me."; + + var replaced = string.replace(/\b\w+\b/g, function () { + return "foo"; + }); + for (var i = 0; i < 3; i++) { + assertEquals( + replaced, + string.replace(/\b\w+\b/g, function () { + return "foo"; + }) + ); + } + + // Check that the result is in a COW array. + var words = string.split(" "); + assertEquals("Friends,", words[0]); + words[0] = "Enemies,"; + words = string.split(" "); + assertEquals("Friends,", words[0]); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/regexp-sort.js b/Tests/LibJS/Runtime/3rdparty/v8/regexp-sort.js new file mode 100644 index 00000000000..95776873c4b --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/regexp-sort.js @@ -0,0 +1,132 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test.xfail("regexp-sort", () => { + function Test(lower, upper) { + var lx = lower + "x"; + var ux = upper + "x"; + var lp = lower + "|"; + var uxp = upper + "x|"; + assertEquals(lx, new RegExp(uxp + lp + lower + "cat", "i").exec(lx) + ""); + assertEquals(ux, new RegExp(uxp + lp + lower + "cat", "i").exec(ux) + ""); + assertEquals(lower, new RegExp(lp + uxp + lower + "cat", "i").exec(lx) + ""); + assertEquals(upper, new RegExp(lp + uxp + lower + "cat", "i").exec(ux) + ""); + } + + function TestFail(lower, upper) { + var lx = lower + "x"; + var ux = upper + "x"; + var lp = lower + "|"; + var uxp = upper + "x|"; + assertEquals(lower, new RegExp(uxp + lp + lower + "cat", "i").exec(lx) + ""); + assertEquals(ux, new RegExp(uxp + lp + lower + "cat", "i").exec(ux) + ""); + assertEquals(lower, new RegExp(lp + uxp + lower + "cat", "i").exec(lx) + ""); + assertEquals(ux, new RegExp(lp + uxp + lower + "cat", "i").exec(ux) + ""); + } + + Test("a", "A"); + Test("0", "0"); + TestFail("a", "b"); + // Small and capital o-umlaut + Test(String.fromCharCode(0xf6), String.fromCharCode(0xd6)); + // Small and capital kha. + Test(String.fromCharCode(0x445), String.fromCharCode(0x425)); + // Small and capital y-umlaut. + Test(String.fromCharCode(0xff), String.fromCharCode(0x178)); + // Small and large Greek mu. + Test(String.fromCharCode(0x3bc), String.fromCharCode(0x39c)); + // Micron and large Greek mu. + Test(String.fromCharCode(0xb5), String.fromCharCode(0x39c)); + // Micron and small Greek mu. + Test(String.fromCharCode(0xb5), String.fromCharCode(0x3bc)); + // German double s and capital S. These are not equivalent since one is double. + TestFail(String.fromCharCode(0xdf), "S"); + // Small i and Turkish capital dotted I. These are not equivalent due to + // 21.2.2.8.2 section 3g. One is below 128 and the other is above 127. + TestFail("i", String.fromCharCode(0x130)); + // Small dotless i and I. These are not equivalent either. + TestFail(String.fromCharCode(0x131), "I"); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/regexp-stack-overflow.js b/Tests/LibJS/Runtime/3rdparty/v8/regexp-stack-overflow.js new file mode 100644 index 00000000000..e8724780a88 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/regexp-stack-overflow.js @@ -0,0 +1,100 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("regexp-stack-overflow", () => { + var re = /\w/; + re.test("a"); // Trigger regexp compile. + + function rec() { + try { + return rec(); + } catch (e) { + return re.test("b"); + } + } + + assertTrue(rec()); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/regexp-standalones.js b/Tests/LibJS/Runtime/3rdparty/v8/regexp-standalones.js new file mode 100644 index 00000000000..8ce635d735c --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/regexp-standalones.js @@ -0,0 +1,162 @@ +// Copyright 2008 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("regexp-standalones", () => { + /* Many of the Mozilla regexp tests used 'toSource' to test their + * results. Since we don't currently support toSource, those tests + * are disabled and standalone versions are included here. + */ + + // Tests from ecma_3/RegExp/regress-78156.js + var string = "aaa\n789\r\nccc\r\n345"; + var pattern = /^\d/gm; + var result = string.match(pattern); + assertEquals(2, result.length, "1"); + assertEquals("7", result[0], "2"); + assertEquals("3", result[1], "3"); + + pattern = /\d$/gm; + result = string.match(pattern); + assertEquals(2, result.length, "4"); + assertEquals("9", result[0], "5"); + assertEquals("5", result[1], "6"); + + string = "aaa\n789\r\nccc\r\nddd"; + pattern = /^\d/gm; + result = string.match(pattern); + assertEquals(1, result.length, "7"); + assertEquals("7", result[0], "8"); + + pattern = /\d$/gm; + result = string.match(pattern); + assertEquals(1, result.length, "9"); + assertEquals("9", result[0], "10"); + + // Tests from ecma_3/RegExp/regress-72964.js + pattern = /[\S]+/; + string = "\u00BF\u00CD\u00BB\u00A7"; + result = string.match(pattern); + assertEquals(1, result.length, "11"); + assertEquals(string, result[0], "12"); + + string = "\u00BF\u00CD \u00BB\u00A7"; + result = string.match(pattern); + assertEquals(1, result.length, "13"); + assertEquals("\u00BF\u00CD", result[0], "14"); + + string = "\u4e00\uac00\u4e03\u4e00"; + result = string.match(pattern); + assertEquals(1, result.length, "15"); + assertEquals(string, result[0], "16"); + + string = "\u4e00\uac00 \u4e03\u4e00"; + result = string.match(pattern); + assertEquals(1, result.length, "17"); + assertEquals("\u4e00\uac00", result[0], "18"); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/regexp-static.js b/Tests/LibJS/Runtime/3rdparty/v8/regexp-static.js new file mode 100644 index 00000000000..8128a88c1cf --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/regexp-static.js @@ -0,0 +1,251 @@ +// Copyright 2008 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("regexp-static", () => { + var re = /((\d+)\.(\d+))/; + var s = "abc123.456def"; + + re.exec(s); + + assertEquals(s, RegExp.input); + assertEquals("123.456", RegExp.lastMatch); + assertEquals("456", RegExp.lastParen); + assertEquals("abc", RegExp.leftContext); + assertEquals("def", RegExp.rightContext); + + assertEquals(s, RegExp["$_"]); + assertEquals("123.456", RegExp["$&"]); + assertEquals("456", RegExp["$+"]); + assertEquals("abc", RegExp["$`"]); + assertEquals("def", RegExp["$'"]); + + assertEquals("123.456", RegExp["$1"]); + assertEquals("123", RegExp["$2"]); + assertEquals("456", RegExp["$3"]); + for (var i = 4; i < 10; ++i) { + assertEquals("", RegExp["$" + i]); + } + + // They should be read only. + RegExp["$1"] = "fisk"; + assertEquals("123.456", RegExp["$1"]); + + // String.prototype.match and String.prototype.replace (when given a + // regexp) and also RegExp.prototype.test should all behave as if + // RegExp.prototype.exec were called. + s = "ghi789.012jkl"; + s.match(re); + assertEquals(s, RegExp.input); + assertEquals("789.012", RegExp.lastMatch); + assertEquals("012", RegExp.lastParen); + assertEquals("ghi", RegExp.leftContext); + assertEquals("jkl", RegExp.rightContext); + assertEquals(s, RegExp["$_"]); + assertEquals("789.012", RegExp["$&"]); + assertEquals("012", RegExp["$+"]); + assertEquals("ghi", RegExp["$`"]); + assertEquals("jkl", RegExp["$'"]); + assertEquals("789.012", RegExp["$1"]); + assertEquals("789", RegExp["$2"]); + assertEquals("012", RegExp["$3"]); + for (var i = 4; i < 10; ++i) { + assertEquals("", RegExp["$" + i]); + } + + s = "abc123.456def"; + s.replace(re, "whocares"); + assertEquals(s, RegExp.input); + assertEquals("123.456", RegExp.lastMatch); + assertEquals("456", RegExp.lastParen); + assertEquals("abc", RegExp.leftContext); + assertEquals("def", RegExp.rightContext); + assertEquals(s, RegExp["$_"]); + assertEquals("123.456", RegExp["$&"]); + assertEquals("456", RegExp["$+"]); + assertEquals("abc", RegExp["$`"]); + assertEquals("def", RegExp["$'"]); + assertEquals("123.456", RegExp["$1"]); + assertEquals("123", RegExp["$2"]); + assertEquals("456", RegExp["$3"]); + for (var i = 4; i < 10; ++i) { + assertEquals("", RegExp["$" + i]); + } + + s = "ghi789.012jkl"; + re.test(s); + assertEquals(s, RegExp.input); + assertEquals("789.012", RegExp.lastMatch); + assertEquals("012", RegExp.lastParen); + assertEquals("ghi", RegExp.leftContext); + assertEquals("jkl", RegExp.rightContext); + assertEquals(s, RegExp["$_"]); + assertEquals("789.012", RegExp["$&"]); + assertEquals("012", RegExp["$+"]); + assertEquals("ghi", RegExp["$`"]); + assertEquals("jkl", RegExp["$'"]); + assertEquals("789.012", RegExp["$1"]); + assertEquals("789", RegExp["$2"]); + assertEquals("012", RegExp["$3"]); + for (var i = 4; i < 10; ++i) { + assertEquals("", RegExp["$" + i]); + } + + // String.prototype.replace must interleave matching and replacing when a + // global regexp is matched and replaced with the result of a function, in + // case the function uses the static properties of the regexp constructor. + re = /(.)/g; + function f() { + return RegExp.$1; + } + assertEquals("dddd", "abcd".replace(re, f)); + + // lastParen where the last parenthesis didn't match. + assertEquals(["foo", undefined], /foo(?:a(x))?/.exec("foobx"), "lastParen setup"); + assertEquals("", RegExp.lastParen, "lastParen"); + + // The same test for $1 to $9. + for (var i = 1; i <= 9; i++) { + var haystack = "foo"; + var re_text = "^foo"; + for (var j = 0; j < i - 1; j++) { + haystack += "x"; + re_text += "(x)"; + } + re_text += "(?:a(x))?"; + haystack += "bx"; + var re = new RegExp(re_text); + assertTrue(re.test(haystack), "$" + i + " setup"); + for (var j = 1; j < i - 1; j++) { + assertEquals("x", RegExp["$" + j], "$" + j + " in $" + i + " setup"); + } + assertEquals("", RegExp["$" + i], "$" + i); + } + + RegExp.input = Number(); + assertTrue(typeof RegExp.input == typeof String(), "RegExp.input coerces values to booleans"); + + // Ensure that we save the correct string as the last subject when + // we do a match on a sliced string (the top one not the underlying). + var foo = + "lsdfj sldkfj sdklfj læsdfjl sdkfjlsdk fjsdl fjsdljskdj flsj flsdkj flskd regexp: /foobar/\nldkfj sdlkfj sdkl"; + assertTrue(/^([a-z]+): (.*)/.test(foo.substring(foo.indexOf("regexp:"))), "regexp: setup"); + assertEquals("regexp", RegExp.$1, "RegExp.$1"); + + // Check that calling with no argument is the same as calling with undefined. + assertTrue(/^undefined$/.test()); + assertEquals(["undefined"], /^undefined$/.exec()); + + assertThrows( + () => { + RegExp.prototype.test.call("xyz", "foo"); + }, + TypeError, + "Method RegExp.prototype.test called on incompatible receiver xyz" + ); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/v8/regexp-string-methods.js b/Tests/LibJS/Runtime/3rdparty/v8/regexp-string-methods.js new file mode 100644 index 00000000000..1c6298ff902 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/v8/regexp-string-methods.js @@ -0,0 +1,130 @@ +// Copyright 2009 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// V8 assertion compatibility shim for Ladybird's test-js harness + +function assertEquals(expected, actual, msg) { + if (expected instanceof RegExp && actual instanceof RegExp) { + expect(actual.source).toBe(expected.source); + expect(actual.flags).toBe(expected.flags); + } else if (Array.isArray(expected) && Array.isArray(actual)) { + expect(actual).toEqual(expected); + } else if (expected !== null && typeof expected === "object" && actual !== null && typeof actual === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } +} + +function assertTrue(val, msg) { + expect(val).toBeTrue(); +} + +function assertFalse(val, msg) { + expect(val).toBeFalse(); +} + +function assertNull(val, msg) { + expect(val).toBeNull(); +} + +function assertNotNull(val, msg) { + expect(val).not.toBeNull(); +} + +function assertThrows(fn, type_opt, msg_opt) { + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + if (typeof fn === "string") { + try { + try { + fn = new Function(fn); + } catch (e) { + return; + } + } catch (e) { + return; + } + } + expect(fn).toThrow(); +} + +function assertDoesNotThrow(fn, msg) { + fn(); +} + +function assertInstanceof(val, type, msg) { + expect(val instanceof type).toBeTrue(); +} + +function assertUnreachable(msg) { + expect().fail("unreachable" + (msg ? ": " + msg : "")); +} + +function assertEarlyError(code) { + assertThrows(() => new Function(code)); +} + +function assertThrowsAtRuntime(code, type_opt) { + const f = new Function(code); + assertThrows(f, type_opt); +} + +function assertArrayEquals(expected, actual) { + expect(actual).toEqual(expected); +} + +test("regexp-string-methods", () => { + var s = new String("foo"); + assertEquals("f", s.slice(0, 1)); + String.prototype.slice = function () { + return "x"; + }; + assertEquals("x", s.slice(0, 1)); + assertEquals(["g"], /g/.exec("gg")); + + // Regexp shouldn't use String.prototype.charAt() + var f1 = new RegExp("f", "i"); + assertEquals(["F"], f1.exec("F")); + assertEquals("f", "foo".charAt(0)); + String.prototype.charAt = function (idx) { + return "g"; + }; + assertEquals("g", "foo".charAt(0)); + var f2 = new RegExp("[g]", "i"); + assertEquals(["G"], f2.exec("G")); + assertTrue(f2.ignoreCase); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/webkit/alternative-length-miscalculation.js b/Tests/LibJS/Runtime/3rdparty/webkit/alternative-length-miscalculation.js new file mode 100644 index 00000000000..44ab695e046 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/webkit/alternative-length-miscalculation.js @@ -0,0 +1,54 @@ +test("alternative-length-miscalculation", () => { + // WebKit assertion compatibility shim for Ladybird's test-js harness + + function description(msg) { + // No-op, just used for test documentation in WebKit. + } + + function shouldBe(actual_code, expected_code) { + let actual = eval(actual_code); + let expected = eval(expected_code); + if (typeof actual === "string" && typeof expected === "string") { + expect(actual).toBe(expected); + } else if (Array.isArray(actual) && Array.isArray(expected)) { + expect(actual).toEqual(expected); + } else if (actual !== null && typeof actual === "object" && expected !== null && typeof expected === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } + } + + function shouldBeTrue(code) { + expect(eval(code)).toBeTrue(); + } + + function shouldBeFalse(code) { + expect(eval(code)).toBeFalse(); + } + + function shouldBeNull(code) { + expect(eval(code)).toBeNull(); + } + + function shouldBeUndefined(code) { + expect(eval(code)).toBeUndefined(); + } + + function shouldThrow(code, expected_error) { + expect(() => eval(code)).toThrow(); + } + + function shouldNotThrow(code) { + eval(code); + } + + description("This page tests for length miscalculations in regular expression processing."); + + var re = /b|[^b]/g; + re.lastIndex = 1; + shouldBe("re.exec('a')", "null"); + + var re2 = /[^a]|ab/; + shouldBe("re2.test('')", "false"); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/webkit/assertion.js b/Tests/LibJS/Runtime/3rdparty/webkit/assertion.js new file mode 100644 index 00000000000..f27e3515df4 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/webkit/assertion.js @@ -0,0 +1,132 @@ +test("assertion", () => { + // WebKit assertion compatibility shim for Ladybird's test-js harness + + function description(msg) { + // No-op, just used for test documentation in WebKit. + } + + function shouldBe(actual_code, expected_code) { + let actual = eval(actual_code); + let expected = eval(expected_code); + if (typeof actual === "string" && typeof expected === "string") { + expect(actual).toBe(expected); + } else if (Array.isArray(actual) && Array.isArray(expected)) { + expect(actual).toEqual(expected); + } else if (actual !== null && typeof actual === "object" && expected !== null && typeof expected === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } + } + + function shouldBeTrue(code) { + expect(eval(code)).toBeTrue(); + } + + function shouldBeFalse(code) { + expect(eval(code)).toBeFalse(); + } + + function shouldBeNull(code) { + expect(eval(code)).toBeNull(); + } + + function shouldBeUndefined(code) { + expect(eval(code)).toBeUndefined(); + } + + function shouldThrow(code, expected_error) { + expect(() => eval(code)).toThrow(); + } + + function shouldNotThrow(code) { + eval(code); + } + + description("This page tests handling of parenthetical assertions."); + + var regex1 = /(x)(?=\1)x/; + shouldBe("regex1.exec('xx')", "['xx','x']"); + + var regex2 = /(.*?)a(?!(a+)b\2c)\2(.*)/; + shouldBe("regex2.exec('baaabaac')", "['baaabaac','ba',undefined,'abaac']"); + + var regex3 = /(?=(a+?))(\1ab)/; + shouldBe("regex3.exec('aaab')", "['aab','a','aab']"); + + var regex4 = /(?=(a+?))(\1ab)/; + shouldBe("regex4.exec('aaab')", "['aab','a','aab']"); + + var regex5 = /^P([1-6])(?=\1)([1-6])$/; + shouldBe("regex5.exec('P11')", "['P11','1','1']"); + + var regex6 = /(([a-c])b*?\2)*/; + shouldBe("regex6.exec('ababbbcbc')", "['ababb','bb','b']"); + + var regex7 = /(x)(?=x)x/; + shouldBe("regex7.exec('xx')", "['xx','x']"); + + var regex8 = /(x)(\1)/; + shouldBe("regex8.exec('xx')", "['xx','x','x']"); + + var regex9 = /(x)(?=\1)x/; + shouldBeNull("regex9.exec('xy')"); + + var regex10 = /(x)(?=x)x/; + shouldBeNull("regex10.exec('xy')"); + + var regex11 = /(x)(\1)/; + shouldBeNull("regex11.exec('xy')"); + + var regex12 = /(x)(?=\1)x/; + shouldBeNull("regex12.exec('x')"); + shouldBe("regex12.exec('xx')", "['xx','x']"); + shouldBe("regex12.exec('xxy')", "['xx','x']"); + + var regex13 = /(x)zzz(?=\1)x/; + shouldBe("regex13.exec('xzzzx')", "['xzzzx','x']"); + shouldBe("regex13.exec('xzzzxy')", "['xzzzx','x']"); + + var regex14 = /(a)\1(?=(b*c))bc/; + shouldBe("regex14.exec('aabc')", "['aabc','a','bc']"); + shouldBe("regex14.exec('aabcx')", "['aabc','a','bc']"); + + var regex15 = /(a)a(?=(b*c))bc/; + shouldBe("regex15.exec('aabc')", "['aabc','a','bc']"); + shouldBe("regex15.exec('aabcx')", "['aabc','a','bc']"); + + var regex16 = /a(?=(b*c))bc/; + shouldBeNull("regex16.exec('ab')"); + shouldBe("regex16.exec('abc')", "['abc','bc']"); + + var regex17 = /(?=((?:ab)*))a/; + shouldBe("regex17.exec('ab')", "['a','ab']"); + shouldBe("regex17.exec('abc')", "['a','ab']"); + + var regex18 = /(?=((?:xx)*))x/; + shouldBe("regex18.exec('x')", "['x','']"); + shouldBe("regex18.exec('xx')", "['x','xx']"); + shouldBe("regex18.exec('xxx')", "['x','xx']"); + + var regex19 = /(?=((xx)*))x/; + shouldBe("regex19.exec('x')", "['x','',undefined]"); + shouldBe("regex19.exec('xx')", "['x','xx','xx']"); + shouldBe("regex19.exec('xxx')", "['x','xx','xx']"); + + var regex20 = /(?=(xx))+x/; + shouldBeNull("regex20.exec('x')"); + shouldBe("regex20.exec('xx')", "['x','xx']"); + shouldBe("regex20.exec('xxx')", "['x','xx']"); + + var regex21 = /(?=a+b)aab/; + shouldBe("regex21.exec('aab')", "['aab']"); + + var regex22 = /(?!(u|m{0,}g+)u{1,}|2{2,}!1%n|(?!K|(?=y)|(?=ip))+?)(?=(?=(((?:7))*?)*?))p/m; + shouldBe("regex22.exec('55up')", "null"); + + var regex23 = /(?=(a)b|c?)()*d/; + shouldBe("regex23.exec('ax')", "null"); + + var regex24 = /(?=a|b?)c/; + shouldBe("regex24.exec('x')", "null"); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/webkit/backreferences.js b/Tests/LibJS/Runtime/3rdparty/webkit/backreferences.js new file mode 100644 index 00000000000..aebbd701efa --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/webkit/backreferences.js @@ -0,0 +1,81 @@ +test.xfail("backreferences", () => { + // WebKit assertion compatibility shim for Ladybird's test-js harness + + function description(msg) { + // No-op, just used for test documentation in WebKit. + } + + function shouldBe(actual_code, expected_code) { + let actual = eval(actual_code); + let expected = eval(expected_code); + if (typeof actual === "string" && typeof expected === "string") { + expect(actual).toBe(expected); + } else if (Array.isArray(actual) && Array.isArray(expected)) { + expect(actual).toEqual(expected); + } else if (actual !== null && typeof actual === "object" && expected !== null && typeof expected === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } + } + + function shouldBeTrue(code) { + expect(eval(code)).toBeTrue(); + } + + function shouldBeFalse(code) { + expect(eval(code)).toBeFalse(); + } + + function shouldBeNull(code) { + expect(eval(code)).toBeNull(); + } + + function shouldBeUndefined(code) { + expect(eval(code)).toBeUndefined(); + } + + function shouldThrow(code, expected_error) { + expect(() => eval(code)).toThrow(); + } + + function shouldNotThrow(code) { + eval(code); + } + + description("This tests backreferences"); + + // Basic counted, greedy and non-greedy back references + shouldBe("/^(.)\\1{3}/.exec('=====')", '["====", "="]'); + + shouldBe("/^(.)\\1*/.exec('=====')", '["=====", "="]'); + shouldBe("/^(.)\\1*?/.exec('=====')", '["=", "="]'); + shouldBe("/^(.)\\1*?$/.exec('=====')", '["=====", "="]'); + + // Back reference back tracking + shouldBe("/(.*)\\1/.exec('======')", '["======", "==="]'); + shouldBe("/(.*)\\1{2}/.exec('======')", '["======", "=="]'); + shouldBe("/(.*)\\1{4}/.exec('======')", '["=====", "="]'); + shouldBe("/(.*)\\1{5}/.exec('======')", '["======", "="]'); + shouldBe("/(=).\\1{3}/.exec('=a==b===')", '["=b===", "="]'); + shouldBe("/(===).\\1*X/.exec('===a==X===b======X')", '["===b======X", "==="]'); + + // Multiple back references + shouldBe( + "/\\w*?(\\w*) (c\\1) is a f\\1 \\2/.exec('That cat is a fat cat')", + '["That cat is a fat cat", "at", "cat"]' + ); + shouldBe("/(\\w)(\\w)(\\w)e\\3\\2\\1/i.exec('Racecar')", '["Racecar", "R", "a", "c"]'); + + // Named capture group back references + shouldBe("/^(?=*)\\k+?$/.exec('======')", '["======", "==="]'); + + // Unicode back references + shouldBe("/^(\\u{10123}*)x\\1?$/u.exec('\\u{10123}x\\u{10123}')", '["\\u{10123}x\\u{10123}", "\\u{10123}"]'); + + // Ignore case back references + shouldBe("/(.{4})\\1/i.exec('ABcdAbCd')", '["ABcdAbCd", "ABcd"]'); + shouldBe("/(.{4})\\1/i.exec('ABc\\u{fd}AbC\\u{dd}')", '["ABc\\u{fd}AbC\\u{dd}", "ABc\\u{fd}"]'); + shouldBe("/(.{4})\\1/i.exec('ABc\\u{b5}AbC\\u{b5}')", '["ABc\\u{b5}AbC\\u{b5}", "ABc\\u{b5}"]'); + shouldBe("/(.{4})\\1/i.exec('ABc\\u{ff}AbC\\u{ff}')", '["ABc\\u{ff}AbC\\u{ff}", "ABc\\u{ff}"]'); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/webkit/constructor.js b/Tests/LibJS/Runtime/3rdparty/webkit/constructor.js new file mode 100644 index 00000000000..53913a53aa0 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/webkit/constructor.js @@ -0,0 +1,54 @@ +test("constructor", () => { + // WebKit assertion compatibility shim for Ladybird's test-js harness + + function description(msg) { + // No-op, just used for test documentation in WebKit. + } + + function shouldBe(actual_code, expected_code) { + let actual = eval(actual_code); + let expected = eval(expected_code); + if (typeof actual === "string" && typeof expected === "string") { + expect(actual).toBe(expected); + } else if (Array.isArray(actual) && Array.isArray(expected)) { + expect(actual).toEqual(expected); + } else if (actual !== null && typeof actual === "object" && expected !== null && typeof expected === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } + } + + function shouldBeTrue(code) { + expect(eval(code)).toBeTrue(); + } + + function shouldBeFalse(code) { + expect(eval(code)).toBeFalse(); + } + + function shouldBeNull(code) { + expect(eval(code)).toBeNull(); + } + + function shouldBeUndefined(code) { + expect(eval(code)).toBeUndefined(); + } + + function shouldThrow(code, expected_error) { + expect(() => eval(code)).toThrow(); + } + + function shouldNotThrow(code) { + eval(code); + } + + description("This test checks use of the regexp constructor."); + + var re = /abc/; + + shouldBeTrue("re === RegExp(re)"); + shouldBeTrue("re !== new RegExp(re)"); + shouldBeTrue("re !== RegExp(re,'i')"); + shouldBeTrue("re !== new RegExp(re,'i')"); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/webkit/dotstar.js b/Tests/LibJS/Runtime/3rdparty/webkit/dotstar.js new file mode 100644 index 00000000000..376a7128dc0 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/webkit/dotstar.js @@ -0,0 +1,200 @@ +test.xfail("dotstar", () => { + // WebKit assertion compatibility shim for Ladybird's test-js harness + + function description(msg) { + // No-op, just used for test documentation in WebKit. + } + + function shouldBe(actual_code, expected_code) { + let actual = eval(actual_code); + let expected = eval(expected_code); + if (typeof actual === "string" && typeof expected === "string") { + expect(actual).toBe(expected); + } else if (Array.isArray(actual) && Array.isArray(expected)) { + expect(actual).toEqual(expected); + } else if (actual !== null && typeof actual === "object" && expected !== null && typeof expected === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } + } + + function shouldBeTrue(code) { + expect(eval(code)).toBeTrue(); + } + + function shouldBeFalse(code) { + expect(eval(code)).toBeFalse(); + } + + function shouldBeNull(code) { + expect(eval(code)).toBeNull(); + } + + function shouldBeUndefined(code) { + expect(eval(code)).toBeUndefined(); + } + + function shouldThrow(code, expected_error) { + expect(() => eval(code)).toThrow(); + } + + function shouldNotThrow(code) { + eval(code); + } + + description("This page tests handling of parentheses subexpressions."); + + var regexp1 = /.*blah.*/; + shouldBeNull("regexp1.exec('test')"); + shouldBe("regexp1.exec('blah')", "['blah']"); + shouldBe("regexp1.exec('1blah')", "['1blah']"); + shouldBe("regexp1.exec('blah1')", "['blah1']"); + shouldBe("regexp1.exec('blah blah blah')", "['blah blah blah']"); + shouldBe("regexp1.exec('blah\\nsecond')", "['blah']"); + shouldBe("regexp1.exec('first\\nblah')", "['blah']"); + shouldBe("regexp1.exec('first\\nblah\\nthird')", "['blah']"); + shouldBe("regexp1.exec('first\\nblah2\\nblah3')", "['blah2']"); + + var regexp2 = /^.*blah.*/; + shouldBeNull("regexp2.exec('test')"); + shouldBe("regexp2.exec('blah')", "['blah']"); + shouldBe("regexp2.exec('1blah')", "['1blah']"); + shouldBe("regexp2.exec('blah1')", "['blah1']"); + shouldBe("regexp2.exec('blah blah blah')", "['blah blah blah']"); + shouldBe("regexp2.exec('blah\\nsecond')", "['blah']"); + shouldBeNull("regexp2.exec('first\\nblah')"); + shouldBeNull("regexp2.exec('first\\nblah\\nthird')"); + shouldBeNull("regexp2.exec('first\\nblah2\\nblah3')"); + + var regexp3 = /.*blah.*$/; + shouldBeNull("regexp3.exec('test')"); + shouldBe("regexp3.exec('blah')", "['blah']"); + shouldBe("regexp3.exec('1blah')", "['1blah']"); + shouldBe("regexp3.exec('blah1')", "['blah1']"); + shouldBe("regexp3.exec('blah blah blah')", "['blah blah blah']"); + shouldBeNull("regexp3.exec('blah\\nsecond')"); + shouldBe("regexp3.exec('first\\nblah')", "['blah']"); + shouldBeNull("regexp3.exec('first\\nblah\\nthird')"); + shouldBe("regexp3.exec('first\\nblah2\\nblah3')", "['blah3']"); + + var regexp4 = /^.*blah.*$/; + shouldBeNull("regexp4.exec('test')"); + shouldBe("regexp4.exec('blah')", "['blah']"); + shouldBe("regexp4.exec('1blah')", "['1blah']"); + shouldBe("regexp4.exec('blah1')", "['blah1']"); + shouldBe("regexp4.exec('blah blah blah')", "['blah blah blah']"); + shouldBeNull("regexp4.exec('blah\\nsecond')"); + shouldBeNull("regexp4.exec('first\\nblah')"); + shouldBeNull("regexp4.exec('first\\nblah\\nthird')"); + shouldBeNull("regexp4.exec('first\\nblah2\\nblah3')"); + + var regexp5 = /.*?blah.*/; + shouldBeNull("regexp5.exec('test')"); + shouldBe("regexp5.exec('blah')", "['blah']"); + shouldBe("regexp5.exec('1blah')", "['1blah']"); + shouldBe("regexp5.exec('blah1')", "['blah1']"); + shouldBe("regexp5.exec('blah blah blah')", "['blah blah blah']"); + shouldBe("regexp5.exec('blah\\nsecond')", "['blah']"); + shouldBe("regexp5.exec('first\\nblah')", "['blah']"); + shouldBe("regexp5.exec('first\\nblah\\nthird')", "['blah']"); + shouldBe("regexp5.exec('first\\nblah2\\nblah3')", "['blah2']"); + + var regexp6 = /.*blah.*?/; + shouldBeNull("regexp6.exec('test')"); + shouldBe("regexp6.exec('blah')", "['blah']"); + shouldBe("regexp6.exec('1blah')", "['1blah']"); + shouldBe("regexp6.exec('blah1')", "['blah']"); + shouldBe("regexp6.exec('blah blah blah')", "['blah blah blah']"); + shouldBe("regexp6.exec('blah\\nsecond')", "['blah']"); + shouldBe("regexp6.exec('first\\nblah')", "['blah']"); + shouldBe("regexp6.exec('first\\nblah\\nthird')", "['blah']"); + shouldBe("regexp6.exec('first\\nblah2\\nblah3')", "['blah']"); + + var regexp7 = /^.*?blah.*?$/; + shouldBeNull("regexp7.exec('test')"); + shouldBe("regexp7.exec('blah')", "['blah']"); + shouldBe("regexp7.exec('1blah')", "['1blah']"); + shouldBe("regexp7.exec('blah1')", "['blah1']"); + shouldBe("regexp7.exec('blah blah blah')", "['blah blah blah']"); + shouldBeNull("regexp7.exec('blah\\nsecond')"); + shouldBeNull("regexp7.exec('first\\nblah')"); + shouldBeNull("regexp7.exec('first\\nblah\\nthird')"); + shouldBeNull("regexp7.exec('first\\nblah2\\nblah3')"); + + var regexp8 = /^(.*)blah.*$/; + shouldBeNull("regexp8.exec('test')"); + shouldBe("regexp8.exec('blah')", "['blah','']"); + shouldBe("regexp8.exec('1blah')", "['1blah','1']"); + shouldBe("regexp8.exec('blah1')", "['blah1','']"); + shouldBe("regexp8.exec('blah blah blah')", "['blah blah blah','blah blah ']"); + shouldBeNull("regexp8.exec('blah\\nsecond')"); + shouldBeNull("regexp8.exec('first\\nblah')"); + shouldBeNull("regexp8.exec('first\\nblah\\nthird')"); + shouldBeNull("regexp8.exec('first\\nblah2\\nblah3')"); + + var regexp9 = /.*blah.*/m; + shouldBeNull("regexp9.exec('test')"); + shouldBe("regexp9.exec('blah')", "['blah']"); + shouldBe("regexp9.exec('1blah')", "['1blah']"); + shouldBe("regexp9.exec('blah1')", "['blah1']"); + shouldBe("regexp9.exec('blah blah blah')", "['blah blah blah']"); + shouldBe("regexp9.exec('blah\\nsecond')", "['blah']"); + shouldBe("regexp9.exec('first\\nblah')", "['blah']"); + shouldBe("regexp9.exec('first\\nblah\\nthird')", "['blah']"); + shouldBe("regexp9.exec('first\\nblah2\\nblah3')", "['blah2']"); + + var regexp10 = /^.*blah.*/m; + shouldBeNull("regexp10.exec('test')"); + shouldBe("regexp10.exec('blah')", "['blah']"); + shouldBe("regexp10.exec('1blah')", "['1blah']"); + shouldBe("regexp10.exec('blah1')", "['blah1']"); + shouldBe("regexp10.exec('blah blah blah')", "['blah blah blah']"); + shouldBe("regexp10.exec('blah\\nsecond')", "['blah']"); + shouldBe("regexp10.exec('first\\nblah')", "['blah']"); + shouldBe("regexp10.exec('first\\nblah\\nthird')", "['blah']"); + shouldBe("regexp10.exec('first\\nblah2\\nblah3')", "['blah2']"); + + var regexp11 = /.*(?:blah).*$/; + shouldBeNull("regexp11.exec('test')"); + shouldBe("regexp11.exec('blah')", "['blah']"); + shouldBe("regexp11.exec('1blah')", "['1blah']"); + shouldBe("regexp11.exec('blah1')", "['blah1']"); + shouldBe("regexp11.exec('blah blah blah')", "['blah blah blah']"); + shouldBeNull("regexp11.exec('blah\\nsecond')"); + shouldBe("regexp11.exec('first\\nblah')", "['blah']"); + shouldBeNull("regexp11.exec('first\\nblah\\nthird')"); + shouldBe("regexp11.exec('first\\nblah2\\nblah3')", "['blah3']"); + + var regexp12 = /.*(?:blah|buzz|bang).*$/; + shouldBeNull("regexp12.exec('test')"); + shouldBe("regexp12.exec('blah')", "['blah']"); + shouldBe("regexp12.exec('1blah')", "['1blah']"); + shouldBe("regexp12.exec('blah1')", "['blah1']"); + shouldBe("regexp12.exec('blah blah blah')", "['blah blah blah']"); + shouldBeNull("regexp12.exec('blah\\nsecond')"); + shouldBe("regexp12.exec('first\\nblah')", "['blah']"); + shouldBeNull("regexp12.exec('first\\nblah\\nthird')"); + shouldBe("regexp12.exec('first\\nblah2\\nblah3')", "['blah3']"); + + var regexp13 = /.*\n\d+.*/; + shouldBe("regexp13.exec('abc\\n123')", "['abc\\n123']"); + + var regexp14 = /.?d.*/; + shouldBe("regexp14.exec('abcdefg')", "['cdefg']"); + + var regexp15 = /.*d.?/; + shouldBe("regexp15.exec('abcdefg')", "['abcde']"); + + var regexp16 = /.?d.?/; + shouldBe("regexp16.exec('abcdefg')", "['cde']"); + + var regexp17 = /.{0,2}d.*/; + shouldBe("regexp17.exec('abcdefg')", "['bcdefg']"); + + var regexp18 = /.*d.{0,2}/; + shouldBe("regexp18.exec('abcdefg')", "['abcdef']"); + + var regexp19 = /.{0,2}d.{0,2}/; + shouldBe("regexp19.exec('abcdefg')", "['bcdef']"); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/webkit/early-acid3-86.js b/Tests/LibJS/Runtime/3rdparty/webkit/early-acid3-86.js new file mode 100644 index 00000000000..75e31e972f2 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/webkit/early-acid3-86.js @@ -0,0 +1,54 @@ +test("early-acid3-86", () => { + // WebKit assertion compatibility shim for Ladybird's test-js harness + + function description(msg) { + // No-op, just used for test documentation in WebKit. + } + + function shouldBe(actual_code, expected_code) { + let actual = eval(actual_code); + let expected = eval(expected_code); + if (typeof actual === "string" && typeof expected === "string") { + expect(actual).toBe(expected); + } else if (Array.isArray(actual) && Array.isArray(expected)) { + expect(actual).toEqual(expected); + } else if (actual !== null && typeof actual === "object" && expected !== null && typeof expected === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } + } + + function shouldBeTrue(code) { + expect(eval(code)).toBeTrue(); + } + + function shouldBeFalse(code) { + expect(eval(code)).toBeFalse(); + } + + function shouldBeNull(code) { + expect(eval(code)).toBeNull(); + } + + function shouldBeUndefined(code) { + expect(eval(code)).toBeUndefined(); + } + + function shouldThrow(code, expected_error) { + expect(() => eval(code)).toThrow(); + } + + function shouldNotThrow(code) { + eval(code); + } + + description("Test that covers capturing brackets, and was adapted from a part of an early version of Acid3."); + + // JS regexps aren't like Perl regexps, if their character + // classes start with a ] that means they're empty. So this + // is a syntax error; if we get here it's a bug. + shouldThrow("/TA[])]/.exec('TA]')"); + shouldBe("/[]/.exec('')", "null"); + shouldBe("/(\\3)(\\1)(a)/.exec('cat').toString()", "'a,,,a'"); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/webkit/ecma-regex-examples.js b/Tests/LibJS/Runtime/3rdparty/webkit/ecma-regex-examples.js new file mode 100644 index 00000000000..7659d2b3420 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/webkit/ecma-regex-examples.js @@ -0,0 +1,83 @@ +test("ecma-regex-examples", () => { + // WebKit assertion compatibility shim for Ladybird's test-js harness + + function description(msg) { + // No-op, just used for test documentation in WebKit. + } + + function shouldBe(actual_code, expected_code) { + let actual = eval(actual_code); + let expected = eval(expected_code); + if (typeof actual === "string" && typeof expected === "string") { + expect(actual).toBe(expected); + } else if (Array.isArray(actual) && Array.isArray(expected)) { + expect(actual).toEqual(expected); + } else if (actual !== null && typeof actual === "object" && expected !== null && typeof expected === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } + } + + function shouldBeTrue(code) { + expect(eval(code)).toBeTrue(); + } + + function shouldBeFalse(code) { + expect(eval(code)).toBeFalse(); + } + + function shouldBeNull(code) { + expect(eval(code)).toBeNull(); + } + + function shouldBeUndefined(code) { + expect(eval(code)).toBeUndefined(); + } + + function shouldThrow(code, expected_error) { + expect(() => eval(code)).toThrow(); + } + + function shouldNotThrow(code) { + eval(code); + } + + description("This page tests the regex examples from the ECMA-262 specification."); + + var regex01 = /a|ab/; + shouldBe('regex01.exec("abc")', '["a"]'); + + var regex02 = /((a)|(ab))((c)|(bc))/; + shouldBe('regex02.exec("abc")', '["abc", "a", "a", undefined, "bc", undefined, "bc"]'); + + var regex03 = /a[a-z]{2,4}/; + shouldBe('regex03.exec("abcdefghi")', '["abcde"]'); + + var regex04 = /a[a-z]{2,4}?/; + shouldBe('regex04.exec("abcdefghi")', '["abc"]'); + + var regex05 = /(aa|aabaac|ba|b|c)*/; + shouldBe('regex05.exec("aabaac")', '["aaba", "ba"]'); + + var regex06 = /^(a+)\1*,\1+$/; + shouldBe('"aaaaaaaaaa,aaaaaaaaaaaaaaa".replace(regex06,"$1")', '"aaaaa"'); + + var regex07 = /(z)((a+)?(b+)?(c))*/; + shouldBe('regex07.exec("zaacbbbcac")', '["zaacbbbcac", "z", "ac", "a", undefined, "c"]'); + + var regex08 = /(a*)*/; + shouldBe('regex08.exec("b")', '["", undefined]'); + + var regex09 = /(a*)b\1+/; + shouldBe('regex09.exec("baaaac")', '["b", ""]'); + + var regex10 = /(?=(a+))/; + shouldBe('regex10.exec("baaabac")', '["", "aaa"]'); + + var regex11 = /(?=(a+))a*b\1/; + shouldBe('regex11.exec("baaabac")', '["aba", "a"]'); + + var regex12 = /(.*?)a(?!(a+)b\2c)\2(.*)/; + shouldBe('regex12.exec("baaabaac")', '["baaabaac", "ba", undefined, "abaac"]'); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/webkit/invalid-range-in-class.js b/Tests/LibJS/Runtime/3rdparty/webkit/invalid-range-in-class.js new file mode 100644 index 00000000000..7f34cd9309b --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/webkit/invalid-range-in-class.js @@ -0,0 +1,71 @@ +test("invalid-range-in-class", () => { + // WebKit assertion compatibility shim for Ladybird's test-js harness + + function description(msg) { + // No-op, just used for test documentation in WebKit. + } + + function shouldBe(actual_code, expected_code) { + let actual = eval(actual_code); + let expected = eval(expected_code); + if (typeof actual === "string" && typeof expected === "string") { + expect(actual).toBe(expected); + } else if (Array.isArray(actual) && Array.isArray(expected)) { + expect(actual).toEqual(expected); + } else if (actual !== null && typeof actual === "object" && expected !== null && typeof expected === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } + } + + function shouldBeTrue(code) { + expect(eval(code)).toBeTrue(); + } + + function shouldBeFalse(code) { + expect(eval(code)).toBeFalse(); + } + + function shouldBeNull(code) { + expect(eval(code)).toBeNull(); + } + + function shouldBeUndefined(code) { + expect(eval(code)).toBeUndefined(); + } + + function shouldThrow(code, expected_error) { + expect(() => eval(code)).toThrow(); + } + + function shouldNotThrow(code) { + eval(code); + } + + description("This page tests invalid character ranges in character classes."); + + // These test a basic range / non range. + shouldBe('/[a-c]+/.exec("-acbd");', '["acb"]'); + shouldBe('/[a\\-c]+/.exec("-acbd")', '["-ac"]'); + + // A reverse-range is invalid. + shouldThrow('/[c-a]+/.exec("-acbd");'); + + // A character-class in a range is invalid, according to ECMA-262, but we allow it. + shouldBe('/[\\d-x]+/.exec("1-3xy");', '["1-3x"]'); + shouldBe('/[x-\\d]+/.exec("1-3xy");', '["1-3x"]'); + shouldBe('/[\\d-\\d]+/.exec("1-3xy");', '["1-3"]'); + + // Whilst we break with ECMA-262's definition of CharacterRange, we do comply with + // the grammar, and as such in the following regex a-z cannot be matched as a range. + shouldBe('/[\\d-a-z]+/.exec("az1-3y");', '["az1-3"]'); + + // An escaped hypen should not be confused for an invalid range. + shouldBe('/[\\d\\-x]+/.exec("1-3xy");', '["1-3x"]'); + shouldBe('/[x\\-\\d]+/.exec("1-3xy");', '["1-3x"]'); + shouldBe('/[\\d\\-\\d]+/.exec("1-3xy");', '["1-3"]'); + + // A hyphen after a character-class is not invalid. + shouldBe('/[\\d-]+/.exec("1-3xy")', '["1-3"]'); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/webkit/lastIndex.js b/Tests/LibJS/Runtime/3rdparty/webkit/lastIndex.js new file mode 100644 index 00000000000..78a6f18e4e0 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/webkit/lastIndex.js @@ -0,0 +1,109 @@ +test("lastIndex", () => { + // WebKit assertion compatibility shim for Ladybird's test-js harness + + function description(msg) { + // No-op, just used for test documentation in WebKit. + } + + function shouldBe(actual_code, expected_code) { + let actual = eval(actual_code); + let expected = eval(expected_code); + if (typeof actual === "string" && typeof expected === "string") { + expect(actual).toBe(expected); + } else if (Array.isArray(actual) && Array.isArray(expected)) { + expect(actual).toEqual(expected); + } else if (actual !== null && typeof actual === "object" && expected !== null && typeof expected === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } + } + + function shouldBeTrue(code) { + expect(eval(code)).toBeTrue(); + } + + function shouldBeFalse(code) { + expect(eval(code)).toBeFalse(); + } + + function shouldBeNull(code) { + expect(eval(code)).toBeNull(); + } + + function shouldBeUndefined(code) { + expect(eval(code)).toBeUndefined(); + } + + function shouldThrow(code, expected_error) { + expect(() => eval(code)).toThrow(); + } + + function shouldNotThrow(code) { + eval(code); + } + + description("This page tests that a RegExp object's lastIndex behaves like a regular property."); + + // lastIndex is not configurable + shouldBeFalse("delete /x/.lastIndex"); + shouldThrow("'use strict'; delete /x/.lastIndex"); + + // lastIndex is not enumerable + shouldBeTrue("'lastIndex' in /x/"); + shouldBeTrue("for (property in /x/) if (property === 'lastIndex') throw false; true"); + + // lastIndex is writable + shouldBeTrue("var re = /x/; re.lastIndex = re; re.lastIndex === re"); + + // Cannot redefine lastIndex as an accessor + shouldThrow("Object.defineProperty(/x/, {get:function(){}})"); + + // Cannot redefine lastIndex as enumerable + shouldThrow("Object.defineProperty(/x/, 'lastIndex', {enumerable:true}); true"); + shouldBeTrue("Object.defineProperty(/x/, 'lastIndex', {enumerable:false}); true"); + + // Cannot redefine lastIndex as configurable + shouldThrow("Object.defineProperty(/x/, 'lastIndex', {configurable:true}); true"); + shouldBeTrue("Object.defineProperty(/x/, 'lastIndex', {configurable:false}); true"); + + // Can redefine lastIndex as read-only + shouldBe( + "var re = Object.defineProperty(/x/, 'lastIndex', {writable:true}); re.lastIndex = 42; re.lastIndex", + "42" + ); + shouldBe( + "var re = Object.defineProperty(/x/, 'lastIndex', {writable:false}); re.lastIndex = 42; re.lastIndex", + "0" + ); + + // Can redefine the value + shouldBe("var re = Object.defineProperty(/x/, 'lastIndex', {value:42}); re.lastIndex", "42"); + + // Cannot redefine read-only lastIndex as writable + shouldThrow( + "Object.defineProperty(Object.defineProperty(/x/, 'lastIndex', {writable:false}), 'lastIndex', {writable:true}); true" + ); + + // Can only redefine the value of a read-only lastIndex as the current value + shouldThrow( + "Object.defineProperty(Object.defineProperty(/x/, 'lastIndex', {writable:false}), 'lastIndex', {value:42}); true" + ); + shouldBeTrue( + "Object.defineProperty(Object.defineProperty(/x/, 'lastIndex', {writable:false}), 'lastIndex', {value:0}); true" + ); + + // Trying to run a global regular expression should throw, if lastIndex is read-only + shouldBe("Object.defineProperty(/x/, 'lastIndex', {writable:false}).exec('')", "null"); + shouldBe("Object.defineProperty(/x/, 'lastIndex', {writable:false}).exec('x')", '["x"]'); + shouldThrow("Object.defineProperty(/x/g, 'lastIndex', {writable:false}).exec('')"); + shouldThrow("Object.defineProperty(/x/g, 'lastIndex', {writable:false}).exec('x')"); + + // Should be able to freeze a regular expression object. + shouldBeTrue("var re = /x/; Object.freeze(re); Object.isFrozen(re);"); + + // Presence of setter on prototype chain should not affect RegexpMatchesArray + shouldBe('/x/.exec("x").input', '"x"'); + Object.defineProperty(Object.prototype, "input", { set: function () {} }); + shouldBe('/x/.exec("x").input', '"x"'); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/webkit/malformed-escapes.js b/Tests/LibJS/Runtime/3rdparty/webkit/malformed-escapes.js new file mode 100644 index 00000000000..7eb3ec814ee --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/webkit/malformed-escapes.js @@ -0,0 +1,92 @@ +test("malformed-escapes", () => { + // WebKit assertion compatibility shim for Ladybird's test-js harness + + function debug(msg) {} + function description(msg) { + // No-op, just used for test documentation in WebKit. + } + + function shouldBe(actual_code, expected_code) { + let actual = eval(actual_code); + let expected = eval(expected_code); + if (typeof actual === "string" && typeof expected === "string") { + expect(actual).toBe(expected); + } else if (Array.isArray(actual) && Array.isArray(expected)) { + expect(actual).toEqual(expected); + } else if (actual !== null && typeof actual === "object" && expected !== null && typeof expected === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } + } + + function shouldBeTrue(code) { + expect(eval(code)).toBeTrue(); + } + + function shouldBeFalse(code) { + expect(eval(code)).toBeFalse(); + } + + function shouldBeNull(code) { + expect(eval(code)).toBeNull(); + } + + function shouldBeUndefined(code) { + expect(eval(code)).toBeUndefined(); + } + + function shouldThrow(code, expected_error) { + expect(() => eval(code)).toThrow(); + } + + function shouldNotThrow(code) { + eval(code); + } + + description("This page tests handling of malformed escape sequences."); + + var regexp; + + regexp = /\ug/gm; + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test('ug')"); + shouldBe("regexp.lastIndex", "2"); + + regexp = /\xg/gm; + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test('xg')"); + shouldBe("regexp.lastIndex", "2"); + + regexp = /\c_/gm; + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test('\\\\c_')"); + shouldBe("regexp.lastIndex", "3"); + + regexp = /[\B]/gm; + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test('B')"); + shouldBe("regexp.lastIndex", "1"); + + regexp = /[\b]/gm; + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test('\\b')"); + shouldBe("regexp.lastIndex", "1"); + + regexp = /\8/gm; + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test('\\\\8')"); + shouldBe("regexp.lastIndex", "2"); + + regexp = /^[\c]$/; + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test('c')"); + + regexp = /^[\c_]$/; + debug("\nTesting regexp: " + regexp); + shouldBeFalse("regexp.test('c')"); + + regexp = /^[\c]]$/; + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test('c]')"); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/webkit/non-capturing-backtracking.js b/Tests/LibJS/Runtime/3rdparty/webkit/non-capturing-backtracking.js new file mode 100644 index 00000000000..ab1f3534a07 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/webkit/non-capturing-backtracking.js @@ -0,0 +1,50 @@ +test("non-capturing-backtracking", () => { + // WebKit assertion compatibility shim for Ladybird's test-js harness + + function description(msg) { + // No-op, just used for test documentation in WebKit. + } + + function shouldBe(actual_code, expected_code) { + let actual = eval(actual_code); + let expected = eval(expected_code); + if (typeof actual === "string" && typeof expected === "string") { + expect(actual).toBe(expected); + } else if (Array.isArray(actual) && Array.isArray(expected)) { + expect(actual).toEqual(expected); + } else if (actual !== null && typeof actual === "object" && expected !== null && typeof expected === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } + } + + function shouldBeTrue(code) { + expect(eval(code)).toBeTrue(); + } + + function shouldBeFalse(code) { + expect(eval(code)).toBeFalse(); + } + + function shouldBeNull(code) { + expect(eval(code)).toBeNull(); + } + + function shouldBeUndefined(code) { + expect(eval(code)).toBeUndefined(); + } + + function shouldThrow(code, expected_error) { + expect(() => eval(code)).toThrow(); + } + + function shouldNotThrow(code) { + eval(code); + } + + description("This page tests for proper backtracking with greedy quantifiers and non-capturing parentheses."); + + var re = /(?:a*)a/; + shouldBe("re.exec('a')", "['a']"); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/webkit/non-pattern-characters.js b/Tests/LibJS/Runtime/3rdparty/webkit/non-pattern-characters.js new file mode 100644 index 00000000000..e67a4c9840a --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/webkit/non-pattern-characters.js @@ -0,0 +1,280 @@ +test("non-pattern-characters", () => { + // WebKit assertion compatibility shim for Ladybird's test-js harness + + function debug(msg) {} + function description(msg) { + // No-op, just used for test documentation in WebKit. + } + + function shouldBe(actual_code, expected_code) { + let actual = eval(actual_code); + let expected = eval(expected_code); + if (typeof actual === "string" && typeof expected === "string") { + expect(actual).toBe(expected); + } else if (Array.isArray(actual) && Array.isArray(expected)) { + expect(actual).toEqual(expected); + } else if (actual !== null && typeof actual === "object" && expected !== null && typeof expected === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } + } + + function shouldBeTrue(code) { + expect(eval(code)).toBeTrue(); + } + + function shouldBeFalse(code) { + expect(eval(code)).toBeFalse(); + } + + function shouldBeNull(code) { + expect(eval(code)).toBeNull(); + } + + function shouldBeUndefined(code) { + expect(eval(code)).toBeUndefined(); + } + + function shouldThrow(code, expected_error) { + expect(() => eval(code)).toThrow(); + } + + function shouldNotThrow(code) { + eval(code); + } + + description( + "This page tests handling of characters which, according to ECMA 262, are not regular expression PatternCharacters. Those characters are: ^ $ \\ . * + ? ( ) [ ] { } |" + ); + + // We test two cases, to match the two cases in the WREC parser. + // Test 1: the character stand-alone. + // Test 2: the character following a PatternCharacter. + + var regexp; + + // ^: Always allowed, always an assertion. + + regexp = /^/g; + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test('')"); + shouldBe("regexp.lastIndex", "0"); + + regexp = /\n^/gm; + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test('\\n\\n')"); + shouldBe("regexp.lastIndex", "1"); + + // $: Always allowed, always an assertion. + + regexp = /$/g; + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test('')"); + shouldBe("regexp.lastIndex", "0"); + + regexp = /\n$/gm; + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test('\\n\\n')"); + shouldBe("regexp.lastIndex", "1"); + + // \: Only allowed as a prefix. Contrary to spec, always treated as an + // IdentityEscape when followed by an invalid escape postfix. + regexp = /\z/; + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test('z')"); // invalid postfix => IdentityEscape + + regexp = /a\z/; + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test('az')"); // invalid postfix => IdentityEscape + + regexp = /\_/; + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test('_')"); // invalid postfix => IdentityEscape + + regexp = /a\_/; + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test('a_')"); // invalid postfix => IdentityEscape + + debug("\nTesting regexp: " + "[invalid \\ variations]"); + shouldThrow("/\\/"); // no postfix => not allowed + shouldThrow("/a\\/"); // no postfix => not allowed + + // .: Always allowed, always a non-newline wildcard. + regexp = /./; + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test('a')"); + shouldBeFalse("regexp.test('\\n')"); + + regexp = /a./; + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test('aa')"); + shouldBeFalse("regexp.test('a\\n')"); + + // *: Only allowed as a postfix to a PatternCharacter. Behaves as a {0,Infinity} quantifier. + regexp = /a*/gm; + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test('b')"); + shouldBe("regexp.lastIndex", "0"); + + shouldBeTrue("regexp.test('aaba')"); + shouldBe("regexp.lastIndex", "2"); + + debug("\nTesting regexp: " + "[invalid * variations]"); + shouldThrow("/*/"); // Unterminated comment. + shouldThrow("/^*/"); // Prefixed by ^ to avoid confusion with comment syntax. + + // +: Only allowed as a postfix to a PatternCharacter. Behaves as a {1,Infinity} quantifier. + regexp = /a+/gm; + debug("\nTesting regexp: " + regexp); + shouldBeFalse("regexp.test('b')"); + + shouldBeTrue("regexp.test('aaba')"); + shouldBe("regexp.lastIndex", "2"); + + debug("\nTesting regexp: " + "[invalid + variations]"); + shouldThrow("/+/"); + + // ?: Only allowed as a postfix to a PatternCharacter. Behaves as a {0,1} quantifier. + regexp = /a?/gm; + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test('b')"); + shouldBe("regexp.lastIndex", "0"); + + shouldBeTrue("regexp.test('aaba')"); + shouldBe("regexp.lastIndex", "1"); + + debug("\nTesting regexp: " + "[invalid ? variations]"); + shouldThrow("/?/"); + + // (: Only allowed if it matches a ). + debug("\nTesting regexp: " + "[invalid ( variations]"); + shouldThrow("/(/"); + shouldThrow("/a(/"); + + // ): Only allowed if it matches a (. + debug("\nTesting regexp: " + "[invalid ) variations]"); + shouldThrow("/)/"); + shouldThrow("/a)/"); + + // [: Only allowed if it matches a ] and the stuff in between is a valid character class. + debug("\nTesting regexp: " + "[invalid [ variations]"); + shouldThrow("/[/"); + shouldThrow("/a[/"); + + shouldThrow("/[b-a]/"); + shouldThrow("/a[b-a]/"); + + // ]: Closes a ]. Contrary to spec, if no [ was seen, acts as a regular PatternCharacter. + regexp = /]/gm; + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test(']')"); + shouldBe("regexp.lastIndex", "1"); + + regexp = /a]/gm; + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test('a]')"); + shouldBe("regexp.lastIndex", "2"); + + // {: Begins a quantifier. Contrary to spec, if no } is seen, or if the stuff in + // between does not lex as a quantifier, acts as a regular PatternCharacter. If + // the stuff in between does lex as a quantifier, but the quantifier is invalid, + // acts as a syntax error. + regexp = /{/gm; + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test('{')"); + shouldBe("regexp.lastIndex", "1"); + + regexp = /a{/gm; + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test('a{')"); + shouldBe("regexp.lastIndex", "2"); + + regexp = /{a/gm; + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test('{a')"); + shouldBe("regexp.lastIndex", "2"); + + regexp = /a{a/gm; + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test('a{a')"); + shouldBe("regexp.lastIndex", "3"); + + regexp = /{1,/gm; + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test('{1,')"); + shouldBe("regexp.lastIndex", "3"); + + regexp = /a{1,/gm; + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test('a{1,')"); + shouldBe("regexp.lastIndex", "4"); + + regexp = /{1,a/gm; + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test('{1,a')"); + shouldBe("regexp.lastIndex", "4"); + + regexp = /{1,0/gm; + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test('{1,0')"); + shouldBe("regexp.lastIndex", "4"); + + regexp = /{1, 0}/gm; + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test('{1, 0}')"); + shouldBe("regexp.lastIndex", "6"); + + regexp = /a{1, 0}/gm; + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test('a{1, 0}')"); + shouldBe("regexp.lastIndex", "7"); + + try { + regexp = new RegExp("a{1,0", "gm"); + } catch (e) { + regexp = e; + } // Work around exception thrown in Firefox -- probably too weird to be worth matching. + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test('a{1,0')"); + shouldBe("regexp.lastIndex", "5"); + + regexp = /a{0}/gm; + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test('a')"); + shouldBe("regexp.lastIndex", "0"); + shouldBeTrue("regexp.test('b')"); + shouldBe("regexp.lastIndex", "0"); + + debug("\nTesting regexp: " + "[invalid {} variations]"); + shouldThrow("/{0}/"); + shouldThrow("/{1,0}/"); + shouldThrow("/a{1,0}/"); + + // }: Ends a quantifier. Same rules as for {. + regexp = /}/gm; + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test('}')"); + shouldBe("regexp.lastIndex", "1"); + + regexp = /a}/gm; + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test('a}')"); + shouldBe("regexp.lastIndex", "2"); + + // |: Always allowed, always separates two alternatives. + regexp = new RegExp("", "gm"); + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test('')"); + shouldBe("regexp.lastIndex", "0"); + + regexp = /|/gm; + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test('|')"); + shouldBe("regexp.lastIndex", "0"); + + regexp = /a|/gm; + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test('|')"); + shouldBe("regexp.lastIndex", "0"); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/webkit/overflow.js b/Tests/LibJS/Runtime/3rdparty/webkit/overflow.js new file mode 100644 index 00000000000..ee0d411b72b --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/webkit/overflow.js @@ -0,0 +1,67 @@ +test.xfail("overflow", () => { + // WebKit assertion compatibility shim for Ladybird's test-js harness + + function description(msg) { + // No-op, just used for test documentation in WebKit. + } + + function shouldBe(actual_code, expected_code) { + let actual = eval(actual_code); + let expected = eval(expected_code); + if (typeof actual === "string" && typeof expected === "string") { + expect(actual).toBe(expected); + } else if (Array.isArray(actual) && Array.isArray(expected)) { + expect(actual).toEqual(expected); + } else if (actual !== null && typeof actual === "object" && expected !== null && typeof expected === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } + } + + function shouldBeTrue(code) { + expect(eval(code)).toBeTrue(); + } + + function shouldBeFalse(code) { + expect(eval(code)).toBeFalse(); + } + + function shouldBeNull(code) { + expect(eval(code)).toBeNull(); + } + + function shouldBeUndefined(code) { + expect(eval(code)).toBeUndefined(); + } + + function shouldThrow(code, expected_error) { + expect(() => eval(code)).toThrow(); + } + + function shouldNotThrow(code) { + eval(code); + } + + description("This test checks expressions with alternative lengths of appox. 2^31."); + + var regexp1 = /(?:(?=g))|(?:m).{2147483648,}/; + shouldBe("regexp1.exec('')", "null"); + + var regexp2 = /(?:(?=g)).{2147483648,}/; + shouldBe("regexp2.exec('')", "null"); + + var s3 = "&{6}u4a64YfQP{C}u88c4u5772Qu8693{4294967167}u85f2u7f3fs((uf202){4})u5bc6u1947"; + var regexp3 = new RegExp(s3, ""); + shouldBe("regexp3.exec(s3)", "null"); + + shouldThrow( + "function f() { /[^a$]{18446744073709551615}/ }", + '"SyntaxError: Invalid regular expression: number too large in {} quantifier"' + ); + + shouldThrow( + "new RegExp('((?=$))??(?:\\\\1){1180591620717411303423,}')", + '"SyntaxError: Invalid regular expression: number too large in {} quantifier"' + ); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/webkit/parentheses.js b/Tests/LibJS/Runtime/3rdparty/webkit/parentheses.js new file mode 100644 index 00000000000..8ff3642f0dc --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/webkit/parentheses.js @@ -0,0 +1,324 @@ +test("parentheses", () => { + // WebKit assertion compatibility shim for Ladybird's test-js harness + + function description(msg) { + // No-op, just used for test documentation in WebKit. + } + + function shouldBe(actual_code, expected_code) { + let actual = eval(actual_code); + let expected = eval(expected_code); + if (typeof actual === "string" && typeof expected === "string") { + expect(actual).toBe(expected); + } else if (Array.isArray(actual) && Array.isArray(expected)) { + expect(actual).toEqual(expected); + } else if (actual !== null && typeof actual === "object" && expected !== null && typeof expected === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } + } + + function shouldBeTrue(code) { + expect(eval(code)).toBeTrue(); + } + + function shouldBeFalse(code) { + expect(eval(code)).toBeFalse(); + } + + function shouldBeNull(code) { + expect(eval(code)).toBeNull(); + } + + function shouldBeUndefined(code) { + expect(eval(code)).toBeUndefined(); + } + + function shouldThrow(code, expected_error) { + expect(() => eval(code)).toThrow(); + } + + function shouldNotThrow(code) { + eval(code); + } + + description("This page tests handling of parentheses subexpressions."); + + var regexp1 = /(a|A)(b|B)/; + shouldBe("regexp1.exec('abc')", "['ab','a','b']"); + + var regexp2 = /(a((b)|c|d))e/; + shouldBe("regexp2.exec('abacadabe')", "['abe','ab','b','b']"); + + var regexp3 = /(a(b|(c)|d))e/; + shouldBe("regexp3.exec('abacadabe')", "['abe','ab','b',undefined]"); + + var regexp4 = /(a(b|c|(d)))e/; + shouldBe("regexp4.exec('abacadabe')", "['abe','ab','b',undefined]"); + + var regexp5 = /(a((b)|(c)|(d)))e/; + shouldBe("regexp5.exec('abacadabe')", "['abe','ab','b','b',undefined,undefined]"); + + var regexp6 = /(a((b)|(c)|(d)))/; + shouldBe("regexp6.exec('abcde')", "['ab','ab','b','b',undefined,undefined]"); + + var regexp7 = /(a(b)??)??c/; + shouldBe("regexp7.exec('abc')", "['abc','ab','b']"); + + var regexp8 = /(a|(e|q))(x|y)/; + shouldBe("regexp8.exec('bcaddxqy')", "['qy','q','q','y']"); + + var regexp9 = /((t|b)?|a)$/; + shouldBe("regexp9.exec('asdfjejgsdflaksdfjkeljghkjea')", "['a','a',undefined]"); + + var regexp10 = /(?:h|e?(?:t|b)?|a?(?:t|b)?)(?:$)/; + shouldBe("regexp10.exec('asdfjejgsdflaksdfjkeljghat')", "['at']"); + + var regexp11 = /([Jj]ava([Ss]cript)?)\sis\s(fun\w*)/; + shouldBeNull("regexp11.exec('Developing with JavaScript is dangerous, do not try it without assistance')"); + + var regexp12 = /(?:(.+), )?(.+), (..) to (?:(.+), )?(.+), (..)/; + shouldBe( + "regexp12.exec('Seattle, WA to Buckley, WA')", + "['Seattle, WA to Buckley, WA', undefined, 'Seattle', 'WA', undefined, 'Buckley', 'WA']" + ); + + var regexp13 = /(A)?(A.*)/; + shouldBe("regexp13.exec('zxcasd;fl\ ^AaaAAaaaf;lrlrzs')", "['AaaAAaaaf;lrlrzs',undefined,'AaaAAaaaf;lrlrzs']"); + + var regexp14 = /(a)|(b)/; + shouldBe("regexp14.exec('b')", "['b',undefined,'b']"); + + var regexp15 = /^(?!(ab)de|x)(abd)(f)/; + shouldBe("regexp15.exec('abdf')", "['abdf',undefined,'abd','f']"); + + var regexp16 = /(a|A)(b|B)/; + shouldBe("regexp16.exec('abc')", "['ab','a','b']"); + + var regexp17 = /(a|d|q|)x/i; + shouldBe("regexp17.exec('bcaDxqy')", "['Dx','D']"); + + var regexp18 = /^.*?(:|$)/; + shouldBe("regexp18.exec('Hello: World')", "['Hello:',':']"); + + var regexp19 = /(ab|^.{0,2})bar/; + shouldBe("regexp19.exec('barrel')", "['bar','']"); + + var regexp20 = /(?:(?!foo)...|^.{0,2})bar(.*)/; + shouldBe("regexp20.exec('barrel')", "['barrel','rel']"); + shouldBe("regexp20.exec('2barrel')", "['2barrel','rel']"); + + var regexp21 = /([a-g](b|B)|xyz)/; + shouldBe("regexp21.exec('abc')", "['ab','ab','b']"); + + var regexp22 = /(?:^|;)\s*abc=([^;]*)/; + shouldBeNull("regexp22.exec('abcdlskfgjdslkfg')"); + + var regexp23 = /"[^<"]*"|'[^<']*'/; + shouldBe("regexp23.exec('\"'\s]*)?)|(/?>)|.[^\w\s>]*)"); + shouldBe("regexp33.exec('> ')", "['>',undefined,undefined,'>']"); + + var regexp34 = /(?:^|\b)btn-\S+/; + shouldBeNull("regexp34.exec('xyz123')"); + shouldBe("regexp34.exec('btn-abc')", "['btn-abc']"); + shouldBeNull("regexp34.exec('btn- abc')"); + shouldBeNull("regexp34.exec('XXbtn-abc')"); + shouldBe("regexp34.exec('XX btn-abc')", "['btn-abc']"); + + var regexp35 = /^((a|b)(x|xxx)|)$/; + shouldBe("regexp35.exec('ax')", "['ax','ax','a','x']"); + shouldBeNull("regexp35.exec('axx')"); + shouldBe("regexp35.exec('axxx')", "['axxx','axxx','a','xxx']"); + shouldBe("regexp35.exec('bx')", "['bx','bx','b','x']"); + shouldBeNull("regexp35.exec('bxx')"); + shouldBe("regexp35.exec('bxxx')", "['bxxx','bxxx','b','xxx']"); + + var regexp36 = /^((\/|\.|\-)(\d\d|\d\d\d\d)|)$/; + shouldBe("regexp36.exec('/2011')", "['/2011','/2011','/','2011']"); + shouldBe("regexp36.exec('/11')", "['/11','/11','/','11']"); + shouldBeNull("regexp36.exec('/123')"); + + var regexp37 = /^([1][0-2]|[0]\d|\d)(\/|\.|\-)([0-2]\d|[3][0-1]|\d)((\/|\.|\-)(\d\d|\d\d\d\d)|)$/; + shouldBe("regexp37.exec('7/4/1776')", "['7/4/1776','7','/','4','/1776','/','1776']"); + shouldBe("regexp37.exec('07-04-1776')", "['07-04-1776','07','-','04','-1776','-','1776']"); + + var regexp38 = /^(z|(x|xx)|b|)$/; + shouldBe("regexp38.exec('xx')", "['xx','xx','xx']"); + shouldBe("regexp38.exec('b')", "['b','b',undefined]"); + shouldBe("regexp38.exec('z')", "['z','z',undefined]"); + shouldBe("regexp38.exec('')", "['','',undefined]"); + + var regexp39 = /(8|((?=P)))?/; + shouldBe("regexp39.exec('')", "['',undefined,undefined]"); + shouldBe("regexp39.exec('8')", "['8','8',undefined]"); + shouldBe("regexp39.exec('zP')", "['',undefined,undefined]"); + + var regexp40 = /((8)|((?=P){4}))?()/; + shouldBe("regexp40.exec('')", "['',undefined,undefined,undefined,'']"); + shouldBe("regexp40.exec('8')", "['8','8','8',undefined,'']"); + shouldBe("regexp40.exec('zPz')", "['',undefined,undefined,undefined,'']"); + shouldBe("regexp40.exec('zPPz')", "['',undefined,undefined,undefined,'']"); + shouldBe("regexp40.exec('zPPPz')", "['',undefined,undefined,undefined,'']"); + shouldBe("regexp40.exec('zPPPPz')", "['',undefined,undefined,undefined,'']"); + + var regexp41 = /(([\w\-]+:\/\/?|www[.])[^\s()<>]+(?:([\w\d]+)|([^\[:punct:\]\s()<>\W]|\/)))/; + shouldBe( + "regexp41.exec('Here is a link: http://www.acme.com/our_products/index.html. That is all we want!')", + "['http://www.acme.com/our_products/index.html','http://www.acme.com/our_products/index.html','http://','l',undefined]" + ); + + var regexp42 = /((?:(4)?))?/; + shouldBe("regexp42.exec('')", "['',undefined,undefined]"); + shouldBe("regexp42.exec('4')", "['4','4','4']"); + shouldBe("regexp42.exec('4321')", "['4','4','4']"); + + shouldBeTrue("/(?!(?=r{0}){2,})|((z)?)?/gi.test('')"); + + var regexp43 = /(?!(?:\1+s))/; + shouldBe("regexp43.exec('SSS')", "['']"); + + var regexp44 = /(?!(?:\3+(s+?)))/g; + shouldBe("regexp44.exec('SSS')", "['',undefined]"); + + var regexp45 = /((?!(?:|)v{2,}|))/; + shouldBeNull("regexp45.exec('vt')"); + + var regexp46 = /(w)(?:5{3}|())|pk/; + shouldBeNull("regexp46.exec('5')"); + shouldBe("regexp46.exec('pk')", "['pk',undefined,undefined]"); + shouldBe("regexp46.exec('Xw555')", "['w555','w',undefined]"); + shouldBe("regexp46.exec('Xw55pk5')", "['w','w','']"); + + var regexp47 = /(.*?)(?:(?:\?(.*?)?)?)(?:(?:#)?)$/; + shouldBe( + "regexp47.exec('/www.acme.com/this/is/a/path/file.txt')", + "['/www.acme.com/this/is/a/path/file.txt','/www.acme.com/this/is/a/path/file.txt',undefined]" + ); + + var regexp48 = /^(?:(\w+):\/*([\w\.\-\d]+)(?::(\d+)|)(?=(?:\/|$))|)(?:$|\/?(.*?)(?:\?(.*?)?|)(?:#(.*)|)$)/; + /* The regexp on the prior line confuses Xcode syntax highlighting, this coment fixes it! */ + shouldBe( + "regexp48.exec('http://www.acme.com/this/is/a/path/file.txt')", + "['http://www.acme.com/this/is/a/path/file.txt','http','www.acme.com',undefined,'this/is/a/path/file.txt',undefined,undefined]" + ); + + var regexp49 = + /(?:([^:]*?)(?:(?:\?(.*?)?)?)(?:(?:#)?)$)|(?:^(?:(\w+):\/*([\w\.\-\d]+)(?::(\d+)|)(?=(?:\/|$))|)(?:$|\/?(.*?)(?:\?(.*?)?|)(?:#(.*)|)$))/; + /* The regexp on the prior line confuses Xcode syntax highlighting, this coment fixes it! */ + shouldBe( + "regexp49.exec('http://www.acme.com/this/is/a/path/file.txt')", + "['http://www.acme.com/this/is/a/path/file.txt',undefined,undefined,'http','www.acme.com',undefined,'this/is/a/path/file.txt',undefined,undefined]" + ); + + var regexp50 = /((a)b{28,}c|d)x/; + shouldBeNull("regexp50.exec('((a)b{28,}c|d)x')"); + shouldBe( + "regexp50.exec('abbbbbbbbbbbbbbbbbbbbbbbbbbbbcx')", + "['abbbbbbbbbbbbbbbbbbbbbbbbbbbbcx', 'abbbbbbbbbbbbbbbbbbbbbbbbbbbbc', 'a']" + ); + shouldBe("regexp50.exec('dx')", "['dx', 'd', undefined]"); + + var s = "((.\s{-}).{28,}\P{Yi}?{,30}\|.)\x9e{-,}\P{Any}"; + var regexp51 = new RegExp(s); + shouldBeNull("regexp51.exec('abc')"); + shouldBe("regexp51.exec(s)", "[')\x9e{-,}P{Any}',')',undefined]"); + + var regexp52 = /(Rob)|(Bob)|(Robert)|(Bobby)/; + shouldBe("'Hi Bob'.match(regexp52)", "['Bob',undefined,'Bob',undefined,undefined]"); + + // Test cases discovered by fuzzing that crashed the compiler. + var regexp53 = /(?=(?:(?:(gB)|(?!cs|<))((?=(?!v6){0,})))|(?=#)+?)/m; + shouldBe("regexp53.exec('#')", "['',undefined,'']"); + var regexp54 = /((?:(?:()|(?!))((?=(?!))))|())/m; + shouldBe("regexp54.exec('#')", "['','',undefined,undefined,'']"); + var regexp55 = /(?:(?:(?:a?|(?:))((?:)))|a?)/m; + shouldBe("regexp55.exec('#')", "['','']"); + + // Test evaluation order of empty subpattern alternatives. + var regexp56 = /(|a)/; + shouldBe("regexp56.exec('a')", "['','']"); + var regexp57 = /(a|)/; + shouldBe("regexp57.exec('a')", "['a','a']"); + + // Tests that non-greedy repeat quantified parentheses will backtrack through multiple frames of subpattern matches. + var regexp58 = /a|b(?:[^b])*?c/; + shouldBe("regexp58.exec('badbc')", "['a']"); + var regexp59 = /(X(?:.(?!X))*?Y)|(Y(?:.(?!Y))*?Z)/g; + shouldBe("'Y aaa X Match1 Y aaa Y Match2 Z'.match(regexp59)", "['X Match1 Y','Y Match2 Z']"); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/webkit/pcre-test-1.js b/Tests/LibJS/Runtime/3rdparty/webkit/pcre-test-1.js new file mode 100644 index 00000000000..8c73b434723 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/webkit/pcre-test-1.js @@ -0,0 +1,6129 @@ +test.skip("pcre-test-1", () => { + // WebKit assertion compatibility shim for Ladybird's test-js harness + + function description(msg) { + // No-op, just used for test documentation in WebKit. + } + + function shouldBe(actual_code, expected_code) { + let actual = eval(actual_code); + let expected = eval(expected_code); + if (typeof actual === "string" && typeof expected === "string") { + expect(actual).toBe(expected); + } else if (Array.isArray(actual) && Array.isArray(expected)) { + expect(actual).toEqual(expected); + } else if (actual !== null && typeof actual === "object" && expected !== null && typeof expected === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } + } + + function shouldBeTrue(code) { + expect(eval(code)).toBeTrue(); + } + + function shouldBeFalse(code) { + expect(eval(code)).toBeFalse(); + } + + function shouldBeNull(code) { + expect(eval(code)).toBeNull(); + } + + function shouldBeUndefined(code) { + expect(eval(code)).toBeUndefined(); + } + + function shouldThrow(code, expected_error) { + expect(() => eval(code)).toThrow(); + } + + function shouldNotThrow(code) { + eval(code); + } + + description("A chunk of our port of PCRE's test suite, adapted to be more applicable to JavaScript."); + + var regex0 = /the quick brown fox/; + var input0 = "the quick brown fox"; + var results = ["the quick brown fox"]; + shouldBe("regex0.exec(input0);", "results"); + var input1 = "The quick brown FOX"; + var results = null; + shouldBe("regex0.exec(input1);", "results"); + var input2 = "What do you know about the quick brown fox?"; + var results = ["the quick brown fox"]; + shouldBe("regex0.exec(input2);", "results"); + var input3 = "What do you know about THE QUICK BROWN FOX?"; + var results = null; + shouldBe("regex0.exec(input3);", "results"); + + var regex1 = /The quick brown fox/i; + var input0 = "the quick brown fox"; + var results = ["the quick brown fox"]; + shouldBe("regex1.exec(input0);", "results"); + var input1 = "The quick brown FOX"; + var results = ["The quick brown FOX"]; + shouldBe("regex1.exec(input1);", "results"); + var input2 = "What do you know about the quick brown fox?"; + var results = ["the quick brown fox"]; + shouldBe("regex1.exec(input2);", "results"); + var input3 = "What do you know about THE QUICK BROWN FOX?"; + var results = ["THE QUICK BROWN FOX"]; + shouldBe("regex1.exec(input3);", "results"); + + var regex2 = /abcd\t\n\r\f\v[\b]\071\x3b\$\\\?caxyz/; + var input0 = "abcd\t\n\r\f\v\b9;\$\\?caxyz"; + var results = ["abcd\x09\x0a\x0d\x0c\x0b\x089;$\\?caxyz"]; + shouldBe("regex2.exec(input0);", "results"); + + var regex3 = /a*abc?xyz+pqr{3}ab{2,}xy{4,5}pq{0,6}AB{0,}zz/; + var input0 = "abxyzpqrrrabbxyyyypqAzz"; + var results = ["abxyzpqrrrabbxyyyypqAzz"]; + shouldBe("regex3.exec(input0);", "results"); + var input1 = "abxyzpqrrrabbxyyyypqAzz"; + var results = ["abxyzpqrrrabbxyyyypqAzz"]; + shouldBe("regex3.exec(input1);", "results"); + var input2 = "aabxyzpqrrrabbxyyyypqAzz"; + var results = ["aabxyzpqrrrabbxyyyypqAzz"]; + shouldBe("regex3.exec(input2);", "results"); + var input3 = "aaabxyzpqrrrabbxyyyypqAzz"; + var results = ["aaabxyzpqrrrabbxyyyypqAzz"]; + shouldBe("regex3.exec(input3);", "results"); + var input4 = "aaaabxyzpqrrrabbxyyyypqAzz"; + var results = ["aaaabxyzpqrrrabbxyyyypqAzz"]; + shouldBe("regex3.exec(input4);", "results"); + var input5 = "abcxyzpqrrrabbxyyyypqAzz"; + var results = ["abcxyzpqrrrabbxyyyypqAzz"]; + shouldBe("regex3.exec(input5);", "results"); + var input6 = "aabcxyzpqrrrabbxyyyypqAzz"; + var results = ["aabcxyzpqrrrabbxyyyypqAzz"]; + shouldBe("regex3.exec(input6);", "results"); + var input7 = "aaabcxyzpqrrrabbxyyyypAzz"; + var results = ["aaabcxyzpqrrrabbxyyyypAzz"]; + shouldBe("regex3.exec(input7);", "results"); + var input8 = "aaabcxyzpqrrrabbxyyyypqAzz"; + var results = ["aaabcxyzpqrrrabbxyyyypqAzz"]; + shouldBe("regex3.exec(input8);", "results"); + var input9 = "aaabcxyzpqrrrabbxyyyypqqAzz"; + var results = ["aaabcxyzpqrrrabbxyyyypqqAzz"]; + shouldBe("regex3.exec(input9);", "results"); + var input10 = "aaabcxyzpqrrrabbxyyyypqqqAzz"; + var results = ["aaabcxyzpqrrrabbxyyyypqqqAzz"]; + shouldBe("regex3.exec(input10);", "results"); + var input11 = "aaabcxyzpqrrrabbxyyyypqqqqAzz"; + var results = ["aaabcxyzpqrrrabbxyyyypqqqqAzz"]; + shouldBe("regex3.exec(input11);", "results"); + var input12 = "aaabcxyzpqrrrabbxyyyypqqqqqAzz"; + var results = ["aaabcxyzpqrrrabbxyyyypqqqqqAzz"]; + shouldBe("regex3.exec(input12);", "results"); + var input13 = "aaabcxyzpqrrrabbxyyyypqqqqqqAzz"; + var results = ["aaabcxyzpqrrrabbxyyyypqqqqqqAzz"]; + shouldBe("regex3.exec(input13);", "results"); + var input14 = "aaaabcxyzpqrrrabbxyyyypqAzz"; + var results = ["aaaabcxyzpqrrrabbxyyyypqAzz"]; + shouldBe("regex3.exec(input14);", "results"); + var input15 = "abxyzzpqrrrabbxyyyypqAzz"; + var results = ["abxyzzpqrrrabbxyyyypqAzz"]; + shouldBe("regex3.exec(input15);", "results"); + var input16 = "aabxyzzzpqrrrabbxyyyypqAzz"; + var results = ["aabxyzzzpqrrrabbxyyyypqAzz"]; + shouldBe("regex3.exec(input16);", "results"); + var input17 = "aaabxyzzzzpqrrrabbxyyyypqAzz"; + var results = ["aaabxyzzzzpqrrrabbxyyyypqAzz"]; + shouldBe("regex3.exec(input17);", "results"); + var input18 = "aaaabxyzzzzpqrrrabbxyyyypqAzz"; + var results = ["aaaabxyzzzzpqrrrabbxyyyypqAzz"]; + shouldBe("regex3.exec(input18);", "results"); + var input19 = "abcxyzzpqrrrabbxyyyypqAzz"; + var results = ["abcxyzzpqrrrabbxyyyypqAzz"]; + shouldBe("regex3.exec(input19);", "results"); + var input20 = "aabcxyzzzpqrrrabbxyyyypqAzz"; + var results = ["aabcxyzzzpqrrrabbxyyyypqAzz"]; + shouldBe("regex3.exec(input20);", "results"); + var input21 = "aaabcxyzzzzpqrrrabbxyyyypqAzz"; + var results = ["aaabcxyzzzzpqrrrabbxyyyypqAzz"]; + shouldBe("regex3.exec(input21);", "results"); + var input22 = "aaaabcxyzzzzpqrrrabbxyyyypqAzz"; + var results = ["aaaabcxyzzzzpqrrrabbxyyyypqAzz"]; + shouldBe("regex3.exec(input22);", "results"); + var input23 = "aaaabcxyzzzzpqrrrabbbxyyyypqAzz"; + var results = ["aaaabcxyzzzzpqrrrabbbxyyyypqAzz"]; + shouldBe("regex3.exec(input23);", "results"); + var input24 = "aaaabcxyzzzzpqrrrabbbxyyyyypqAzz"; + var results = ["aaaabcxyzzzzpqrrrabbbxyyyyypqAzz"]; + shouldBe("regex3.exec(input24);", "results"); + var input25 = "aaabcxyzpqrrrabbxyyyypABzz"; + var results = ["aaabcxyzpqrrrabbxyyyypABzz"]; + shouldBe("regex3.exec(input25);", "results"); + var input26 = "aaabcxyzpqrrrabbxyyyypABBzz"; + var results = ["aaabcxyzpqrrrabbxyyyypABBzz"]; + shouldBe("regex3.exec(input26);", "results"); + var input27 = ">>>aaabxyzpqrrrabbxyyyypqAzz"; + var results = ["aaabxyzpqrrrabbxyyyypqAzz"]; + shouldBe("regex3.exec(input27);", "results"); + var input28 = ">aaaabxyzpqrrrabbxyyyypqAzz"; + var results = ["aaaabxyzpqrrrabbxyyyypqAzz"]; + shouldBe("regex3.exec(input28);", "results"); + var input29 = ">>>>abcxyzpqrrrabbxyyyypqAzz"; + var results = ["abcxyzpqrrrabbxyyyypqAzz"]; + shouldBe("regex3.exec(input29);", "results"); + // Failers + var input30 = "abxyzpqrrabbxyyyypqAzz"; + var results = null; + shouldBe("regex3.exec(input30);", "results"); + var input31 = "abxyzpqrrrrabbxyyyypqAzz"; + var results = null; + shouldBe("regex3.exec(input31);", "results"); + var input32 = "abxyzpqrrrabxyyyypqAzz"; + var results = null; + shouldBe("regex3.exec(input32);", "results"); + var input33 = "aaaabcxyzzzzpqrrrabbbxyyyyyypqAzz"; + var results = null; + shouldBe("regex3.exec(input33);", "results"); + var input34 = "aaaabcxyzzzzpqrrrabbbxyyypqAzz"; + var results = null; + shouldBe("regex3.exec(input34);", "results"); + var input35 = "aaabcxyzpqrrrabbxyyyypqqqqqqqAzz"; + var results = null; + shouldBe("regex3.exec(input35);", "results"); + + var regex4 = /^(abc){1,2}zz/; + var input0 = "abczz"; + var results = ["abczz", "abc"]; + shouldBe("regex4.exec(input0);", "results"); + var input1 = "abcabczz"; + var results = ["abcabczz", "abc"]; + shouldBe("regex4.exec(input1);", "results"); + // Failers + var input2 = "zz"; + var results = null; + shouldBe("regex4.exec(input2);", "results"); + var input3 = "abcabcabczz"; + var results = null; + shouldBe("regex4.exec(input3);", "results"); + var input4 = ">>abczz"; + var results = null; + shouldBe("regex4.exec(input4);", "results"); + + var regex5 = /^(b+?|a){1,2}?c/; + var input0 = "bc"; + var results = ["bc", "b"]; + shouldBe("regex5.exec(input0);", "results"); + var input1 = "bbc"; + var results = ["bbc", "b"]; + shouldBe("regex5.exec(input1);", "results"); + var input2 = "bbbc"; + var results = ["bbbc", "bb"]; + shouldBe("regex5.exec(input2);", "results"); + var input3 = "bac"; + var results = ["bac", "a"]; + shouldBe("regex5.exec(input3);", "results"); + var input4 = "bbac"; + var results = ["bbac", "a"]; + shouldBe("regex5.exec(input4);", "results"); + var input5 = "aac"; + var results = ["aac", "a"]; + shouldBe("regex5.exec(input5);", "results"); + var input6 = "abbbbbbbbbbbc"; + var results = ["abbbbbbbbbbbc", "bbbbbbbbbbb"]; + shouldBe("regex5.exec(input6);", "results"); + var input7 = "bbbbbbbbbbbac"; + var results = ["bbbbbbbbbbbac", "a"]; + shouldBe("regex5.exec(input7);", "results"); + // Failers + var input8 = "aaac"; + var results = null; + shouldBe("regex5.exec(input8);", "results"); + var input9 = "abbbbbbbbbbbac"; + var results = null; + shouldBe("regex5.exec(input9);", "results"); + + var regex6 = /^(b+|a){1,2}c/; + var input0 = "bc"; + var results = ["bc", "b"]; + shouldBe("regex6.exec(input0);", "results"); + var input1 = "bbc"; + var results = ["bbc", "bb"]; + shouldBe("regex6.exec(input1);", "results"); + var input2 = "bbbc"; + var results = ["bbbc", "bbb"]; + shouldBe("regex6.exec(input2);", "results"); + var input3 = "bac"; + var results = ["bac", "a"]; + shouldBe("regex6.exec(input3);", "results"); + var input4 = "bbac"; + var results = ["bbac", "a"]; + shouldBe("regex6.exec(input4);", "results"); + var input5 = "aac"; + var results = ["aac", "a"]; + shouldBe("regex6.exec(input5);", "results"); + var input6 = "abbbbbbbbbbbc"; + var results = ["abbbbbbbbbbbc", "bbbbbbbbbbb"]; + shouldBe("regex6.exec(input6);", "results"); + var input7 = "bbbbbbbbbbbac"; + var results = ["bbbbbbbbbbbac", "a"]; + shouldBe("regex6.exec(input7);", "results"); + // Failers + var input8 = "aaac"; + var results = null; + shouldBe("regex6.exec(input8);", "results"); + var input9 = "abbbbbbbbbbbac"; + var results = null; + shouldBe("regex6.exec(input9);", "results"); + + var regex7 = /^(b+|a){1,2}?bc/; + var input0 = "bbc"; + var results = ["bbc", "b"]; + shouldBe("regex7.exec(input0);", "results"); + + var regex8 = /^(b*|ba){1,2}?bc/; + var input0 = "babc"; + var results = ["babc", "ba"]; + shouldBe("regex8.exec(input0);", "results"); + var input1 = "bbabc"; + var results = ["bbabc", "ba"]; + shouldBe("regex8.exec(input1);", "results"); + var input2 = "bababc"; + var results = ["bababc", "ba"]; + shouldBe("regex8.exec(input2);", "results"); + // Failers + var input3 = "bababbc"; + var results = null; + shouldBe("regex8.exec(input3);", "results"); + var input4 = "babababc"; + var results = null; + shouldBe("regex8.exec(input4);", "results"); + + var regex9 = /^(ba|b*){1,2}?bc/; + var input0 = "babc"; + var results = ["babc", "ba"]; + shouldBe("regex9.exec(input0);", "results"); + var input1 = "bbabc"; + var results = ["bbabc", "ba"]; + shouldBe("regex9.exec(input1);", "results"); + var input2 = "bababc"; + var results = ["bababc", "ba"]; + shouldBe("regex9.exec(input2);", "results"); + // Failers + var input3 = "bababbc"; + var results = null; + shouldBe("regex9.exec(input3);", "results"); + var input4 = "babababc"; + var results = null; + shouldBe("regex9.exec(input4);", "results"); + + var regex10 = /^\ca\cA/; + var input0 = "\x01\x01"; + var results = ["\x01\x01"]; + shouldBe("regex10.exec(input0);", "results"); + + var regex11 = /^[ab\]cde]/; + var input0 = "athing"; + var results = ["a"]; + shouldBe("regex11.exec(input0);", "results"); + var input1 = "bthing"; + var results = ["b"]; + shouldBe("regex11.exec(input1);", "results"); + var input2 = "]thing"; + var results = ["]"]; + shouldBe("regex11.exec(input2);", "results"); + var input3 = "cthing"; + var results = ["c"]; + shouldBe("regex11.exec(input3);", "results"); + var input4 = "dthing"; + var results = ["d"]; + shouldBe("regex11.exec(input4);", "results"); + var input5 = "ething"; + var results = ["e"]; + shouldBe("regex11.exec(input5);", "results"); + // Failers + var input6 = "fthing"; + var results = null; + shouldBe("regex11.exec(input6);", "results"); + var input7 = "[thing"; + var results = null; + shouldBe("regex11.exec(input7);", "results"); + var input8 = "\\thing"; + var results = null; + shouldBe("regex11.exec(input8);", "results"); + + var regex12 = /^[\]cde]/; + var input0 = "]thing"; + var results = ["]"]; + shouldBe("regex12.exec(input0);", "results"); + var input1 = "cthing"; + var results = ["c"]; + shouldBe("regex12.exec(input1);", "results"); + var input2 = "dthing"; + var results = ["d"]; + shouldBe("regex12.exec(input2);", "results"); + var input3 = "ething"; + var results = ["e"]; + shouldBe("regex12.exec(input3);", "results"); + // Failers + var input4 = "athing"; + var results = null; + shouldBe("regex12.exec(input4);", "results"); + var input5 = "fthing"; + var results = null; + shouldBe("regex12.exec(input5);", "results"); + + var regex13 = /^[^ab\]cde]/; + var input0 = "fthing"; + var results = ["f"]; + shouldBe("regex13.exec(input0);", "results"); + var input1 = "[thing"; + var results = ["["]; + shouldBe("regex13.exec(input1);", "results"); + var input2 = "\\thing"; + var results = ["\\"]; + shouldBe("regex13.exec(input2);", "results"); + // Failers + var input3 = "athing"; + var results = null; + shouldBe("regex13.exec(input3);", "results"); + var input4 = "bthing"; + var results = null; + shouldBe("regex13.exec(input4);", "results"); + var input5 = "]thing"; + var results = null; + shouldBe("regex13.exec(input5);", "results"); + var input6 = "cthing"; + var results = null; + shouldBe("regex13.exec(input6);", "results"); + var input7 = "dthing"; + var results = null; + shouldBe("regex13.exec(input7);", "results"); + var input8 = "ething"; + var results = null; + shouldBe("regex13.exec(input8);", "results"); + + var regex14 = /^[^\]cde]/; + var input0 = "athing"; + var results = ["a"]; + shouldBe("regex14.exec(input0);", "results"); + var input1 = "fthing"; + var results = ["f"]; + shouldBe("regex14.exec(input1);", "results"); + // Failers + var input2 = "]thing"; + var results = null; + shouldBe("regex14.exec(input2);", "results"); + var input3 = "cthing"; + var results = null; + shouldBe("regex14.exec(input3);", "results"); + var input4 = "dthing"; + var results = null; + shouldBe("regex14.exec(input4);", "results"); + var input5 = "ething"; + var results = null; + shouldBe("regex14.exec(input5);", "results"); + + var regex15 = /^\xc2/; + var input0 = "\xc2"; + var results = ["\xc2"]; + shouldBe("regex15.exec(input0);", "results"); + + var regex16 = /^\xc3/; + var input0 = "\xc3"; + var results = ["\xc3"]; + shouldBe("regex16.exec(input0);", "results"); + + var regex17 = /^[0-9]+$/; + var input0 = "0"; + var results = ["0"]; + shouldBe("regex17.exec(input0);", "results"); + var input1 = "1"; + var results = ["1"]; + shouldBe("regex17.exec(input1);", "results"); + var input2 = "2"; + var results = ["2"]; + shouldBe("regex17.exec(input2);", "results"); + var input3 = "3"; + var results = ["3"]; + shouldBe("regex17.exec(input3);", "results"); + var input4 = "4"; + var results = ["4"]; + shouldBe("regex17.exec(input4);", "results"); + var input5 = "5"; + var results = ["5"]; + shouldBe("regex17.exec(input5);", "results"); + var input6 = "6"; + var results = ["6"]; + shouldBe("regex17.exec(input6);", "results"); + var input7 = "7"; + var results = ["7"]; + shouldBe("regex17.exec(input7);", "results"); + var input8 = "8"; + var results = ["8"]; + shouldBe("regex17.exec(input8);", "results"); + var input9 = "9"; + var results = ["9"]; + shouldBe("regex17.exec(input9);", "results"); + var input10 = "10"; + var results = ["10"]; + shouldBe("regex17.exec(input10);", "results"); + var input11 = "100"; + var results = ["100"]; + shouldBe("regex17.exec(input11);", "results"); + // Failers + var input12 = "abc"; + var results = null; + shouldBe("regex17.exec(input12);", "results"); + + var regex18 = /^.*nter/; + var input0 = "enter"; + var results = ["enter"]; + shouldBe("regex18.exec(input0);", "results"); + var input1 = "inter"; + var results = ["inter"]; + shouldBe("regex18.exec(input1);", "results"); + var input2 = "uponter"; + var results = ["uponter"]; + shouldBe("regex18.exec(input2);", "results"); + + var regex19 = /^xxx[0-9]+$/; + var input0 = "xxx0"; + var results = ["xxx0"]; + shouldBe("regex19.exec(input0);", "results"); + var input1 = "xxx1234"; + var results = ["xxx1234"]; + shouldBe("regex19.exec(input1);", "results"); + // Failers + var input2 = "xxx"; + var results = null; + shouldBe("regex19.exec(input2);", "results"); + + var regex20 = /^.+[0-9][0-9][0-9]$/; + var input0 = "x123"; + var results = ["x123"]; + shouldBe("regex20.exec(input0);", "results"); + var input1 = "xx123"; + var results = ["xx123"]; + shouldBe("regex20.exec(input1);", "results"); + var input2 = "123456"; + var results = ["123456"]; + shouldBe("regex20.exec(input2);", "results"); + // Failers + var input3 = "123"; + var results = null; + shouldBe("regex20.exec(input3);", "results"); + var input4 = "x1234"; + var results = ["x1234"]; + shouldBe("regex20.exec(input4);", "results"); + + var regex21 = /^.+?[0-9][0-9][0-9]$/; + var input0 = "x123"; + var results = ["x123"]; + shouldBe("regex21.exec(input0);", "results"); + var input1 = "xx123"; + var results = ["xx123"]; + shouldBe("regex21.exec(input1);", "results"); + var input2 = "123456"; + var results = ["123456"]; + shouldBe("regex21.exec(input2);", "results"); + // Failers + var input3 = "123"; + var results = null; + shouldBe("regex21.exec(input3);", "results"); + var input4 = "x1234"; + var results = ["x1234"]; + shouldBe("regex21.exec(input4);", "results"); + + var regex22 = /^([^!]+)!(.+)=apquxz\.ixr\.zzz\.ac\.uk$/; + var input0 = "abc!pqr=apquxz.ixr.zzz.ac.uk"; + var results = ["abc!pqr=apquxz.ixr.zzz.ac.uk", "abc", "pqr"]; + shouldBe("regex22.exec(input0);", "results"); + // Failers + var input1 = "!pqr=apquxz.ixr.zzz.ac.uk"; + var results = null; + shouldBe("regex22.exec(input1);", "results"); + var input2 = "abc!=apquxz.ixr.zzz.ac.uk"; + var results = null; + shouldBe("regex22.exec(input2);", "results"); + var input3 = "abc!pqr=apquxz:ixr.zzz.ac.uk"; + var results = null; + shouldBe("regex22.exec(input3);", "results"); + var input4 = "abc!pqr=apquxz.ixr.zzz.ac.ukk"; + var results = null; + shouldBe("regex22.exec(input4);", "results"); + + var regex23 = /:/; + var input0 = "Well, we need a colon: somewhere"; + var results = [":"]; + shouldBe("regex23.exec(input0);", "results"); + var input1 = "*** Fail if we don't"; + var results = null; + shouldBe("regex23.exec(input1);", "results"); + + var regex24 = /([\da-f:]+)$/i; + var input0 = "0abc"; + var results = ["0abc", "0abc"]; + shouldBe("regex24.exec(input0);", "results"); + var input1 = "abc"; + var results = ["abc", "abc"]; + shouldBe("regex24.exec(input1);", "results"); + var input2 = "fed"; + var results = ["fed", "fed"]; + shouldBe("regex24.exec(input2);", "results"); + var input3 = "E"; + var results = ["E", "E"]; + shouldBe("regex24.exec(input3);", "results"); + var input4 = "::"; + var results = ["::", "::"]; + shouldBe("regex24.exec(input4);", "results"); + var input5 = "5f03:12C0::932e"; + var results = ["5f03:12C0::932e", "5f03:12C0::932e"]; + shouldBe("regex24.exec(input5);", "results"); + var input6 = "fed def"; + var results = ["def", "def"]; + shouldBe("regex24.exec(input6);", "results"); + var input7 = "Any old stuff"; + var results = ["ff", "ff"]; + shouldBe("regex24.exec(input7);", "results"); + // Failers + var input8 = "0zzz"; + var results = null; + shouldBe("regex24.exec(input8);", "results"); + var input9 = "gzzz"; + var results = null; + shouldBe("regex24.exec(input9);", "results"); + var input10 = "fed\x20"; + var results = null; + shouldBe("regex24.exec(input10);", "results"); + var input11 = "Any old rubbish"; + var results = null; + shouldBe("regex24.exec(input11);", "results"); + + var regex25 = /^.*\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/; + var input0 = ".1.2.3"; + var results = [".1.2.3", "1", "2", "3"]; + shouldBe("regex25.exec(input0);", "results"); + var input1 = "A.12.123.0"; + var results = ["A.12.123.0", "12", "123", "0"]; + shouldBe("regex25.exec(input1);", "results"); + // Failers + var input2 = ".1.2.3333"; + var results = null; + shouldBe("regex25.exec(input2);", "results"); + var input3 = "1.2.3"; + var results = null; + shouldBe("regex25.exec(input3);", "results"); + var input4 = "1234.2.3"; + var results = null; + shouldBe("regex25.exec(input4);", "results"); + + var regex26 = /^(\d+)\s+IN\s+SOA\s+(\S+)\s+(\S+)\s*\(\s*$/; + var input0 = "1 IN SOA non-sp1 non-sp2("; + var results = ["1 IN SOA non-sp1 non-sp2(", "1", "non-sp1", "non-sp2"]; + shouldBe("regex26.exec(input0);", "results"); + var input1 = "1 IN SOA non-sp1 non-sp2 ("; + var results = ["1 IN SOA non-sp1 non-sp2 (", "1", "non-sp1", "non-sp2"]; + shouldBe("regex26.exec(input1);", "results"); + // Failers + var input2 = "1IN SOA non-sp1 non-sp2("; + var results = null; + shouldBe("regex26.exec(input2);", "results"); + + var regex27 = /^[a-zA-Z\d][a-zA-Z\d\-]*(\.[a-zA-Z\d][a-zA-z\d\-]*)*\.$/; + var input0 = "a."; + var results = ["a.", undefined]; + shouldBe("regex27.exec(input0);", "results"); + var input1 = "Z."; + var results = ["Z.", undefined]; + shouldBe("regex27.exec(input1);", "results"); + var input2 = "2."; + var results = ["2.", undefined]; + shouldBe("regex27.exec(input2);", "results"); + var input3 = "ab-c.pq-r."; + var results = ["ab-c.pq-r.", ".pq-r"]; + shouldBe("regex27.exec(input3);", "results"); + var input4 = "sxk.zzz.ac.uk."; + var results = ["sxk.zzz.ac.uk.", ".uk"]; + shouldBe("regex27.exec(input4);", "results"); + var input5 = "x-.y-."; + var results = ["x-.y-.", ".y-"]; + shouldBe("regex27.exec(input5);", "results"); + // Failers + var input6 = "-abc.peq."; + var results = null; + shouldBe("regex27.exec(input6);", "results"); + + var regex28 = /^\*\.[a-z]([a-z\-\d]*[a-z\d]+)?(\.[a-z]([a-z\-\d]*[a-z\d]+)?)*$/; + var input0 = "*.a"; + var results = ["*.a", undefined, undefined, undefined]; + shouldBe("regex28.exec(input0);", "results"); + var input1 = "*.b0-a"; + var results = ["*.b0-a", "0-a", undefined, undefined]; + shouldBe("regex28.exec(input1);", "results"); + var input2 = "*.c3-b.c"; + var results = ["*.c3-b.c", "3-b", ".c", undefined]; + shouldBe("regex28.exec(input2);", "results"); + var input3 = "*.c-a.b-c"; + var results = ["*.c-a.b-c", "-a", ".b-c", "-c"]; + shouldBe("regex28.exec(input3);", "results"); + // Failers + var input4 = "*.0"; + var results = null; + shouldBe("regex28.exec(input4);", "results"); + var input5 = "*.a-"; + var results = null; + shouldBe("regex28.exec(input5);", "results"); + var input6 = "*.a-b.c-"; + var results = null; + shouldBe("regex28.exec(input6);", "results"); + var input7 = "*.c-a.0-c"; + var results = null; + shouldBe("regex28.exec(input7);", "results"); + + var regex29 = /^(?=ab(de))(abd)(e)/; + var input0 = "abde"; + var results = ["abde", "de", "abd", "e"]; + shouldBe("regex29.exec(input0);", "results"); + + var regex30 = /^(?!(ab)de|x)(abd)(f)/; + var input0 = "abdf"; + var results = ["abdf", undefined, "abd", "f"]; + shouldBe("regex30.exec(input0);", "results"); + + var regex31 = /^(?=(ab(cd)))(ab)/; + var input0 = "abcd"; + var results = ["ab", "abcd", "cd", "ab"]; + shouldBe("regex31.exec(input0);", "results"); + + var regex32 = /^[\da-f](\.[\da-f])*$/i; + var input0 = "a.b.c.d"; + var results = ["a.b.c.d", ".d"]; + shouldBe("regex32.exec(input0);", "results"); + var input1 = "A.B.C.D"; + var results = ["A.B.C.D", ".D"]; + shouldBe("regex32.exec(input1);", "results"); + var input2 = "a.b.c.1.2.3.C"; + var results = ["a.b.c.1.2.3.C", ".C"]; + shouldBe("regex32.exec(input2);", "results"); + + var regex33 = /^\".*\"\s*(;.*)?$/; + var input0 = '"1234"'; + var results = ['"1234"', undefined]; + shouldBe("regex33.exec(input0);", "results"); + var input1 = '"abcd" ;'; + var results = ['"abcd" ;', ";"]; + shouldBe("regex33.exec(input1);", "results"); + var input2 = '"" ; rhubarb'; + var results = ['"" ; rhubarb', "; rhubarb"]; + shouldBe("regex33.exec(input2);", "results"); + // Failers + var input3 = '"1234" : things'; + var results = null; + shouldBe("regex33.exec(input3);", "results"); + + var regex34 = /^$/; + var input0 = ""; + var results = [""]; + shouldBe("regex34.exec(input0);", "results"); + + var regex35 = /^a\ b[c ]d$/; + var input0 = "a bcd"; + var results = ["a bcd"]; + shouldBe("regex35.exec(input0);", "results"); + var input1 = "a b d"; + var results = ["a b d"]; + shouldBe("regex35.exec(input1);", "results"); + var input2 = "abcd"; + var results = null; + shouldBe("regex35.exec(input2);", "results"); + var input3 = "ab d"; + var results = null; + shouldBe("regex35.exec(input3);", "results"); + + var regex36 = /^(a(b(c)))(d(e(f)))(h(i(j)))(k(l(m)))$/; + var input0 = "abcdefhijklm"; + var results = ["abcdefhijklm", "abc", "bc", "c", "def", "ef", "f", "hij", "ij", "j", "klm", "lm", "m"]; + shouldBe("regex36.exec(input0);", "results"); + + var regex37 = /^(?:a(b(c)))(?:d(e(f)))(?:h(i(j)))(?:k(l(m)))$/; + var input0 = "abcdefhijklm"; + var results = ["abcdefhijklm", "bc", "c", "ef", "f", "ij", "j", "lm", "m"]; + shouldBe("regex37.exec(input0);", "results"); + + var regex38 = /^[\w][\W][\s][\S][\d][\D][\n][\cc][\022]/; + var input0 = "a+ Z0+\n\x03\x12"; + var results = ["a+ Z0+\x0a\x03\x12"]; + shouldBe("regex38.exec(input0);", "results"); + + var regex39 = /^[.^$|()*+?{,}]+/; + var input0 = ".^\$(*+)|{?,?}"; + var results = [".^$(*+)|{?,?}"]; + shouldBe("regex39.exec(input0);", "results"); + + var regex40 = /^a*\w/; + var input0 = "z"; + var results = ["z"]; + shouldBe("regex40.exec(input0);", "results"); + var input1 = "az"; + var results = ["az"]; + shouldBe("regex40.exec(input1);", "results"); + var input2 = "aaaz"; + var results = ["aaaz"]; + shouldBe("regex40.exec(input2);", "results"); + var input3 = "a"; + var results = ["a"]; + shouldBe("regex40.exec(input3);", "results"); + var input4 = "aa"; + var results = ["aa"]; + shouldBe("regex40.exec(input4);", "results"); + var input5 = "aaaa"; + var results = ["aaaa"]; + shouldBe("regex40.exec(input5);", "results"); + var input6 = "a+"; + var results = ["a"]; + shouldBe("regex40.exec(input6);", "results"); + var input7 = "aa+"; + var results = ["aa"]; + shouldBe("regex40.exec(input7);", "results"); + + var regex41 = /^a*?\w/; + var input0 = "z"; + var results = ["z"]; + shouldBe("regex41.exec(input0);", "results"); + var input1 = "az"; + var results = ["a"]; + shouldBe("regex41.exec(input1);", "results"); + var input2 = "aaaz"; + var results = ["a"]; + shouldBe("regex41.exec(input2);", "results"); + var input3 = "a"; + var results = ["a"]; + shouldBe("regex41.exec(input3);", "results"); + var input4 = "aa"; + var results = ["a"]; + shouldBe("regex41.exec(input4);", "results"); + var input5 = "aaaa"; + var results = ["a"]; + shouldBe("regex41.exec(input5);", "results"); + var input6 = "a+"; + var results = ["a"]; + shouldBe("regex41.exec(input6);", "results"); + var input7 = "aa+"; + var results = ["a"]; + shouldBe("regex41.exec(input7);", "results"); + + var regex42 = /^a+\w/; + var input0 = "az"; + var results = ["az"]; + shouldBe("regex42.exec(input0);", "results"); + var input1 = "aaaz"; + var results = ["aaaz"]; + shouldBe("regex42.exec(input1);", "results"); + var input2 = "aa"; + var results = ["aa"]; + shouldBe("regex42.exec(input2);", "results"); + var input3 = "aaaa"; + var results = ["aaaa"]; + shouldBe("regex42.exec(input3);", "results"); + var input4 = "aa+"; + var results = ["aa"]; + shouldBe("regex42.exec(input4);", "results"); + + var regex43 = /^a+?\w/; + var input0 = "az"; + var results = ["az"]; + shouldBe("regex43.exec(input0);", "results"); + var input1 = "aaaz"; + var results = ["aa"]; + shouldBe("regex43.exec(input1);", "results"); + var input2 = "aa"; + var results = ["aa"]; + shouldBe("regex43.exec(input2);", "results"); + var input3 = "aaaa"; + var results = ["aa"]; + shouldBe("regex43.exec(input3);", "results"); + var input4 = "aa+"; + var results = ["aa"]; + shouldBe("regex43.exec(input4);", "results"); + + var regex44 = /^\d{8}\w{2,}/; + var input0 = "1234567890"; + var results = ["1234567890"]; + shouldBe("regex44.exec(input0);", "results"); + var input1 = "12345678ab"; + var results = ["12345678ab"]; + shouldBe("regex44.exec(input1);", "results"); + var input2 = "12345678__"; + var results = ["12345678__"]; + shouldBe("regex44.exec(input2);", "results"); + // Failers + var input3 = "1234567"; + var results = null; + shouldBe("regex44.exec(input3);", "results"); + + var regex45 = /^[aeiou\d]{4,5}$/; + var input0 = "uoie"; + var results = ["uoie"]; + shouldBe("regex45.exec(input0);", "results"); + var input1 = "1234"; + var results = ["1234"]; + shouldBe("regex45.exec(input1);", "results"); + var input2 = "12345"; + var results = ["12345"]; + shouldBe("regex45.exec(input2);", "results"); + var input3 = "aaaaa"; + var results = ["aaaaa"]; + shouldBe("regex45.exec(input3);", "results"); + // Failers + var input4 = "123456"; + var results = null; + shouldBe("regex45.exec(input4);", "results"); + + var regex46 = /^[aeiou\d]{4,5}?/; + var input0 = "uoie"; + var results = ["uoie"]; + shouldBe("regex46.exec(input0);", "results"); + var input1 = "1234"; + var results = ["1234"]; + shouldBe("regex46.exec(input1);", "results"); + var input2 = "12345"; + var results = ["1234"]; + shouldBe("regex46.exec(input2);", "results"); + var input3 = "aaaaa"; + var results = ["aaaa"]; + shouldBe("regex46.exec(input3);", "results"); + var input4 = "123456"; + var results = ["1234"]; + shouldBe("regex46.exec(input4);", "results"); + + var regex47 = /^(abc|def)=(\1){2,3}$/; + var input0 = "abc=abcabc"; + var results = ["abc=abcabc", "abc", "abc"]; + shouldBe("regex47.exec(input0);", "results"); + var input1 = "def=defdefdef"; + var results = ["def=defdefdef", "def", "def"]; + shouldBe("regex47.exec(input1);", "results"); + // Failers + var input2 = "abc=defdef"; + var results = null; + shouldBe("regex47.exec(input2);", "results"); + + var regex48 = /^(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)\11*(\3\4)\1(?:)2$/; + var input0 = "abcdefghijkcda2"; + var results = ["abcdefghijkcda2", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "cd"]; + shouldBe("regex48.exec(input0);", "results"); + var input1 = "abcdefghijkkkkcda2"; + var results = ["abcdefghijkkkkcda2", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "cd"]; + shouldBe("regex48.exec(input1);", "results"); + + var regex49 = /(cat(a(ract|tonic)|erpillar)) \1()2(3)/; + var input0 = "cataract cataract23"; + var results = ["cataract cataract23", "cataract", "aract", "ract", "", "3"]; + shouldBe("regex49.exec(input0);", "results"); + var input1 = "catatonic catatonic23"; + var results = ["catatonic catatonic23", "catatonic", "atonic", "tonic", "", "3"]; + shouldBe("regex49.exec(input1);", "results"); + var input2 = "caterpillar caterpillar23"; + var results = ["caterpillar caterpillar23", "caterpillar", "erpillar", undefined, "", "3"]; + shouldBe("regex49.exec(input2);", "results"); + + var regex50 = + /^From +([^ ]+) +[a-zA-Z][a-zA-Z][a-zA-Z] +[a-zA-Z][a-zA-Z][a-zA-Z] +[0-9]?[0-9] +[0-9][0-9]:[0-9][0-9]/; + var input0 = "From abcd Mon Sep 01 12:33:02 1997"; + var results = ["From abcd Mon Sep 01 12:33", "abcd"]; + shouldBe("regex50.exec(input0);", "results"); + + var regex51 = /^From\s+\S+\s+([a-zA-Z]{3}\s+){2}\d{1,2}\s+\d\d:\d\d/; + var input0 = "From abcd Mon Sep 01 12:33:02 1997"; + var results = ["From abcd Mon Sep 01 12:33", "Sep "]; + shouldBe("regex51.exec(input0);", "results"); + var input1 = "From abcd Mon Sep 1 12:33:02 1997"; + var results = ["From abcd Mon Sep 1 12:33", "Sep "]; + shouldBe("regex51.exec(input1);", "results"); + // Failers + var input2 = "From abcd Sep 01 12:33:02 1997"; + var results = null; + shouldBe("regex51.exec(input2);", "results"); + + var regex52 = /^12.34/; + // Failers + var input0 = "12\n34"; + var results = null; + shouldBe("regex52.exec(input0);", "results"); + var input1 = "12\r34"; + var results = null; + shouldBe("regex52.exec(input1);", "results"); + + var regex53 = /\w+(?=\t)/; + var input0 = "the quick brown\t fox"; + var results = ["brown"]; + shouldBe("regex53.exec(input0);", "results"); + + var regex54 = /foo(?!bar)(.*)/; + var input0 = "foobar is foolish see?"; + var results = ["foolish see?", "lish see?"]; + shouldBe("regex54.exec(input0);", "results"); + + var regex55 = /(?:(?!foo)...|^.{0,2})bar(.*)/; + var input0 = "foobar crowbar etc"; + var results = ["rowbar etc", " etc"]; + shouldBe("regex55.exec(input0);", "results"); + var input1 = "barrel"; + var results = ["barrel", "rel"]; + shouldBe("regex55.exec(input1);", "results"); + var input2 = "2barrel"; + var results = ["2barrel", "rel"]; + shouldBe("regex55.exec(input2);", "results"); + var input3 = "A barrel"; + var results = ["A barrel", "rel"]; + shouldBe("regex55.exec(input3);", "results"); + + var regex56 = /^(\D*)(?=\d)(?!123)/; + var input0 = "abc456"; + var results = ["abc", "abc"]; + shouldBe("regex56.exec(input0);", "results"); + // Failers + var input1 = "abc123"; + var results = null; + shouldBe("regex56.exec(input1);", "results"); + + var regex57 = /^(a)\1{2,3}(.)/; + var input0 = "aaab"; + var results = ["aaab", "a", "b"]; + shouldBe("regex57.exec(input0);", "results"); + var input1 = "aaaab"; + var results = ["aaaab", "a", "b"]; + shouldBe("regex57.exec(input1);", "results"); + var input2 = "aaaaab"; + var results = ["aaaaa", "a", "a"]; + shouldBe("regex57.exec(input2);", "results"); + var input3 = "aaaaaab"; + var results = ["aaaaa", "a", "a"]; + shouldBe("regex57.exec(input3);", "results"); + + var regex58 = /(?!^)abc/; + var input0 = "the abc"; + var results = ["abc"]; + shouldBe("regex58.exec(input0);", "results"); + // Failers + var input1 = "abc"; + var results = null; + shouldBe("regex58.exec(input1);", "results"); + + var regex59 = /(?=^)abc/; + var input0 = "abc"; + var results = ["abc"]; + shouldBe("regex59.exec(input0);", "results"); + // Failers + var input1 = "the abc"; + var results = null; + shouldBe("regex59.exec(input1);", "results"); + + var regex60 = /^[ab]{1,3}(ab*|b)/; + var input0 = "aabbbbb"; + var results = ["aabb", "b"]; + shouldBe("regex60.exec(input0);", "results"); + + var regex61 = /^[ab]{1,3}?(ab*|b)/; + var input0 = "aabbbbb"; + var results = ["aabbbbb", "abbbbb"]; + shouldBe("regex61.exec(input0);", "results"); + + var regex62 = /^[ab]{1,3}?(ab*?|b)/; + var input0 = "aabbbbb"; + var results = ["aa", "a"]; + shouldBe("regex62.exec(input0);", "results"); + + var regex63 = /^[ab]{1,3}(ab*?|b)/; + var input0 = "aabbbbb"; + var results = ["aabb", "b"]; + shouldBe("regex63.exec(input0);", "results"); + + var regex64 = /abc\0def\00pqr\000xyz\0000AB/; + var input0 = "abc\0def\0pqr\0xyz\0" + "0AB"; + var results = ["abc\0def\0pqr\0xyz\0" + "0AB"]; + shouldBe("regex64.exec(input0);", "results"); + var input1 = "abc456 abc\0def\0pqr\0xyz\0" + "0ABCDE"; + var results = ["abc\0def\0pqr\0xyz\0" + "0AB"]; + shouldBe("regex64.exec(input1);", "results"); + + var regex65 = /abc\x0def\x00pqr\x000xyz\x0000AB/; + var input0 = "abc\x0def\x00pqr\x000xyz\x0000AB"; + var results = ["abc\x0def\x00pqr\x000xyz\x0000AB"]; + shouldBe("regex65.exec(input0);", "results"); + var input1 = "abc456 abc\x0def\x00pqr\x000xyz\x0000ABCDE"; + var results = ["abc\x0def\x00pqr\x000xyz\x0000AB"]; + shouldBe("regex65.exec(input1);", "results"); + + var regex66 = /^[\000-\037]/; + var input0 = "\0A"; + var results = ["\x00"]; + shouldBe("regex66.exec(input0);", "results"); + var input1 = "\01B"; + var results = ["\x01"]; + shouldBe("regex66.exec(input1);", "results"); + var input2 = "\037C"; + var results = ["\x1f"]; + shouldBe("regex66.exec(input2);", "results"); + + var regex67 = /\0*/; + var input0 = "\0\0\0\0"; + var results = ["\x00\x00\x00\x00"]; + shouldBe("regex67.exec(input0);", "results"); + + var regex68 = /A\0{2,3}Z/; + var input0 = "The A\0\0Z"; + var results = ["A\x00\x00Z"]; + shouldBe("regex68.exec(input0);", "results"); + var input1 = "An A\0\0\0Z"; + var results = ["A\x00\x00\x00Z"]; + shouldBe("regex68.exec(input1);", "results"); + // Failers + var input2 = "A\0Z"; + var results = null; + shouldBe("regex68.exec(input2);", "results"); + var input3 = "A\0\0\0\0Z"; + var results = null; + shouldBe("regex68.exec(input3);", "results"); + + var regex69 = /^(cow|)\1(bell)/; + var input0 = "cowcowbell"; + var results = ["cowcowbell", "cow", "bell"]; + shouldBe("regex69.exec(input0);", "results"); + var input1 = "bell"; + var results = ["bell", "", "bell"]; + shouldBe("regex69.exec(input1);", "results"); + // Failers + var input2 = "cowbell"; + var results = null; + shouldBe("regex69.exec(input2);", "results"); + + var regex70 = /^\s/; + var input0 = "\040abc"; + var results = [" "]; + shouldBe("regex70.exec(input0);", "results"); + var input1 = "\x0cabc"; + var results = ["\x0c"]; + shouldBe("regex70.exec(input1);", "results"); + var input2 = "\nabc"; + var results = ["\x0a"]; + shouldBe("regex70.exec(input2);", "results"); + var input3 = "\rabc"; + var results = ["\x0d"]; + shouldBe("regex70.exec(input3);", "results"); + var input4 = "\tabc"; + var results = ["\x09"]; + shouldBe("regex70.exec(input4);", "results"); + // Failers + var input5 = "abc"; + var results = null; + shouldBe("regex70.exec(input5);", "results"); + + var regex71 = /^(a|)\1*b/; + var input0 = "ab"; + var results = ["ab", "a"]; + shouldBe("regex71.exec(input0);", "results"); + var input1 = "aaaab"; + var results = ["aaaab", "a"]; + shouldBe("regex71.exec(input1);", "results"); + var input2 = "b"; + var results = ["b", ""]; + shouldBe("regex71.exec(input2);", "results"); + // Failers + var input3 = "acb"; + var results = null; + shouldBe("regex71.exec(input3);", "results"); + + var regex72 = /^(a|)\1+b/; + var input0 = "aab"; + var results = ["aab", "a"]; + shouldBe("regex72.exec(input0);", "results"); + var input1 = "aaaab"; + var results = ["aaaab", "a"]; + shouldBe("regex72.exec(input1);", "results"); + var input2 = "b"; + var results = ["b", ""]; + shouldBe("regex72.exec(input2);", "results"); + // Failers + var input3 = "ab"; + var results = null; + shouldBe("regex72.exec(input3);", "results"); + + var regex73 = /^(a|)\1?b/; + var input0 = "ab"; + var results = ["ab", "a"]; + shouldBe("regex73.exec(input0);", "results"); + var input1 = "aab"; + var results = ["aab", "a"]; + shouldBe("regex73.exec(input1);", "results"); + var input2 = "b"; + var results = ["b", ""]; + shouldBe("regex73.exec(input2);", "results"); + // Failers + var input3 = "acb"; + var results = null; + shouldBe("regex73.exec(input3);", "results"); + + var regex74 = /^(a|)\1{2}b/; + var input0 = "aaab"; + var results = ["aaab", "a"]; + shouldBe("regex74.exec(input0);", "results"); + var input1 = "b"; + var results = ["b", ""]; + shouldBe("regex74.exec(input1);", "results"); + // Failers + var input2 = "ab"; + var results = null; + shouldBe("regex74.exec(input2);", "results"); + var input3 = "aab"; + var results = null; + shouldBe("regex74.exec(input3);", "results"); + var input4 = "aaaab"; + var results = null; + shouldBe("regex74.exec(input4);", "results"); + + var regex75 = /^(a|)\1{2,3}b/; + var input0 = "aaab"; + var results = ["aaab", "a"]; + shouldBe("regex75.exec(input0);", "results"); + var input1 = "aaaab"; + var results = ["aaaab", "a"]; + shouldBe("regex75.exec(input1);", "results"); + var input2 = "b"; + var results = ["b", ""]; + shouldBe("regex75.exec(input2);", "results"); + // Failers + var input3 = "ab"; + var results = null; + shouldBe("regex75.exec(input3);", "results"); + var input4 = "aab"; + var results = null; + shouldBe("regex75.exec(input4);", "results"); + var input5 = "aaaaab"; + var results = null; + shouldBe("regex75.exec(input5);", "results"); + + var regex76 = /ab{1,3}bc/; + var input0 = "abbbbc"; + var results = ["abbbbc"]; + shouldBe("regex76.exec(input0);", "results"); + var input1 = "abbbc"; + var results = ["abbbc"]; + shouldBe("regex76.exec(input1);", "results"); + var input2 = "abbc"; + var results = ["abbc"]; + shouldBe("regex76.exec(input2);", "results"); + // Failers + var input3 = "abc"; + var results = null; + shouldBe("regex76.exec(input3);", "results"); + var input4 = "abbbbbc"; + var results = null; + shouldBe("regex76.exec(input4);", "results"); + + var regex77 = /([^.]*)\.([^:]*):[T ]+(.*)/; + var input0 = "track1.title:TBlah blah blah"; + var results = ["track1.title:TBlah blah blah", "track1", "title", "Blah blah blah"]; + shouldBe("regex77.exec(input0);", "results"); + + var regex78 = /([^.]*)\.([^:]*):[T ]+(.*)/i; + var input0 = "track1.title:TBlah blah blah"; + var results = ["track1.title:TBlah blah blah", "track1", "title", "Blah blah blah"]; + shouldBe("regex78.exec(input0);", "results"); + + var regex79 = /([^.]*)\.([^:]*):[t ]+(.*)/i; + var input0 = "track1.title:TBlah blah blah"; + var results = ["track1.title:TBlah blah blah", "track1", "title", "Blah blah blah"]; + shouldBe("regex79.exec(input0);", "results"); + + var regex80 = /^[W-c]+$/; + var input0 = "WXY_^abc"; + var results = ["WXY_^abc"]; + shouldBe("regex80.exec(input0);", "results"); + // Failers + var input1 = "wxy"; + var results = null; + shouldBe("regex80.exec(input1);", "results"); + + var regex81 = /^[W-c]+$/i; + var input0 = "WXY_^abc"; + var results = ["WXY_^abc"]; + shouldBe("regex81.exec(input0);", "results"); + var input1 = "wxy_^ABC"; + var results = ["wxy_^ABC"]; + shouldBe("regex81.exec(input1);", "results"); + + var regex82 = /^[\x3f-\x5F]+$/i; + var input0 = "WXY_^abc"; + var results = ["WXY_^abc"]; + shouldBe("regex82.exec(input0);", "results"); + var input1 = "wxy_^ABC"; + var results = ["wxy_^ABC"]; + shouldBe("regex82.exec(input1);", "results"); + + var regex83 = /^abc$/m; + var input0 = "abc"; + var results = ["abc"]; + shouldBe("regex83.exec(input0);", "results"); + var input1 = "qqq\nabc"; + var results = ["abc"]; + shouldBe("regex83.exec(input1);", "results"); + var input2 = "abc\nzzz"; + var results = ["abc"]; + shouldBe("regex83.exec(input2);", "results"); + var input3 = "qqq\nabc\nzzz"; + var results = ["abc"]; + shouldBe("regex83.exec(input3);", "results"); + + var regex84 = /^abc$/; + var input0 = "abc"; + var results = ["abc"]; + shouldBe("regex84.exec(input0);", "results"); + var input1 = "abbbbc"; + var results = null; + shouldBe("regex84.exec(input1);", "results"); + var input2 = "abcc"; + var results = null; + shouldBe("regex84.exec(input2);", "results"); + var input3 = "qqq\nabc"; + var results = null; + shouldBe("regex84.exec(input3);", "results"); + var input4 = "abc\nzzz"; + var results = null; + shouldBe("regex84.exec(input4);", "results"); + var input5 = "qqq\nabc\nzzz"; + var results = null; + shouldBe("regex84.exec(input5);", "results"); + + var regex85 = /^abc$/m; + var input0 = "abc"; + var results = ["abc"]; + shouldBe("regex85.exec(input0);", "results"); + var input1 = "abc\n"; + var results = ["abc"]; + shouldBe("regex85.exec(input1);", "results"); + var input2 = "qqq\nabc"; + var results = ["abc"]; + shouldBe("regex85.exec(input2);", "results"); + var input3 = "abc\nzzz"; + var results = ["abc"]; + shouldBe("regex85.exec(input3);", "results"); + var input4 = "qqq\nabc\nzzz"; + var results = ["abc"]; + shouldBe("regex85.exec(input4);", "results"); + + var regex86 = /^([\w\W])*$/; + var input0 = "abc\ndef"; + var results = ["abc\x0adef", "f"]; + shouldBe("regex86.exec(input0);", "results"); + + var regex87 = /^(.)*$/m; + var input0 = "abc\ndef"; + var results = ["abc", "c"]; + shouldBe("regex87.exec(input0);", "results"); + + var regex88 = /(?:b)|(?::+)/; + var input0 = "b::c"; + var results = ["b"]; + shouldBe("regex88.exec(input0);", "results"); + var input1 = "c::b"; + var results = ["::"]; + shouldBe("regex88.exec(input1);", "results"); + + var regex89 = /[-az]+/; + var input0 = "az-"; + var results = ["az-"]; + shouldBe("regex89.exec(input0);", "results"); + // Failers + var input1 = "b"; + var results = null; + shouldBe("regex89.exec(input1);", "results"); + + var regex90 = /[az-]+/; + var input0 = "za-"; + var results = ["za-"]; + shouldBe("regex90.exec(input0);", "results"); + // Failers + var input1 = "b"; + var results = null; + shouldBe("regex90.exec(input1);", "results"); + + var regex91 = /[a\-z]+/; + var input0 = "a-z"; + var results = ["a-z"]; + shouldBe("regex91.exec(input0);", "results"); + // Failers + var input1 = "b"; + var results = null; + shouldBe("regex91.exec(input1);", "results"); + + var regex92 = /[a-z]+/; + var input0 = "abcdxyz"; + var results = ["abcdxyz"]; + shouldBe("regex92.exec(input0);", "results"); + + var regex93 = /[\d-]+/; + var input0 = "12-34"; + var results = ["12-34"]; + shouldBe("regex93.exec(input0);", "results"); + // Failers + var input1 = "aaa"; + var results = null; + shouldBe("regex93.exec(input1);", "results"); + + var regex94 = /[\d-z]+/; + var input0 = "12-34z"; + var results = ["12-34z"]; + shouldBe("regex94.exec(input0);", "results"); + // Failers + var input1 = "aaa"; + var results = null; + shouldBe("regex94.exec(input1);", "results"); + + var regex95 = /\x5c/; + var input0 = "\\"; + var results = ["\\"]; + shouldBe("regex95.exec(input0);", "results"); + + var regex96 = /\x20Z/; + var input0 = "the Zoo"; + var results = [" Z"]; + shouldBe("regex96.exec(input0);", "results"); + // Failers + var input1 = "Zulu"; + var results = null; + shouldBe("regex96.exec(input1);", "results"); + + var regex97 = /(abc)\1/i; + var input0 = "abcabc"; + var results = ["abcabc", "abc"]; + shouldBe("regex97.exec(input0);", "results"); + var input1 = "ABCabc"; + var results = ["ABCabc", "ABC"]; + shouldBe("regex97.exec(input1);", "results"); + var input2 = "abcABC"; + var results = ["abcABC", "abc"]; + shouldBe("regex97.exec(input2);", "results"); + + var regex98 = /ab{3cd/; + var input0 = "ab{3cd"; + var results = ["ab{3cd"]; + shouldBe("regex98.exec(input0);", "results"); + + var regex99 = /ab{3,cd/; + var input0 = "ab{3,cd"; + var results = ["ab{3,cd"]; + shouldBe("regex99.exec(input0);", "results"); + + var regex100 = /ab{3,4a}cd/; + var input0 = "ab{3,4a}cd"; + var results = ["ab{3,4a}cd"]; + shouldBe("regex100.exec(input0);", "results"); + + var regex101 = /{4,5a}bc/; + var input0 = "{4,5a}bc"; + var results = ["{4,5a}bc"]; + shouldBe("regex101.exec(input0);", "results"); + + var regex102 = /abc$/; + var input0 = "abc"; + var results = ["abc"]; + shouldBe("regex102.exec(input0);", "results"); + // Failers + var input1 = "abc\n"; + var results = null; + shouldBe("regex102.exec(input1);", "results"); + var input2 = "abc\ndef"; + var results = null; + shouldBe("regex102.exec(input2);", "results"); + + var regex103 = /abc$/m; + var input0 = "abc"; + var results = ["abc"]; + shouldBe("regex103.exec(input0);", "results"); + var input1 = "abc\n"; + var results = ["abc"]; + shouldBe("regex103.exec(input1);", "results"); + var input2 = "abc\ndef"; + var results = ["abc"]; + shouldBe("regex103.exec(input2);", "results"); + + var regex104 = /(abc)\123/; + var input0 = "abc\x53"; + var results = ["abcS", "abc"]; + shouldBe("regex104.exec(input0);", "results"); + + var regex105 = /(abc)\223/; + var input0 = "abc\x93"; + var results = ["abc\x93", "abc"]; + shouldBe("regex105.exec(input0);", "results"); + + var regex106 = /(abc)\323/; + var input0 = "abc\xd3"; + var results = ["abc\xd3", "abc"]; + shouldBe("regex106.exec(input0);", "results"); + + var regex107 = /(abc)\100/; + var input0 = "abc\x40"; + var results = ["abc@", "abc"]; + shouldBe("regex107.exec(input0);", "results"); + var input1 = "abc\100"; + var results = ["abc@", "abc"]; + shouldBe("regex107.exec(input1);", "results"); + + var regex108 = /(abc)\1000/; + var input0 = "abc\x400"; + var results = ["abc@0", "abc"]; + shouldBe("regex108.exec(input0);", "results"); + var input1 = "abc\x40\x30"; + var results = ["abc@0", "abc"]; + shouldBe("regex108.exec(input1);", "results"); + var input2 = "abc\1000"; + var results = ["abc@0", "abc"]; + shouldBe("regex108.exec(input2);", "results"); + var input3 = "abc\100\x30"; + var results = ["abc@0", "abc"]; + shouldBe("regex108.exec(input3);", "results"); + var input4 = "abc\100\060"; + var results = ["abc@0", "abc"]; + shouldBe("regex108.exec(input4);", "results"); + var input5 = "abc\100\60"; + var results = ["abc@0", "abc"]; + shouldBe("regex108.exec(input5);", "results"); + + var regex109 = /abc\081/; + var input0 = "abc\081"; + var results = ["abc\x0081"]; + shouldBe("regex109.exec(input0);", "results"); + var input1 = "abc\0\x38\x31"; + var results = ["abc\x0081"]; + shouldBe("regex109.exec(input1);", "results"); + + var regex110 = /(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)(l)\12\123/; + var input0 = "abcdefghijkllS"; + var results = ["abcdefghijkllS", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l"]; + shouldBe("regex110.exec(input0);", "results"); + + var regex111 = /(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)\12\123/; + var input0 = "abcdefghijk\12S"; + var results = ["abcdefghijk\x0aS", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"]; + shouldBe("regex111.exec(input0);", "results"); + + var regex112 = /ab\idef/; + var input0 = "abidef"; + var results = ["abidef"]; + shouldBe("regex112.exec(input0);", "results"); + + var regex113 = /a{0}bc/; + var input0 = "bc"; + var results = ["bc"]; + shouldBe("regex113.exec(input0);", "results"); + + var regex114 = /(?:a|(?:bc)){0,0}?xyz/; + var input0 = "xyz"; + var results = ["xyz"]; + shouldBe("regex114.exec(input0);", "results"); + + var regex115 = /abc[\10]de/; + var input0 = "abc\010de"; + var results = ["abc\x08de"]; + shouldBe("regex115.exec(input0);", "results"); + + var regex116 = /abc[\1]de/; + var input0 = "abc\1de"; + var results = ["abc\x01de"]; + shouldBe("regex116.exec(input0);", "results"); + + var regex117 = /(abc)[\1]de/; + var input0 = "abc\1de"; + var results = ["abc\x01de", "abc"]; + shouldBe("regex117.exec(input0);", "results"); + + var regex118 = /a.b/; + var input0 = "a\nb"; + var results = null; + shouldBe("regex118.exec(input0);", "results"); + + var regex119 = /^([^a])([^\b])([^c]*)([^d]{3,4})/; + var input0 = "baNOTccccd"; + var results = ["baNOTcccc", "b", "a", "NOT", "cccc"]; + shouldBe("regex119.exec(input0);", "results"); + var input1 = "baNOTcccd"; + var results = ["baNOTccc", "b", "a", "NOT", "ccc"]; + shouldBe("regex119.exec(input1);", "results"); + var input2 = "baNOTccd"; + var results = ["baNOTcc", "b", "a", "NO", "Tcc"]; + shouldBe("regex119.exec(input2);", "results"); + var input3 = "bacccd"; + var results = ["baccc", "b", "a", "", "ccc"]; + shouldBe("regex119.exec(input3);", "results"); + // Failers + var input4 = "anything"; + var results = null; + shouldBe("regex119.exec(input4);", "results"); + var input5 = "b\bc"; + var results = null; + shouldBe("regex119.exec(input5);", "results"); + var input6 = "baccd"; + var results = null; + shouldBe("regex119.exec(input6);", "results"); + + var regex120 = /[^a]/; + var input0 = "Abc"; + var results = ["A"]; + shouldBe("regex120.exec(input0);", "results"); + + var regex121 = /[^a]/i; + var input0 = "Abc"; + var results = ["b"]; + shouldBe("regex121.exec(input0);", "results"); + + var regex122 = /[^a]+/; + var input0 = "AAAaAbc"; + var results = ["AAA"]; + shouldBe("regex122.exec(input0);", "results"); + + var regex123 = /[^a]+/i; + var input0 = "AAAaAbc"; + var results = ["bc"]; + shouldBe("regex123.exec(input0);", "results"); + + var regex124 = /[^a]+/; + var input0 = "bbb\nccc"; + var results = ["bbb\x0accc"]; + shouldBe("regex124.exec(input0);", "results"); + + var regex125 = /[^k]$/; + var input0 = "abc"; + var results = ["c"]; + shouldBe("regex125.exec(input0);", "results"); + // Failers + var input1 = "abk"; + var results = null; + shouldBe("regex125.exec(input1);", "results"); + + var regex126 = /[^k]{2,3}$/; + var input0 = "abc"; + var results = ["abc"]; + shouldBe("regex126.exec(input0);", "results"); + var input1 = "kbc"; + var results = ["bc"]; + shouldBe("regex126.exec(input1);", "results"); + var input2 = "kabc"; + var results = ["abc"]; + shouldBe("regex126.exec(input2);", "results"); + // Failers + var input3 = "abk"; + var results = null; + shouldBe("regex126.exec(input3);", "results"); + var input4 = "akb"; + var results = null; + shouldBe("regex126.exec(input4);", "results"); + var input5 = "akk"; + var results = null; + shouldBe("regex126.exec(input5);", "results"); + + var regex127 = /^\d{8,}\@.+[^k]$/; + var input0 = "12345678\@a.b.c.d"; + var results = ["12345678@a.b.c.d"]; + shouldBe("regex127.exec(input0);", "results"); + var input1 = "123456789\@x.y.z"; + var results = ["123456789@x.y.z"]; + shouldBe("regex127.exec(input1);", "results"); + // Failers + var input2 = "12345678\@x.y.uk"; + var results = null; + shouldBe("regex127.exec(input2);", "results"); + var input3 = "1234567\@a.b.c.d"; + var results = null; + shouldBe("regex127.exec(input3);", "results"); + + var regex128 = /(a)\1{8,}/; + var input0 = "aaaaaaaaa"; + var results = ["aaaaaaaaa", "a"]; + shouldBe("regex128.exec(input0);", "results"); + var input1 = "aaaaaaaaaa"; + var results = ["aaaaaaaaaa", "a"]; + shouldBe("regex128.exec(input1);", "results"); + // Failers + var input2 = "aaaaaaa"; + var results = null; + shouldBe("regex128.exec(input2);", "results"); + + var regex129 = /[^a]/; + var input0 = "aaaabcd"; + var results = ["b"]; + shouldBe("regex129.exec(input0);", "results"); + var input1 = "aaAabcd"; + var results = ["A"]; + shouldBe("regex129.exec(input1);", "results"); + + var regex130 = /[^a]/i; + var input0 = "aaaabcd"; + var results = ["b"]; + shouldBe("regex130.exec(input0);", "results"); + var input1 = "aaAabcd"; + var results = ["b"]; + shouldBe("regex130.exec(input1);", "results"); + + var regex131 = /[^az]/; + var input0 = "aaaabcd"; + var results = ["b"]; + shouldBe("regex131.exec(input0);", "results"); + var input1 = "aaAabcd"; + var results = ["A"]; + shouldBe("regex131.exec(input1);", "results"); + + var regex132 = /[^az]/i; + var input0 = "aaaabcd"; + var results = ["b"]; + shouldBe("regex132.exec(input0);", "results"); + var input1 = "aaAabcd"; + var results = ["b"]; + shouldBe("regex132.exec(input1);", "results"); + + var regex133 = + /\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377/; + var input0 = + "\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377"; + var results = [ + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff", + ]; + shouldBe("regex133.exec(input0);", "results"); + + var regex134 = /P[^*]TAIRE[^*]{1,6}?LL/; + var input0 = "xxxxxxxxxxxPSTAIREISLLxxxxxxxxx"; + var results = ["PSTAIREISLL"]; + shouldBe("regex134.exec(input0);", "results"); + + var regex135 = /P[^*]TAIRE[^*]{1,}?LL/; + var input0 = "xxxxxxxxxxxPSTAIREISLLxxxxxxxxx"; + var results = ["PSTAIREISLL"]; + shouldBe("regex135.exec(input0);", "results"); + + var regex136 = /(\.\d\d[1-9]?)\d+/; + var input0 = "1.230003938"; + var results = [".230003938", ".23"]; + shouldBe("regex136.exec(input0);", "results"); + var input1 = "1.875000282"; + var results = [".875000282", ".875"]; + shouldBe("regex136.exec(input1);", "results"); + var input2 = "1.235"; + var results = [".235", ".23"]; + shouldBe("regex136.exec(input2);", "results"); + + var regex137 = /(\.\d\d((?=0)|\d(?=\d)))/; + var input0 = "1.230003938"; + var results = [".23", ".23", ""]; + shouldBe("regex137.exec(input0);", "results"); + var input1 = "1.875000282"; + var results = [".875", ".875", "5"]; + shouldBe("regex137.exec(input1);", "results"); + // Failers + var input2 = "1.235"; + var results = null; + shouldBe("regex137.exec(input2);", "results"); + + var regex138 = /a(?:)b/; + var input0 = "ab"; + var results = ["ab"]; + shouldBe("regex138.exec(input0);", "results"); + + var regex139 = /\b(foo)\s+(\w+)/i; + var input0 = "Food is on the foo table"; + var results = ["foo table", "foo", "table"]; + shouldBe("regex139.exec(input0);", "results"); + + var regex140 = /foo(.*)bar/; + var input0 = "The food is under the bar in the barn."; + var results = ["food is under the bar in the bar", "d is under the bar in the "]; + shouldBe("regex140.exec(input0);", "results"); + + var regex141 = /foo(.*?)bar/; + var input0 = "The food is under the bar in the barn."; + var results = ["food is under the bar", "d is under the "]; + shouldBe("regex141.exec(input0);", "results"); + + var regex142 = /(.*)(\d*)/; + var input0 = "I have 2 numbers: 53147"; + var results = ["I have 2 numbers: 53147", "I have 2 numbers: 53147", ""]; + shouldBe("regex142.exec(input0);", "results"); + + var regex143 = /(.*)(\d+)/; + var input0 = "I have 2 numbers: 53147"; + var results = ["I have 2 numbers: 53147", "I have 2 numbers: 5314", "7"]; + shouldBe("regex143.exec(input0);", "results"); + + var regex144 = /(.*?)(\d*)/; + var input0 = "I have 2 numbers: 53147"; + var results = ["", "", ""]; + shouldBe("regex144.exec(input0);", "results"); + + var regex145 = /(.*?)(\d+)/; + var input0 = "I have 2 numbers: 53147"; + var results = ["I have 2", "I have ", "2"]; + shouldBe("regex145.exec(input0);", "results"); + + var regex146 = /(.*)(\d+)$/; + var input0 = "I have 2 numbers: 53147"; + var results = ["I have 2 numbers: 53147", "I have 2 numbers: 5314", "7"]; + shouldBe("regex146.exec(input0);", "results"); + + var regex147 = /(.*?)(\d+)$/; + var input0 = "I have 2 numbers: 53147"; + var results = ["I have 2 numbers: 53147", "I have 2 numbers: ", "53147"]; + shouldBe("regex147.exec(input0);", "results"); + + var regex148 = /(.*)\b(\d+)$/; + var input0 = "I have 2 numbers: 53147"; + var results = ["I have 2 numbers: 53147", "I have 2 numbers: ", "53147"]; + shouldBe("regex148.exec(input0);", "results"); + + var regex149 = /(.*\D)(\d+)$/; + var input0 = "I have 2 numbers: 53147"; + var results = ["I have 2 numbers: 53147", "I have 2 numbers: ", "53147"]; + shouldBe("regex149.exec(input0);", "results"); + + var regex150 = /^\D*(?!123)/; + var input0 = "ABC123"; + var results = ["AB"]; + shouldBe("regex150.exec(input0);", "results"); + + var regex151 = /^(\D*)(?=\d)(?!123)/; + var input0 = "ABC445"; + var results = ["ABC", "ABC"]; + shouldBe("regex151.exec(input0);", "results"); + // Failers + var input1 = "ABC123"; + var results = null; + shouldBe("regex151.exec(input1);", "results"); + + var regex152 = /^[W-]46]/; + var input0 = "W46]789"; + var results = ["W46]"]; + shouldBe("regex152.exec(input0);", "results"); + var input1 = "-46]789"; + var results = ["-46]"]; + shouldBe("regex152.exec(input1);", "results"); + // Failers + var input2 = "Wall"; + var results = null; + shouldBe("regex152.exec(input2);", "results"); + var input3 = "Zebra"; + var results = null; + shouldBe("regex152.exec(input3);", "results"); + var input4 = "42"; + var results = null; + shouldBe("regex152.exec(input4);", "results"); + var input5 = "[abcd]"; + var results = null; + shouldBe("regex152.exec(input5);", "results"); + var input6 = "]abcd["; + var results = null; + shouldBe("regex152.exec(input6);", "results"); + + var regex153 = /^[W-\]46]/; + var input0 = "W46]789"; + var results = ["W"]; + shouldBe("regex153.exec(input0);", "results"); + var input1 = "Wall"; + var results = ["W"]; + shouldBe("regex153.exec(input1);", "results"); + var input2 = "Zebra"; + var results = ["Z"]; + shouldBe("regex153.exec(input2);", "results"); + var input3 = "Xylophone"; + var results = ["X"]; + shouldBe("regex153.exec(input3);", "results"); + var input4 = "42"; + var results = ["4"]; + shouldBe("regex153.exec(input4);", "results"); + var input5 = "[abcd]"; + var results = ["["]; + shouldBe("regex153.exec(input5);", "results"); + var input6 = "]abcd["; + var results = ["]"]; + shouldBe("regex153.exec(input6);", "results"); + var input7 = "\\backslash"; + var results = ["\\"]; + shouldBe("regex153.exec(input7);", "results"); + // Failers + var input8 = "-46]789"; + var results = null; + shouldBe("regex153.exec(input8);", "results"); + var input9 = "well"; + var results = null; + shouldBe("regex153.exec(input9);", "results"); + + var regex154 = /\d\d\/\d\d\/\d\d\d\d/; + var input0 = "01/01/2000"; + var results = ["01/01/2000"]; + shouldBe("regex154.exec(input0);", "results"); + + var regex155 = /word (?:[a-zA-Z0-9]+ ){0,10}otherword/; + var input0 = "word cat dog elephant mussel cow horse canary baboon snake shark otherword"; + var results = ["word cat dog elephant mussel cow horse canary baboon snake shark otherword"]; + shouldBe("regex155.exec(input0);", "results"); + var input1 = "word cat dog elephant mussel cow horse canary baboon snake shark"; + var results = null; + shouldBe("regex155.exec(input1);", "results"); + + var regex156 = /word (?:[a-zA-Z0-9]+ ){0,300}otherword/; + var input0 = + "word cat dog elephant mussel cow horse canary baboon snake shark the quick brown fox and the lazy dog and several other words getting close to thirty by now I hope"; + var results = null; + shouldBe("regex156.exec(input0);", "results"); + + var regex157 = /^(?:a){0,0}/; + var input0 = "bcd"; + var results = [""]; + shouldBe("regex157.exec(input0);", "results"); + var input1 = "abc"; + var results = [""]; + shouldBe("regex157.exec(input1);", "results"); + var input2 = "aab"; + var results = [""]; + shouldBe("regex157.exec(input2);", "results"); + + var regex158 = /^(a){0,1}/; + var input0 = "bcd"; + var results = ["", undefined]; + shouldBe("regex158.exec(input0);", "results"); + var input1 = "abc"; + var results = ["a", "a"]; + shouldBe("regex158.exec(input1);", "results"); + var input2 = "aab"; + var results = ["a", "a"]; + shouldBe("regex158.exec(input2);", "results"); + + var regex159 = /^(a){0,2}/; + var input0 = "bcd"; + var results = ["", undefined]; + shouldBe("regex159.exec(input0);", "results"); + var input1 = "abc"; + var results = ["a", "a"]; + shouldBe("regex159.exec(input1);", "results"); + var input2 = "aab"; + var results = ["aa", "a"]; + shouldBe("regex159.exec(input2);", "results"); + + var regex160 = /^(a){0,3}/; + var input0 = "bcd"; + var results = ["", undefined]; + shouldBe("regex160.exec(input0);", "results"); + var input1 = "abc"; + var results = ["a", "a"]; + shouldBe("regex160.exec(input1);", "results"); + var input2 = "aab"; + var results = ["aa", "a"]; + shouldBe("regex160.exec(input2);", "results"); + var input3 = "aaa"; + var results = ["aaa", "a"]; + shouldBe("regex160.exec(input3);", "results"); + + var regex161 = /^(a){0,}/; + var input0 = "bcd"; + var results = ["", undefined]; + shouldBe("regex161.exec(input0);", "results"); + var input1 = "abc"; + var results = ["a", "a"]; + shouldBe("regex161.exec(input1);", "results"); + var input2 = "aab"; + var results = ["aa", "a"]; + shouldBe("regex161.exec(input2);", "results"); + var input3 = "aaa"; + var results = ["aaa", "a"]; + shouldBe("regex161.exec(input3);", "results"); + var input4 = "aaaaaaaa"; + var results = ["aaaaaaaa", "a"]; + shouldBe("regex161.exec(input4);", "results"); + + var regex162 = /^(a){1,1}/; + var input0 = "bcd"; + var results = null; + shouldBe("regex162.exec(input0);", "results"); + var input1 = "abc"; + var results = ["a", "a"]; + shouldBe("regex162.exec(input1);", "results"); + var input2 = "aab"; + var results = ["a", "a"]; + shouldBe("regex162.exec(input2);", "results"); + + var regex163 = /^(a){1,2}/; + var input0 = "bcd"; + var results = null; + shouldBe("regex163.exec(input0);", "results"); + var input1 = "abc"; + var results = ["a", "a"]; + shouldBe("regex163.exec(input1);", "results"); + var input2 = "aab"; + var results = ["aa", "a"]; + shouldBe("regex163.exec(input2);", "results"); + + var regex164 = /^(a){1,3}/; + var input0 = "bcd"; + var results = null; + shouldBe("regex164.exec(input0);", "results"); + var input1 = "abc"; + var results = ["a", "a"]; + shouldBe("regex164.exec(input1);", "results"); + var input2 = "aab"; + var results = ["aa", "a"]; + shouldBe("regex164.exec(input2);", "results"); + var input3 = "aaa"; + var results = ["aaa", "a"]; + shouldBe("regex164.exec(input3);", "results"); + + var regex165 = /^(a){1,}/; + var input0 = "bcd"; + var results = null; + shouldBe("regex165.exec(input0);", "results"); + var input1 = "abc"; + var results = ["a", "a"]; + shouldBe("regex165.exec(input1);", "results"); + var input2 = "aab"; + var results = ["aa", "a"]; + shouldBe("regex165.exec(input2);", "results"); + var input3 = "aaa"; + var results = ["aaa", "a"]; + shouldBe("regex165.exec(input3);", "results"); + var input4 = "aaaaaaaa"; + var results = ["aaaaaaaa", "a"]; + shouldBe("regex165.exec(input4);", "results"); + + var regex166 = /.*\.gif/; + var input0 = "borfle\nbib.gif\nno"; + var results = ["bib.gif"]; + shouldBe("regex166.exec(input0);", "results"); + + var regex167 = /.{0,}\.gif/; + var input0 = "borfle\nbib.gif\nno"; + var results = ["bib.gif"]; + shouldBe("regex167.exec(input0);", "results"); + + var regex168 = /.*\.gif/m; + var input0 = "borfle\nbib.gif\nno"; + var results = ["bib.gif"]; + shouldBe("regex168.exec(input0);", "results"); + + var regex169 = /.*\.gif/; + var input0 = "borfle\nbib.gif\nno"; + var results = ["bib.gif"]; + shouldBe("regex169.exec(input0);", "results"); + + var regex170 = /.*\.gif/m; + var input0 = "borfle\nbib.gif\nno"; + var results = ["bib.gif"]; + shouldBe("regex170.exec(input0);", "results"); + + var regex171 = /.*$/; + var input0 = "borfle\nbib.gif\nno"; + var results = ["no"]; + shouldBe("regex171.exec(input0);", "results"); + + var regex172 = /.*$/m; + var input0 = "borfle\nbib.gif\nno"; + var results = ["borfle"]; + shouldBe("regex172.exec(input0);", "results"); + + var regex173 = /[\w\W]*?$/; + var input0 = "borfle\nbib.gif\nno"; + var results = ["borfle\nbib.gif\x0ano"]; + shouldBe("regex173.exec(input0);", "results"); + + var regex174 = /[\w\W]*?$/m; + var input0 = "borfle\nbib.gif\nno"; + var results = ["borfle"]; + shouldBe("regex174.exec(input0);", "results"); + + var regex175 = /.*$/; + var input0 = "borfle\nbib.gif\nno\n"; + var results = [""]; + shouldBe("regex175.exec(input0);", "results"); + + var regex176 = /.*$/m; + var input0 = "borfle\nbib.gif\nno\n"; + var results = ["borfle"]; + shouldBe("regex176.exec(input0);", "results"); + + var regex177 = /.*$/; + var input0 = "borfle\nbib.gif\nno\n"; + var results = [""]; + shouldBe("regex177.exec(input0);", "results"); + + var regex178 = /.*$/m; + var input0 = "borfle\nbib.gif\nno\n"; + var results = ["borfle"]; + shouldBe("regex178.exec(input0);", "results"); + + var regex179 = /(.*X|^B)/; + var input0 = "abcde\n1234Xyz"; + var results = ["1234X", "1234X"]; + shouldBe("regex179.exec(input0);", "results"); + var input1 = "BarFoo"; + var results = ["B", "B"]; + shouldBe("regex179.exec(input1);", "results"); + // Failers + var input2 = "abcde\nBar"; + var results = null; + shouldBe("regex179.exec(input2);", "results"); + + var regex180 = /(.*X|^B)/m; + var input0 = "abcde\n1234Xyz"; + var results = ["1234X", "1234X"]; + shouldBe("regex180.exec(input0);", "results"); + var input1 = "BarFoo"; + var results = ["B", "B"]; + shouldBe("regex180.exec(input1);", "results"); + var input2 = "abcde\nBar"; + var results = ["B", "B"]; + shouldBe("regex180.exec(input2);", "results"); + + var regex181 = /([\w\W]*X|^B)/; + var input0 = "abcde\n1234Xyz"; + var results = ["abcde\x0a1234X", "abcde\x0a1234X"]; + shouldBe("regex181.exec(input0);", "results"); + var input1 = "BarFoo"; + var results = ["B", "B"]; + shouldBe("regex181.exec(input1);", "results"); + // Failers + var input2 = "abcde\nBar"; + var results = null; + shouldBe("regex181.exec(input2);", "results"); + + var regex182 = /([\w\W]*X|^B)/m; + var input0 = "abcde\n1234Xyz"; + var results = ["abcde\x0a1234X", "abcde\x0a1234X"]; + shouldBe("regex182.exec(input0);", "results"); + var input1 = "BarFoo"; + var results = ["B", "B"]; + shouldBe("regex182.exec(input1);", "results"); + var input2 = "abcde\nBar"; + var results = ["B", "B"]; + shouldBe("regex182.exec(input2);", "results"); + + var regex183 = /([\w\W]*X|^B)/; + var input0 = "abcde\n1234Xyz"; + var results = ["abcde\x0a1234X", "abcde\x0a1234X"]; + shouldBe("regex183.exec(input0);", "results"); + var input1 = "BarFoo"; + var results = ["B", "B"]; + shouldBe("regex183.exec(input1);", "results"); + // Failers + var input2 = "abcde\nBar"; + var results = null; + shouldBe("regex183.exec(input2);", "results"); + + var regex184 = /(?:.*X|^B)/; + var input0 = "abcde\n1234Xyz"; + var results = ["1234X"]; + shouldBe("regex184.exec(input0);", "results"); + var input1 = "BarFoo"; + var results = ["B"]; + shouldBe("regex184.exec(input1);", "results"); + // Failers + var input2 = "abcde\nBar"; + var results = null; + shouldBe("regex184.exec(input2);", "results"); + + var regex185 = /^.*B/; + // Failers + var input0 = "abc\nB"; + var results = null; + shouldBe("regex185.exec(input0);", "results"); + + var regex186 = /^[\w\W]*B/; + var input0 = "abc\nB"; + var results = ["abc\x0aB"]; + shouldBe("regex186.exec(input0);", "results"); + + var regex187 = /.*B/; + var input0 = "abc\nB"; + var results = ["B"]; + shouldBe("regex187.exec(input0);", "results"); + + var regex188 = /^.*B/; + // Failers + var input0 = "abc\nB"; + var results = null; + shouldBe("regex188.exec(input0);", "results"); + + var regex189a = /^B/; + // Failers + var input0 = "abc\nB"; + var results = null; + shouldBe("regex189a.exec(input0);", "results"); + + var regex189b = /^B/m; + var input0 = "abc\nB"; + var results = ["B"]; + shouldBe("regex189b.exec(input0);", "results"); + + var regex190a = /B$/; + // Failers + var input0 = "B\n"; + var results = null; + shouldBe("regex190a.exec(input0);", "results"); + + var regex190b = /B$/m; + var input0 = "B\n"; + var results = ["B"]; + shouldBe("regex190b.exec(input0);", "results"); + + var regex191 = /^[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]/; + var input0 = "123456654321"; + var results = ["123456654321"]; + shouldBe("regex191.exec(input0);", "results"); + + var regex192 = /^\d\d\d\d\d\d\d\d\d\d\d\d/; + var input0 = "123456654321"; + var results = ["123456654321"]; + shouldBe("regex192.exec(input0);", "results"); + + var regex193 = /^[\d][\d][\d][\d][\d][\d][\d][\d][\d][\d][\d][\d]/; + var input0 = "123456654321"; + var results = ["123456654321"]; + shouldBe("regex193.exec(input0);", "results"); + + var regex194 = /^[abc]{12}/; + var input0 = "abcabcabcabc"; + var results = ["abcabcabcabc"]; + shouldBe("regex194.exec(input0);", "results"); + + var regex195 = /^[a-c]{12}/; + var input0 = "abcabcabcabc"; + var results = ["abcabcabcabc"]; + shouldBe("regex195.exec(input0);", "results"); + + var regex196 = /^(a|b|c){12}/; + var input0 = "abcabcabcabc"; + var results = ["abcabcabcabc", "c"]; + shouldBe("regex196.exec(input0);", "results"); + + var regex197 = /^[abcdefghijklmnopqrstuvwxy0123456789]/; + var input0 = "n"; + var results = ["n"]; + shouldBe("regex197.exec(input0);", "results"); + // Failers + var input1 = "z"; + var results = null; + shouldBe("regex197.exec(input1);", "results"); + + var regex198 = /abcde{0,0}/; + var input0 = "abcd"; + var results = ["abcd"]; + shouldBe("regex198.exec(input0);", "results"); + // Failers + var input1 = "abce"; + var results = null; + shouldBe("regex198.exec(input1);", "results"); + + var regex199 = /ab[cd]{0,0}e/; + var input0 = "abe"; + var results = ["abe"]; + shouldBe("regex199.exec(input0);", "results"); + // Failers + var input1 = "abcde"; + var results = null; + shouldBe("regex199.exec(input1);", "results"); + + var regex200 = /ab(c){0,0}d/; + var input0 = "abd"; + var results = ["abd", undefined]; + shouldBe("regex200.exec(input0);", "results"); + // Failers + var input1 = "abcd"; + var results = null; + shouldBe("regex200.exec(input1);", "results"); + + var regex201 = /a(b*)/; + var input0 = "a"; + var results = ["a", ""]; + shouldBe("regex201.exec(input0);", "results"); + var input1 = "ab"; + var results = ["ab", "b"]; + shouldBe("regex201.exec(input1);", "results"); + var input2 = "abbbb"; + var results = ["abbbb", "bbbb"]; + shouldBe("regex201.exec(input2);", "results"); + // Failers + var input3 = "bbbbb"; + var results = null; + shouldBe("regex201.exec(input3);", "results"); + + var regex202 = /ab\d{0}e/; + var input0 = "abe"; + var results = ["abe"]; + shouldBe("regex202.exec(input0);", "results"); + // Failers + var input1 = "ab1e"; + var results = null; + shouldBe("regex202.exec(input1);", "results"); + + var regex203 = /"([^\\"]+|\\.)*"/; + var input0 = 'the "quick" brown fox'; + var results = ['"quick"', "quick"]; + shouldBe("regex203.exec(input0);", "results"); + var input1 = '"the \\"quick\\" brown fox"'; + var results = ['"the \\"quick\\" brown fox"', " brown fox"]; + shouldBe("regex203.exec(input1);", "results"); + + var regex204 = + /]{0,})>]{0,})>([\d]{0,}\.)(.*)((([\w\W\s\d][^<>]{0,})|[\s]{0,}))<\/a><\/TD>]{0,})>([\w\W\s\d][^<>]{0,})<\/TD>]{0,})>([\w\W\s\d][^<>]{0,})<\/TD><\/TR>/i; + var input0 = + "43.Word Processor(N-1286)Lega lstaff.comCA - Statewide"; + var results = [ + "43.Word Processor(N-1286)Lega lstaff.comCA - Statewide", + " BGCOLOR=\'#DBE9E9\'", + " align=left valign=top", + "43.", + "Word Processor(N-1286)", + "", + "", + undefined, + " align=left valign=top", + "Lega lstaff.com", + " align=left valign=top", + "CA - Statewide", + ]; + shouldBe("regex204.exec(input0);", "results"); + + var regex205 = /a[^a]b/; + var input0 = "acb"; + var results = ["acb"]; + shouldBe("regex205.exec(input0);", "results"); + var input1 = "a\nb"; + var results = ["a\x0ab"]; + shouldBe("regex205.exec(input1);", "results"); + + var regex206 = /a.b/; + var input0 = "acb"; + var results = ["acb"]; + shouldBe("regex206.exec(input0);", "results"); + // Failers + var input1 = "a\nb"; + var results = null; + shouldBe("regex206.exec(input1);", "results"); + + var regex207 = /a[^a]b/; + var input0 = "acb"; + var results = ["acb"]; + shouldBe("regex207.exec(input0);", "results"); + var input1 = "a\nb"; + var results = ["a\x0ab"]; + shouldBe("regex207.exec(input1);", "results"); + + var regex208 = /a[\w\W]b/; + var input0 = "acb"; + var results = ["acb"]; + shouldBe("regex208.exec(input0);", "results"); + var input1 = "a\nb"; + var results = ["a\x0ab"]; + shouldBe("regex208.exec(input1);", "results"); + + var regex209 = /^(b+?|a){1,2}?c/; + var input0 = "bac"; + var results = ["bac", "a"]; + shouldBe("regex209.exec(input0);", "results"); + var input1 = "bbac"; + var results = ["bbac", "a"]; + shouldBe("regex209.exec(input1);", "results"); + var input2 = "bbbac"; + var results = ["bbbac", "a"]; + shouldBe("regex209.exec(input2);", "results"); + var input3 = "bbbbac"; + var results = ["bbbbac", "a"]; + shouldBe("regex209.exec(input3);", "results"); + var input4 = "bbbbbac"; + var results = ["bbbbbac", "a"]; + shouldBe("regex209.exec(input4);", "results"); + + var regex210 = /^(b+|a){1,2}?c/; + var input0 = "bac"; + var results = ["bac", "a"]; + shouldBe("regex210.exec(input0);", "results"); + var input1 = "bbac"; + var results = ["bbac", "a"]; + shouldBe("regex210.exec(input1);", "results"); + var input2 = "bbbac"; + var results = ["bbbac", "a"]; + shouldBe("regex210.exec(input2);", "results"); + var input3 = "bbbbac"; + var results = ["bbbbac", "a"]; + shouldBe("regex210.exec(input3);", "results"); + var input4 = "bbbbbac"; + var results = ["bbbbbac", "a"]; + shouldBe("regex210.exec(input4);", "results"); + + var regex211 = /(?!^)x/m; + var input0 = "a\bx\n"; + var results = ["x"]; + shouldBe("regex211.exec(input0);", "results"); + // Failers + var input1 = "x\nb\n"; + var results = null; + shouldBe("regex211.exec(input1);", "results"); + + var regex212 = /\0{ab}/; + var input0 = "\0{ab}"; + var results = ["\x00{ab}"]; + shouldBe("regex212.exec(input0);", "results"); + + var regex213 = /(A|B)*?CD/; + var input0 = "CD"; + var results = ["CD", undefined]; + shouldBe("regex213.exec(input0);", "results"); + + var regex214 = /(A|B)*CD/; + var input0 = "CD"; + var results = ["CD", undefined]; + shouldBe("regex214.exec(input0);", "results"); + + var regex215 = /^((AB)+?)\2$/; + var input0 = "ABABAB"; + var results = ["ABABAB", "ABAB", "AB"]; + shouldBe("regex215.exec(input0);", "results"); + + var regex216 = /(AB)*\1/; + var input0 = "ABABAB"; + var results = ["ABABAB", "AB"]; + shouldBe("regex216.exec(input0);", "results"); + + var regex220 = /^abc$/m; + var input0 = "abc"; + var results = ["abc"]; + shouldBe("regex220.exec(input0);", "results"); + var input1 = "abc\n"; + var results = ["abc"]; + shouldBe("regex220.exec(input1);", "results"); + var input2 = "qqq\nabc"; + var results = ["abc"]; + shouldBe("regex220.exec(input2);", "results"); + var input3 = "abc\nzzz"; + var results = ["abc"]; + shouldBe("regex220.exec(input3);", "results"); + var input4 = "qqq\nabc\nzzz"; + var results = ["abc"]; + shouldBe("regex220.exec(input4);", "results"); + + var regex225 = /(\d+)(\w)/; + var input0 = "12345a"; + var results = ["12345a", "12345", "a"]; + shouldBe("regex225.exec(input0);", "results"); + var input1 = "12345+"; + var results = ["12345", "1234", "5"]; + shouldBe("regex225.exec(input1);", "results"); + + var regex234 = /ab/; + var input0 = "ab"; + var results = ["ab"]; + shouldBe("regex234.exec(input0);", "results"); + // Failers + var input1 = "Ab"; + var results = null; + shouldBe("regex234.exec(input1);", "results"); + var input2 = "aB"; + var results = null; + shouldBe("regex234.exec(input2);", "results"); + var input3 = "AB"; + var results = null; + shouldBe("regex234.exec(input3);", "results"); + + var regex235 = /(a bc)d e/; + var input0 = "a bcd e"; + var results = ["a bcd e", "a bc"]; + shouldBe("regex235.exec(input0);", "results"); + // Failers + var input1 = "a b cd e"; + var results = null; + shouldBe("regex235.exec(input1);", "results"); + var input2 = "abcd e"; + var results = null; + shouldBe("regex235.exec(input2);", "results"); + var input3 = "a bcde"; + var results = null; + shouldBe("regex235.exec(input3);", "results"); + + var regex236 = /(a bcde f)/; + var input0 = "a bcde f"; + var results = ["a bcde f", "a bcde f"]; + shouldBe("regex236.exec(input0);", "results"); + // Failers + var input1 = "abcdef"; + var results = null; + shouldBe("regex236.exec(input1);", "results"); + + var regex237 = /(a[bB])c/; + var input0 = "abc"; + var results = ["abc", "ab"]; + shouldBe("regex237.exec(input0);", "results"); + var input1 = "aBc"; + var results = ["aBc", "aB"]; + shouldBe("regex237.exec(input1);", "results"); + // Failers + var input2 = "abC"; + var results = null; + shouldBe("regex237.exec(input2);", "results"); + var input3 = "aBC"; + var results = null; + shouldBe("regex237.exec(input3);", "results"); + var input4 = "Abc"; + var results = null; + shouldBe("regex237.exec(input4);", "results"); + var input5 = "ABc"; + var results = null; + shouldBe("regex237.exec(input5);", "results"); + var input6 = "ABC"; + var results = null; + shouldBe("regex237.exec(input6);", "results"); + var input7 = "AbC"; + var results = null; + shouldBe("regex237.exec(input7);", "results"); + + var regex238 = /a[bB]c/; + var input0 = "abc"; + var results = ["abc"]; + shouldBe("regex238.exec(input0);", "results"); + var input1 = "aBc"; + var results = ["aBc"]; + shouldBe("regex238.exec(input1);", "results"); + // Failers + var input2 = "ABC"; + var results = null; + shouldBe("regex238.exec(input2);", "results"); + var input3 = "abC"; + var results = null; + shouldBe("regex238.exec(input3);", "results"); + var input4 = "aBC"; + var results = null; + shouldBe("regex238.exec(input4);", "results"); + + var regex239 = /a[bB]*c/; + var input0 = "aBc"; + var results = ["aBc"]; + shouldBe("regex239.exec(input0);", "results"); + var input1 = "aBBc"; + var results = ["aBBc"]; + shouldBe("regex239.exec(input1);", "results"); + // Failers + var input2 = "aBC"; + var results = null; + shouldBe("regex239.exec(input2);", "results"); + var input3 = "aBBC"; + var results = null; + shouldBe("regex239.exec(input3);", "results"); + + var regex240 = /a(?=b[cC])\w\wd/; + var input0 = "abcd"; + var results = ["abcd"]; + shouldBe("regex240.exec(input0);", "results"); + var input1 = "abCd"; + var results = ["abCd"]; + shouldBe("regex240.exec(input1);", "results"); + // Failers + var input2 = "aBCd"; + var results = null; + shouldBe("regex240.exec(input2);", "results"); + var input3 = "abcD"; + var results = null; + shouldBe("regex240.exec(input3);", "results"); + + var regex241 = /(?:more[\w\W]*than).*million/i; + var input0 = "more than million"; + var results = ["more than million"]; + shouldBe("regex241.exec(input0);", "results"); + var input1 = "more than MILLION"; + var results = ["more than MILLION"]; + shouldBe("regex241.exec(input1);", "results"); + var input2 = "more \n than Million"; + var results = ["more \x0a than Million"]; + shouldBe("regex241.exec(input2);", "results"); + var input3 = "MORE THAN MILLION"; + var results = ["MORE THAN MILLION"]; + // Failers + shouldBe("regex241.exec(input3);", "results"); + var input4 = "more \n than \n million"; + var results = null; + shouldBe("regex241.exec(input4);", "results"); + + var regex242 = /(?:more[\w\W]*than).*million/i; + var input0 = "more than million"; + var results = ["more than million"]; + shouldBe("regex242.exec(input0);", "results"); + var input1 = "more than MILLION"; + var results = ["more than MILLION"]; + shouldBe("regex242.exec(input1);", "results"); + var input2 = "more \n than Million"; + var results = ["more \x0a than Million"]; + shouldBe("regex242.exec(input2);", "results"); + var input3 = "MORE THAN MILLION"; + var results = ["MORE THAN MILLION"]; + // Failers + shouldBe("regex242.exec(input3);", "results"); + var input4 = "more \n than \n million"; + var results = null; + shouldBe("regex242.exec(input4);", "results"); + + var regex243 = /(?:ab+)+c/i; + var input0 = "abc"; + var results = ["abc"]; + shouldBe("regex243.exec(input0);", "results"); + var input1 = "aBbc"; + var results = ["aBbc"]; + shouldBe("regex243.exec(input1);", "results"); + var input2 = "aBBc"; + var results = ["aBBc"]; + shouldBe("regex243.exec(input2);", "results"); + var input3 = "Abc"; + var results = ["Abc"]; + shouldBe("regex243.exec(input3);", "results"); + var input4 = "abbC"; + var results = ["abbC"]; + shouldBe("regex243.exec(input4);", "results"); + // Failers + var input5 = "abAb"; + var results = null; + shouldBe("regex243.exec(input5);", "results"); + + var regex244 = /(?=a[bB])\w\wc/; + var input0 = "abc"; + var results = ["abc"]; + shouldBe("regex244.exec(input0);", "results"); + var input1 = "aBc"; + var results = ["aBc"]; + shouldBe("regex244.exec(input1);", "results"); + // Failers + var input2 = "Ab"; + var results = null; + shouldBe("regex244.exec(input2);", "results"); + var input3 = "abC"; + var results = null; + shouldBe("regex244.exec(input3);", "results"); + var input4 = "aBC"; + var results = null; + shouldBe("regex244.exec(input4);", "results"); + + var regex246 = /(?:(a)|b)(?:A|B)/; + var input0 = "aA"; + var results = ["aA", "a"]; + shouldBe("regex246.exec(input0);", "results"); + var input1 = "bB"; + var results = ["bB", undefined]; + shouldBe("regex246.exec(input1);", "results"); + var input2 = "aB"; + var results = ["aB", "a"]; + shouldBe("regex246.exec(input2);", "results"); + var input3 = "bA"; + var results = ["bA", undefined]; + shouldBe("regex246.exec(input3);", "results"); + + var regex247 = /^(a)?(?:a|b)+$/; + var input0 = "aa"; + var results = ["aa", "a"]; + shouldBe("regex247.exec(input0);", "results"); + var input1 = "b"; + var results = ["b", undefined]; + shouldBe("regex247.exec(input1);", "results"); + var input2 = "bb"; + var results = ["bb", undefined]; + shouldBe("regex247.exec(input2);", "results"); + var input3 = "ab"; + var results = ["ab", "a"]; + shouldBe("regex247.exec(input3);", "results"); + + var regex248 = /^(?:(?=abc)\w{3}:|\d\d)$/; + var input0 = "abc:"; + var results = ["abc:"]; + shouldBe("regex248.exec(input0);", "results"); + var input1 = "12"; + var results = ["12"]; + shouldBe("regex248.exec(input1);", "results"); + // Failers + var input2 = "123"; + var results = null; + shouldBe("regex248.exec(input2);", "results"); + var input3 = "xyz"; + var results = null; + shouldBe("regex248.exec(input3);", "results"); + + var regex249 = /^(?:(?!abc)\d\d|\w{3}:)$/; + var input0 = "abc:"; + var results = ["abc:"]; + shouldBe("regex249.exec(input0);", "results"); + var input1 = "12"; + var results = ["12"]; + shouldBe("regex249.exec(input1);", "results"); + // Failers + var input2 = "123"; + var results = null; + shouldBe("regex249.exec(input2);", "results"); + var input3 = "xyz"; + var results = null; + shouldBe("regex249.exec(input3);", "results"); + + var regex252 = /(?=\()(\()[^()]+\)|[^()]+/; + var input0 = "abcd"; + var results = ["abcd", undefined]; + shouldBe("regex252.exec(input0);", "results"); + var input1 = "(abcd)"; + var results = ["(abcd)", "("]; + shouldBe("regex252.exec(input1);", "results"); + var input2 = "the quick (abcd) fox"; + var results = ["the quick ", undefined]; + shouldBe("regex252.exec(input2);", "results"); + var input3 = "(abcd"; + var results = ["abcd", undefined]; + shouldBe("regex252.exec(input3);", "results"); + + var regex253 = /^(?:a|(1)(2))+$/; + var input0 = "12"; + var results = ["12", "1", "2"]; + shouldBe("regex253.exec(input0);", "results"); + var input1 = "12a"; + var results = ["12a", undefined, undefined]; + shouldBe("regex253.exec(input1);", "results"); + var input2 = "12aa"; + var results = ["12aa", undefined, undefined]; + shouldBe("regex253.exec(input2);", "results"); + // Failers + var input3 = "1234"; + var results = null; + shouldBe("regex253.exec(input3);", "results"); + + var regex254 = /(blah)\s+\1/i; + var input0 = "blah blah"; + var results = ["blah blah", "blah"]; + shouldBe("regex254.exec(input0);", "results"); + var input1 = "BLAH BLAH"; + var results = ["BLAH BLAH", "BLAH"]; + shouldBe("regex254.exec(input1);", "results"); + var input2 = "Blah Blah"; + var results = ["Blah Blah", "Blah"]; + shouldBe("regex254.exec(input2);", "results"); + var input3 = "blaH blaH"; + var results = ["blaH blaH", "blaH"]; + shouldBe("regex254.exec(input3);", "results"); + var input4 = "blah BLAH"; + var results = ["blah BLAH", "blah"]; + shouldBe("regex254.exec(input4);", "results"); + var input5 = "Blah blah"; + var results = ["Blah blah", "Blah"]; + shouldBe("regex254.exec(input5);", "results"); + var input6 = "blaH blah"; + var results = ["blaH blah", "blaH"]; + shouldBe("regex254.exec(input6);", "results"); + + var regex255 = /(blah)\s+(?:\1)/i; + var input0 = "blah blah"; + var results = ["blah blah", "blah"]; + shouldBe("regex255.exec(input0);", "results"); + var input1 = "BLAH BLAH"; + var results = ["BLAH BLAH", "BLAH"]; + shouldBe("regex255.exec(input1);", "results"); + var input2 = "Blah Blah"; + var results = ["Blah Blah", "Blah"]; + shouldBe("regex255.exec(input2);", "results"); + var input3 = "blaH blaH"; + var results = ["blaH blaH", "blaH"]; + shouldBe("regex255.exec(input3);", "results"); + var input4 = "blah BLAH"; + var results = ["blah BLAH", "blah"]; + shouldBe("regex255.exec(input4);", "results"); + var input5 = "Blah blah"; + var results = ["Blah blah", "Blah"]; + shouldBe("regex255.exec(input5);", "results"); + var input6 = "blaH blah"; + var results = ["blaH blah", "blaH"]; + shouldBe("regex255.exec(input6);", "results"); + + var regex257 = /(abc|)+/; + var input0 = "abc"; + var results = ["abc", "abc"]; + shouldBe("regex257.exec(input0);", "results"); + var input1 = "abcabc"; + var results = ["abcabc", "abc"]; + shouldBe("regex257.exec(input1);", "results"); + var input2 = "abcabcabc"; + var results = ["abcabcabc", "abc"]; + shouldBe("regex257.exec(input2);", "results"); + var input3 = "xyz"; + var results = ["", ""]; + shouldBe("regex257.exec(input3);", "results"); + + var regex258 = /([a]*)*/; + var input0 = "a"; + var results = ["a", "a"]; + shouldBe("regex258.exec(input0);", "results"); + var input1 = "aaaaa"; + var results = ["aaaaa", "aaaaa"]; + shouldBe("regex258.exec(input1);", "results"); + + var regex259 = /([ab]*)*/; + var input0 = "a"; + var results = ["a", "a"]; + shouldBe("regex259.exec(input0);", "results"); + var input1 = "b"; + var results = ["b", "b"]; + shouldBe("regex259.exec(input1);", "results"); + var input2 = "ababab"; + var results = ["ababab", "ababab"]; + shouldBe("regex259.exec(input2);", "results"); + var input3 = "aaaabcde"; + var results = ["aaaab", "aaaab"]; + shouldBe("regex259.exec(input3);", "results"); + var input4 = "bbbb"; + var results = ["bbbb", "bbbb"]; + shouldBe("regex259.exec(input4);", "results"); + + var regex260 = /([^a]*)*/; + var input0 = "b"; + var results = ["b", "b"]; + shouldBe("regex260.exec(input0);", "results"); + var input1 = "bbbb"; + var results = ["bbbb", "bbbb"]; + shouldBe("regex260.exec(input1);", "results"); + var input2 = "aaa"; + var results = ["", undefined]; + shouldBe("regex260.exec(input2);", "results"); + + var regex261 = /([^ab]*)*/; + var input0 = "cccc"; + var results = ["cccc", "cccc"]; + shouldBe("regex261.exec(input0);", "results"); + var input1 = "abab"; + var results = ["", undefined]; + shouldBe("regex261.exec(input1);", "results"); + + var regex262 = /([a]*?)*/; + var input0 = "a"; + var results = ["a", "a"]; + shouldBe("regex262.exec(input0);", "results"); + var input1 = "aaaa"; + var results = ["aaaa", "a"]; + shouldBe("regex262.exec(input1);", "results"); + + var regex263 = /([ab]*?)*/; + var input0 = "a"; + var results = ["a", "a"]; + shouldBe("regex263.exec(input0);", "results"); + var input1 = "b"; + var results = ["b", "b"]; + shouldBe("regex263.exec(input1);", "results"); + var input2 = "abab"; + var results = ["abab", "b"]; + shouldBe("regex263.exec(input2);", "results"); + var input3 = "baba"; + var results = ["baba", "a"]; + shouldBe("regex263.exec(input3);", "results"); + + var regex264 = /([^a]*?)*/; + var input0 = "b"; + var results = ["b", "b"]; + shouldBe("regex264.exec(input0);", "results"); + var input1 = "bbbb"; + var results = ["bbbb", "b"]; + shouldBe("regex264.exec(input1);", "results"); + var input2 = "aaa"; + var results = ["", undefined]; + shouldBe("regex264.exec(input2);", "results"); + + var regex265 = /([^ab]*?)*/; + var input0 = "c"; + var results = ["c", "c"]; + shouldBe("regex265.exec(input0);", "results"); + var input1 = "cccc"; + var results = ["cccc", "c"]; + shouldBe("regex265.exec(input1);", "results"); + var input2 = "baba"; + var results = ["", undefined]; + shouldBe("regex265.exec(input2);", "results"); + + var regex269 = /(?=[^a-z]+[a-z])\d{2}-[a-z]{3}-\d{2}|(?![^a-z]+[a-z])\d{2}-\d{2}-\d{2}/; + var input0 = "12-sep-98"; + var results = ["12-sep-98"]; + shouldBe("regex269.exec(input0);", "results"); + var input1 = "12-09-98"; + var results = ["12-09-98"]; + shouldBe("regex269.exec(input1);", "results"); + var input2 = "sep-12-98"; + var results = null; + shouldBe("regex269.exec(input2);", "results"); + + var regex271 = /(?:saturday|sunday)/i; + var input0 = "saturday"; + var results = ["saturday"]; + shouldBe("regex271.exec(input0);", "results"); + var input1 = "sunday"; + var results = ["sunday"]; + shouldBe("regex271.exec(input1);", "results"); + var input2 = "Saturday"; + var results = ["Saturday"]; + shouldBe("regex271.exec(input2);", "results"); + var input3 = "Sunday"; + var results = ["Sunday"]; + shouldBe("regex271.exec(input3);", "results"); + var input4 = "SATURDAY"; + var results = ["SATURDAY"]; + shouldBe("regex271.exec(input4);", "results"); + var input5 = "SUNDAY"; + var results = ["SUNDAY"]; + shouldBe("regex271.exec(input5);", "results"); + var input6 = "SunDay"; + var results = ["SunDay"]; + shouldBe("regex271.exec(input6);", "results"); + + var regex272 = /([aA][bB][cC]|[bB][bB])x/; + var input0 = "abcx"; + var results = ["abcx", "abc"]; + shouldBe("regex272.exec(input0);", "results"); + var input1 = "aBCx"; + var results = ["aBCx", "aBC"]; + shouldBe("regex272.exec(input1);", "results"); + var input2 = "bbx"; + var results = ["bbx", "bb"]; + shouldBe("regex272.exec(input2);", "results"); + var input3 = "BBx"; + var results = ["BBx", "BB"]; + shouldBe("regex272.exec(input3);", "results"); + // Failers + var input4 = "abcX"; + var results = null; + shouldBe("regex272.exec(input4);", "results"); + var input5 = "aBCX"; + var results = null; + shouldBe("regex272.exec(input5);", "results"); + var input6 = "bbX"; + var results = null; + shouldBe("regex272.exec(input6);", "results"); + var input7 = "BBX"; + var results = null; + shouldBe("regex272.exec(input7);", "results"); + + var regex273 = /^([ab][cd]|[ef])/i; + var input0 = "ac"; + var results = ["ac", "ac"]; + shouldBe("regex273.exec(input0);", "results"); + var input1 = "aC"; + var results = ["aC", "aC"]; + shouldBe("regex273.exec(input1);", "results"); + var input2 = "bD"; + var results = ["bD", "bD"]; + shouldBe("regex273.exec(input2);", "results"); + var input3 = "elephant"; + var results = ["e", "e"]; + shouldBe("regex273.exec(input3);", "results"); + var input4 = "Europe"; + var results = ["E", "E"]; + shouldBe("regex273.exec(input4);", "results"); + var input5 = "frog"; + var results = ["f", "f"]; + shouldBe("regex273.exec(input5);", "results"); + var input6 = "France"; + var results = ["F", "F"]; + shouldBe("regex273.exec(input6);", "results"); + // Failers + var input7 = "Africa"; + var results = null; + shouldBe("regex273.exec(input7);", "results"); + + var regex274 = /^(ab|a[b-cB-C]d|x[yY]|[zZ])/; + var input0 = "ab"; + var results = ["ab", "ab"]; + shouldBe("regex274.exec(input0);", "results"); + var input1 = "aBd"; + var results = ["aBd", "aBd"]; + shouldBe("regex274.exec(input1);", "results"); + var input2 = "xy"; + var results = ["xy", "xy"]; + shouldBe("regex274.exec(input2);", "results"); + var input3 = "xY"; + var results = ["xY", "xY"]; + shouldBe("regex274.exec(input3);", "results"); + var input4 = "zebra"; + var results = ["z", "z"]; + shouldBe("regex274.exec(input4);", "results"); + var input5 = "Zambesi"; + var results = ["Z", "Z"]; + shouldBe("regex274.exec(input5);", "results"); + // Failers + var input6 = "aCD"; + var results = null; + shouldBe("regex274.exec(input6);", "results"); + var input7 = "XY"; + var results = null; + shouldBe("regex274.exec(input7);", "results"); + + var regex277 = /^(a\1?){4}$/; + var input0 = "a"; + var results = null; + shouldBe("regex277.exec(input0);", "results"); + var input1 = "aa"; + var results = null; + shouldBe("regex277.exec(input1);", "results"); + var input2 = "aaa"; + var results = null; + shouldBe("regex277.exec(input2);", "results"); + var input3 = "aaaa"; + var results = ["aaaa", "a"]; + shouldBe("regex277.exec(input3);", "results"); + var input4 = "aaaaa"; + var results = null; + shouldBe("regex277.exec(input4);", "results"); + var input5 = "aaaaaaa"; + var results = null; + shouldBe("regex277.exec(input5);", "results"); + var input6 = "aaaaaaaa"; + var results = null; + shouldBe("regex277.exec(input6);", "results"); + var input7 = "aaaaaaaaa"; + var results = null; + shouldBe("regex277.exec(input7);", "results"); + var input8 = "aaaaaaaaaa"; + var results = null; + shouldBe("regex277.exec(input8);", "results"); + var input9 = "aaaaaaaaaaa"; + var results = null; + shouldBe("regex277.exec(input9);", "results"); + var input10 = "aaaaaaaaaaaa"; + var results = null; + shouldBe("regex277.exec(input10);", "results"); + var input11 = "aaaaaaaaaaaaa"; + var results = null; + shouldBe("regex277.exec(input11);", "results"); + var input12 = "aaaaaaaaaaaaaa"; + var results = null; + shouldBe("regex277.exec(input12);", "results"); + var input13 = "aaaaaaaaaaaaaaa"; + var results = null; + shouldBe("regex277.exec(input13);", "results"); + var input14 = "aaaaaaaaaaaaaaaa"; + var results = null; + shouldBe("regex277.exec(input14);", "results"); + + var regex278 = /^(a\1?)(a\1?)(a\2?)(a\3?)$/; + var input0 = "a"; + var results = null; + shouldBe("regex278.exec(input0);", "results"); + var input1 = "aa"; + var results = null; + shouldBe("regex278.exec(input1);", "results"); + var input2 = "aaa"; + var results = null; + shouldBe("regex278.exec(input2);", "results"); + var input3 = "aaaa"; + var results = ["aaaa", "a", "a", "a", "a"]; + shouldBe("regex278.exec(input3);", "results"); + var input4 = "aaaaa"; + var results = ["aaaaa", "a", "aa", "a", "a"]; + shouldBe("regex278.exec(input4);", "results"); + var input5 = "aaaaaa"; + var results = ["aaaaaa", "a", "aa", "a", "aa"]; + shouldBe("regex278.exec(input5);", "results"); + var input6 = "aaaaaaa"; + var results = ["aaaaaaa", "a", "aa", "aaa", "a"]; + shouldBe("regex278.exec(input6);", "results"); + var input7 = "aaaaaaaa"; + var results = null; + shouldBe("regex278.exec(input7);", "results"); + var input8 = "aaaaaaaaa"; + var results = null; + shouldBe("regex278.exec(input8);", "results"); + var input9 = "aaaaaaaaaa"; + var results = ["aaaaaaaaaa", "a", "aa", "aaa", "aaaa"]; + shouldBe("regex278.exec(input9);", "results"); + var input10 = "aaaaaaaaaaa"; + var results = null; + shouldBe("regex278.exec(input10);", "results"); + var input11 = "aaaaaaaaaaaa"; + var results = null; + shouldBe("regex278.exec(input11);", "results"); + var input12 = "aaaaaaaaaaaaa"; + var results = null; + shouldBe("regex278.exec(input12);", "results"); + var input13 = "aaaaaaaaaaaaaa"; + var results = null; + shouldBe("regex278.exec(input13);", "results"); + var input14 = "aaaaaaaaaaaaaaa"; + var results = null; + shouldBe("regex278.exec(input14);", "results"); + var input15 = "aaaaaaaaaaaaaaaa"; + var results = null; + shouldBe("regex278.exec(input15);", "results"); + + var regex279 = /abc/; + var input0 = "abc"; + var results = ["abc"]; + shouldBe("regex279.exec(input0);", "results"); + var input1 = "xabcy"; + var results = ["abc"]; + shouldBe("regex279.exec(input1);", "results"); + var input2 = "ababc"; + var results = ["abc"]; + shouldBe("regex279.exec(input2);", "results"); + // Failers + var input3 = "xbc"; + var results = null; + shouldBe("regex279.exec(input3);", "results"); + var input4 = "axc"; + var results = null; + shouldBe("regex279.exec(input4);", "results"); + var input5 = "abx"; + var results = null; + shouldBe("regex279.exec(input5);", "results"); + + var regex280 = /ab*c/; + var input0 = "abc"; + var results = ["abc"]; + shouldBe("regex280.exec(input0);", "results"); + + var regex281 = /ab*bc/; + var input0 = "abc"; + var results = ["abc"]; + shouldBe("regex281.exec(input0);", "results"); + var input1 = "abbc"; + var results = ["abbc"]; + shouldBe("regex281.exec(input1);", "results"); + var input2 = "abbbbc"; + var results = ["abbbbc"]; + shouldBe("regex281.exec(input2);", "results"); + + var regex282 = /.{1}/; + var input0 = "abbbbc"; + var results = ["a"]; + shouldBe("regex282.exec(input0);", "results"); + + var regex283 = /.{3,4}/; + var input0 = "abbbbc"; + var results = ["abbb"]; + shouldBe("regex283.exec(input0);", "results"); + + var regex284 = /ab{0,}bc/; + var input0 = "abbbbc"; + var results = ["abbbbc"]; + shouldBe("regex284.exec(input0);", "results"); + + var regex285 = /ab+bc/; + var input0 = "abbc"; + var results = ["abbc"]; + shouldBe("regex285.exec(input0);", "results"); + // Failers + var input1 = "abc"; + var results = null; + shouldBe("regex285.exec(input1);", "results"); + var input2 = "abq"; + var results = null; + shouldBe("regex285.exec(input2);", "results"); + + var regex286 = /ab+bc/; + var input0 = "abbbbc"; + var results = ["abbbbc"]; + shouldBe("regex286.exec(input0);", "results"); + + var regex287 = /ab{1,}bc/; + var input0 = "abbbbc"; + var results = ["abbbbc"]; + shouldBe("regex287.exec(input0);", "results"); + + var regex288 = /ab{1,3}bc/; + var input0 = "abbbbc"; + var results = ["abbbbc"]; + shouldBe("regex288.exec(input0);", "results"); + + var regex289 = /ab{3,4}bc/; + var input0 = "abbbbc"; + var results = ["abbbbc"]; + shouldBe("regex289.exec(input0);", "results"); + + var regex290 = /ab{4,5}bc/; + // Failers + var input0 = "abq"; + var results = null; + shouldBe("regex290.exec(input0);", "results"); + var input1 = "abbbbc"; + var results = null; + shouldBe("regex290.exec(input1);", "results"); + + var regex291 = /ab?bc/; + var input0 = "abbc"; + var results = ["abbc"]; + shouldBe("regex291.exec(input0);", "results"); + var input1 = "abc"; + var results = ["abc"]; + shouldBe("regex291.exec(input1);", "results"); + + var regex292 = /ab{0,1}bc/; + var input0 = "abc"; + var results = ["abc"]; + shouldBe("regex292.exec(input0);", "results"); + + var regex293 = /ab?c/; + var input0 = "abc"; + var results = ["abc"]; + shouldBe("regex293.exec(input0);", "results"); + + var regex294 = /ab{0,1}c/; + var input0 = "abc"; + var results = ["abc"]; + shouldBe("regex294.exec(input0);", "results"); + + var regex295 = /^abc/; + var input0 = "abcc"; + var results = ["abc"]; + shouldBe("regex295.exec(input0);", "results"); + + var regex296 = /abc$/; + var input0 = "aabc"; + var results = ["abc"]; + shouldBe("regex296.exec(input0);", "results"); + // Failers + var input1 = "aabc"; + var results = ["abc"]; + shouldBe("regex296.exec(input1);", "results"); + var input2 = "aabcd"; + var results = null; + shouldBe("regex296.exec(input2);", "results"); + + var regex297 = /^/; + var input0 = "abc"; + var results = [""]; + shouldBe("regex297.exec(input0);", "results"); + + var regex298 = /$/; + var input0 = "abc"; + var results = [""]; + shouldBe("regex298.exec(input0);", "results"); + + var regex299 = /a.c/; + var input0 = "abc"; + var results = ["abc"]; + shouldBe("regex299.exec(input0);", "results"); + var input1 = "axc"; + var results = ["axc"]; + shouldBe("regex299.exec(input1);", "results"); + + var regex300 = /a.*c/; + var input0 = "axyzc"; + var results = ["axyzc"]; + shouldBe("regex300.exec(input0);", "results"); + + var regex301 = /a[bc]d/; + var input0 = "abd"; + var results = ["abd"]; + shouldBe("regex301.exec(input0);", "results"); + // Failers + var input1 = "axyzd"; + var results = null; + shouldBe("regex301.exec(input1);", "results"); + var input2 = "abc"; + var results = null; + shouldBe("regex301.exec(input2);", "results"); + + var regex302 = /a[b-d]e/; + var input0 = "ace"; + var results = ["ace"]; + shouldBe("regex302.exec(input0);", "results"); + + var regex303 = /a[b-d]/; + var input0 = "aac"; + var results = ["ac"]; + shouldBe("regex303.exec(input0);", "results"); + + var regex304 = /a[-b]/; + var input0 = "a-"; + var results = ["a-"]; + shouldBe("regex304.exec(input0);", "results"); + + var regex305 = /a[b-]/; + var input0 = "a-"; + var results = ["a-"]; + shouldBe("regex305.exec(input0);", "results"); + + var regex306 = /a]/; + var input0 = "a]"; + var results = ["a]"]; + shouldBe("regex306.exec(input0);", "results"); + + var regex307 = /a[\]]b/; + var input0 = "a]b"; + var results = ["a]b"]; + shouldBe("regex307.exec(input0);", "results"); + + var regex308 = /a[^bc]d/; + var input0 = "aed"; + var results = ["aed"]; + shouldBe("regex308.exec(input0);", "results"); + // Failers + var input1 = "abd"; + var results = null; + shouldBe("regex308.exec(input1);", "results"); + var input2 = "abd"; + var results = null; + shouldBe("regex308.exec(input2);", "results"); + + var regex309 = /a[^-b]c/; + var input0 = "adc"; + var results = ["adc"]; + shouldBe("regex309.exec(input0);", "results"); + + var regex310 = /a[^\]b]c/; + var input0 = "adc"; + var results = ["adc"]; + shouldBe("regex310.exec(input0);", "results"); + var input1 = "a-c"; + var results = ["a-c"]; + shouldBe("regex310.exec(input1);", "results"); + // Failers + var input2 = "a]c"; + var results = null; + shouldBe("regex310.exec(input2);", "results"); + + var regex311 = /\ba\b/; + var input0 = "a-"; + var results = ["a"]; + shouldBe("regex311.exec(input0);", "results"); + var input1 = "-a"; + var results = ["a"]; + shouldBe("regex311.exec(input1);", "results"); + var input2 = "-a-"; + var results = ["a"]; + shouldBe("regex311.exec(input2);", "results"); + + var regex312 = /\by\b/; + // Failers + var input0 = "xy"; + var results = null; + shouldBe("regex312.exec(input0);", "results"); + var input1 = "yz"; + var results = null; + shouldBe("regex312.exec(input1);", "results"); + var input2 = "xyz"; + var results = null; + shouldBe("regex312.exec(input2);", "results"); + + var regex313 = /\Ba\B/; + // Failers + var input0 = "a-"; + var results = null; + shouldBe("regex313.exec(input0);", "results"); + var input1 = "-a"; + var results = null; + shouldBe("regex313.exec(input1);", "results"); + var input2 = "-a-"; + var results = null; + shouldBe("regex313.exec(input2);", "results"); + + var regex314 = /\By\b/; + var input0 = "xy"; + var results = ["y"]; + shouldBe("regex314.exec(input0);", "results"); + + var regex315 = /\by\B/; + var input0 = "yz"; + var results = ["y"]; + shouldBe("regex315.exec(input0);", "results"); + + var regex316 = /\By\B/; + var input0 = "xyz"; + var results = ["y"]; + shouldBe("regex316.exec(input0);", "results"); + + var regex317 = /\w/; + var input0 = "a"; + var results = ["a"]; + shouldBe("regex317.exec(input0);", "results"); + + var regex318 = /\W/; + var input0 = "-"; + var results = ["-"]; + shouldBe("regex318.exec(input0);", "results"); + // Failers + var input1 = "-"; + var results = ["-"]; + shouldBe("regex318.exec(input1);", "results"); + var input2 = "a"; + var results = null; + shouldBe("regex318.exec(input2);", "results"); + + var regex319 = /a\sb/; + var input0 = "a b"; + var results = ["a b"]; + shouldBe("regex319.exec(input0);", "results"); + + var regex320 = /a\Sb/; + var input0 = "a-b"; + var results = ["a-b"]; + shouldBe("regex320.exec(input0);", "results"); + // Failers + var input1 = "a-b"; + var results = ["a-b"]; + shouldBe("regex320.exec(input1);", "results"); + var input2 = "a b"; + var results = null; + shouldBe("regex320.exec(input2);", "results"); + + var regex321 = /\d/; + var input0 = "1"; + var results = ["1"]; + shouldBe("regex321.exec(input0);", "results"); + + var regex322 = /\D/; + var input0 = "-"; + var results = ["-"]; + shouldBe("regex322.exec(input0);", "results"); + // Failers + var input1 = "-"; + var results = ["-"]; + shouldBe("regex322.exec(input1);", "results"); + var input2 = "1"; + var results = null; + shouldBe("regex322.exec(input2);", "results"); + + var regex323 = /[\w]/; + var input0 = "a"; + var results = ["a"]; + shouldBe("regex323.exec(input0);", "results"); + + var regex324 = /[\W]/; + var input0 = "-"; + var results = ["-"]; + shouldBe("regex324.exec(input0);", "results"); + // Failers + var input1 = "-"; + var results = ["-"]; + shouldBe("regex324.exec(input1);", "results"); + var input2 = "a"; + var results = null; + shouldBe("regex324.exec(input2);", "results"); + + var regex325 = /a[\s]b/; + var input0 = "a b"; + var results = ["a b"]; + shouldBe("regex325.exec(input0);", "results"); + + var regex326 = /a[\S]b/; + var input0 = "a-b"; + var results = ["a-b"]; + shouldBe("regex326.exec(input0);", "results"); + // Failers + var input1 = "a-b"; + var results = ["a-b"]; + shouldBe("regex326.exec(input1);", "results"); + var input2 = "a b"; + var results = null; + shouldBe("regex326.exec(input2);", "results"); + + var regex327 = /[\d]/; + var input0 = "1"; + var results = ["1"]; + shouldBe("regex327.exec(input0);", "results"); + + var regex328 = /[\D]/; + var input0 = "-"; + var results = ["-"]; + shouldBe("regex328.exec(input0);", "results"); + // Failers + var input1 = "-"; + var results = ["-"]; + shouldBe("regex328.exec(input1);", "results"); + var input2 = "1"; + var results = null; + shouldBe("regex328.exec(input2);", "results"); + + var regex329 = /ab|cd/; + var input0 = "abc"; + var results = ["ab"]; + shouldBe("regex329.exec(input0);", "results"); + var input1 = "abcd"; + var results = ["ab"]; + shouldBe("regex329.exec(input1);", "results"); + + var regex330 = /()ef/; + var input0 = "def"; + var results = ["ef", ""]; + shouldBe("regex330.exec(input0);", "results"); + + var regex331 = /a\(b/; + var input0 = "a(b"; + var results = ["a(b"]; + shouldBe("regex331.exec(input0);", "results"); + + var regex332 = /a\(*b/; + var input0 = "ab"; + var results = ["ab"]; + shouldBe("regex332.exec(input0);", "results"); + var input1 = "a((b"; + var results = ["a((b"]; + shouldBe("regex332.exec(input1);", "results"); + + var regex333 = /a\\b/; + var input0 = "a\b"; + var results = null; + shouldBe("regex333.exec(input0);", "results"); + + var regex334 = /((a))/; + var input0 = "abc"; + var results = ["a", "a", "a"]; + shouldBe("regex334.exec(input0);", "results"); + + var regex335 = /(a)b(c)/; + var input0 = "abc"; + var results = ["abc", "a", "c"]; + shouldBe("regex335.exec(input0);", "results"); + + var regex336 = /a+b+c/; + var input0 = "aabbabc"; + var results = ["abc"]; + shouldBe("regex336.exec(input0);", "results"); + + var regex337 = /a{1,}b{1,}c/; + var input0 = "aabbabc"; + var results = ["abc"]; + shouldBe("regex337.exec(input0);", "results"); + + var regex338 = /a.+?c/; + var input0 = "abcabc"; + var results = ["abc"]; + shouldBe("regex338.exec(input0);", "results"); + + var regex339 = /(a+|b)*/; + var input0 = "ab"; + var results = ["ab", "b"]; + shouldBe("regex339.exec(input0);", "results"); + + var regex340 = /(a+|b){0,}/; + var input0 = "ab"; + var results = ["ab", "b"]; + shouldBe("regex340.exec(input0);", "results"); + + var regex341 = /(a+|b)+/; + var input0 = "ab"; + var results = ["ab", "b"]; + shouldBe("regex341.exec(input0);", "results"); + + var regex342 = /(a+|b){1,}/; + var input0 = "ab"; + var results = ["ab", "b"]; + shouldBe("regex342.exec(input0);", "results"); + + var regex343 = /(a+|b)?/; + var input0 = "ab"; + var results = ["a", "a"]; + shouldBe("regex343.exec(input0);", "results"); + + var regex344 = /(a+|b){0,1}/; + var input0 = "ab"; + var results = ["a", "a"]; + shouldBe("regex344.exec(input0);", "results"); + + var regex345 = /[^ab]*/; + var input0 = "cde"; + var results = ["cde"]; + shouldBe("regex345.exec(input0);", "results"); + + var regex346 = /abc/; + // Failers + var input0 = "b"; + var results = null; + shouldBe("regex346.exec(input0);", "results"); + + var regex347 = /([abc])*d/; + var input0 = "abbbcd"; + var results = ["abbbcd", "c"]; + shouldBe("regex347.exec(input0);", "results"); + + var regex348 = /([abc])*bcd/; + var input0 = "abcd"; + var results = ["abcd", "a"]; + shouldBe("regex348.exec(input0);", "results"); + + var regex349 = /a|b|c|d|e/; + var input0 = "e"; + var results = ["e"]; + shouldBe("regex349.exec(input0);", "results"); + + var regex350 = /(a|b|c|d|e)f/; + var input0 = "ef"; + var results = ["ef", "e"]; + shouldBe("regex350.exec(input0);", "results"); + + var regex351 = /abcd*efg/; + var input0 = "abcdefg"; + var results = ["abcdefg"]; + shouldBe("regex351.exec(input0);", "results"); + + var regex352 = /ab*/; + var input0 = "xabyabbbz"; + var results = ["ab"]; + shouldBe("regex352.exec(input0);", "results"); + var input1 = "xayabbbz"; + var results = ["a"]; + shouldBe("regex352.exec(input1);", "results"); + + var regex353 = /(ab|cd)e/; + var input0 = "abcde"; + var results = ["cde", "cd"]; + shouldBe("regex353.exec(input0);", "results"); + + var regex354 = /[abhgefdc]ij/; + var input0 = "hij"; + var results = ["hij"]; + shouldBe("regex354.exec(input0);", "results"); + + var regex355 = /(abc|)ef/; + var input0 = "abcdef"; + var results = ["ef", ""]; + shouldBe("regex355.exec(input0);", "results"); + + var regex356 = /(a|b)c*d/; + var input0 = "abcd"; + var results = ["bcd", "b"]; + shouldBe("regex356.exec(input0);", "results"); + + var regex357 = /(ab|ab*)bc/; + var input0 = "abc"; + var results = ["abc", "a"]; + shouldBe("regex357.exec(input0);", "results"); + + var regex358 = /a([bc]*)c*/; + var input0 = "abc"; + var results = ["abc", "bc"]; + shouldBe("regex358.exec(input0);", "results"); + + var regex359 = /a([bc]*)(c*d)/; + var input0 = "abcd"; + var results = ["abcd", "bc", "d"]; + shouldBe("regex359.exec(input0);", "results"); + + var regex360 = /a([bc]+)(c*d)/; + var input0 = "abcd"; + var results = ["abcd", "bc", "d"]; + shouldBe("regex360.exec(input0);", "results"); + + var regex361 = /a([bc]*)(c+d)/; + var input0 = "abcd"; + var results = ["abcd", "b", "cd"]; + shouldBe("regex361.exec(input0);", "results"); + + var regex362 = /a[bcd]*dcdcde/; + var input0 = "adcdcde"; + var results = ["adcdcde"]; + shouldBe("regex362.exec(input0);", "results"); + + var regex363 = /a[bcd]+dcdcde/; + // Failers + var input0 = "abcde"; + var results = null; + shouldBe("regex363.exec(input0);", "results"); + var input1 = "adcdcde"; + var results = null; + shouldBe("regex363.exec(input1);", "results"); + + var regex364 = /(ab|a)b*c/; + var input0 = "abc"; + var results = ["abc", "ab"]; + shouldBe("regex364.exec(input0);", "results"); + + var regex365 = /((a)(b)c)(d)/; + var input0 = "abcd"; + var results = ["abcd", "abc", "a", "b", "d"]; + shouldBe("regex365.exec(input0);", "results"); + + var regex366 = /[a-zA-Z_][a-zA-Z0-9_]*/; + var input0 = "alpha"; + var results = ["alpha"]; + shouldBe("regex366.exec(input0);", "results"); + + var regex367 = /^a(bc+|b[eh])g|.h$/; + var input0 = "abh"; + var results = ["bh", undefined]; + shouldBe("regex367.exec(input0);", "results"); + + var regex368 = /(bc+d$|ef*g.|h?i(j|k))/; + var input0 = "effgz"; + var results = ["effgz", "effgz", undefined]; + shouldBe("regex368.exec(input0);", "results"); + var input1 = "ij"; + var results = ["ij", "ij", "j"]; + shouldBe("regex368.exec(input1);", "results"); + var input2 = "reffgz"; + var results = ["effgz", "effgz", undefined]; + shouldBe("regex368.exec(input2);", "results"); + // Failers + var input3 = "effg"; + var results = null; + shouldBe("regex368.exec(input3);", "results"); + var input4 = "bcdd"; + var results = null; + shouldBe("regex368.exec(input4);", "results"); + + var regex369 = /((((((((((a))))))))))/; + var input0 = "a"; + var results = ["a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a"]; + shouldBe("regex369.exec(input0);", "results"); + + var regex370 = /((((((((((a))))))))))\10/; + var input0 = "aa"; + var results = ["aa", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a"]; + shouldBe("regex370.exec(input0);", "results"); + + var regex371 = /(((((((((a)))))))))/; + var input0 = "a"; + var results = ["a", "a", "a", "a", "a", "a", "a", "a", "a", "a"]; + shouldBe("regex371.exec(input0);", "results"); + + var regex372 = /multiple words of text/; + // Failers + var input0 = "aa"; + var results = null; + shouldBe("regex372.exec(input0);", "results"); + var input1 = "uh-uh"; + var results = null; + shouldBe("regex372.exec(input1);", "results"); + + var regex373 = /multiple words/; + var input0 = "multiple words, yeah"; + var results = ["multiple words"]; + shouldBe("regex373.exec(input0);", "results"); + + var regex374 = /(.*)c(.*)/; + var input0 = "abcde"; + var results = ["abcde", "ab", "de"]; + shouldBe("regex374.exec(input0);", "results"); + + var regex375 = /\((.*), (.*)\)/; + var input0 = "(a, b)"; + var results = ["(a, b)", "a", "b"]; + shouldBe("regex375.exec(input0);", "results"); + + var regex376 = /abcd/; + var input0 = "abcd"; + var results = ["abcd"]; + shouldBe("regex376.exec(input0);", "results"); + + var regex377 = /a(bc)d/; + var input0 = "abcd"; + var results = ["abcd", "bc"]; + shouldBe("regex377.exec(input0);", "results"); + + var regex378 = /a[-]?c/; + var input0 = "ac"; + var results = ["ac"]; + shouldBe("regex378.exec(input0);", "results"); + + var regex379 = /(abc)\1/; + var input0 = "abcabc"; + var results = ["abcabc", "abc"]; + shouldBe("regex379.exec(input0);", "results"); + + var regex380 = /([a-c]*)\1/; + var input0 = "abcabc"; + var results = ["abcabc", "abc"]; + shouldBe("regex380.exec(input0);", "results"); + + var regex381 = /(a)|\1/; + var input0 = "a"; + var results = ["a", "a"]; + shouldBe("regex381.exec(input0);", "results"); + var input1 = "ab"; + var results = ["a", "a"]; + shouldBe("regex381.exec(input1);", "results"); + var input2 = "x"; + var results = ["", undefined]; + shouldBe("regex381.exec(input2);", "results"); + + var regex382 = /(([a-c])b*?\2)*/; + var input0 = "ababbbcbc"; + var results = ["ababb", "bb", "b"]; + shouldBe("regex382.exec(input0);", "results"); + + var regex383 = /(([a-c])b*?\2){3}/; + var input0 = "ababbbcbc"; + var results = ["ababbbcbc", "cbc", "c"]; + shouldBe("regex383.exec(input0);", "results"); + + var regex384 = /((\3|b)\2(a)x)+/; + var input0 = "aaaxabaxbaaxbbax"; + var results = ["ax", "ax", "", "a"]; + shouldBe("regex384.exec(input0);", "results"); + + var regex385 = /((\3|b)\2(a)){2,}/; + var input0 = "bbaababbabaaaaabbaaaabba"; + var results = ["bbaa", "a", "", "a"]; + shouldBe("regex385.exec(input0);", "results"); + + var regex386 = /abc/i; + var input0 = "ABC"; + var results = ["ABC"]; + shouldBe("regex386.exec(input0);", "results"); + var input1 = "XABCY"; + var results = ["ABC"]; + shouldBe("regex386.exec(input1);", "results"); + var input2 = "ABABC"; + var results = ["ABC"]; + shouldBe("regex386.exec(input2);", "results"); + // Failers + var input3 = "aaxabxbaxbbx"; + var results = null; + shouldBe("regex386.exec(input3);", "results"); + var input4 = "XBC"; + var results = null; + shouldBe("regex386.exec(input4);", "results"); + var input5 = "AXC"; + var results = null; + shouldBe("regex386.exec(input5);", "results"); + var input6 = "ABX"; + var results = null; + shouldBe("regex386.exec(input6);", "results"); + + var regex387 = /ab*c/i; + var input0 = "ABC"; + var results = ["ABC"]; + shouldBe("regex387.exec(input0);", "results"); + + var regex388 = /ab*bc/i; + var input0 = "ABC"; + var results = ["ABC"]; + shouldBe("regex388.exec(input0);", "results"); + var input1 = "ABBC"; + var results = ["ABBC"]; + shouldBe("regex388.exec(input1);", "results"); + + var regex389 = /ab*?bc/i; + var input0 = "ABBBBC"; + var results = ["ABBBBC"]; + shouldBe("regex389.exec(input0);", "results"); + + var regex390 = /ab{0,}?bc/i; + var input0 = "ABBBBC"; + var results = ["ABBBBC"]; + shouldBe("regex390.exec(input0);", "results"); + + var regex391 = /ab+?bc/i; + var input0 = "ABBC"; + var results = ["ABBC"]; + shouldBe("regex391.exec(input0);", "results"); + + var regex392 = /ab+bc/i; + // Failers + var input0 = "ABC"; + var results = null; + shouldBe("regex392.exec(input0);", "results"); + var input1 = "ABQ"; + var results = null; + shouldBe("regex392.exec(input1);", "results"); + + var regex393 = /ab+bc/i; + var input0 = "ABBBBC"; + var results = ["ABBBBC"]; + shouldBe("regex393.exec(input0);", "results"); + + var regex394 = /ab{1,}?bc/i; + var input0 = "ABBBBC"; + var results = ["ABBBBC"]; + shouldBe("regex394.exec(input0);", "results"); + + var regex395 = /ab{1,3}?bc/i; + var input0 = "ABBBBC"; + var results = ["ABBBBC"]; + shouldBe("regex395.exec(input0);", "results"); + + var regex396 = /ab{3,4}?bc/i; + var input0 = "ABBBBC"; + var results = ["ABBBBC"]; + shouldBe("regex396.exec(input0);", "results"); + + var regex397 = /ab{4,5}?bc/i; + // Failers + var input0 = "ABQ"; + var results = null; + shouldBe("regex397.exec(input0);", "results"); + var input1 = "ABBBBC"; + var results = null; + shouldBe("regex397.exec(input1);", "results"); + + var regex398 = /ab??bc/i; + var input0 = "ABBC"; + var results = ["ABBC"]; + shouldBe("regex398.exec(input0);", "results"); + var input1 = "ABC"; + var results = ["ABC"]; + shouldBe("regex398.exec(input1);", "results"); + + var regex399 = /ab{0,1}?bc/i; + var input0 = "ABC"; + var results = ["ABC"]; + shouldBe("regex399.exec(input0);", "results"); + + var regex400 = /ab??c/i; + var input0 = "ABC"; + var results = ["ABC"]; + shouldBe("regex400.exec(input0);", "results"); + + var regex401 = /ab{0,1}?c/i; + var input0 = "ABC"; + var results = ["ABC"]; + shouldBe("regex401.exec(input0);", "results"); + + var regex402 = /^abc$/i; + var input0 = "ABC"; + var results = ["ABC"]; + shouldBe("regex402.exec(input0);", "results"); + // Failers + var input1 = "ABBBBC"; + var results = null; + shouldBe("regex402.exec(input1);", "results"); + var input2 = "ABCC"; + var results = null; + shouldBe("regex402.exec(input2);", "results"); + + var regex403 = /^abc/i; + var input0 = "ABCC"; + var results = ["ABC"]; + shouldBe("regex403.exec(input0);", "results"); + + var regex404 = /abc$/i; + var input0 = "AABC"; + var results = ["ABC"]; + shouldBe("regex404.exec(input0);", "results"); + + var regex405 = /^/i; + var input0 = "ABC"; + var results = [""]; + shouldBe("regex405.exec(input0);", "results"); + + var regex406 = /$/i; + var input0 = "ABC"; + var results = [""]; + shouldBe("regex406.exec(input0);", "results"); + + var regex407 = /a.c/i; + var input0 = "ABC"; + var results = ["ABC"]; + shouldBe("regex407.exec(input0);", "results"); + var input1 = "AXC"; + var results = ["AXC"]; + shouldBe("regex407.exec(input1);", "results"); + + var regex408 = /a.*?c/i; + var input0 = "AXYZC"; + var results = ["AXYZC"]; + shouldBe("regex408.exec(input0);", "results"); + + var regex409 = /a.*c/i; + // Failers + var input0 = "AABC"; + var results = ["AABC"]; + shouldBe("regex409.exec(input0);", "results"); + var input1 = "AXYZD"; + var results = null; + shouldBe("regex409.exec(input1);", "results"); + + var regex410 = /a[bc]d/i; + var input0 = "ABD"; + var results = ["ABD"]; + shouldBe("regex410.exec(input0);", "results"); + + var regex411 = /a[b-d]e/i; + var input0 = "ACE"; + var results = ["ACE"]; + shouldBe("regex411.exec(input0);", "results"); + // Failers + var input1 = "ABC"; + var results = null; + shouldBe("regex411.exec(input1);", "results"); + var input2 = "ABD"; + var results = null; + shouldBe("regex411.exec(input2);", "results"); + + var regex412 = /a[b-d]/i; + var input0 = "AAC"; + var results = ["AC"]; + shouldBe("regex412.exec(input0);", "results"); + + var regex413 = /a[-b]/i; + var input0 = "A-"; + var results = ["A-"]; + shouldBe("regex413.exec(input0);", "results"); + + var regex414 = /a[b-]/i; + var input0 = "A-"; + var results = ["A-"]; + shouldBe("regex414.exec(input0);", "results"); + + var regex415 = /a]/i; + var input0 = "A]"; + var results = ["A]"]; + shouldBe("regex415.exec(input0);", "results"); + + var regex416 = /a[\]]b/i; + var input0 = "A]B"; + var results = ["A]B"]; + shouldBe("regex416.exec(input0);", "results"); + + var regex417 = /a[^bc]d/i; + var input0 = "AED"; + var results = ["AED"]; + shouldBe("regex417.exec(input0);", "results"); + + var regex418 = /a[^-b]c/i; + var input0 = "ADC"; + var results = ["ADC"]; + shouldBe("regex418.exec(input0);", "results"); + // Failers + var input1 = "ABD"; + var results = null; + shouldBe("regex418.exec(input1);", "results"); + var input2 = "A-C"; + var results = null; + shouldBe("regex418.exec(input2);", "results"); + + var regex419 = /a[^\]b]c/i; + var input0 = "ADC"; + var results = ["ADC"]; + shouldBe("regex419.exec(input0);", "results"); + + var regex420 = /ab|cd/i; + var input0 = "ABC"; + var results = ["AB"]; + shouldBe("regex420.exec(input0);", "results"); + var input1 = "ABCD"; + var results = ["AB"]; + shouldBe("regex420.exec(input1);", "results"); + + var regex421 = /()ef/i; + var input0 = "DEF"; + var results = ["EF", ""]; + shouldBe("regex421.exec(input0);", "results"); + + var regex422 = /$b/i; + // Failers + var input0 = "A]C"; + var results = null; + shouldBe("regex422.exec(input0);", "results"); + var input1 = "B"; + var results = null; + shouldBe("regex422.exec(input1);", "results"); + + var regex423 = /a\(b/i; + var input0 = "A(B"; + var results = ["A(B"]; + shouldBe("regex423.exec(input0);", "results"); + + var regex424 = /a\(*b/i; + var input0 = "AB"; + var results = ["AB"]; + shouldBe("regex424.exec(input0);", "results"); + var input1 = "A((B"; + var results = ["A((B"]; + shouldBe("regex424.exec(input1);", "results"); + + var regex425 = /a\\b/i; + var input0 = "A\B"; + var results = null; + shouldBe("regex425.exec(input0);", "results"); + + var regex426 = /((a))/i; + var input0 = "ABC"; + var results = ["A", "A", "A"]; + shouldBe("regex426.exec(input0);", "results"); + + var regex427 = /(a)b(c)/i; + var input0 = "ABC"; + var results = ["ABC", "A", "C"]; + shouldBe("regex427.exec(input0);", "results"); + + var regex428 = /a+b+c/i; + var input0 = "AABBABC"; + var results = ["ABC"]; + shouldBe("regex428.exec(input0);", "results"); + + var regex429 = /a{1,}b{1,}c/i; + var input0 = "AABBABC"; + var results = ["ABC"]; + shouldBe("regex429.exec(input0);", "results"); + + var regex430 = /a.+?c/i; + var input0 = "ABCABC"; + var results = ["ABC"]; + shouldBe("regex430.exec(input0);", "results"); + + var regex431 = /a.*?c/i; + var input0 = "ABCABC"; + var results = ["ABC"]; + shouldBe("regex431.exec(input0);", "results"); + + var regex432 = /a.{0,5}?c/i; + var input0 = "ABCABC"; + var results = ["ABC"]; + shouldBe("regex432.exec(input0);", "results"); + + var regex433 = /(a+|b)*/i; + var input0 = "AB"; + var results = ["AB", "B"]; + shouldBe("regex433.exec(input0);", "results"); + + var regex434 = /(a+|b){0,}/i; + var input0 = "AB"; + var results = ["AB", "B"]; + shouldBe("regex434.exec(input0);", "results"); + + var regex435 = /(a+|b)+/i; + var input0 = "AB"; + var results = ["AB", "B"]; + shouldBe("regex435.exec(input0);", "results"); + + var regex436 = /(a+|b){1,}/i; + var input0 = "AB"; + var results = ["AB", "B"]; + shouldBe("regex436.exec(input0);", "results"); + + var regex437 = /(a+|b)?/i; + var input0 = "AB"; + var results = ["A", "A"]; + shouldBe("regex437.exec(input0);", "results"); + + var regex438 = /(a+|b){0,1}/i; + var input0 = "AB"; + var results = ["A", "A"]; + shouldBe("regex438.exec(input0);", "results"); + + var regex439 = /(a+|b){0,1}?/i; + var input0 = "AB"; + var results = ["", undefined]; + shouldBe("regex439.exec(input0);", "results"); + + var regex440 = /[^ab]*/i; + var input0 = "CDE"; + var results = ["CDE"]; + shouldBe("regex440.exec(input0);", "results"); + + var regex441 = /([abc])*d/i; + var input0 = "ABBBCD"; + var results = ["ABBBCD", "C"]; + shouldBe("regex441.exec(input0);", "results"); + + var regex442 = /([abc])*bcd/i; + var input0 = "ABCD"; + var results = ["ABCD", "A"]; + shouldBe("regex442.exec(input0);", "results"); + + var regex443 = /a|b|c|d|e/i; + var input0 = "E"; + var results = ["E"]; + shouldBe("regex443.exec(input0);", "results"); + + var regex444 = /(a|b|c|d|e)f/i; + var input0 = "EF"; + var results = ["EF", "E"]; + shouldBe("regex444.exec(input0);", "results"); + + var regex445 = /abcd*efg/i; + var input0 = "ABCDEFG"; + var results = ["ABCDEFG"]; + shouldBe("regex445.exec(input0);", "results"); + + var regex446 = /ab*/i; + var input0 = "XABYABBBZ"; + var results = ["AB"]; + shouldBe("regex446.exec(input0);", "results"); + var input1 = "XAYABBBZ"; + var results = ["A"]; + shouldBe("regex446.exec(input1);", "results"); + + var regex447 = /(ab|cd)e/i; + var input0 = "ABCDE"; + var results = ["CDE", "CD"]; + shouldBe("regex447.exec(input0);", "results"); + + var regex448 = /[abhgefdc]ij/i; + var input0 = "HIJ"; + var results = ["HIJ"]; + shouldBe("regex448.exec(input0);", "results"); + + var regex449 = /^(ab|cd)e/i; + var input0 = "ABCDE"; + var results = null; + shouldBe("regex449.exec(input0);", "results"); + + var regex450 = /(abc|)ef/i; + var input0 = "ABCDEF"; + var results = ["EF", ""]; + shouldBe("regex450.exec(input0);", "results"); + + var regex451 = /(a|b)c*d/i; + var input0 = "ABCD"; + var results = ["BCD", "B"]; + shouldBe("regex451.exec(input0);", "results"); + + var regex452 = /(ab|ab*)bc/i; + var input0 = "ABC"; + var results = ["ABC", "A"]; + shouldBe("regex452.exec(input0);", "results"); + + var regex453 = /a([bc]*)c*/i; + var input0 = "ABC"; + var results = ["ABC", "BC"]; + shouldBe("regex453.exec(input0);", "results"); + + var regex454 = /a([bc]*)(c*d)/i; + var input0 = "ABCD"; + var results = ["ABCD", "BC", "D"]; + shouldBe("regex454.exec(input0);", "results"); + + var regex455 = /a([bc]+)(c*d)/i; + var input0 = "ABCD"; + var results = ["ABCD", "BC", "D"]; + shouldBe("regex455.exec(input0);", "results"); + + var regex456 = /a([bc]*)(c+d)/i; + var input0 = "ABCD"; + var results = ["ABCD", "B", "CD"]; + shouldBe("regex456.exec(input0);", "results"); + + var regex457 = /a[bcd]*dcdcde/i; + var input0 = "ADCDCDE"; + var results = ["ADCDCDE"]; + shouldBe("regex457.exec(input0);", "results"); + + var regex458 = /(ab|a)b*c/i; + var input0 = "ABC"; + var results = ["ABC", "AB"]; + shouldBe("regex458.exec(input0);", "results"); + + var regex459 = /((a)(b)c)(d)/i; + var input0 = "ABCD"; + var results = ["ABCD", "ABC", "A", "B", "D"]; + shouldBe("regex459.exec(input0);", "results"); + + var regex460 = /[a-zA-Z_][a-zA-Z0-9_]*/i; + var input0 = "ALPHA"; + var results = ["ALPHA"]; + shouldBe("regex460.exec(input0);", "results"); + + var regex461 = /^a(bc+|b[eh])g|.h$/i; + var input0 = "ABH"; + var results = ["BH", undefined]; + shouldBe("regex461.exec(input0);", "results"); + + var regex462 = /(bc+d$|ef*g.|h?i(j|k))/i; + var input0 = "EFFGZ"; + var results = ["EFFGZ", "EFFGZ", undefined]; + shouldBe("regex462.exec(input0);", "results"); + var input1 = "IJ"; + var results = ["IJ", "IJ", "J"]; + shouldBe("regex462.exec(input1);", "results"); + var input2 = "REFFGZ"; + var results = ["EFFGZ", "EFFGZ", undefined]; + shouldBe("regex462.exec(input2);", "results"); + // Failers + var input3 = "ADCDCDE"; + var results = null; + shouldBe("regex462.exec(input3);", "results"); + var input4 = "EFFG"; + var results = null; + shouldBe("regex462.exec(input4);", "results"); + var input5 = "BCDD"; + var results = null; + shouldBe("regex462.exec(input5);", "results"); + + var regex463 = /((((((((((a))))))))))/i; + var input0 = "A"; + var results = ["A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A"]; + shouldBe("regex463.exec(input0);", "results"); + + var regex464 = /((((((((((a))))))))))\10/i; + var input0 = "AA"; + var results = ["AA", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A"]; + shouldBe("regex464.exec(input0);", "results"); + + var regex465 = /(((((((((a)))))))))/i; + var input0 = "A"; + var results = ["A", "A", "A", "A", "A", "A", "A", "A", "A", "A"]; + shouldBe("regex465.exec(input0);", "results"); + + var regex466 = /(?:(?:(?:(?:(?:(?:(?:(?:(?:(a))))))))))/i; + var input0 = "A"; + var results = ["A", "A"]; + shouldBe("regex466.exec(input0);", "results"); + + var regex467 = /(?:(?:(?:(?:(?:(?:(?:(?:(?:(a|b|c))))))))))/i; + var input0 = "C"; + var results = ["C", "C"]; + shouldBe("regex467.exec(input0);", "results"); + + var regex468 = /multiple words of text/i; + // Failers + var input0 = "AA"; + var results = null; + shouldBe("regex468.exec(input0);", "results"); + var input1 = "UH-UH"; + var results = null; + shouldBe("regex468.exec(input1);", "results"); + + var regex469 = /multiple words/i; + var input0 = "MULTIPLE WORDS, YEAH"; + var results = ["MULTIPLE WORDS"]; + shouldBe("regex469.exec(input0);", "results"); + + var regex470 = /(.*)c(.*)/i; + var input0 = "ABCDE"; + var results = ["ABCDE", "AB", "DE"]; + shouldBe("regex470.exec(input0);", "results"); + + var regex471 = /\((.*), (.*)\)/i; + var input0 = "(A, B)"; + var results = ["(A, B)", "A", "B"]; + shouldBe("regex471.exec(input0);", "results"); + + var regex472 = /abcd/i; + var input0 = "ABCD"; + var results = ["ABCD"]; + shouldBe("regex472.exec(input0);", "results"); + + var regex473 = /a(bc)d/i; + var input0 = "ABCD"; + var results = ["ABCD", "BC"]; + shouldBe("regex473.exec(input0);", "results"); + + var regex474 = /a[-]?c/i; + var input0 = "AC"; + var results = ["AC"]; + shouldBe("regex474.exec(input0);", "results"); + + var regex475 = /(abc)\1/i; + var input0 = "ABCABC"; + var results = ["ABCABC", "ABC"]; + shouldBe("regex475.exec(input0);", "results"); + + var regex476 = /([a-c]*)\1/i; + var input0 = "ABCABC"; + var results = ["ABCABC", "ABC"]; + shouldBe("regex476.exec(input0);", "results"); + + var regex477 = /a(?!b)./; + var input0 = "abad"; + var results = ["ad"]; + shouldBe("regex477.exec(input0);", "results"); + + var regex478 = /a(?=d)./; + var input0 = "abad"; + var results = ["ad"]; + shouldBe("regex478.exec(input0);", "results"); + + var regex479 = /a(?=c|d)./; + var input0 = "abad"; + var results = ["ad"]; + shouldBe("regex479.exec(input0);", "results"); + + var regex480 = /a(?:b|c|d)(.)/; + var input0 = "ace"; + var results = ["ace", "e"]; + shouldBe("regex480.exec(input0);", "results"); + + var regex481 = /a(?:b|c|d)*(.)/; + var input0 = "ace"; + var results = ["ace", "e"]; + shouldBe("regex481.exec(input0);", "results"); + + var regex482 = /a(?:b|c|d)+?(.)/; + var input0 = "ace"; + var results = ["ace", "e"]; + shouldBe("regex482.exec(input0);", "results"); + var input1 = "acdbcdbe"; + var results = ["acd", "d"]; + shouldBe("regex482.exec(input1);", "results"); + + var regex483 = /a(?:b|c|d)+(.)/; + var input0 = "acdbcdbe"; + var results = ["acdbcdbe", "e"]; + shouldBe("regex483.exec(input0);", "results"); + + var regex484 = /a(?:b|c|d){2}(.)/; + var input0 = "acdbcdbe"; + var results = ["acdb", "b"]; + shouldBe("regex484.exec(input0);", "results"); + + var regex485 = /a(?:b|c|d){4,5}(.)/; + var input0 = "acdbcdbe"; + var results = ["acdbcdb", "b"]; + shouldBe("regex485.exec(input0);", "results"); + + var regex486 = /a(?:b|c|d){4,5}?(.)/; + var input0 = "acdbcdbe"; + var results = ["acdbcd", "d"]; + shouldBe("regex486.exec(input0);", "results"); + + var regex487 = /((foo)|(bar))*/; + var input0 = "foobar"; + var results = ["foobar", "bar", undefined, "bar"]; + shouldBe("regex487.exec(input0);", "results"); + + var regex488 = /a(?:b|c|d){6,7}(.)/; + var input0 = "acdbcdbe"; + var results = ["acdbcdbe", "e"]; + shouldBe("regex488.exec(input0);", "results"); + + var regex489 = /a(?:b|c|d){6,7}?(.)/; + var input0 = "acdbcdbe"; + var results = ["acdbcdbe", "e"]; + shouldBe("regex489.exec(input0);", "results"); + + var regex490 = /a(?:b|c|d){5,6}(.)/; + var input0 = "acdbcdbe"; + var results = ["acdbcdbe", "e"]; + shouldBe("regex490.exec(input0);", "results"); + + var regex491 = /a(?:b|c|d){5,6}?(.)/; + var input0 = "acdbcdbe"; + var results = ["acdbcdb", "b"]; + shouldBe("regex491.exec(input0);", "results"); + + var regex492 = /a(?:b|c|d){5,7}(.)/; + var input0 = "acdbcdbe"; + var results = ["acdbcdbe", "e"]; + shouldBe("regex492.exec(input0);", "results"); + + var regex493 = /a(?:b|c|d){5,7}?(.)/; + var input0 = "acdbcdbe"; + var results = ["acdbcdb", "b"]; + shouldBe("regex493.exec(input0);", "results"); + + var regex494 = /a(?:b|(c|e){1,2}?|d)+?(.)/; + var input0 = "ace"; + var results = ["ace", "c", "e"]; + shouldBe("regex494.exec(input0);", "results"); + + var regex495 = /^(.+)?B/; + var input0 = "AB"; + var results = ["AB", "A"]; + shouldBe("regex495.exec(input0);", "results"); + + var regex496 = /^([^a-z])|(\^)$/; + var input0 = "."; + var results = [".", ".", undefined]; + shouldBe("regex496.exec(input0);", "results"); + + var regex497 = /^[<>]&/; + var input0 = "<&OUT"; + var results = ["<&"]; + shouldBe("regex497.exec(input0);", "results"); + + var regex498 = /^(a\1?){4}$/; + var input0 = "aaaaaaaaaa"; + var results = null; + shouldBe("regex498.exec(input0);", "results"); + // Failers + var input1 = "AB"; + var results = null; + shouldBe("regex498.exec(input1);", "results"); + var input2 = "aaaaaaaaa"; + var results = null; + shouldBe("regex498.exec(input2);", "results"); + var input3 = "aaaaaaaaaaa"; + var results = null; + shouldBe("regex498.exec(input3);", "results"); + + var regex499 = /^(a(?:\1)){4}$/; + var input0 = "aaaa"; + var results = ["aaaa", "a"]; + shouldBe("regex499.exec(input0);", "results"); + // Failers + var input1 = "aaaaaaaaa"; + var results = null; + shouldBe("regex499.exec(input1);", "results"); + var input2 = "aaaaaaaaaaa"; + var results = null; + shouldBe("regex499.exec(input2);", "results"); + var input3 = "aaaaaaaaaa"; + var results = null; + shouldBe("regex499.exec(input3);", "results"); + + var regex500 = /(?:(f)(o)(o)|(b)(a)(r))*/; + var input0 = "foobar"; + var results = ["foobar", undefined, undefined, undefined, "b", "a", "r"]; + shouldBe("regex500.exec(input0);", "results"); + + var regex503 = /(?:..)*a/; + var input0 = "aba"; + var results = ["aba"]; + shouldBe("regex503.exec(input0);", "results"); + + var regex504 = /(?:..)*?a/; + var input0 = "aba"; + var results = ["a"]; + shouldBe("regex504.exec(input0);", "results"); + + var regex505 = /^(?:b|a(?=(.)))*\1/; + var input0 = "abc"; + var results = ["ab", undefined]; + shouldBe("regex505.exec(input0);", "results"); + + var regex506 = /^(){3,5}/; + var input0 = "abc"; + var results = ["", ""]; + shouldBe("regex506.exec(input0);", "results"); + + var regex507 = /^(a+)*ax/; + var input0 = "aax"; + var results = ["aax", "a"]; + shouldBe("regex507.exec(input0);", "results"); + + var regex508 = /^((a|b)+)*ax/; + var input0 = "aax"; + var results = ["aax", "a", "a"]; + shouldBe("regex508.exec(input0);", "results"); + + var regex509 = /^((a|bc)+)*ax/; + var input0 = "aax"; + var results = ["aax", "a", "a"]; + shouldBe("regex509.exec(input0);", "results"); + + var regex510 = /(a|x)*ab/; + var input0 = "cab"; + var results = ["ab", undefined]; + shouldBe("regex510.exec(input0);", "results"); + + var regex511 = /(a)*ab/; + var input0 = "cab"; + var results = ["ab", undefined]; + shouldBe("regex511.exec(input0);", "results"); + + var regex512 = /(?:a)b/; + var input0 = "ab"; + var results = ["ab"]; + shouldBe("regex512.exec(input0);", "results"); + + var regex513 = /(a)b/; + var input0 = "ab"; + var results = ["ab", "a"]; + shouldBe("regex513.exec(input0);", "results"); + + var regex514 = /(?:a)b/i; + var input0 = "Ab"; + var results = ["Ab"]; + shouldBe("regex514.exec(input0);", "results"); + + var regex515 = /(a)b/i; + var input0 = "Ab"; + var results = ["Ab", "A"]; + shouldBe("regex515.exec(input0);", "results"); + + var regex516 = /(?:[aA])b/; + // Failers + var input0 = "cb"; + var results = null; + shouldBe("regex516.exec(input0);", "results"); + var input1 = "aB"; + var results = null; + shouldBe("regex516.exec(input1);", "results"); + + var regex517 = /(?:a)b/; + var input0 = "ab"; + var results = ["ab"]; + shouldBe("regex517.exec(input0);", "results"); + + var regex518 = /((?:a))b/; + var input0 = "ab"; + var results = ["ab", "a"]; + shouldBe("regex518.exec(input0);", "results"); + + var regex519 = /(?:a)b/i; + var input0 = "Ab"; + var results = ["Ab"]; + shouldBe("regex519.exec(input0);", "results"); + + var regex520 = /((?:a))b/i; + var input0 = "Ab"; + var results = ["Ab", "A"]; + shouldBe("regex520.exec(input0);", "results"); + + var regex521 = /(?:a)b/; + // Failers + var input0 = "aB"; + var results = null; + shouldBe("regex521.exec(input0);", "results"); + var input1 = "aB"; + var results = null; + shouldBe("regex521.exec(input1);", "results"); + + var regex522 = /(?:a)b/i; + var input0 = "ab"; + var results = ["ab"]; + shouldBe("regex522.exec(input0);", "results"); + + var regex523 = /(a)b/i; + var input0 = "ab"; + var results = ["ab", "a"]; + shouldBe("regex523.exec(input0);", "results"); + + var regex524 = /(?:a)b/i; + var input0 = "aB"; + var results = ["aB"]; + shouldBe("regex524.exec(input0);", "results"); + + var regex525 = /(a)b/i; + var input0 = "aB"; + var results = ["aB", "a"]; + shouldBe("regex525.exec(input0);", "results"); + + var regex526 = /(?:a)[bB]/; + // Failers + var input0 = "aB"; + var results = ["aB"]; + shouldBe("regex526.exec(input0);", "results"); + var input1 = "Ab"; + var results = null; + shouldBe("regex526.exec(input1);", "results"); + + var regex527 = /(?:a)b/i; + var input0 = "aB"; + var results = ["aB"]; + shouldBe("regex527.exec(input0);", "results"); + + var regex528 = /(a)b/i; + var input0 = "aB"; + var results = ["aB", "a"]; + shouldBe("regex528.exec(input0);", "results"); + + var regex529 = /(?:a)[bB]/; + // Failers + var input0 = "Ab"; + var results = null; + shouldBe("regex529.exec(input0);", "results"); + var input1 = "AB"; + var results = null; + shouldBe("regex529.exec(input1);", "results"); + + var regex530 = /(?:a)b/; + var input0 = "ab"; + var results = ["ab"]; + shouldBe("regex530.exec(input0);", "results"); + + var regex531 = /((?:a))b/i; + var input0 = "ab"; + var results = ["ab", "a"]; + shouldBe("regex531.exec(input0);", "results"); + + var regex532 = /(?:a)b/i; + var input0 = "aB"; + var results = ["aB"]; + shouldBe("regex532.exec(input0);", "results"); + + var regex533 = /((?:a))b/i; + var input0 = "aB"; + var results = ["aB", "a"]; + shouldBe("regex533.exec(input0);", "results"); + + var regex534 = /(?:a)[bB]/; + // Failers + var input0 = "AB"; + var results = null; + shouldBe("regex534.exec(input0);", "results"); + var input1 = "Ab"; + var results = null; + shouldBe("regex534.exec(input1);", "results"); + + var regex535 = /(?:a)b/i; + var input0 = "aB"; + var results = ["aB"]; + shouldBe("regex535.exec(input0);", "results"); + + var regex536 = /((?:a))b/i; + var input0 = "aB"; + var results = ["aB", "a"]; + shouldBe("regex536.exec(input0);", "results"); + + var regex537 = /(?:a)[bB]/; + // Failers + var input0 = "Ab"; + var results = null; + shouldBe("regex537.exec(input0);", "results"); + var input1 = "AB"; + var results = null; + shouldBe("regex537.exec(input1);", "results"); + + var regex538 = /((?:a.))b/i; + // Failers + var input0 = "AB"; + var results = null; + shouldBe("regex538.exec(input0);", "results"); + var input1 = "a\nB"; + var results = null; + shouldBe("regex538.exec(input1);", "results"); + + var regex539 = /((?:a[\w\W]))b/i; + var input0 = "a\nB"; + var results = ["a\x0aB", "a\x0a"]; + shouldBe("regex539.exec(input0);", "results"); + + var regex540 = /(?:c|d)(?:)(?:a(?:)(?:b)(?:b(?:))(?:b(?:)(?:b)))/; + var input0 = "cabbbb"; + var results = ["cabbbb"]; + shouldBe("regex540.exec(input0);", "results"); + + var regex541 = /(?:c|d)(?:)(?:aaaaaaaa(?:)(?:bbbbbbbb)(?:bbbbbbbb(?:))(?:bbbbbbbb(?:)(?:bbbbbbbb)))/; + var input0 = "caaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"; + var results = ["caaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"]; + shouldBe("regex541.exec(input0);", "results"); + + var regex542 = /(ab)\d\1/i; + var input0 = "Ab4ab"; + var results = ["Ab4ab", "Ab"]; + shouldBe("regex542.exec(input0);", "results"); + var input1 = "ab4Ab"; + var results = ["ab4Ab", "ab"]; + shouldBe("regex542.exec(input1);", "results"); + + var regex543 = /foo\w*\d{4}baz/; + var input0 = "foobar1234baz"; + var results = ["foobar1234baz"]; + shouldBe("regex543.exec(input0);", "results"); + + var regex544 = /x(~~)*(?:(?:F)?)?/; + var input0 = "x~~"; + var results = ["x~~", "~~"]; + shouldBe("regex544.exec(input0);", "results"); + + var regex545 = /^a{3}c/; + var input0 = "aaac"; + var results = ["aaac"]; + shouldBe("regex545.exec(input0);", "results"); + + var regex550 = /^(?:a?b?)*$/; + var input0 = ""; + var results = [""]; + shouldBe("regex550.exec(input0);", "results"); + var input1 = "a"; + var results = ["a"]; + shouldBe("regex550.exec(input1);", "results"); + var input2 = "ab"; + var results = ["ab"]; + shouldBe("regex550.exec(input2);", "results"); + var input3 = "aaa"; + var results = ["aaa"]; + shouldBe("regex550.exec(input3);", "results"); + // Failers + var input4 = "dbcb"; + var results = null; + shouldBe("regex550.exec(input4);", "results"); + var input5 = "a--"; + var results = null; + shouldBe("regex550.exec(input5);", "results"); + var input6 = "aa--"; + var results = null; + shouldBe("regex550.exec(input6);", "results"); + + var regex551 = /(^a([\w\W]))(^b$)/m; + var input0 = "a\nb\nc\n"; + var results = ["a\x0ab", "a\x0a", "\x0a", "b"]; + shouldBe("regex551.exec(input0);", "results"); + + var regex552 = /(^b$)/m; + var input0 = "a\nb\nc\n"; + var results = ["b", "b"]; + shouldBe("regex552.exec(input0);", "results"); + + var regex553 = /^b/m; + var input0 = "a\nb\n"; + var results = ["b"]; + shouldBe("regex553.exec(input0);", "results"); + + var regex554 = /^(b)/m; + var input0 = "a\nb\n"; + var results = ["b", "b"]; + shouldBe("regex554.exec(input0);", "results"); + + var regex555 = /(^b)/m; + var input0 = "a\nb\n"; + var results = ["b", "b"]; + shouldBe("regex555.exec(input0);", "results"); + + var regex556 = /\n(^b)/m; + var input0 = "a\nb\n"; + var results = ["\x0ab", "b"]; + shouldBe("regex556.exec(input0);", "results"); + + var regex557 = /([\w\W])c(?!.)/m; + var input0 = "a\nb\nc\n"; + var results = ["\x0ac", "\x0a"]; + shouldBe("regex557.exec(input0);", "results"); + var input1 = "a\nb\nc\n"; + var results = ["\x0ac", "\x0a"]; + shouldBe("regex557.exec(input1);", "results"); + + var regex558 = /(b[\w\W])c(?!.)/m; + var input0 = "a\nb\nc\n"; + var results = ["b\x0ac", "b\x0a"]; + shouldBe("regex558.exec(input0);", "results"); + var input1 = "a\nb\nc\n"; + var results = ["b\x0ac", "b\x0a"]; + shouldBe("regex558.exec(input1);", "results"); + + var regex559 = /()^b/; + // Failers + var input0 = "a\nb\nc\n"; + var results = null; + shouldBe("regex559.exec(input0);", "results"); + var input1 = "a\nb\nc\n"; + var results = null; + shouldBe("regex559.exec(input1);", "results"); + + var regex560 = /(^b)/m; + var input0 = "a\nb\nc\n"; + var results = ["b", "b"]; + shouldBe("regex560.exec(input0);", "results"); + + var regex561 = /(?:b|a)/; + var input0 = "a"; + var results = ["a"]; + shouldBe("regex561.exec(input0);", "results"); + + var regex562 = /(x)?(?:a|b)/; + var input0 = "xa"; + var results = ["xa", "x"]; + shouldBe("regex562.exec(input0);", "results"); + var input1 = "a"; + var results = ["a", undefined]; + shouldBe("regex562.exec(input1);", "results"); + + var regex563 = /(x)?(?:b|a)/; + var input0 = "a"; + var results = ["a", undefined]; + shouldBe("regex563.exec(input0);", "results"); + + var regex564 = /()?(?:b|a)/; + var input0 = "a"; + var results = ["a", undefined]; + shouldBe("regex564.exec(input0);", "results"); + + var regex565 = /()?(?:a|b)/; + var input0 = "a"; + var results = ["a", undefined]; + shouldBe("regex565.exec(input0);", "results"); + + var regex566 = /^(\()?blah(?:(\))?)$/; + var input0 = "(blah)"; + var results = ["(blah)", "(", ")"]; + shouldBe("regex566.exec(input0);", "results"); + var input1 = "blah"; + var results = ["blah", undefined, undefined]; + shouldBe("regex566.exec(input1);", "results"); + var input2 = "blah)"; + var results = ["blah)", undefined, ")"]; + shouldBe("regex566.exec(input2);", "results"); + var input3 = "(blah"; + var results = ["(blah", "(", undefined]; + shouldBe("regex566.exec(input3);", "results"); + // Failers + var input4 = "a"; + var results = null; + shouldBe("regex566.exec(input4);", "results"); + + var regex567 = /^(\(+)?blah(?:(\))?)$/; + var input0 = "(blah)"; + var results = ["(blah)", "(", ")"]; + shouldBe("regex567.exec(input0);", "results"); + var input1 = "blah"; + var results = ["blah", undefined, undefined]; + shouldBe("regex567.exec(input1);", "results"); + var input2 = "blah)"; + var results = ["blah)", undefined, ")"]; + shouldBe("regex567.exec(input2);", "results"); + var input3 = "(blah"; + var results = ["(blah", "(", undefined]; + shouldBe("regex567.exec(input3);", "results"); + + var regex568 = /((?!a)b|a)/; + var input0 = "a"; + var results = ["a", "a"]; + shouldBe("regex568.exec(input0);", "results"); + + var regex569 = /((?=a)b|a)/; + var input0 = "a"; + var results = ["a", "a"]; + shouldBe("regex569.exec(input0);", "results"); + var input1 = "a"; + var results = ["a", "a"]; + shouldBe("regex569.exec(input1);", "results"); + + var regex570 = /((?=a)a|b)/; + var input0 = "a"; + var results = ["a", "a"]; + shouldBe("regex570.exec(input0);", "results"); + + var regex571 = /(?=(a+?))(\1ab)/; + var input0 = "aaab"; + var results = ["aab", "a", "aab"]; + shouldBe("regex571.exec(input0);", "results"); + + var regex572 = /(\w+:)+/; + var input0 = "one:"; + var results = ["one:", "one:"]; + shouldBe("regex572.exec(input0);", "results"); + + var regex574 = /(?=(a+?))(\1ab)/; + var input0 = "aaab"; + var results = ["aab", "a", "aab"]; + shouldBe("regex574.exec(input0);", "results"); + + var regex575 = /^(?=(a+?))\1ab/; + // Failers + var input0 = "aaab"; + var results = null; + shouldBe("regex575.exec(input0);", "results"); + var input1 = "aaab"; + var results = null; + shouldBe("regex575.exec(input1);", "results"); + + var regex576 = /([\w:]+::)?(\w+)$/; + var input0 = "abcd"; + var results = ["abcd", undefined, "abcd"]; + shouldBe("regex576.exec(input0);", "results"); + var input1 = "xy:z:::abcd"; + var results = ["xy:z:::abcd", "xy:z:::", "abcd"]; + shouldBe("regex576.exec(input1);", "results"); + + var regex577 = /^[^bcd]*(c+)/; + var input0 = "aexycd"; + var results = ["aexyc", "c"]; + shouldBe("regex577.exec(input0);", "results"); + + var regex578 = /(a*)b+/; + var input0 = "caab"; + var results = ["aab", "aa"]; + shouldBe("regex578.exec(input0);", "results"); + + var regex579 = /([\w:]+::)?(\w+)$/; + var input0 = "abcd"; + var results = ["abcd", undefined, "abcd"]; + shouldBe("regex579.exec(input0);", "results"); + var input1 = "xy:z:::abcd"; + var results = ["xy:z:::abcd", "xy:z:::", "abcd"]; + shouldBe("regex579.exec(input1);", "results"); + // Failers + var input2 = "abcd:"; + var results = null; + shouldBe("regex579.exec(input2);", "results"); + var input3 = "abcd:"; + var results = null; + shouldBe("regex579.exec(input3);", "results"); + + var regex580 = /^[^bcd]*(c+)/; + var input0 = "aexycd"; + var results = ["aexyc", "c"]; + shouldBe("regex580.exec(input0);", "results"); + + var regex582 = /([[:]+)/; + var input0 = "a:[b]:"; + var results = [":[", ":["]; + shouldBe("regex582.exec(input0);", "results"); + + var regex583 = /([[=]+)/; + var input0 = "a=[b]="; + var results = ["=[", "=["]; + shouldBe("regex583.exec(input0);", "results"); + + var regex584 = /([[.]+)/; + var input0 = "a.[b]."; + var results = [".[", ".["]; + shouldBe("regex584.exec(input0);", "results"); + + var regex588 = /a$/; + var input0 = "aaab"; + var results = null; + shouldBe("regex588.exec(input0);", "results"); + var input1 = "a\nb\n"; + var results = null; + shouldBe("regex588.exec(input1);", "results"); + + var regex589 = /b$/; + var input0 = "a\nb"; + var results = ["b"]; + shouldBe("regex589.exec(input0);", "results"); + // Failers + var input1 = "a\nb\n"; + var results = null; + shouldBe("regex589.exec(input1);", "results"); + + var regex590 = /b$/m; + var input0 = "a\nb"; + var results = ["b"]; + shouldBe("regex590.exec(input0);", "results"); + var input1 = "a\nb\n"; + var results = ["b"]; + shouldBe("regex590.exec(input1);", "results"); + + var regex600 = /) constructs. These are not currently valid in ECMAScript, + // but these tests may be useful if similar constructs are introduced in the future. + + //var regex217 = /(?.*\/)foo/; + //var input0 = "/this/is/a/very/long/line/in/deed/with/very/many/slashes/in/it/you/see/"; + //var results = null; + //shouldBe('regex221.exec(input0);', 'results'); + // + //var regex222 = /(?>.*\/)foo/; + //var input0 = "/this/is/a/very/long/line/in/deed/with/very/many/slashes/in/and/foo"; + //var results = ["/this/is/a/very/long/line/in/deed/with/very/many/slashes/in/and/foo"]; + //shouldBe('regex222.exec(input0);', 'results'); + // + //var regex223 = /(?>(\.\d\d[1-9]?))\d+/; + //var input0 = "1.230003938"; + //var results = [".230003938", ".23"]; + //shouldBe('regex223.exec(input0);', 'results'); + //var input1 = "1.875000282"; + //var results = [".875000282", ".875"]; + //shouldBe('regex223.exec(input1);', 'results'); + //// Failers + //var input2 = "1.235"; + //var results = null; + //shouldBe('regex223.exec(input2);', 'results'); + // + //var regex224 = /^((?>\w+)|(?>\s+))*$/; + //var input0 = "now is the time for all good men to come to the aid of the party"; + //var results = ["now is the time for all good men to come to the aid of the party", "party"]; + //shouldBe('regex224.exec(input0);', 'results'); + //// Failers + //var input1 = "this is not a line with only words and spaces!"; + //var results = null; + //shouldBe('regex224.exec(input1);', 'results'); + // + //var regex226 = /((?>\d+))(\w)/; + //var input0 = "12345a"; + //var results = ["12345a", "12345", "a"]; + //shouldBe('regex226.exec(input0);', 'results'); + //// Failers + //var input1 = "12345+"; + //var results = null; + //shouldBe('regex226.exec(input1);', 'results'); + // + //var regex227 = /(?>a+)b/; + //var input0 = "aaab"; + //var results = ["aaab"]; + //shouldBe('regex227.exec(input0);', 'results'); + // + //var regex228 = /((?>a+)b)/; + //var input0 = "aaab"; + //var results = ["aaab", "aaab"]; + //shouldBe('regex228.exec(input0);', 'results'); + // + //var regex229 = /(?>(a+))b/; + //var input0 = "aaab"; + //var results = ["aaab", "aaa"]; + //shouldBe('regex229.exec(input0);', 'results'); + // + //var regex230 = /(?>b)+/; + //var input0 = "aaabbbccc"; + //var results = ["bbb"]; + //shouldBe('regex230.exec(input0);', 'results'); + // + //var regex231 = /(?>a+|b+|c+)*c/; + //var input0 = "aaabbbbccccd"; + //var results = ["aaabbbbc"]; + //shouldBe('regex231.exec(input0);', 'results'); + // + //var regex232 = /((?>[^()]+)|\([^()]*\))+/; + //var input0 = "((abc(ade)ufh()()x"; + //var results = ["abc(ade)ufh()()x", "x"]; + //shouldBe('regex232.exec(input0);', 'results'); + // + //var regex233 = /\(((?>[^()]+)|\([^()]+\))+\)/ ; + //var input0 = "(abc)"; + //var results = ["(abc)", "abc"]; + //shouldBe('regex233.exec(input0);', 'results'); + //var input1 = "(abc(def)xyz)"; + //var results = ["(abc(def)xyz)", "xyz"]; + //shouldBe('regex233.exec(input1);', 'results'); + //// Failers + //var input2 = "((()aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + //var results = null; + //shouldBe('regex233.exec(input2);', 'results'); + // + //var regex245 = /(?<=ab)(\w\w)c/; + //var input0 = "abxxc"; + //var results = ["xxc", "xx"]; + //shouldBe('regex245.exec(input0);', 'results'); + //var input1 = "aBxxc"; + //var results = ["xxc", "xx"]; + //shouldBe('regex245.exec(input1);', 'results'); + //// Failers + //var input2 = "Abxxc"; + //var results = null; + //shouldBe('regex245.exec(input2);', 'results'); + //var input3 = "ABxxc"; + //var results = null; + //shouldBe('regex245.exec(input3);', 'results'); + //var input4 = "abxxC"; + //var results = null; + //shouldBe('regex245.exec(input4);', 'results'); + // + //var regex250 = /(?(?<=foo)bar|cat)/; + //var input0 = "foobar"; + //var results = ["bar"]; + //shouldBe('regex250.exec(input0);', 'results'); + //var input1 = "cat"; + //var results = ["cat"]; + //shouldBe('regex250.exec(input1);', 'results'); + //var input2 = "fcat"; + //var results = ["cat"]; + //shouldBe('regex250.exec(input2);', 'results'); + //var input3 = "focat"; + //var results = ["cat"]; + //shouldBe('regex250.exec(input3);', 'results'); + //// Failers + //var input4 = "foocat"; + //var results = null; + //shouldBe('regex250.exec(input4);', 'results'); + // + //var regex251 = /(?(?a*)*/; + //var input0 = "a"; + //var results = ["a"]; + //shouldBe('regex256.exec(input0);', 'results'); + //var input1 = "aa"; + //var results = ["aa"]; + //shouldBe('regex256.exec(input1);', 'results'); + //var input2 = "aaaa"; + //var results = ["aaaa"]; + //shouldBe('regex256.exec(input2);', 'results'); + // + //var regex266 = /(?>a*)*/; + //var input0 = "a"; + //var results = ["a"]; + //shouldBe('regex266.exec(input0);', 'results'); + //var input1 = "aaabcde"; + //var results = ["aaa"]; + //shouldBe('regex266.exec(input1);', 'results'); + // + //var regex267 = /((?>a*))*/; + //var input0 = "aaaaa"; + //var results = ["aaaaa", ""]; + //shouldBe('regex267.exec(input0);', 'results'); + //var input1 = "aabbaa"; + //var results = ["aa", ""]; + //shouldBe('regex267.exec(input1);', 'results'); + // + //var regex268 = /((?>a*?))*/; + //var input0 = "aaaaa"; + //var results = ["", ""]; + //shouldBe('regex268.exec(input0);', 'results'); + //var input1 = "aabbaa"; + //var results = ["", ""]; + //shouldBe('regex268.exec(input1);', 'results'); + // + //var regex270 = /(?<=(foo))bar\1/; + //var input0 = "foobarfoo"; + //var results = ["barfoo", "foo"]; + //shouldBe('regex270.exec(input0);', 'results'); + //var input1 = "foobarfootling"; + //var results = ["barfoo", "foo"]; + //shouldBe('regex270.exec(input1);', 'results'); + //// Failers + //var input2 = "foobar"; + //var results = null; + //shouldBe('regex270.exec(input2);', 'results'); + //var input3 = "barfoo"; + //var results = null; + //shouldBe('regex270.exec(input3);', 'results'); + // + //var regex275 = /(?<=foo\n)^bar/m; + //var input0 = "foo\nbar"; + //var results = ["bar"]; + //shouldBe('regex275.exec(input0);', 'results'); + //// Failers + //var input1 = "bar"; + //var results = null; + //shouldBe('regex275.exec(input1);', 'results'); + //var input2 = "baz\nbar"; + //var results = null; + //shouldBe('regex275.exec(input2);', 'results'); + // + //var regex276 = /(?<=(?a+)b/; + //var input0 = "aaab"; + //var results = ["aaab"]; + //shouldBe('regex581.exec(input0);', 'results'); + // + //var regex585 = /((?>a+)b)/; + //var input0 = "aaab"; + //var results = ["aaab", "aaab"]; + //shouldBe('regex585.exec(input0);', 'results'); + // + //var regex586 = /(?>(a+))b/; + //var input0 = "aaab"; + //var results = ["aaab", "aaa"]; + //shouldBe('regex586.exec(input0);', 'results'); + // + //var regex587 = /((?>[^()]+)|\([^()]*\))+/; + //var input0 = "((abc(ade)ufh()()x"; + //var results = ["abc(ade)ufh()()x", "x"]; + //shouldBe('regex587.exec(input0);', 'results'); + // + //var regex592 = /^(?>(?(1)\.|())[^\W_](?>[a-z0-9-]*[^\W_])?)+$/; + //var input0 = "a"; + //var results = ["a", ""]; + //shouldBe('regex592.exec(input0);', 'results'); + //var input1 = "abc"; + //var results = ["abc", ""]; + //shouldBe('regex592.exec(input1);', 'results'); + //var input2 = "a-b"; + //var results = ["a-b", ""]; + //shouldBe('regex592.exec(input2);', 'results'); + //var input3 = "0-9"; + //var results = ["0-9", ""]; + //shouldBe('regex592.exec(input3);', 'results'); + //var input4 = "a.b"; + //var results = ["a.b", ""]; + //shouldBe('regex592.exec(input4);', 'results'); + //var input5 = "5.6.7"; + //var results = ["5.6.7", ""]; + //shouldBe('regex592.exec(input5);', 'results'); + //var input6 = "the.quick.brown.fox"; + //var results = ["the.quick.brown.fox", ""]; + //shouldBe('regex592.exec(input6);', 'results'); + //var input7 = "a100.b200.300c"; + //var results = ["a100.b200.300c", ""]; + //shouldBe('regex592.exec(input7);', 'results'); + //var input8 = "12-ab.1245"; + //var results = ["12-ab.1245", ""]; + //shouldBe('regex592.exec(input8);', 'results'); + //// Failers + //var input9 = "\"; + //var results = null; + //shouldBe('regex592.exec(input9);', 'results'); + //var input10 = ".a"; + //var results = null; + //shouldBe('regex592.exec(input10);', 'results'); + //var input11 = "-a"; + //var results = null; + //shouldBe('regex592.exec(input11);', 'results'); + //var input12 = "a-"; + //var results = null; + //shouldBe('regex592.exec(input12);', 'results'); + //var input13 = "a."; + //var results = null; + //shouldBe('regex592.exec(input13);', 'results'); + //var input14 = "a_b"; + //var results = null; + //shouldBe('regex592.exec(input14);', 'results'); + //var input15 = "a.-"; + //var results = null; + //shouldBe('regex592.exec(input15);', 'results'); + //var input16 = "a.."; + //var results = null; + //shouldBe('regex592.exec(input16);', 'results'); + //var input17 = "ab..bc"; + //var results = null; + //shouldBe('regex592.exec(input17);', 'results'); + //var input18 = "the.quick.brown.fox-"; + //var results = null; + //shouldBe('regex592.exec(input18);', 'results'); + //var input19 = "the.quick.brown.fox."; + //var results = null; + //shouldBe('regex592.exec(input19);', 'results'); + //var input20 = "the.quick.brown.fox_"; + //var results = null; + //shouldBe('regex592.exec(input20);', 'results'); + //var input21 = "the.quick.brown.fox+"; + //var results = null; + //shouldBe('regex592.exec(input21);', 'results'); + // + //var regex593 = /(?>.*)(?<=(abcd|wxyz))/; + //var input0 = "alphabetabcd"; + //var results = ["alphabetabcd", "abcd"]; + //shouldBe('regex593.exec(input0);', 'results'); + //var input1 = "endingwxyz"; + //var results = ["endingwxyz", "wxyz"]; + //shouldBe('regex593.exec(input1);', 'results'); + //// Failers + //var input2 = "a rather long string that doesn't end with one of them"; + //var results = null; + //shouldBe('regex593.exec(input2);', 'results'); + // + //var regex594 = /word (?>(?:(?!otherword)[a-zA-Z0-9]+ ){0,30})otherword/; + //var input0 = "word cat dog elephant mussel cow horse canary baboon snake shark otherword"; + //var results = ["word cat dog elephant mussel cow horse canary baboon snake shark otherword"]; + //shouldBe('regex594.exec(input0);', 'results'); + //var input1 = "word cat dog elephant mussel cow horse canary baboon snake shark"; + //var results = null; + //shouldBe('regex594.exec(input1);', 'results'); + // + //var regex595 = /word (?>[a-zA-Z0-9]+ ){0,30}otherword/; + //var input0 = "word cat dog elephant mussel cow horse canary baboon snake shark the quick brown fox and the lazy dog and several other words getting close to thirty by now I hope"; + //var results = null; + //shouldBe('regex595.exec(input0);', 'results'); + // + //var regex596 = /(?<=\d{3}(?!999))foo/; + //var input0 = "999foo"; + //var results = ["foo"]; + //shouldBe('regex596.exec(input0);', 'results'); + //var input1 = "123999foo"; + //var results = ["foo"]; + //shouldBe('regex596.exec(input1);', 'results'); + //// Failers + //var input2 = "123abcfoo"; + //var results = null; + //shouldBe('regex596.exec(input2);', 'results'); + // + //var regex597 = /(?<=(?!...999)\d{3})foo/; + //var input0 = "999foo"; + //var results = ["foo"]; + //shouldBe('regex597.exec(input0);', 'results'); + //var input1 = "123999foo"; + //var results = ["foo"]; + //shouldBe('regex597.exec(input1);', 'results'); + //// Failers + //var input2 = "123abcfoo"; + //var results = null; + //shouldBe('regex597.exec(input2);', 'results'); + // + //var regex598 = /(?<=\d{3}(?!999)...)foo/; + //var input0 = "123abcfoo"; + //var results = ["foo"]; + //shouldBe('regex598.exec(input0);', 'results'); + //var input1 = "123456foo"; + //var results = ["foo"]; + //shouldBe('regex598.exec(input1);', 'results'); + //// Failers + //var input2 = "123999foo"; + //var results = null; + //shouldBe('regex598.exec(input2);', 'results'); + // + //var regex599 = /(?<=\d{3}...)(?\s*)=(?>\s*)(["'])?(?(1) (.*?)\1 | (\S+))/i; + //var input0 = "Z)+|A)*/; + //var input0 = "ZABCDEFG"; + //var results = ["ZA", "A"]; + //shouldBe('regex606.exec(input0);', 'results'); + // + //var regex607 = /((?>)+|A)*/; + //var input0 = "ZABCDEFG"; + //var results = ["", ""]; + //shouldBe('regex607.exec(input0);', 'results'); + // + //var regex635 = /(?<=Z)X./; + //var input0 = "\x84XAZXB"; + //var results = ["XB"]; + //shouldBe('regex635.exec(input0);', 'results'); + // + //var regex638 = /(?a|)*\d/; + //var input0 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + //var results = null; + //shouldBe('regex666.exec(input0);', 'results'); + //var input1 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4"; + //var results = ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa4"]; + //shouldBe('regex666.exec(input1);', 'results'); + // + //var regex668 = /^(?>.*)(? { + // WebKit assertion compatibility shim for Ladybird's test-js harness + + function description(msg) { + // No-op, just used for test documentation in WebKit. + } + + function shouldBe(actual_code, expected_code) { + let actual = eval(actual_code); + let expected = eval(expected_code); + if (typeof actual === "string" && typeof expected === "string") { + expect(actual).toBe(expected); + } else if (Array.isArray(actual) && Array.isArray(expected)) { + expect(actual).toEqual(expected); + } else if (actual !== null && typeof actual === "object" && expected !== null && typeof expected === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } + } + + function shouldBeTrue(code) { + expect(eval(code)).toBeTrue(); + } + + function shouldBeFalse(code) { + expect(eval(code)).toBeFalse(); + } + + function shouldBeNull(code) { + expect(eval(code)).toBeNull(); + } + + function shouldBeUndefined(code) { + expect(eval(code)).toBeUndefined(); + } + + function shouldThrow(code, expected_error) { + expect(() => eval(code)).toThrow(); + } + + function shouldNotThrow(code) { + eval(code); + } + + description("A chunk of our port of PCRE's test suite, adapted to be more applicable to JavaScript."); + + var regex0 = /a.b/; + var input0 = "acb"; + var results = ["acb"]; + shouldBe("regex0.exec(input0);", "results"); + var input1 = "a\x7fb"; + var results = ["a\u007fb"]; + shouldBe("regex0.exec(input1);", "results"); + var input2 = "a\u0100b"; + var results = ["a\u0100b"]; + shouldBe("regex0.exec(input2);", "results"); + // Failers + var input3 = "a\nb"; + var results = null; + shouldBe("regex0.exec(input3);", "results"); + + var regex1 = /a(.{3})b/; + var input0 = "a\u4000xyb"; + var results = ["a\u4000xyb", "\u4000xy"]; + shouldBe("regex1.exec(input0);", "results"); + var input1 = "a\u4000\x7fyb"; + var results = ["a\u4000\u007fyb", "\u4000\u007fy"]; + shouldBe("regex1.exec(input1);", "results"); + var input2 = "a\u4000\u0100yb"; + var results = ["a\u4000\u0100yb", "\u4000\u0100y"]; + shouldBe("regex1.exec(input2);", "results"); + // Failers + var input3 = "a\u4000b"; + var results = null; + shouldBe("regex1.exec(input3);", "results"); + var input4 = "ac\ncb"; + var results = null; + shouldBe("regex1.exec(input4);", "results"); + + var regex2 = /a(.*?)(.)/; + var input0 = "a\xc0\x88b"; + var results = ["a\xc0", "", "\xc0"]; + shouldBe("regex2.exec(input0);", "results"); + + var regex3 = /a(.*?)(.)/; + var input0 = "a\u0100b"; + var results = ["a\u0100", "", "\u0100"]; + shouldBe("regex3.exec(input0);", "results"); + + var regex4 = /a(.*)(.)/; + var input0 = "a\xc0\x88b"; + var results = ["a\xc0\x88b", "\xc0\x88", "b"]; + shouldBe("regex4.exec(input0);", "results"); + + var regex5 = /a(.*)(.)/; + var input0 = "a\u0100b"; + var results = ["a\u0100b", "\u0100", "b"]; + shouldBe("regex5.exec(input0);", "results"); + + var regex6 = /a(.)(.)/; + var input0 = "a\xc0\x92bcd"; + var results = ["a\xc0\x92", "\xc0", "\x92"]; + shouldBe("regex6.exec(input0);", "results"); + + var regex7 = /a(.)(.)/; + var input0 = "a\u0240bcd"; + var results = ["a\u0240b", "\u0240", "b"]; + shouldBe("regex7.exec(input0);", "results"); + + var regex8 = /a(.?)(.)/; + var input0 = "a\xc0\x92bcd"; + var results = ["a\xc0\x92", "\xc0", "\x92"]; + shouldBe("regex8.exec(input0);", "results"); + + var regex9 = /a(.?)(.)/; + var input0 = "a\u0240bcd"; + var results = ["a\u0240b", "\u0240", "b"]; + shouldBe("regex9.exec(input0);", "results"); + + var regex10 = /a(.??)(.)/; + var input0 = "a\xc0\x92bcd"; + var results = ["a\xc0", "", "\xc0"]; + shouldBe("regex10.exec(input0);", "results"); + + var regex11 = /a(.??)(.)/; + var input0 = "a\u0240bcd"; + var results = ["a\u0240", "", "\u0240"]; + shouldBe("regex11.exec(input0);", "results"); + + var regex12 = /a(.{3})b/; + var input0 = "a\u1234xyb"; + var results = ["a\u1234xyb", "\u1234xy"]; + shouldBe("regex12.exec(input0);", "results"); + var input1 = "a\u1234\u4321yb"; + var results = ["a\u1234\u4321yb", "\u1234\u4321y"]; + shouldBe("regex12.exec(input1);", "results"); + var input2 = "a\u1234\u4321\u3412b"; + var results = ["a\u1234\u4321\u3412b", "\u1234\u4321\u3412"]; + shouldBe("regex12.exec(input2);", "results"); + // Failers + var input3 = "a\u1234b"; + var results = null; + shouldBe("regex12.exec(input3);", "results"); + var input4 = "ac\ncb"; + var results = null; + shouldBe("regex12.exec(input4);", "results"); + + var regex13 = /a(.{3,})b/; + var input0 = "a\u1234xyb"; + var results = ["a\u1234xyb", "\u1234xy"]; + shouldBe("regex13.exec(input0);", "results"); + var input1 = "a\u1234\u4321yb"; + var results = ["a\u1234\u4321yb", "\u1234\u4321y"]; + shouldBe("regex13.exec(input1);", "results"); + var input2 = "a\u1234\u4321\u3412b"; + var results = ["a\u1234\u4321\u3412b", "\u1234\u4321\u3412"]; + shouldBe("regex13.exec(input2);", "results"); + var input3 = "axxxxbcdefghijb"; + var results = ["axxxxbcdefghijb", "xxxxbcdefghij"]; + shouldBe("regex13.exec(input3);", "results"); + var input4 = "a\u1234\u4321\u3412\u3421b"; + var results = ["a\u1234\u4321\u3412\u3421b", "\u1234\u4321\u3412\u3421"]; + shouldBe("regex13.exec(input4);", "results"); + // Failers + var input5 = "a\u1234b"; + var results = null; + shouldBe("regex13.exec(input5);", "results"); + + var regex14 = /a(.{3,}?)b/; + var input0 = "a\u1234xyb"; + var results = ["a\u1234xyb", "\u1234xy"]; + shouldBe("regex14.exec(input0);", "results"); + var input1 = "a\u1234\u4321yb"; + var results = ["a\u1234\u4321yb", "\u1234\u4321y"]; + shouldBe("regex14.exec(input1);", "results"); + var input2 = "a\u1234\u4321\u3412b"; + var results = ["a\u1234\u4321\u3412b", "\u1234\u4321\u3412"]; + shouldBe("regex14.exec(input2);", "results"); + var input3 = "axxxxbcdefghijb"; + var results = ["axxxxb", "xxxx"]; + shouldBe("regex14.exec(input3);", "results"); + var input4 = "a\u1234\u4321\u3412\u3421b"; + var results = ["a\u1234\u4321\u3412\u3421b", "\u1234\u4321\u3412\u3421"]; + shouldBe("regex14.exec(input4);", "results"); + // Failers + var input5 = "a\u1234b"; + var results = null; + shouldBe("regex14.exec(input5);", "results"); + + var regex15 = /a(.{3,5})b/; + var input0 = "a\u1234xyb"; + var results = ["a\u1234xyb", "\u1234xy"]; + shouldBe("regex15.exec(input0);", "results"); + var input1 = "a\u1234\u4321yb"; + var results = ["a\u1234\u4321yb", "\u1234\u4321y"]; + shouldBe("regex15.exec(input1);", "results"); + var input2 = "a\u1234\u4321\u3412b"; + var results = ["a\u1234\u4321\u3412b", "\u1234\u4321\u3412"]; + shouldBe("regex15.exec(input2);", "results"); + var input3 = "axxxxbcdefghijb"; + var results = ["axxxxb", "xxxx"]; + shouldBe("regex15.exec(input3);", "results"); + var input4 = "a\u1234\u4321\u3412\u3421b"; + var results = ["a\u1234\u4321\u3412\u3421b", "\u1234\u4321\u3412\u3421"]; + shouldBe("regex15.exec(input4);", "results"); + var input5 = "axbxxbcdefghijb"; + var results = ["axbxxb", "xbxx"]; + shouldBe("regex15.exec(input5);", "results"); + var input6 = "axxxxxbcdefghijb"; + var results = ["axxxxxb", "xxxxx"]; + shouldBe("regex15.exec(input6);", "results"); + // Failers + var input7 = "a\u1234b"; + var results = null; + shouldBe("regex15.exec(input7);", "results"); + var input8 = "axxxxxxbcdefghijb"; + var results = null; + shouldBe("regex15.exec(input8);", "results"); + + var regex16 = /a(.{3,5}?)b/; + var input0 = "a\u1234xyb"; + var results = ["a\u1234xyb", "\u1234xy"]; + shouldBe("regex16.exec(input0);", "results"); + var input1 = "a\u1234\u4321yb"; + var results = ["a\u1234\u4321yb", "\u1234\u4321y"]; + shouldBe("regex16.exec(input1);", "results"); + var input2 = "a\u1234\u4321\u3412b"; + var results = ["a\u1234\u4321\u3412b", "\u1234\u4321\u3412"]; + shouldBe("regex16.exec(input2);", "results"); + var input3 = "axxxxbcdefghijb"; + var results = ["axxxxb", "xxxx"]; + shouldBe("regex16.exec(input3);", "results"); + var input4 = "a\u1234\u4321\u3412\u3421b"; + var results = ["a\u1234\u4321\u3412\u3421b", "\u1234\u4321\u3412\u3421"]; + shouldBe("regex16.exec(input4);", "results"); + var input5 = "axbxxbcdefghijb"; + var results = ["axbxxb", "xbxx"]; + shouldBe("regex16.exec(input5);", "results"); + var input6 = "axxxxxbcdefghijb"; + var results = ["axxxxxb", "xxxxx"]; + shouldBe("regex16.exec(input6);", "results"); + // Failers + var input7 = "a\u1234b"; + var results = null; + shouldBe("regex16.exec(input7);", "results"); + var input8 = "axxxxxxbcdefghijb"; + var results = null; + shouldBe("regex16.exec(input8);", "results"); + + var regex17 = /^[a\u00c0]/; + // Failers + var input0 = "\u0100"; + var results = null; + shouldBe("regex17.exec(input0);", "results"); + + var regex21 = /(?:\u0100){3}b/; + var input0 = "\u0100\u0100\u0100b"; + var results = ["\u0100\u0100\u0100b"]; + shouldBe("regex21.exec(input0);", "results"); + // Failers + var input1 = "\u0100\u0100b"; + var results = null; + shouldBe("regex21.exec(input1);", "results"); + + var regex22 = /\u00ab/; + var input0 = "\u00ab"; + var results = ["\u00ab"]; + shouldBe("regex22.exec(input0);", "results"); + var input1 = "\xc2\xab"; + var results = ["\u00ab"]; + shouldBe("regex22.exec(input1);", "results"); + // Failers + var input2 = "\x00{ab}"; + var results = null; + shouldBe("regex22.exec(input2);", "results"); + + var regex30 = /^[^a]{2}/; + var input0 = "\u0100bc"; + var results = ["\u0100b"]; + shouldBe("regex30.exec(input0);", "results"); + + var regex31 = /^[^a]{2,}/; + var input0 = "\u0100bcAa"; + var results = ["\u0100bcA"]; + shouldBe("regex31.exec(input0);", "results"); + + var regex32 = /^[^a]{2,}?/; + var input0 = "\u0100bca"; + var results = ["\u0100b"]; + shouldBe("regex32.exec(input0);", "results"); + + var regex33 = /^[^a]{2}/i; + var input0 = "\u0100bc"; + var results = ["\u0100b"]; + shouldBe("regex33.exec(input0);", "results"); + + var regex34 = /^[^a]{2,}/i; + var input0 = "\u0100bcAa"; + var results = ["\u0100bc"]; + shouldBe("regex34.exec(input0);", "results"); + + var regex35 = /^[^a]{2,}?/i; + var input0 = "\u0100bca"; + var results = ["\u0100b"]; + shouldBe("regex35.exec(input0);", "results"); + + var regex36 = /\u0100{0,0}/; + var input0 = "abcd"; + var results = [""]; + shouldBe("regex36.exec(input0);", "results"); + + var regex37 = /\u0100?/; + var input0 = "abcd"; + var results = [""]; + shouldBe("regex37.exec(input0);", "results"); + var input1 = "\u0100\u0100"; + var results = ["\u0100"]; + shouldBe("regex37.exec(input1);", "results"); + + var regex38 = /\u0100{0,3}/; + var input0 = "\u0100\u0100"; + var results = ["\u0100\u0100"]; + shouldBe("regex38.exec(input0);", "results"); + var input1 = "\u0100\u0100\u0100\u0100"; + var results = ["\u0100\u0100\u0100"]; + shouldBe("regex38.exec(input1);", "results"); + + var regex39 = /\u0100*/; + var input0 = "abce"; + var results = [""]; + shouldBe("regex39.exec(input0);", "results"); + var input1 = "\u0100\u0100\u0100\u0100"; + var results = ["\u0100\u0100\u0100\u0100"]; + shouldBe("regex39.exec(input1);", "results"); + + var regex40 = /\u0100{1,1}/; + var input0 = "abcd\u0100\u0100\u0100\u0100"; + var results = ["\u0100"]; + shouldBe("regex40.exec(input0);", "results"); + + var regex41 = /\u0100{1,3}/; + var input0 = "abcd\u0100\u0100\u0100\u0100"; + var results = ["\u0100\u0100\u0100"]; + shouldBe("regex41.exec(input0);", "results"); + + var regex42 = /\u0100+/; + var input0 = "abcd\u0100\u0100\u0100\u0100"; + var results = ["\u0100\u0100\u0100\u0100"]; + shouldBe("regex42.exec(input0);", "results"); + + var regex43 = /\u0100{3}/; + var input0 = "abcd\u0100\u0100\u0100XX"; + var results = ["\u0100\u0100\u0100"]; + shouldBe("regex43.exec(input0);", "results"); + + var regex44 = /\u0100{3,5}/; + var input0 = "abcd\u0100\u0100\u0100\u0100\u0100\u0100\u0100XX"; + var results = ["\u0100\u0100\u0100\u0100\u0100"]; + shouldBe("regex44.exec(input0);", "results"); + + var regex45 = /\u0100{3,}/; + var input0 = "abcd\u0100\u0100\u0100\u0100\u0100\u0100\u0100XX"; + var results = ["\u0100\u0100\u0100\u0100\u0100\u0100\u0100"]; + shouldBe("regex45.exec(input0);", "results"); + + var regex47 = /\D*/; + var input0 = + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + var results = [ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + ]; + shouldBe("regex47.exec(input0);", "results"); + + var regex48 = /\D*/; + var input0 = + "\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100"; + var results = [ + "\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100", + ]; + shouldBe("regex48.exec(input0);", "results"); + + var regex49 = /\D/; + var input0 = "1X2"; + var results = ["X"]; + shouldBe("regex49.exec(input0);", "results"); + var input1 = "1\u01002"; + var results = ["\u0100"]; + shouldBe("regex49.exec(input1);", "results"); + + var regex50 = />\S/; + var input0 = "> >X Y"; + var results = [">X"]; + shouldBe("regex50.exec(input0);", "results"); + var input1 = "> >\u0100 Y"; + var results = [">\u0100"]; + shouldBe("regex50.exec(input1);", "results"); + + var regex51 = /\d/; + var input0 = "\u01003"; + var results = ["3"]; + shouldBe("regex51.exec(input0);", "results"); + + var regex52 = /\s/; + var input0 = "\u0100 X"; + var results = [" "]; + shouldBe("regex52.exec(input0);", "results"); + + var regex53 = /\D+/; + var input0 = "12abcd34"; + var results = ["abcd"]; + shouldBe("regex53.exec(input0);", "results"); + // Failers + var input1 = "1234"; + var results = null; + shouldBe("regex53.exec(input1);", "results"); + + var regex54 = /\D{2,3}/; + var input0 = "12abcd34"; + var results = ["abc"]; + shouldBe("regex54.exec(input0);", "results"); + var input1 = "12ab34"; + var results = ["ab"]; + shouldBe("regex54.exec(input1);", "results"); + // Failers + var input2 = "1234"; + var results = null; + shouldBe("regex54.exec(input2);", "results"); + var input3 = "12a34"; + var results = null; + shouldBe("regex54.exec(input3);", "results"); + + var regex55 = /\D{2,3}?/; + var input0 = "12abcd34"; + var results = ["ab"]; + shouldBe("regex55.exec(input0);", "results"); + var input1 = "12ab34"; + var results = ["ab"]; + shouldBe("regex55.exec(input1);", "results"); + // Failers + var input2 = "1234"; + var results = null; + shouldBe("regex55.exec(input2);", "results"); + var input3 = "12a34"; + var results = null; + shouldBe("regex55.exec(input3);", "results"); + + var regex56 = /\d+/; + var input0 = "12abcd34"; + var results = ["12"]; + shouldBe("regex56.exec(input0);", "results"); + + var regex57 = /\d{2,3}/; + var input0 = "12abcd34"; + var results = ["12"]; + shouldBe("regex57.exec(input0);", "results"); + var input1 = "1234abcd"; + var results = ["123"]; + shouldBe("regex57.exec(input1);", "results"); + // Failers + var input2 = "1.4"; + var results = null; + shouldBe("regex57.exec(input2);", "results"); + + var regex58 = /\d{2,3}?/; + var input0 = "12abcd34"; + var results = ["12"]; + shouldBe("regex58.exec(input0);", "results"); + var input1 = "1234abcd"; + var results = ["12"]; + shouldBe("regex58.exec(input1);", "results"); + // Failers + var input2 = "1.4"; + var results = null; + shouldBe("regex58.exec(input2);", "results"); + + var regex59 = /\S+/; + var input0 = "12abcd34"; + var results = ["12abcd34"]; + shouldBe("regex59.exec(input0);", "results"); + // Failers + var input1 = " "; + var results = null; + shouldBe("regex59.exec(input1);", "results"); + + var regex60 = /\S{2,3}/; + var input0 = "12abcd34"; + var results = ["12a"]; + shouldBe("regex60.exec(input0);", "results"); + var input1 = "1234abcd"; + var results = ["123"]; + shouldBe("regex60.exec(input1);", "results"); + // Failers + var input2 = " "; + var results = null; + shouldBe("regex60.exec(input2);", "results"); + + var regex61 = /\S{2,3}?/; + var input0 = "12abcd34"; + var results = ["12"]; + shouldBe("regex61.exec(input0);", "results"); + var input1 = "1234abcd"; + var results = ["12"]; + shouldBe("regex61.exec(input1);", "results"); + // Failers + var input2 = " "; + var results = null; + shouldBe("regex61.exec(input2);", "results"); + + var regex62 = />\s+; + var input0 = "12> <34"; + var results = ["> <"]; + shouldBe("regex62.exec(input0);", "results"); + + var regex63 = />\s{2,3}; + var input0 = "ab> <"]; + shouldBe("regex63.exec(input0);", "results"); + var input1 = "ab> <"]; + shouldBe("regex63.exec(input1);", "results"); + // Failers + var input2 = "ab> \s{2,3}?; + var input0 = "ab> <"]; + shouldBe("regex64.exec(input0);", "results"); + var input1 = "ab> <"]; + shouldBe("regex64.exec(input1);", "results"); + // Failers + var input2 = "ab> ) constructs. These are not currently valid in ECMAScript, + // but these tests may be useful if similar constructs are introduced in the future. + + //var regex18 = /(?<=aXb)cd/; + //var input0 = "aXbcd"; + //var results = ["cd"]; + //shouldBe('regex18.exec(input0);', 'results'); + // + //var regex19 = /(?<=a\u0100b)cd/; + //var input0 = "a\u0100bcd"; + //var results = ["cd"]; + //shouldBe('regex19.exec(input0);', 'results'); + // + //var regex20 = /(?<=a\u100000b)cd/; + //var input0 = "a\u100000bcd"; + //var results = ["cd"]; + //shouldBe('regex20.exec(input0);', 'results'); + // + //var regex23 = /(?<=(.))X/; + //var input0 = "WXYZ"; + //var results = ["X", "W"]; + //shouldBe('regex23.exec(input0);', 'results'); + //var input1 = "\u0256XYZ"; + //var results = ["X", "\u0256"]; + //shouldBe('regex23.exec(input1);', 'results'); + //// Failers + //var input2 = "XYZ"; + //var results = null; + //shouldBe('regex23.exec(input2);', 'results'); + // + //var regex46 = /(?<=a\u0100{2}b)X/; + //var input0 = "Xyyya\u0100\u0100bXzzz"; + //var results = ["X"]; + //shouldBe('regex46.exec(input0);', 'results'); + // + //var regex83 = /(?<=[\u0100\u0200])X/; + //var input0 = "abc\u0200X"; + //var results = ["X"]; + //shouldBe('regex83.exec(input0);', 'results'); + //var input1 = "abc\u0100X"; + //var results = ["X"]; + //shouldBe('regex83.exec(input1);', 'results'); + //// Failers + //var input2 = "X"; + //var results = null; + //shouldBe('regex83.exec(input2);', 'results'); + // + //var regex84 = /(?<=[Q\u0100\u0200])X/; + //var input0 = "abc\u0200X"; + //var results = ["X"]; + //shouldBe('regex84.exec(input0);', 'results'); + //var input1 = "abc\u0100X"; + //var results = ["X"]; + //shouldBe('regex84.exec(input1);', 'results'); + //var input2 = "abQX"; + //var results = ["X"]; + //shouldBe('regex84.exec(input2);', 'results'); + //// Failers + //var input3 = "X"; + //var results = null; + //shouldBe('regex84.exec(input3);', 'results'); + // + //var regex85 = /(?<=[\u0100\u0200]{3})X/; + //var input0 = "abc\u0100\u0200\u0100X"; + //var results = ["X"]; + //shouldBe('regex85.exec(input0);', 'results'); + //// Failers + //var input1 = "abc\u0200X"; + //var results = null; + //shouldBe('regex85.exec(input1);', 'results'); + //var input2 = "X"; + //var results = null; + //shouldBe('regex85.exec(input2);', 'results'); + + // DISABLED: + // These tests use PCRE's \C token. This is not currently valid in ECMAScript, + // but these tests may be useful if similar constructs are introduced in the future. + + //var regex24 = /X(\C{3})/; + //var input0 = "X\u1234"; + //var results = ["X\u1234", "\u1234"]; + //shouldBe('regex24.exec(input0);', 'results'); + // + //var regex25 = /X(\C{4})/; + //var input0 = "X\u1234YZ"; + //var results = ["X\u1234Y", "\u1234Y"]; + //shouldBe('regex25.exec(input0);', 'results'); + // + //var regex26 = /X\C*/; + //var input0 = "XYZabcdce"; + //var results = ["XYZabcdce"]; + //shouldBe('regex26.exec(input0);', 'results'); + // + //var regex27 = /X\C*?/; + //var input0 = "XYZabcde"; + //var results = ["X"]; + //shouldBe('regex27.exec(input0);', 'results'); + // + //var regex28 = /X\C{3,5}/; + //var input0 = "Xabcdefg"; + //var results = ["Xabcde"]; + //shouldBe('regex28.exec(input0);', 'results'); + //var input1 = "X\u1234"; + //var results = ["X\u1234"]; + //shouldBe('regex28.exec(input1);', 'results'); + //var input2 = "X\u1234YZ"; + //var results = ["X\u1234YZ"]; + //shouldBe('regex28.exec(input2);', 'results'); + //var input3 = "X\u1234\u0512"; + //var results = ["X\u1234\u0512"]; + //shouldBe('regex28.exec(input3);', 'results'); + //var input4 = "X\u1234\u0512YZ"; + //var results = ["X\u1234\u0512"]; + //shouldBe('regex28.exec(input4);', 'results'); + // + //var regex29 = /X\C{3,5}?/; + //var input0 = "Xabcdefg"; + //var results = ["Xabc"]; + //shouldBe('regex29.exec(input0);', 'results'); + //var input1 = "X\u1234"; + //var results = ["X\u1234"]; + //shouldBe('regex29.exec(input1);', 'results'); + //var input2 = "X\u1234YZ"; + //var results = ["X\u1234"]; + //shouldBe('regex29.exec(input2);', 'results'); + //var input3 = "X\u1234\u0512"; + //var results = ["X\u1234"]; + //shouldBe('regex29.exec(input3);', 'results'); + // + //var regex89 = /a\Cb/; + //var input0 = "aXb"; + //var results = ["aXb"]; + //shouldBe('regex89.exec(input0);', 'results'); + //var input1 = "a\nb"; + //var results = ["a\x0ab"]; + //shouldBe('regex89.exec(input1);', 'results'); + // + //var regex90 = /a\Cb/; + //var input0 = "aXb"; + //var results = ["aXb"]; + //shouldBe('regex90.exec(input0);', 'results'); + //var input1 = "a\nb"; + //var results = ["a\u000ab"]; + //shouldBe('regex90.exec(input1);', 'results'); + //// Failers + //var input2 = "a\u0100b"; + //var results = null; + //shouldBe('regex90.exec(input2);', 'results'); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/webkit/quantified-assertions.js b/Tests/LibJS/Runtime/3rdparty/webkit/quantified-assertions.js new file mode 100644 index 00000000000..c6fe850e25f --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/webkit/quantified-assertions.js @@ -0,0 +1,72 @@ +test("quantified-assertions", () => { + // WebKit assertion compatibility shim for Ladybird's test-js harness + + function debug(msg) {} + function description(msg) { + // No-op, just used for test documentation in WebKit. + } + + function shouldBe(actual_code, expected_code) { + let actual = eval(actual_code); + let expected = eval(expected_code); + if (typeof actual === "string" && typeof expected === "string") { + expect(actual).toBe(expected); + } else if (Array.isArray(actual) && Array.isArray(expected)) { + expect(actual).toEqual(expected); + } else if (actual !== null && typeof actual === "object" && expected !== null && typeof expected === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } + } + + function shouldBeTrue(code) { + expect(eval(code)).toBeTrue(); + } + + function shouldBeFalse(code) { + expect(eval(code)).toBeFalse(); + } + + function shouldBeNull(code) { + expect(eval(code)).toBeNull(); + } + + function shouldBeUndefined(code) { + expect(eval(code)).toBeUndefined(); + } + + function shouldThrow(code, expected_error) { + expect(() => eval(code)).toThrow(); + } + + function shouldNotThrow(code) { + eval(code); + } + + description("This page tests assertions followed by quantifiers."); + + var regexp; + + regexp = /(?=a){0}/gm; + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test('a')"); + shouldBe("regexp.lastIndex", "0"); + + regexp = /(?=a){1}/gm; + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test('a')"); + shouldBe("regexp.lastIndex", "0"); + + regexp = /(?!a){0}/gm; + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test('b')"); + shouldBe("regexp.lastIndex", "0"); + + regexp = /(?!a){1}/gm; + debug("\nTesting regexp: " + regexp); + shouldBeTrue("regexp.test('b')"); + shouldBe("regexp.lastIndex", "0"); + + shouldBeTrue('/^(?=a)?b$/.test("b")'); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/webkit/repeat-match-waldemar.js b/Tests/LibJS/Runtime/3rdparty/webkit/repeat-match-waldemar.js new file mode 100644 index 00000000000..b04b5c6cbd7 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/webkit/repeat-match-waldemar.js @@ -0,0 +1,77 @@ +test.xfail("repeat-match-waldemar", () => { + // WebKit assertion compatibility shim for Ladybird's test-js harness + + function description(msg) { + // No-op, just used for test documentation in WebKit. + } + + function shouldBe(actual_code, expected_code) { + let actual = eval(actual_code); + let expected = eval(expected_code); + if (typeof actual === "string" && typeof expected === "string") { + expect(actual).toBe(expected); + } else if (Array.isArray(actual) && Array.isArray(expected)) { + expect(actual).toEqual(expected); + } else if (actual !== null && typeof actual === "object" && expected !== null && typeof expected === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } + } + + function shouldBeTrue(code) { + expect(eval(code)).toBeTrue(); + } + + function shouldBeFalse(code) { + expect(eval(code)).toBeFalse(); + } + + function shouldBeNull(code) { + expect(eval(code)).toBeNull(); + } + + function shouldBeUndefined(code) { + expect(eval(code)).toBeUndefined(); + } + + function shouldThrow(code, expected_error) { + expect(() => eval(code)).toThrow(); + } + + function shouldNotThrow(code) { + eval(code); + } + + description( + "Some test cases identified by Waldemar Horwat in response to this bug: https://bugs.webkit.org/show_bug.cgi?id=48101" + ); + + shouldBe('/(?:a*?){2,}/.exec("aa")', '["aa"]'); + shouldBe('/(?:a*?){2,}/.exec("a")', '["a"]'); + shouldBe('/(?:a*?){2,}/.exec("")', '[""]'); + + shouldBe('/(?:a*?)/.exec("aa")', '[""]'); + shouldBe('/(?:a*?)/.exec("a")', '[""]'); + shouldBe('/(?:a*?)/.exec("")', '[""]'); + + shouldBe('/(?:a*?)(?:a*?)(?:a*?)/.exec("aa")', '[""]'); + shouldBe('/(?:a*?)(?:a*?)(?:a*?)/.exec("a")', '[""]'); + shouldBe('/(?:a*?)(?:a*?)(?:a*?)/.exec("")', '[""]'); + + shouldBe('/(?:a*?){2}/.exec("aa")', '[""]'); + shouldBe('/(?:a*?){2}/.exec("a")', '[""]'); + shouldBe('/(?:a*?){2}/.exec("")', '[""]'); + + shouldBe('/(?:a*?){2,3}/.exec("aa")', '["a"]'); + shouldBe('/(?:a*?){2,3}/.exec("a")', '["a"]'); + shouldBe('/(?:a*?){2,3}/.exec("")', '[""]'); + + shouldBe('/(?:a*?)?/.exec("aa")', '["a"]'); + shouldBe('/(?:a*?)?/.exec("a")', '["a"]'); + shouldBe('/(?:a*?)?/.exec("")', '[""]'); + + shouldBe('/(?:a*?)*/.exec("aa")', '["aa"]'); + shouldBe('/(?:a*?)*/.exec("a")', '["a"]'); + shouldBe('/(?:a*?)*/.exec("")', '[""]'); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/webkit/slow.js b/Tests/LibJS/Runtime/3rdparty/webkit/slow.js new file mode 100644 index 00000000000..873b55c2759 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/webkit/slow.js @@ -0,0 +1,51 @@ +test.xfail("slow", () => { + // WebKit assertion compatibility shim for Ladybird's test-js harness + + function description(msg) { + // No-op, just used for test documentation in WebKit. + } + + function shouldBe(actual_code, expected_code) { + let actual = eval(actual_code); + let expected = eval(expected_code); + if (typeof actual === "string" && typeof expected === "string") { + expect(actual).toBe(expected); + } else if (Array.isArray(actual) && Array.isArray(expected)) { + expect(actual).toEqual(expected); + } else if (actual !== null && typeof actual === "object" && expected !== null && typeof expected === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } + } + + function shouldBeTrue(code) { + expect(eval(code)).toBeTrue(); + } + + function shouldBeFalse(code) { + expect(eval(code)).toBeFalse(); + } + + function shouldBeNull(code) { + expect(eval(code)).toBeNull(); + } + + function shouldBeUndefined(code) { + expect(eval(code)).toBeUndefined(); + } + + function shouldThrow(code, expected_error) { + expect(() => eval(code)).toThrow(); + } + + function shouldNotThrow(code) { + eval(code); + } + + description( + "Test for expressions that would hang when evaluated due to exponential matching behavior. If the test does not hang it is a success." + ); + + shouldBe('/(?:[^(?!)]||){23}z/.test("/(?:[^(?!)]||){23}z/")', "false"); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/webkit/string-split-newline.js b/Tests/LibJS/Runtime/3rdparty/webkit/string-split-newline.js new file mode 100644 index 00000000000..e82a8e1369d --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/webkit/string-split-newline.js @@ -0,0 +1,106 @@ +test("string-split-newline", () => { + // WebKit assertion compatibility shim for Ladybird's test-js harness + + function description(msg) { + // No-op, just used for test documentation in WebKit. + } + + function shouldBe(actual_code, expected_code) { + let actual = eval(actual_code); + let expected = eval(expected_code); + if (typeof actual === "string" && typeof expected === "string") { + expect(actual).toBe(expected); + } else if (Array.isArray(actual) && Array.isArray(expected)) { + expect(actual).toEqual(expected); + } else if (actual !== null && typeof actual === "object" && expected !== null && typeof expected === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } + } + + function shouldBeTrue(code) { + expect(eval(code)).toBeTrue(); + } + + function shouldBeFalse(code) { + expect(eval(code)).toBeFalse(); + } + + function shouldBeNull(code) { + expect(eval(code)).toBeNull(); + } + + function shouldBeUndefined(code) { + expect(eval(code)).toBeUndefined(); + } + + function shouldThrow(code, expected_error) { + expect(() => eval(code)).toThrow(); + } + + function shouldNotThrow(code) { + eval(code); + } + + description("This test checks the SIMD-optimized newline splitting patterns for correctness."); + + // Test the optimized patterns: /\r\n?|\n/ and /\n|\r\n?/ + // These patterns match LF (\n), CR (\r), and CRLF (\r\n) + + var newlinePatterns = [/\r\n?|\n/, /\n|\r\n?/]; + var newlineTypes = ["\\n", "\\r", "\\r\\n"]; + + newlinePatterns.forEach(function (pattern, patternIndex) { + shouldBe(`"".split(newlinePatterns[${patternIndex}])`, '[""]'); + shouldBe(`"no newlines".split(newlinePatterns[${patternIndex}])`, '["no newlines"]'); + shouldBe(`"abc".split(newlinePatterns[${patternIndex}])`, '["abc"]'); + shouldBe( + `"Line1\\r\\nLine2\\nLine3\\rLine4".split(newlinePatterns[${patternIndex}])`, + '["Line1", "Line2", "Line3", "Line4"]' + ); + newlineTypes.forEach(function (nl) { + shouldBe(`"${nl}".split(newlinePatterns[${patternIndex}])`, '["", ""]'); + shouldBe(`"${nl}text".split(newlinePatterns[${patternIndex}])`, '["", "text"]'); + shouldBe(`"a${nl}b".split(newlinePatterns[${patternIndex}])`, '["a", "b"]'); + shouldBe(`"a${nl}b${nl}c".split(newlinePatterns[${patternIndex}])`, '["a", "b", "c"]'); + shouldBe(`"text${nl}".split(newlinePatterns[${patternIndex}])`, '["text", ""]'); + shouldBe(`"${nl}${nl}".split(newlinePatterns[${patternIndex}])`, '["", "", ""]'); + shouldBe(`"a${nl}${nl}b".split(newlinePatterns[${patternIndex}])`, '["a", "", "b"]'); + shouldBe(`"a${nl}b${nl}c".split(newlinePatterns[${patternIndex}], 2)`, '["a", "b"]'); + shouldBe(`"a${nl}b${nl}".split(newlinePatterns[${patternIndex}], 2)`, '["a", "b"]'); + shouldBe(`"a${nl}b${nl}c${nl}".split(newlinePatterns[${patternIndex}], 3)`, '["a", "b", "c"]'); + shouldBe( + `"This is a very long string that exceeds 32 chars to test vectorMatch in the SIMD-optimized function${nl}Second line".split(newlinePatterns[${patternIndex}])`, + '["This is a very long string that exceeds 32 chars to test vectorMatch in the SIMD-optimized function", "Second line"]' + ); + }); + }); + + /(test)(123)/.exec("test123"); + shouldBe("RegExp.$1", '"test"'); + shouldBe("RegExp.$2", '"123"'); + + "".split(/\r\n?|\n/); + shouldBe("RegExp.$1", '"test"'); + shouldBe("RegExp.$2", '"123"'); + + "a\nb\nc".split(/\r\n?|\n/); + shouldBe("RegExp.$1", '""'); + shouldBe("RegExp.$2", '""'); + + /(foo)(bar)/.exec("foobar"); + shouldBe("RegExp.$1", '"foo"'); + shouldBe("RegExp.$2", '"bar"'); + + "x\ny\nz".split(/\n|\r\n?/); + shouldBe("RegExp.$1", '""'); + shouldBe("RegExp.$2", '""'); + + "hello\nworld".split(/\r\n?|\n/); + shouldBe("RegExp.lastMatch", '"\\n"'); + "hello\r\nworld".split(/\r\n?|\n/); + shouldBe("RegExp.lastMatch", '"\\r\\n"'); + "hello\rworld".split(/\r\n?|\n/); + shouldBe("RegExp.lastMatch", '"\\r"'); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/webkit/toString.js b/Tests/LibJS/Runtime/3rdparty/webkit/toString.js new file mode 100644 index 00000000000..3a21a31c0b3 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/webkit/toString.js @@ -0,0 +1,110 @@ +test("toString", () => { + // WebKit assertion compatibility shim for Ladybird's test-js harness + + function description(msg) { + // No-op, just used for test documentation in WebKit. + } + + function shouldBe(actual_code, expected_code) { + let actual = eval(actual_code); + let expected = eval(expected_code); + if (typeof actual === "string" && typeof expected === "string") { + expect(actual).toBe(expected); + } else if (Array.isArray(actual) && Array.isArray(expected)) { + expect(actual).toEqual(expected); + } else if (actual !== null && typeof actual === "object" && expected !== null && typeof expected === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } + } + + function shouldBeTrue(code) { + expect(eval(code)).toBeTrue(); + } + + function shouldBeFalse(code) { + expect(eval(code)).toBeFalse(); + } + + function shouldBeNull(code) { + expect(eval(code)).toBeNull(); + } + + function shouldBeUndefined(code) { + expect(eval(code)).toBeUndefined(); + } + + function shouldThrow(code, expected_error) { + expect(() => eval(code)).toThrow(); + } + + function shouldNotThrow(code) { + eval(code); + } + + description( + "This page tests toString conversion of RegExp objects, particularly wrt to '/' characters and RegExp.prototype." + ); + + function testForwardSlash(pattern, _string) { + string = _string; + + re1 = new RegExp(pattern); + re2 = eval(re1.toString()); + + return re1.test(string) && re2.test(string); + } + + function testLineTerminator(pattern) { + re1 = new RegExp(pattern); + + return /\n|\r|\u2028|\u2029/.test(re1.toString()); + } + + shouldBe("RegExp('/').source", '"\\\\/"'); + shouldBe("RegExp('').source", '"(?:)"'); + shouldBe("RegExp.prototype.source", '"(?:)"'); + + shouldBe("RegExp('/').toString()", '"/\\\\//"'); + shouldBe("RegExp('').toString()", '"/(?:)/"'); + shouldBe("RegExp.prototype.toString()", '"/(?:)/"'); + + // These strings are equivalent, since the '\' is identity escaping the '/' at the string level. + shouldBeTrue('testForwardSlash("^/$", "/");'); + shouldBeTrue('testForwardSlash("^\/$", "/");'); + // This string passes "^\/$" to the RegExp, so the '/' is escaped in the re! + shouldBeTrue('testForwardSlash("^\\/$", "/");'); + // These strings pass "^\\/$" and "^\\\/$" respectively to the RegExp, giving one '\' to match. + shouldBeTrue('testForwardSlash("^\\\\/$", "\\/");'); + shouldBeTrue('testForwardSlash("^\\\\\\/$", "\\/");'); + // These strings match two backslashes (the second with the '/' escaped). + shouldBeTrue('testForwardSlash("^\\\\\\\\/$", "\\\\/");'); + shouldBeTrue('testForwardSlash("^\\\\\\\\\\/$", "\\\\/");'); + // Test that nothing goes wrongif there are multiple forward slashes! + shouldBeTrue('testForwardSlash("x/x/x", "x\\/x\\/x");'); + shouldBeTrue('testForwardSlash("x\\/x/x", "x\\/x\\/x");'); + shouldBeTrue('testForwardSlash("x/x\\/x", "x\\/x\\/x");'); + shouldBeTrue('testForwardSlash("x\\/x\\/x", "x\\/x\\/x");'); + + shouldBeFalse('testLineTerminator("\\n");'); + shouldBeFalse('testLineTerminator("\\\\n");'); + shouldBeFalse('testLineTerminator("\\r");'); + shouldBeFalse('testLineTerminator("\\\\r");'); + shouldBeFalse('testLineTerminator("\\u2028");'); + shouldBeFalse('testLineTerminator("\\\\u2028");'); + shouldBeFalse('testLineTerminator("\\u2029");'); + shouldBeFalse('testLineTerminator("\\\\u2029");'); + + shouldBe("RegExp('[/]').source", "'[/]'"); + shouldBe("RegExp('\\\\[/]').source", "'\\\\[\\\\/]'"); + + // See 15.10.6.4 + // The first half of this checks that: + // Return the String value formed by concatenating the Strings "/", the + // String value of the source property of this RegExp object, and "/"; + // The second half checks that: + // The returned String has the form of a RegularExpressionLiteral that + // evaluates to another RegExp object with the same behaviour as this object. + shouldBe("var o = new RegExp(); o.toString() === '/'+o.source+'/' && eval(o.toString()+'.exec(String())')", '[""]'); +}); diff --git a/Tests/LibJS/Runtime/3rdparty/webkit/unicodeCaseInsensitive.js b/Tests/LibJS/Runtime/3rdparty/webkit/unicodeCaseInsensitive.js new file mode 100644 index 00000000000..c8ae26af8c9 --- /dev/null +++ b/Tests/LibJS/Runtime/3rdparty/webkit/unicodeCaseInsensitive.js @@ -0,0 +1,129 @@ +test("unicodeCaseInsensitive", () => { + // WebKit assertion compatibility shim for Ladybird's test-js harness + + function description(msg) { + // No-op, just used for test documentation in WebKit. + } + + function shouldBe(actual_code, expected_code) { + let actual = eval(actual_code); + let expected = eval(expected_code); + if (typeof actual === "string" && typeof expected === "string") { + expect(actual).toBe(expected); + } else if (Array.isArray(actual) && Array.isArray(expected)) { + expect(actual).toEqual(expected); + } else if (actual !== null && typeof actual === "object" && expected !== null && typeof expected === "object") { + expect(actual).toEqual(expected); + } else { + expect(actual).toBe(expected); + } + } + + function shouldBeTrue(code) { + expect(eval(code)).toBeTrue(); + } + + function shouldBeFalse(code) { + expect(eval(code)).toBeFalse(); + } + + function shouldBeNull(code) { + expect(eval(code)).toBeNull(); + } + + function shouldBeUndefined(code) { + expect(eval(code)).toBeUndefined(); + } + + function shouldThrow(code, expected_error) { + expect(() => eval(code)).toThrow(); + } + + function shouldNotThrow(code) { + eval(code); + } + + description("https://bugs.webkit.org/show_bug.cgi?id=82063"); + + shouldBeTrue('/ΣΤΙΓΜΑΣ/i.test("στιγμας")'); + shouldBeTrue('/ΔΣΔ/i.test("δςδ")'); + shouldBeTrue('/ς/i.test("σ")'); + shouldBeTrue('/σ/i.test("ς")'); + + // Simple case, has no canonical equivalents + shouldBeTrue('/\u1f16/i.test("\u1f16")'); + + // Test the sets of USC2 code points that have more than one canonically equivalent value. + function ucs2CodePoint(x) { + var s = x.toString(16); + while (s.length < 4) s = 0 + s; + return eval('"\\u' + s + '"'); + } + function testSet(set) { + for (i in set) { + for (j in set) { + shouldBeTrue("/" + ucs2CodePoint(set[i]) + '/i.test("' + ucs2CodePoint(set[j]) + '")'); + shouldBeTrue( + "/[" + + ucs2CodePoint(set[i] - 1) + + "-" + + ucs2CodePoint(set[i] + 1) + + ']/i.test("' + + ucs2CodePoint(set[j]) + + '")' + ); + } + } + } + testSet([0x01c4, 0x01c5, 0x01c6]); + testSet([0x01c7, 0x01c8, 0x01c9]); + testSet([0x01ca, 0x01cb, 0x01cc]); + testSet([0x01f1, 0x01f2, 0x01f3]); + testSet([0x0392, 0x03b2, 0x03d0]); + testSet([0x0395, 0x03b5, 0x03f5]); + testSet([0x0398, 0x03b8, 0x03d1]); + testSet([0x0345, 0x0399, 0x03b9, 0x1fbe]); + testSet([0x039a, 0x03ba, 0x03f0]); + testSet([0x00b5, 0x039c, 0x03bc]); + testSet([0x03a0, 0x03c0, 0x03d6]); + testSet([0x03a1, 0x03c1, 0x03f1]); + testSet([0x03a3, 0x03c2, 0x03c3]); + testSet([0x03a6, 0x03c6, 0x03d5]); + testSet([0x1e60, 0x1e61, 0x1e9b]); + + // Test a couple of lo/hi pairs + shouldBeTrue('/\u03cf/i.test("\u03cf")'); + shouldBeTrue('/\u03d7/i.test("\u03cf")'); + shouldBeTrue('/\u03cf/i.test("\u03d7")'); + shouldBeTrue('/\u03d7/i.test("\u03d7")'); + shouldBeTrue('/\u1f11/i.test("\u1f11")'); + shouldBeTrue('/\u1f19/i.test("\u1f11")'); + shouldBeTrue('/\u1f11/i.test("\u1f19")'); + shouldBeTrue('/\u1f19/i.test("\u1f19")'); + + // Test an aligned alternating capitalization pair. + shouldBeFalse('/\u0489/i.test("\u048a")'); + shouldBeTrue('/\u048a/i.test("\u048a")'); + shouldBeTrue('/\u048b/i.test("\u048a")'); + shouldBeFalse('/\u048c/i.test("\u048a")'); + shouldBeFalse('/\u0489/i.test("\u048b")'); + shouldBeTrue('/\u048a/i.test("\u048b")'); + shouldBeTrue('/\u048b/i.test("\u048b")'); + shouldBeFalse('/\u048c/i.test("\u048b")'); + shouldBeTrue('/[\u0489-\u048a]/i.test("\u048b")'); + shouldBeTrue('/[\u048b-\u048c]/i.test("\u048a")'); + + // Test an unaligned alternating capitalization pair. + shouldBeFalse('/\u04c4/i.test("\u04c5")'); + shouldBeTrue('/\u04c5/i.test("\u04c5")'); + shouldBeTrue('/\u04c6/i.test("\u04c5")'); + shouldBeFalse('/\u04c7/i.test("\u04c5")'); + shouldBeFalse('/\u04c4/i.test("\u04c6")'); + shouldBeTrue('/\u04c5/i.test("\u04c6")'); + shouldBeTrue('/\u04c6/i.test("\u04c6")'); + shouldBeFalse('/\u04c7/i.test("\u04c6")'); + shouldBeTrue('/[\u04c4-\u04c5]/i.test("\u04c6")'); + shouldBeTrue('/[\u04c6-\u04c7]/i.test("\u04c5")'); + + var successfullyParsed = true; +});