diff options
Diffstat (limited to 'js/src/builtin/RegExpGlobalReplaceOpt.h.js')
-rw-r--r-- | js/src/builtin/RegExpGlobalReplaceOpt.h.js | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/js/src/builtin/RegExpGlobalReplaceOpt.h.js b/js/src/builtin/RegExpGlobalReplaceOpt.h.js new file mode 100644 index 000000000..fbe50a3f9 --- /dev/null +++ b/js/src/builtin/RegExpGlobalReplaceOpt.h.js @@ -0,0 +1,128 @@ +// Function template for the following functions: +// * RegExpGlobalReplaceOpt +// * RegExpGlobalReplaceOptFunc +// * RegExpGlobalReplaceOptSubst +// * RegExpGlobalReplaceOptElemBase +// Define the following macro and include this file to declare function: +// * FUNC_NAME -- function name (required) +// e.g. +// #define FUNC_NAME RegExpGlobalReplaceOpt +// Define the following macro (without value) to switch the code: +// * SUBSTITUTION -- replaceValue is a string with "$" +// * FUNCTIONAL -- replaceValue is a function +// * ELEMBASE -- replaceValue is a function that returns an element +// of an object +// * none of above -- replaceValue is a string without "$" + +// ES 2017 draft 03bfda119d060aca4099d2b77cf43f6d4f11cfa2 21.2.5.8 +// steps 8.b-16. +// Optimized path for @@replace with the following conditions: +// * global flag is true +function FUNC_NAME(rx, S, lengthS, replaceValue, fullUnicode +#ifdef SUBSTITUTION + , firstDollarIndex +#endif +#ifdef ELEMBASE + , elemBase +#endif + ) +{ + // Step 8.b. + var lastIndex = 0; + rx.lastIndex = 0; + +#if defined(FUNCTIONAL) || defined(SUBSTITUTION) + // Clone RegExp object here to avoid the effect of RegExp#compile, + // that may be called in replaceValue function. + rx = regexp_clone(rx); +#endif + + // Step 12 (reordered). + var accumulatedResult = ""; + + // Step 13 (reordered). + var nextSourcePosition = 0; + + // Step 11. + while (true) { + // Step 11.a. + var result = RegExpMatcher(rx, S, lastIndex); + + // Step 11.b. + if (result === null) + break; + + var nCaptures; +#if defined(FUNCTIONAL) || defined(SUBSTITUTION) + // Steps 14.a-b. + nCaptures = std_Math_max(result.length - 1, 0); +#endif + + // Step 14.c (reordered). + var matched = result[0]; + + // Step 14.d. + var matchLength = matched.length; + + // Steps 14.e-f. + var position = result.index; + lastIndex = position + matchLength; + + // Steps g-j. + var replacement; +#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); +#elif defined(ELEMBASE) + if (IsObject(elemBase)) { + var prop = GetStringDataProperty(elemBase, matched); + if (prop !== undefined) { + assert(typeof prop === "string", "GetStringDataProperty should return either string or undefined"); + replacement = prop; + } else { + elemBase = undefined; + } + } + + if (!IsObject(elemBase)) { + // Steps 14.a-b (reordered). + nCaptures = std_Math_max(result.length - 1, 0); + + replacement = RegExpGetComplexReplacement(result, matched, S, position, + + nCaptures, replaceValue, + true, -1); + } +#else + replacement = replaceValue; +#endif + + // Step 14.l.ii. + accumulatedResult += Substring(S, nextSourcePosition, + position - nextSourcePosition) + replacement; + + // Step 14.l.iii. + nextSourcePosition = lastIndex; + + // Step 11.c.iii.2. + if (matchLength === 0) { + lastIndex = fullUnicode ? AdvanceStringIndex(S, lastIndex) : lastIndex + 1; + if (lastIndex > lengthS) + break; + } + } + + // Step 15. + if (nextSourcePosition >= lengthS) + return accumulatedResult; + + // Step 16. + return accumulatedResult + Substring(S, nextSourcePosition, lengthS - nextSourcePosition); +} |