From 3646912c5c8f20fbc0a90ec3ac318df09ac66591 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Wed, 25 Mar 2026 10:45:59 +0100 Subject: [PATCH] Tests: Import V8 and WebKit regexp suites Add scripts for importing the V8 and WebKit regexp suites into `Tests/LibJS/Runtime/3rdparty/` and commit the imported tests. Also update the local harness helpers so these suites can run under LibJS. In particular, teach the assertion shims to compare RegExp values the way the imported tests expect and to treat `new Function(...)` throwing as a valid `assertThrows` case. This gives the regex rewrite a large bank of external conformance tests that exercise parser and matcher behavior beyond in-tree coverage. --- Meta/import-v8-regexp-tests.py | 310 + Meta/import-webkit-regexp-tests.py | 220 + .../v8/es6/array-concat-spreadable-regexp.js | 92 + .../3rdparty/v8/es6/regexp-constructor.js | 204 + .../Runtime/3rdparty/v8/es6/regexp-flags.js | 219 + .../3rdparty/v8/es6/regexp-match-lastindex.js | 81 + .../3rdparty/v8/es6/regexp-prototype.js | 85 + .../v8/es6/regexp-replace-lastindex.js | 86 + .../Runtime/3rdparty/v8/es6/regexp-sticky.js | 208 + .../3rdparty/v8/es6/regexp-tolength.js | 86 + .../3rdparty/v8/es6/regexp-tostring.js | 125 + .../v8/es6/unicode-escapes-in-regexps.js | 335 + .../v8/es6/unicode-regexp-backrefs.js | 115 + .../es6/unicode-regexp-ignore-case-noi18n.js | 137 + .../v8/es6/unicode-regexp-ignore-case.js | 135 + .../v8/es6/unicode-regexp-last-index.js | 168 + .../es6/unicode-regexp-restricted-syntax.js | 111 + .../es6/unicode-regexp-unanchored-advance.js | 75 + .../v8/es6/unicode-regexp-zero-length.js | 122 + .../3rdparty/v8/harmony/regexp-change-exec.js | 78 + .../3rdparty/v8/harmony/regexp-dotall.js | 202 + .../v8/harmony/regexp-property-binary.js | 239 + .../v8/harmony/regexp-property-char-class.js | 95 + .../v8/harmony/regexp-property-enumerated.js | 92 + .../v8/harmony/regexp-property-exact-match.js | 109 + .../regexp-property-general-category.js | 136 + .../v8/harmony/regexp-property-invalid.js | 107 + .../v8/harmony/regexp-property-lu-ui.js | 96 + .../regexp-property-script-extensions.js | 508 ++ .../v8/harmony/regexp-property-scripts.js | 107 + .../v8/harmony/regexp-property-special.js | 144 + .../LibJS/Runtime/3rdparty/v8/regexp-UC16.js | 126 + .../Runtime/3rdparty/v8/regexp-boyer-moore.js | 99 + .../3rdparty/v8/regexp-cache-replace.js | 118 + .../3rdparty/v8/regexp-call-as-function.js | 118 + .../Runtime/3rdparty/v8/regexp-capture-3.js | 339 + .../Runtime/3rdparty/v8/regexp-capture-4.js | 101 + .../Runtime/3rdparty/v8/regexp-capture.js | 149 + .../Runtime/3rdparty/v8/regexp-captures.js | 116 + .../Runtime/3rdparty/v8/regexp-compile.js | 133 + .../v8/regexp-duplicate-named-groups.js | 268 + .../Runtime/3rdparty/v8/regexp-global.js | 351 + .../Runtime/3rdparty/v8/regexp-indexof.js | 196 + .../Runtime/3rdparty/v8/regexp-lastIndex.js | 102 + .../Runtime/3rdparty/v8/regexp-lookahead.js | 249 + .../3rdparty/v8/regexp-loop-capture.js | 113 + .../Runtime/3rdparty/v8/regexp-modifiers.js | 147 + .../Runtime/3rdparty/v8/regexp-multiline.js | 192 + .../3rdparty/v8/regexp-override-exec.js | 107 + .../v8/regexp-override-symbol-match-all.js | 94 + .../v8/regexp-override-symbol-match.js | 94 + .../v8/regexp-override-symbol-replace.js | 94 + .../v8/regexp-override-symbol-search.js | 94 + .../v8/regexp-override-symbol-split.js | 94 + .../Runtime/3rdparty/v8/regexp-peephole.js | 99 + .../Runtime/3rdparty/v8/regexp-regexpexec.js | 90 + .../3rdparty/v8/regexp-results-cache.js | 166 + .../LibJS/Runtime/3rdparty/v8/regexp-sort.js | 132 + .../3rdparty/v8/regexp-stack-overflow.js | 100 + .../Runtime/3rdparty/v8/regexp-standalones.js | 162 + .../Runtime/3rdparty/v8/regexp-static.js | 251 + .../3rdparty/v8/regexp-string-methods.js | 130 + .../alternative-length-miscalculation.js | 54 + .../Runtime/3rdparty/webkit/assertion.js | 132 + .../Runtime/3rdparty/webkit/backreferences.js | 81 + .../Runtime/3rdparty/webkit/constructor.js | 54 + .../LibJS/Runtime/3rdparty/webkit/dotstar.js | 200 + .../Runtime/3rdparty/webkit/early-acid3-86.js | 54 + .../3rdparty/webkit/ecma-regex-examples.js | 83 + .../3rdparty/webkit/invalid-range-in-class.js | 71 + .../Runtime/3rdparty/webkit/lastIndex.js | 109 + .../3rdparty/webkit/malformed-escapes.js | 92 + .../webkit/non-capturing-backtracking.js | 50 + .../3rdparty/webkit/non-pattern-characters.js | 280 + .../LibJS/Runtime/3rdparty/webkit/overflow.js | 67 + .../Runtime/3rdparty/webkit/parentheses.js | 324 + .../Runtime/3rdparty/webkit/pcre-test-1.js | 6129 +++++++++++++++++ .../Runtime/3rdparty/webkit/pcre-test-4.js | 1196 ++++ .../3rdparty/webkit/quantified-assertions.js | 72 + .../3rdparty/webkit/repeat-match-waldemar.js | 77 + Tests/LibJS/Runtime/3rdparty/webkit/slow.js | 51 + .../3rdparty/webkit/string-split-newline.js | 106 + .../LibJS/Runtime/3rdparty/webkit/toString.js | 110 + .../3rdparty/webkit/unicodeCaseInsensitive.js | 129 + 84 files changed, 18972 insertions(+) create mode 100644 Meta/import-v8-regexp-tests.py create mode 100644 Meta/import-webkit-regexp-tests.py create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/es6/array-concat-spreadable-regexp.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/es6/regexp-constructor.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/es6/regexp-flags.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/es6/regexp-match-lastindex.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/es6/regexp-prototype.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/es6/regexp-replace-lastindex.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/es6/regexp-sticky.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/es6/regexp-tolength.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/es6/regexp-tostring.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/es6/unicode-escapes-in-regexps.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/es6/unicode-regexp-backrefs.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/es6/unicode-regexp-ignore-case-noi18n.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/es6/unicode-regexp-ignore-case.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/es6/unicode-regexp-last-index.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/es6/unicode-regexp-restricted-syntax.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/es6/unicode-regexp-unanchored-advance.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/es6/unicode-regexp-zero-length.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-change-exec.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-dotall.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-property-binary.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-property-char-class.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-property-enumerated.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-property-exact-match.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-property-general-category.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-property-invalid.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-property-lu-ui.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-property-script-extensions.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-property-scripts.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/harmony/regexp-property-special.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/regexp-UC16.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/regexp-boyer-moore.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/regexp-cache-replace.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/regexp-call-as-function.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/regexp-capture-3.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/regexp-capture-4.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/regexp-capture.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/regexp-captures.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/regexp-compile.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/regexp-duplicate-named-groups.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/regexp-global.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/regexp-indexof.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/regexp-lastIndex.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/regexp-lookahead.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/regexp-loop-capture.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/regexp-modifiers.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/regexp-multiline.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/regexp-override-exec.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/regexp-override-symbol-match-all.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/regexp-override-symbol-match.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/regexp-override-symbol-replace.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/regexp-override-symbol-search.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/regexp-override-symbol-split.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/regexp-peephole.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/regexp-regexpexec.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/regexp-results-cache.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/regexp-sort.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/regexp-stack-overflow.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/regexp-standalones.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/regexp-static.js create mode 100644 Tests/LibJS/Runtime/3rdparty/v8/regexp-string-methods.js create mode 100644 Tests/LibJS/Runtime/3rdparty/webkit/alternative-length-miscalculation.js create mode 100644 Tests/LibJS/Runtime/3rdparty/webkit/assertion.js create mode 100644 Tests/LibJS/Runtime/3rdparty/webkit/backreferences.js create mode 100644 Tests/LibJS/Runtime/3rdparty/webkit/constructor.js create mode 100644 Tests/LibJS/Runtime/3rdparty/webkit/dotstar.js create mode 100644 Tests/LibJS/Runtime/3rdparty/webkit/early-acid3-86.js create mode 100644 Tests/LibJS/Runtime/3rdparty/webkit/ecma-regex-examples.js create mode 100644 Tests/LibJS/Runtime/3rdparty/webkit/invalid-range-in-class.js create mode 100644 Tests/LibJS/Runtime/3rdparty/webkit/lastIndex.js create mode 100644 Tests/LibJS/Runtime/3rdparty/webkit/malformed-escapes.js create mode 100644 Tests/LibJS/Runtime/3rdparty/webkit/non-capturing-backtracking.js create mode 100644 Tests/LibJS/Runtime/3rdparty/webkit/non-pattern-characters.js create mode 100644 Tests/LibJS/Runtime/3rdparty/webkit/overflow.js create mode 100644 Tests/LibJS/Runtime/3rdparty/webkit/parentheses.js create mode 100644 Tests/LibJS/Runtime/3rdparty/webkit/pcre-test-1.js create mode 100644 Tests/LibJS/Runtime/3rdparty/webkit/pcre-test-4.js create mode 100644 Tests/LibJS/Runtime/3rdparty/webkit/quantified-assertions.js create mode 100644 Tests/LibJS/Runtime/3rdparty/webkit/repeat-match-waldemar.js create mode 100644 Tests/LibJS/Runtime/3rdparty/webkit/slow.js create mode 100644 Tests/LibJS/Runtime/3rdparty/webkit/string-split-newline.js create mode 100644 Tests/LibJS/Runtime/3rdparty/webkit/toString.js create mode 100644 Tests/LibJS/Runtime/3rdparty/webkit/unicodeCaseInsensitive.js 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+ <34"; + var results = ["> <"]; + shouldBe("regex62.exec(input0);", "results"); + + var regex63 = />\s{2,3} <"]; + shouldBe("regex63.exec(input0);", "results"); + var input1 = "ab> <"]; + shouldBe("regex63.exec(input1);", "results"); + // Failers + var input2 = "ab> \s{2,3}? <"]; + 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; +});