summaryrefslogtreecommitdiffstats
path: root/js/src/builtin/RegExpLocalReplaceOpt.h.js
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /js/src/builtin/RegExpLocalReplaceOpt.h.js
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/builtin/RegExpLocalReplaceOpt.h.js')
-rw-r--r--js/src/builtin/RegExpLocalReplaceOpt.h.js160
1 files changed, 160 insertions, 0 deletions
diff --git a/js/src/builtin/RegExpLocalReplaceOpt.h.js b/js/src/builtin/RegExpLocalReplaceOpt.h.js
new file mode 100644
index 0000000000..869f03fe07
--- /dev/null
+++ b/js/src/builtin/RegExpLocalReplaceOpt.h.js
@@ -0,0 +1,160 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Function template for the following functions:
+// * RegExpLocalReplaceOptSimple
+// * 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 one of the following macros (without value) to switch the code:
+// * SUBSTITUTION -- replaceValue is a string with "$"
+// * FUNCTIONAL -- replaceValue is a function
+// * SIMPLE -- replaceValue is a string without "$"
+
+// ES2023 draft rev 2c78e6f6b5bc6bfbf79dd8a12a9593e5b57afcd2
+// 22.2.5.11 RegExp.prototype [ @@replace ] ( string, replaceValue )
+// Steps 12.a-17.
+// Optimized path for @@replace with the following conditions:
+// * global flag is false
+function FUNC_NAME(
+ rx,
+ S,
+ lengthS,
+ replaceValue,
+#ifdef SUBSTITUTION
+ firstDollarIndex
+#endif
+) {
+ // 21.2.5.2.2 RegExpBuiltinExec, step 4.
+ var lastIndex = ToLength(rx.lastIndex);
+
+ // 21.2.5.2.2 RegExpBuiltinExec, step 5.
+ // Side-effects in step 4 can recompile the RegExp, so we need to read the
+ // flags again and handle the case when global was enabled even though this
+ // function is optimized for non-global RegExps.
+ var flags = UnsafeGetInt32FromReservedSlot(rx, REGEXP_FLAGS_SLOT);
+
+ // 21.2.5.2.2 RegExpBuiltinExec, steps 6-7.
+ var globalOrSticky = !!(flags & (REGEXP_GLOBAL_FLAG | REGEXP_STICKY_FLAG));
+
+ if (globalOrSticky) {
+ // 21.2.5.2.2 RegExpBuiltinExec, step 12.a.
+ if (lastIndex > lengthS) {
+ if (globalOrSticky) {
+ rx.lastIndex = 0;
+ }
+
+ // Steps 12-16.
+ return S;
+ }
+ } else {
+ // 21.2.5.2.2 RegExpBuiltinExec, step 8.
+ lastIndex = 0;
+ }
+
+#if !defined(SIMPLE)
+ // Step 12.a.
+ var result = RegExpMatcher(rx, S, lastIndex);
+
+ // Step 12.b.
+ if (result === null) {
+ // 21.2.5.2.2 RegExpBuiltinExec, steps 12.a.i, 12.c.i.
+ if (globalOrSticky) {
+ rx.lastIndex = 0;
+ }
+
+ // Steps 13-17.
+ return S;
+ }
+#else
+ // Step 12.a.
+ var position = RegExpSearcher(rx, S, lastIndex);
+
+ // Step 12.b.
+ if (position === -1) {
+ // 21.2.5.2.2 RegExpBuiltinExec, steps 12.a.i, 12.c.i.
+ if (globalOrSticky) {
+ rx.lastIndex = 0;
+ }
+
+ // Steps 13-17.
+ return S;
+ }
+#endif
+
+ // Steps 12.c, 13-14.
+
+#if !defined(SIMPLE)
+ // Steps 15.a-b.
+ assert(result.length >= 1, "RegExpMatcher doesn't return an empty array");
+
+ // Step 15.c.
+ var matched = result[0];
+
+ // Step 15.d.
+ var matchLength = matched.length;
+
+ // Step 15.e-f.
+ var position = result.index;
+
+ // Step 15.m.iii (reordered)
+ // To set rx.lastIndex before RegExpGetFunctionalReplacement.
+ var nextSourcePosition = position + matchLength;
+#else
+ // Steps 15.a-f (skipped).
+
+ // Step 15.m.iii (reordered)
+ var nextSourcePosition = RegExpSearcherLastLimit(S);
+#endif
+
+ // 21.2.5.2.2 RegExpBuiltinExec, step 15.
+ if (globalOrSticky) {
+ rx.lastIndex = nextSourcePosition;
+ }
+
+ var replacement;
+ // Steps 15.g-l.
+#if defined(FUNCTIONAL)
+ replacement = RegExpGetFunctionalReplacement(
+ result,
+ S,
+ position,
+ replaceValue
+ );
+#elif defined(SUBSTITUTION)
+ // Step 15.l.i
+ var namedCaptures = result.groups;
+ if (namedCaptures !== undefined) {
+ namedCaptures = ToObject(namedCaptures);
+ }
+ // Step 15.l.ii
+ replacement = RegExpGetSubstitution(
+ result,
+ S,
+ position,
+ replaceValue,
+ firstDollarIndex,
+ namedCaptures
+ );
+#else
+ replacement = replaceValue;
+#endif
+
+ // Step 15.m.ii.
+ var accumulatedResult = Substring(S, 0, position) + replacement;
+
+ // Step 16.
+ if (nextSourcePosition >= lengthS) {
+ return accumulatedResult;
+ }
+
+ // Step 17.
+ return (
+ accumulatedResult +
+ Substring(S, nextSourcePosition, lengthS - nextSourcePosition)
+ );
+}