diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /js/src/builtin/RegExpGlobalReplaceOpt.h.js | |
parent | Initial commit. (diff) | |
download | firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip |
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/builtin/RegExpGlobalReplaceOpt.h.js')
-rw-r--r-- | js/src/builtin/RegExpGlobalReplaceOpt.h.js | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/js/src/builtin/RegExpGlobalReplaceOpt.h.js b/js/src/builtin/RegExpGlobalReplaceOpt.h.js new file mode 100644 index 0000000000..8a11370991 --- /dev/null +++ b/js/src/builtin/RegExpGlobalReplaceOpt.h.js @@ -0,0 +1,139 @@ +/* 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: +// * 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, flags +#ifdef SUBSTITUTION + , firstDollarIndex +#endif +#ifdef ELEMBASE + , elemBase +#endif + ) +{ + // Step 8.a. + var fullUnicode = !!(flags & REGEXP_UNICODE_FLAG); + + // Step 8.b. + var lastIndex = 0; + rx.lastIndex = 0; + +#if defined(FUNCTIONAL) || defined(ELEMBASE) + // Save the original source and flags, so we can check if the replacer + // function recompiled the regexp. + var originalSource = UnsafeGetStringFromReservedSlot(rx, REGEXP_SOURCE_SLOT); + var originalFlags = flags; +#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; + + // Steps 14.a-b (skipped). + assert(result.length >= 1, "RegExpMatcher doesn't return an empty array"); + + // Step 14.c. + var matched = result[0]; + + // Step 14.d. + var matchLength = matched.length | 0; + + // Steps 14.e-f. + var position = result.index | 0; + lastIndex = position + matchLength; + + // Steps g-l. + var replacement; +#if defined(FUNCTIONAL) + replacement = RegExpGetFunctionalReplacement(result, S, position, replaceValue); +#elif defined(SUBSTITUTION) + // Step l.i + var namedCaptures = result.groups; + if (namedCaptures !== undefined) { + namedCaptures = ToObject(namedCaptures); + } + // Step l.ii + replacement = RegExpGetSubstitution(result, S, position, replaceValue, + firstDollarIndex, namedCaptures); +#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)) + replacement = RegExpGetFunctionalReplacement(result, S, position, replaceValue); +#else + replacement = replaceValue; +#endif + + // Step 14.m.ii. + accumulatedResult += Substring(S, nextSourcePosition, + position - nextSourcePosition) + replacement; + + // Step 14.m.iii. + nextSourcePosition = lastIndex; + + // Step 11.c.iii.2. + if (matchLength === 0) { + lastIndex = fullUnicode ? AdvanceStringIndex(S, lastIndex) : lastIndex + 1; + if (lastIndex > lengthS) + break; + lastIndex |= 0; + } + +#if defined(FUNCTIONAL) || defined(ELEMBASE) + // Ensure the current source and flags match the original regexp, the + // replaceValue function may have called RegExp#compile. + if (UnsafeGetStringFromReservedSlot(rx, REGEXP_SOURCE_SLOT) !== originalSource || + UnsafeGetInt32FromReservedSlot(rx, REGEXP_FLAGS_SLOT) !== originalFlags) + { + rx = regexp_construct_raw_flags(originalSource, originalFlags); + } +#endif + } + + // Step 15. + if (nextSourcePosition >= lengthS) + return accumulatedResult; + + // Step 16. + return accumulatedResult + Substring(S, nextSourcePosition, lengthS - nextSourcePosition); +} |