summaryrefslogtreecommitdiffstats
path: root/js/src/tests/ecma_2017/lastIndex-exec.js
blob: f42facbe340e1bbe11f7aa7588ed16324a40faaf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
// RegExp.prototype.exec: Test lastIndex changes for ES2017.

// Test various combinations of:
// - Pattern matches or doesn't match
// - Global and/or sticky flag is set.
// - lastIndex exceeds the input string length
// - lastIndex is +-0
const testCases = [
    { regExp: /a/,  lastIndex: 0, input: "a", result: 0 },
    { regExp: /a/g, lastIndex: 0, input: "a", result: 1 },
    { regExp: /a/y, lastIndex: 0, input: "a", result: 1 },

    { regExp: /a/,  lastIndex: 0, input: "b", result: 0 },
    { regExp: /a/g, lastIndex: 0, input: "b", result: 0 },
    { regExp: /a/y, lastIndex: 0, input: "b", result: 0 },

    { regExp: /a/,  lastIndex: -0, input: "a", result: -0 },
    { regExp: /a/g, lastIndex: -0, input: "a", result: 1 },
    { regExp: /a/y, lastIndex: -0, input: "a", result: 1 },

    { regExp: /a/,  lastIndex: -0, input: "b", result: -0 },
    { regExp: /a/g, lastIndex: -0, input: "b", result: 0 },
    { regExp: /a/y, lastIndex: -0, input: "b", result: 0 },

    { regExp: /a/,  lastIndex: -1, input: "a", result: -1 },
    { regExp: /a/g, lastIndex: -1, input: "a", result: 1 },
    { regExp: /a/y, lastIndex: -1, input: "a", result: 1 },

    { regExp: /a/,  lastIndex: -1, input: "b", result: -1 },
    { regExp: /a/g, lastIndex: -1, input: "b", result: 0 },
    { regExp: /a/y, lastIndex: -1, input: "b", result: 0 },

    { regExp: /a/,  lastIndex: 100, input: "a", result: 100 },
    { regExp: /a/g, lastIndex: 100, input: "a", result: 0 },
    { regExp: /a/y, lastIndex: 100, input: "a", result: 0 },
];

// Basic test.
for (let {regExp, lastIndex, input, result} of testCases) {
    let re = new RegExp(regExp);
    re.lastIndex = lastIndex;
    re.exec(input);
    assertEq(re.lastIndex, result);
}

// Test when lastIndex is non-writable.
for (let {regExp, lastIndex, input} of testCases) {
    let re = new RegExp(regExp);
    Object.defineProperty(re, "lastIndex", { value: lastIndex, writable: false });
    if (re.global || re.sticky) {
        assertThrowsInstanceOf(() => re.exec(input), TypeError);
    } else {
        re.exec(input);
    }
    assertEq(re.lastIndex, lastIndex);
}

// Test when lastIndex is changed to non-writable as a side-effect.
for (let {regExp, lastIndex, input} of testCases) {
    let re = new RegExp(regExp);
    let called = false;
    re.lastIndex = {
        valueOf() {
            assertEq(called, false);
            called = true;
            Object.defineProperty(re, "lastIndex", { value: 9000, writable: false });
            return lastIndex;
        }
    };
    if (re.global || re.sticky) {
        assertThrowsInstanceOf(() => re.exec(input), TypeError);
    } else {
        re.exec(input);
    }
    assertEq(re.lastIndex, 9000);
    assertEq(called, true);
}

if (typeof reportCompare === "function")
    reportCompare(true, true);