summaryrefslogtreecommitdiff
path: root/js/src/builtin/RegExpLocalReplaceOpt.h.js
blob: edc2e2056c13646690e3ee1199ff699e6096c1b8 (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
81
82
83
84
85
86
87
88
89
90
91
92
// Function template for the following functions:
//   * RegExpLocalReplaceOpt
//   * RegExpLocalReplaceOptFunc
//   * RegExpLocalReplaceOptSubst
// Define the following macro and include this file to declare function:
//   * FUNC_NAME     -- function name (required)
//       e.g.
//         #define FUNC_NAME RegExpLocalReplaceOpt
// Define the following macro (without value) to switch the code:
//   * SUBSTITUTION     -- replaceValue is a string with "$"
//   * FUNCTIONAL       -- replaceValue is a function
//   * neither of above -- replaceValue is a string without "$"

// ES 2017 draft 03bfda119d060aca4099d2b77cf43f6d4f11cfa2 21.2.5.8
// steps 11.a-16.
// Optimized path for @@replace with the following conditions:
//   * global flag is false
function FUNC_NAME(rx, S, lengthS, replaceValue, sticky
#ifdef SUBSTITUTION
                   , firstDollarIndex
#endif
                  )
{
    var lastIndex;
    if (sticky) {
        lastIndex = ToLength(rx.lastIndex);
        if (lastIndex > lengthS) {
            rx.lastIndex = 0;
            return S;
        }
    } else {
        lastIndex = 0;
    }

    // Step 11.a.
    var result = RegExpMatcher(rx, S, lastIndex);

    // Step 11.b.
    if (result === null) {
        rx.lastIndex = 0;
        return S;
    }

    // Steps 11.c, 12-13, 14.a-b (skipped).

#if defined(FUNCTIONAL) || defined(SUBSTITUTION)
    // Steps 14.a-b.
    var nCaptures = std_Math_max(result.length - 1, 0);
#endif

    // Step 14.c.
    var matched = result[0];

    // Step 14.d.
    var matchLength = matched.length;

    // Step 14.e-f.
    var position = result.index;

    // Step 14.l.iii (reordered)
    // To set rx.lastIndex before RegExpGetComplexReplacement.
    var nextSourcePosition = position + matchLength;

    if (sticky)
       rx.lastIndex = nextSourcePosition;

    var replacement;
    // Steps g-j.
#if defined(FUNCTIONAL)
    replacement = RegExpGetComplexReplacement(result, matched, S, position,

                                              nCaptures, replaceValue,
                                              true, -1);
#elif defined(SUBSTITUTION)
    replacement = RegExpGetComplexReplacement(result, matched, S, position,

                                              nCaptures, replaceValue,
                                              false, firstDollarIndex);
#else
    replacement = replaceValue;
#endif

    // Step 14.l.ii.
    var accumulatedResult = Substring(S, 0, position) + replacement;

    // Step 15.
    if (nextSourcePosition >= lengthS)
        return accumulatedResult;

    // Step 16.
    return accumulatedResult + Substring(S, nextSourcePosition, lengthS - nextSourcePosition);
}