summaryrefslogtreecommitdiffstats
path: root/js/src/builtin/RegExpGlobalReplaceOpt.h.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/builtin/RegExpGlobalReplaceOpt.h.js')
-rw-r--r--js/src/builtin/RegExpGlobalReplaceOpt.h.js128
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);
+}