/* 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/. */
// https://github.com/tc39/ecma262/pull/2418 22.2.6.4 get RegExp.prototype.flags // https://arai-a.github.io/ecma262-compare/?pr=2418&id=sec-get-regexp.prototype.flags // Uncloned functions with `$` prefix are allocated as extended function // to store the original name in `SetCanonicalName`. function $RegExpFlagsGetter() { // Steps 1-2. var R = this; if (!IsObject(R)) {
ThrowTypeError(JSMSG_OBJECT_REQUIRED, R === null ? "null" : typeof R);
}
// Step 3. var result = "";
// Steps 4-5. if (R.hasIndices) {
result += "d";
}
// Steps 6-7. if (R.global) {
result += "g";
}
// Steps 8-9. if (R.ignoreCase) {
result += "i";
}
// Steps 10-11. if (R.multiline) {
result += "m";
}
// Steps 12-13. if (R.dotAll) {
result += "s";
}
// Steps 14-15. if (R.unicode) {
result += "u";
}
// Steps 16-17. if (R.unicodeSets) {
result += "v";
}
// ES 2016 draft Mar 25, 2016 21.2.5.2.3. function AdvanceStringIndex(S, index) { // Step 1. assert(typeof S === "string", "Expected string as 1st argument");
// Step 2. assert(
index >= 0 && index <= MAX_NUMERIC_INDEX, "Expected integer as 2nd argument"
);
// Step 3 (skipped).
// Step 4 (skipped).
// Steps 5-11. var supplementary = (
index < S.length &&
callFunction(std_String_codePointAt, S, index) > 0xffff
); return index + 1 + supplementary;
}
// Optimized paths for simple cases. if (IsRegExpMethodOptimizable(rx)) { // Step 4. var flags = UnsafeGetInt32FromReservedSlot(rx, REGEXP_FLAGS_SLOT); var global = !!(flags & REGEXP_GLOBAL_FLAG);
if (global) { // Step 6.a. var fullUnicode = !!(flags & REGEXP_UNICODE_FLAG) || !!(flags & REGEXP_UNICODESETS_FLAG);
// Checks if following properties and getters are not modified, and accessing // them not observed by content script: // * flags // * hasIndices // * global // * ignoreCase // * multiline // * dotAll // * sticky // * unicode // * unicodeSets // * exec // * lastIndex function IsRegExpMethodOptimizable(rx) { if (!IsRegExpObject(rx)) { returnfalse;
}
var RegExpProto = GetBuiltinPrototype("RegExp"); // If RegExpPrototypeOptimizable and RegExpInstanceOptimizable succeed, // `RegExpProto.exec` is guaranteed to be data properties. return (
RegExpPrototypeOptimizable(RegExpProto) &&
RegExpInstanceOptimizable(rx, RegExpProto) &&
RegExpProto.exec === RegExp_prototype_Exec
);
}
// Step 5. var functionalReplace = IsCallable(replaceValue);
// Step 6. var firstDollarIndex = -1; if (!functionalReplace) { // Step 6.a.
replaceValue = ToString(replaceValue);
// Skip if replaceValue is an empty string or a single character. // A single character string may contain "$", but that cannot be a // substitution. if (replaceValue.length > 1) {
firstDollarIndex = GetFirstDollarIndex(replaceValue);
}
}
// Optimized paths. if (IsRegExpMethodOptimizable(rx)) { // Step 7. var flags = UnsafeGetInt32FromReservedSlot(rx, REGEXP_FLAGS_SLOT);
// Step 9. var global = !!(flags & REGEXP_GLOBAL_FLAG);
// Steps 9-17. if (global) { if (functionalReplace) { // For large strings check if the replacer function is // applicable for the elem-base optimization. if (lengthS > 5000) { var elemBase = GetElemBaseForLambda(replaceValue); if (IsObject(elemBase)) { return RegExpGlobalReplaceOptElemBase(
rx,
S,
lengthS,
replaceValue,
flags,
elemBase
);
}
} return RegExpGlobalReplaceOptFunc(rx, S, lengthS, replaceValue, flags);
} if (firstDollarIndex !== -1) { return RegExpGlobalReplaceOptSubst(
rx,
S,
lengthS,
replaceValue,
flags,
firstDollarIndex
);
} return RegExpGlobalReplaceOptSimple(rx, S, lengthS, replaceValue, flags);
}
// Steps 15.j, 15.l.i. // We don't need namedCaptures, but ToObject is visible to script. var namedCaptures = result.groups; if (namedCaptures !== undefined) {
ToObject(namedCaptures);
}
// Step 15.l.ii.
replacement = replaceValue;
}
// Step 15.m. if (position >= nextSourcePosition) { // Step 15.m.ii.
accumulatedResult +=
Substring(S, nextSourcePosition, position - nextSourcePosition) +
replacement;
// Step 15.m.iii.
nextSourcePosition = position + matchLength;
}
}
// Conditions: // * global flag is true // * replaceValue is a function
#define FUNC_NAME RegExpGlobalReplaceOptFunc
#define FUNCTIONAL
#include "RegExpGlobalReplaceOpt.h.js"
#undef FUNCTIONAL
#undef FUNC_NAME /* global RegExpGlobalReplaceOptFunc */
// Conditions: // * global flag is true // * replaceValue is a function that returns element of an object
#define FUNC_NAME RegExpGlobalReplaceOptElemBase
#define ELEMBASE
#include "RegExpGlobalReplaceOpt.h.js"
#undef ELEMBASE
#undef FUNC_NAME /* global RegExpGlobalReplaceOptElemBase */
// Conditions: // * global flag is true // * replaceValue is a string with "$"
#define FUNC_NAME RegExpGlobalReplaceOptSubst
#define SUBSTITUTION
#include "RegExpGlobalReplaceOpt.h.js"
#undef SUBSTITUTION
#undef FUNC_NAME /* global RegExpGlobalReplaceOptSubst */
// Conditions: // * global flag is false // * replaceValue is a string without "$"
#define FUNC_NAME RegExpLocalReplaceOptSimple
#define SIMPLE
#include "RegExpLocalReplaceOpt.h.js"
#undef SIMPLE
#undef FUNC_NAME /* global RegExpLocalReplaceOptSimple */
// Conditions: // * global flag is false // * replaceValue is a function
#define FUNC_NAME RegExpLocalReplaceOptFunc
#define FUNCTIONAL
#include "RegExpLocalReplaceOpt.h.js"
#undef FUNCTIONAL
#undef FUNC_NAME /* global RegExpLocalReplaceOptFunc */
// Conditions: // * global flag is false // * replaceValue is a string with "$"
#define FUNC_NAME RegExpLocalReplaceOptSubst
#define SUBSTITUTION
#include "RegExpLocalReplaceOpt.h.js"
#undef SUBSTITUTION
#undef FUNC_NAME /* global RegExpLocalReplaceOptSubst */
// Step 5. var lastIndexIsZero = SameValue(previousLastIndex, 0); if (!lastIndexIsZero) {
rx.lastIndex = 0;
}
if (IsRegExpMethodOptimizable(rx) && S.length < 0x7fff) { // Step 6. var result = RegExpSearcher(rx, S, 0);
// We need to consider two cases: // // 1. Neither global nor sticky is set: // RegExpBuiltinExec doesn't modify lastIndex for local RegExps, that // means |SameValue(rx.lastIndex, 0)| is true after calling exec. The // comparison in steps 7-8 |SameValue(rx.lastIndex, previousLastIndex)| // is therefore equal to the already computed |lastIndexIsZero| value. // // 2. Global or sticky flag is set. // RegExpBuiltinExec will always update lastIndex and we need to // restore the property to its original value.
// Steps 7-8. if (!lastIndexIsZero) {
rx.lastIndex = previousLastIndex;
} else { var flags = UnsafeGetInt32FromReservedSlot(rx, REGEXP_FLAGS_SLOT); if (flags & (REGEXP_GLOBAL_FLAG | REGEXP_STICKY_FLAG)) {
rx.lastIndex = previousLastIndex;
}
}
function IsRegExpSplitOptimizable(rx, C) { if (!IsRegExpObject(rx)) { returnfalse;
}
var RegExpCtor = GetBuiltinConstructor("RegExp"); if (C !== RegExpCtor) { returnfalse;
}
var RegExpProto = RegExpCtor.prototype; // If RegExpPrototypeOptimizable succeeds, `RegExpProto.exec` is guaranteed // to be a data property. return (
RegExpPrototypeOptimizable(RegExpProto) &&
RegExpInstanceOptimizable(rx, RegExpProto) &&
RegExpProto.exec === RegExp_prototype_Exec
);
}
// ES 2017 draft 6859bb9ccaea9c6ede81d71e5320e3833b92cb3e 21.2.5.11. function RegExpSplit(string, limit) { // Step 1. var rx = this;
// Step 17. if (size === 0) { // Step 17.a-b. if (optimizable) { if (RegExpSearcher(splitter, S, 0) !== -1) { return A;
}
} else { if (RegExpExec(splitter, S) !== null) { return A;
}
}
// Step 17.d.
DefineDataProperty(A, 0, S);
// Step 17.e. return A;
}
// Step 18. var q = p;
var optimizableNoCaptures = optimizable && !RegExpHasCaptureGroups(splitter, S);
// Step 19. while (q < size) { var e, z; if (optimizableNoCaptures) { // If there are no capturing groups, avoid allocating the match result // object |z| (we set it to null). This is the only difference between // this branch and the |if (optimizable)| case below.
// Step 19.a (skipped). // splitter.lastIndex is not used.
// ES6 21.2.5.2. // NOTE: This is not RegExpExec (21.2.5.2.1). function RegExp_prototype_Exec(string) { // Steps 1-3. var R = this; if (!IsObject(R) || !IsRegExpObject(R)) { return callFunction(
CallRegExpMethodIfWrapped,
R,
string, "RegExp_prototype_Exec"
);
}
// Steps 4-5. var S = ToString(string);
// Step 6. return RegExpBuiltinExec(R, S);
}
// ES6 21.2.5.13. function RegExpTest(string) { // Steps 1-2. var R = this; if (!IsObject(R)) {
ThrowTypeError(JSMSG_OBJECT_REQUIRED, R === null ? "null" : typeof R);
}
// Steps 3-4. var S = ToString(string);
// Steps 5-6. return RegExpExecForTest(R, S);
}
// ES 2016 draft Mar 25, 2016 21.2.4.2. function $RegExpSpecies() { // Step 1. returnthis;
}
SetCanonicalName($RegExpSpecies, "get [Symbol.species]");
function IsRegExpMatchAllOptimizable(rx, C) { if (!IsRegExpObject(rx)) { returnfalse;
}
var RegExpCtor = GetBuiltinConstructor("RegExp"); if (C !== RegExpCtor) { returnfalse;
}
function IsRegExpStringIteratorNextOptimizable() { var RegExpProto = GetBuiltinPrototype("RegExp"); // If RegExpPrototypeOptimizable succeeds, `RegExpProto.exec` is // guaranteed to be a data property. return (
RegExpPrototypeOptimizable(RegExpProto) &&
RegExpProto.exec === RegExp_prototype_Exec
);
}
// Mark the iterator as no longer optimizable.
UnsafeSetReservedSlot(
obj,
REGEXP_STRING_ITERATOR_LASTINDEX_SLOT,
REGEXP_STRING_ITERATOR_LASTINDEX_SLOW
);
}
// Step 9. var match = RegExpExec(regexp, string);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.