tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit d835cf9f440ec066f7c9ecb6cef034d7f46d3a50
parent 98c4e2c567edf03c9082a4e595b0377169ac90cf
Author: Cristina Horotan <chorotan@mozilla.com>
Date:   Wed, 26 Nov 2025 20:58:49 +0200

Revert "Bug 1306461 - Normalise and partially disable RegExp legacy features, r=iain" for causing SM failures on Value.h

This reverts commit 9b7cbea13fbf47b5723739a3329f9491b141a744.

Diffstat:
Mjs/public/friend/ErrorNumbers.msg | 4----
Mjs/src/builtin/RegExp.cpp | 194+++++++++----------------------------------------------------------------------
Mjs/src/builtin/RegExp.h | 3+--
Mjs/src/jit-test/tests/basic/testCrossCompartmentTransparency.js | 1+
Djs/src/jit-test/tests/regexp/legacy-features-enabled.js | 43-------------------------------------------
Mjs/src/jit/CodeGenerator.cpp | 13-------------
Mjs/src/shell/js.cpp | 7+------
Mjs/src/tests/non262/regress/regress-591846.js | 11++++-------
Mjs/src/tests/test262-update.py | 3++-
Mjs/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/index/prop-desc.js | 2+-
Mjs/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/index/this-cross-realm-constructor.js | 2+-
Mjs/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/index/this-not-regexp-constructor.js | 2+-
Mjs/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/index/this-subclass-constructor.js | 2+-
Mjs/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/input/prop-desc.js | 2+-
Mjs/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/input/this-cross-realm-constructor.js | 2+-
Mjs/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/input/this-not-regexp-constructor.js | 2+-
Mjs/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/input/this-subclass-constructor.js | 2+-
Mjs/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/lastMatch/prop-desc.js | 2+-
Mjs/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/lastMatch/this-cross-realm-constructor.js | 2+-
Mjs/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/lastMatch/this-not-regexp-constructor.js | 2+-
Mjs/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/lastMatch/this-subclass-constructor.js | 2+-
Mjs/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/lastParen/prop-desc.js | 2+-
Mjs/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/lastParen/this-cross-realm-constructor.js | 2+-
Mjs/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/lastParen/this-not-regexp-constructor.js | 2+-
Mjs/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/lastParen/this-subclass-constructor.js | 2+-
Mjs/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/leftContext/prop-desc.js | 2+-
Mjs/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/leftContext/this-cross-realm-constructor.js | 2+-
Mjs/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/leftContext/this-not-regexp-constructor.js | 2+-
Mjs/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/leftContext/this-subclass-constructor.js | 2+-
Mjs/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/rightContext/prop-desc.js | 2+-
Mjs/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/rightContext/this-cross-realm-constructor.js | 2+-
Mjs/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/rightContext/this-not-regexp-constructor.js | 2+-
Mjs/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/rightContext/this-subclass-constructor.js | 2+-
Mjs/src/tests/test262/annexB/built-ins/RegExp/prototype/compile/this-cross-realm-instance.js | 2+-
Mjs/src/tests/test262/annexB/built-ins/RegExp/prototype/compile/this-subclass-instance.js | 2+-
Mjs/src/vm/RegExpObject.cpp | 55+++++++++++--------------------------------------------
Mjs/src/vm/RegExpObject.h | 47++++++-----------------------------------------
Mjs/src/vm/RegExpStatics.h | 52+---------------------------------------------------
Mjs/src/vm/SelfHosting.cpp | 2+-
Mmodules/libpref/init/StaticPrefList.yaml | 7-------
40 files changed, 75 insertions(+), 419 deletions(-)

diff --git a/js/public/friend/ErrorNumbers.msg b/js/public/friend/ErrorNumbers.msg @@ -687,10 +687,6 @@ MSG_DEF(JSMSG_INVALID_CLASS_SET_OP, 0, JSEXN_SYNTAXERR, "invalid class se MSG_DEF(JSMSG_INVALID_CHAR_IN_CLASS, 0, JSEXN_SYNTAXERR, "invalid character in class in regular expression") MSG_DEF(JSMSG_NEGATED_CLASS_WITH_STR, 0, JSEXN_SYNTAXERR, "negated character class with strings in regular expression") MSG_DEF(JSMSG_MULTIPLE_FLAG_DASHES, 0, JSEXN_SYNTAXERR, "multiple dashes in flag group") -MSG_DEF(JSMSG_INCOMPATIBLE_RECEIVER, 1, JSEXN_TYPEERR, "RegExp static property '{0}' called with incompatible receiver") -MSG_DEF(JSMSG_REGEXP_STATIC_EMPTY, 1, JSEXN_TYPEERR, "RegExp static property '{0}' is invalid") -MSG_DEF(JSMSG_REGEXP_CROSS_REALM, 0, JSEXN_TYPEERR, "RegExp operation not permitted on object from different realm") -MSG_DEF(JSMSG_REGEXP_LEGACY_FEATURES_DISABLED, 0, JSEXN_TYPEERR, "RegExp legacy features are disabled") // Typed object MSG_DEF(JSMSG_TYPEDOBJECT_SETTING_IMMUTABLE, 0, JSEXN_ERR, "setting immutable field") diff --git a/js/src/builtin/RegExp.cpp b/js/src/builtin/RegExp.cpp @@ -20,7 +20,6 @@ #include "js/PropertySpec.h" #include "js/RegExpFlags.h" // JS::RegExpFlag, JS::RegExpFlags #include "util/StringBuilder.h" -#include "vm/EqualityOperations.h" #include "vm/Interpreter.h" #include "vm/JSContext.h" #include "vm/RegExpObject.h" @@ -318,27 +317,6 @@ static int32_t CreateRegExpSearchResult(JSContext* cx, cx->regExpSearcherLastLimit = matches[0].limit; return matches[0].start; } -/* - * https://github.com/tc39/proposal-regexp-legacy-features/blob/master/README.md#regexpbuiltinexec--r-s- - * - */ - -static bool ShouldUpdateRegExpStatics(JSContext* cx, - Handle<RegExpObject*> regexp) { - if (!JS::Prefs::experimental_legacy_regexp()) { - return true; - } - // Step 5. Let thisRealm be the current Realm Record. - JS::Realm* thisRealm = cx->realm(); - // Step 6. Let rRealm be the value of R's [[Realm]] internal slot. - JS::Realm* rRealm = regexp->realm(); - - // Step 7. If SameValue(thisRealm, rRealm) is true, then - if (thisRealm == rRealm) { - return regexp->legacyFeaturesEnabled(); - } - return false; -} /* * ES 2017 draft rev 6a13789aa9e7c6de4e96b7d3e24d9e6eba6584ad 21.2.5.2.2 @@ -348,19 +326,14 @@ static RegExpRunStatus ExecuteRegExpImpl(JSContext* cx, RegExpStatics* res, MutableHandleRegExpShared re, Handle<JSLinearString*> input, size_t searchIndex, - VectorMatchPairs* matches, - Handle<RegExpObject*> regexp) { + VectorMatchPairs* matches) { RegExpRunStatus status = RegExpShared::execute(cx, re, input, searchIndex, matches); /* Out of spec: Update RegExpStatics. */ if (status == RegExpRunStatus::Success && res) { - if (ShouldUpdateRegExpStatics(cx, regexp)) { - if (!res->updateFromMatchPairs(cx, input, *matches)) { - return RegExpRunStatus::Error; - } - } else { - res->invalidate(); + if (!res->updateFromMatchPairs(cx, input, *matches)) { + return RegExpRunStatus::Error; } } return status; @@ -381,7 +354,7 @@ bool js::ExecuteRegExpLegacy(JSContext* cx, RegExpStatics* res, VectorMatchPairs matches; RegExpRunStatus status = - ExecuteRegExpImpl(cx, res, &shared, input, *lastIndex, &matches, reobj); + ExecuteRegExpImpl(cx, res, &shared, input, *lastIndex, &matches); if (status == RegExpRunStatus::Error) { return false; } @@ -501,10 +474,9 @@ static bool RegExpInitializeIgnoringLastIndex(JSContext* cx, /* ES 2016 draft Mar 25, 2016 21.2.3.2.3. */ bool js::RegExpCreate(JSContext* cx, HandleValue patternValue, - HandleValue flagsValue, MutableHandleValue rval, - HandleObject newTarget) { + HandleValue flagsValue, MutableHandleValue rval) { /* Step 1. */ - Rooted<RegExpObject*> regexp(cx, RegExpAlloc(cx, GenericObject, newTarget)); + Rooted<RegExpObject*> regexp(cx, RegExpAlloc(cx, GenericObject)); if (!regexp) { return false; } @@ -574,51 +546,21 @@ static bool SetLastIndex(JSContext* cx, Handle<RegExpObject*> regexp, return SetProperty(cx, regexp, cx->names().lastIndex, val); } -/* - * RegExp.prototype.compile ( pattern, flags ) - * https://github.com/tc39/proposal-regexp-legacy-features?tab=readme-ov-file#regexpprototypecompile--pattern-flags- - * ES6 B.2.5.1. - */ +/* ES6 B.2.5.1. */ MOZ_ALWAYS_INLINE bool regexp_compile_impl(JSContext* cx, const CallArgs& args) { MOZ_ASSERT(IsRegExpObject(args.thisv())); Rooted<RegExpObject*> regexp(cx, &args.thisv().toObject().as<RegExpObject>()); - if (JS::Prefs::experimental_legacy_regexp()) { - // Step 3. Let thisRealm be the current Realm Record. - JS::Realm* thisRealm = cx->realm(); - - // Step 4. Let oRealm be the value of O’s [[Realm]] internal slot. - JS::Realm* oRealm = regexp->realm(); - - // Step 5. If SameValue(thisRealm, oRealm) is false, throw a TypeError - // exception. - if (thisRealm != oRealm) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_REGEXP_CROSS_REALM); - return false; - } - - // Step 6. If the value of R’s [[LegacyFeaturesEnabled]] internal slot is - // false, throw a TypeError exception. - bool legacyEnabled = regexp->legacyFeaturesEnabled(); - if (!legacyEnabled) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_REGEXP_LEGACY_FEATURES_DISABLED); - return false; - } - } - - // Step 7. If Type(pattern) is Object and pattern has a [[RegExpMatcher]] - // internal slot, then + // Step 3. RootedValue patternValue(cx, args.get(0)); ESClass cls; if (!GetClassOfValue(cx, patternValue, &cls)) { return false; } if (cls == ESClass::RegExp) { - // Step 7.i. If flags is not undefined, throw a TypeError exception. + // Step 3a. if (args.hasDefined(1)) { JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_NEWREGEXP_FLAGGED); @@ -633,8 +575,7 @@ MOZ_ALWAYS_INLINE bool regexp_compile_impl(JSContext* cx, Rooted<JSAtom*> sourceAtom(cx); RegExpFlags flags = RegExpFlag::NoFlags; { - // Step 7.ii. Let P be the value of pattern’s [[OriginalSource]] internal - // slot. + // Step 3b. RegExpShared* shared = RegExpToShared(cx, patternObj); if (!shared) { return false; @@ -644,20 +585,20 @@ MOZ_ALWAYS_INLINE bool regexp_compile_impl(JSContext* cx, flags = shared->getFlags(); } - // Step 9, minus lastIndex zeroing. + // Step 5, minus lastIndex zeroing. regexp->initIgnoringLastIndex(sourceAtom, flags); } else { - // Step 8. + // Step 4. RootedValue P(cx, patternValue); RootedValue F(cx, args.get(1)); - // Step 9, minus lastIndex zeroing. + // Step 5, minus lastIndex zeroing. if (!RegExpInitializeIgnoringLastIndex(cx, regexp, P, F)) { return false; } } - // The final niggling bit of step 8. + // The final niggling bit of step 5. // // |regexp| is user-exposed, so its "lastIndex" property might be // non-writable. @@ -683,14 +624,15 @@ bool js::regexp_construct(JSContext* cx, unsigned argc, Value* vp) { AutoJSConstructorProfilerEntry pseudoFrame(cx, "RegExp"); CallArgs args = CallArgsFromVp(argc, vp); - RootedObject newTarget(cx); - // Steps 1. bool patternIsRegExp; if (!IsRegExp(cx, args.get(0), &patternIsRegExp)) { return false; } + // We can delay step 3 and step 4a until later, during + // GetPrototypeFromBuiltinConstructor calls. Accessing the new.target + // and the callee from the stack is unobservable. if (!args.isConstructing()) { // Step 3.b. if (patternIsRegExp && !args.hasDefined(1)) { @@ -710,8 +652,6 @@ bool js::regexp_construct(JSContext* cx, unsigned argc, Value* vp) { return true; } } - } else { - newTarget = &args.newTarget().toObject(); } RootedValue patternValue(cx, args.get(0)); @@ -753,8 +693,7 @@ bool js::regexp_construct(JSContext* cx, unsigned argc, Value* vp) { return false; } - Rooted<RegExpObject*> regexp( - cx, RegExpAlloc(cx, GenericObject, proto, newTarget)); + Rooted<RegExpObject*> regexp(cx, RegExpAlloc(cx, GenericObject, proto)); if (!regexp) { return false; } @@ -830,8 +769,7 @@ bool js::regexp_construct(JSContext* cx, unsigned argc, Value* vp) { return false; } - Rooted<RegExpObject*> regexp( - cx, RegExpAlloc(cx, GenericObject, proto, newTarget)); + Rooted<RegExpObject*> regexp(cx, RegExpAlloc(cx, GenericObject, proto)); if (!regexp) { return false; } @@ -1366,45 +1304,11 @@ static bool regexp_escape(JSContext* cx, unsigned argc, Value* vp) { * RegExp.rightContext $' */ -static bool checkRegexpLegacyFeatures(JSContext* cx, const CallArgs& args, - const char* name) { - if (JS::Prefs::experimental_legacy_regexp()) { - /* Step 1. Assert C is an object that has an internal slot named - * internalSlotName.*/ - JSObject* regexpCtor = - GlobalObject::getOrCreateRegExpConstructor(cx, cx->global()); - if (!regexpCtor) return false; - - /* Step 2. If SameValue(C, thisValue) is false, throw TypeError */ - bool same = false; - if (!args.thisv().isObject() || - !SameValue(cx, args.thisv(), ObjectValue(*regexpCtor), &same) || - !same) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_INCOMPATIBLE_RECEIVER, name, - InformalValueTypeName(args.thisv())); - return false; - } - - /* Step 4. If val is empty, throw a TypeError exception */ - RegExpStatics* res = GlobalObject::getRegExpStatics(cx, cx->global()); - if (!res) return false; - if (res->isInvalidated()) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_REGEXP_STATIC_EMPTY, name, - InformalValueTypeName(args.thisv())); - return false; - } - } - return true; -} - #define DEFINE_STATIC_GETTER(name, code) \ static bool name(JSContext* cx, unsigned argc, Value* vp) { \ CallArgs args = CallArgsFromVp(argc, vp); \ RegExpStatics* res = GlobalObject::getRegExpStatics(cx, cx->global()); \ if (!res) return false; \ - if (!checkRegexpLegacyFeatures(cx, args, #name)) return false; \ code; \ } @@ -1431,80 +1335,29 @@ DEFINE_STATIC_GETTER(static_paren9_getter, STATIC_PAREN_GETTER_CODE(9)) #define DEFINE_STATIC_SETTER(name, code) \ static bool name(JSContext* cx, unsigned argc, Value* vp) { \ - CallArgs args = CallArgsFromVp(argc, vp); \ RegExpStatics* res = GlobalObject::getRegExpStatics(cx, cx->global()); \ if (!res) return false; \ - if (!checkRegexpLegacyFeatures(cx, args, #name)) return false; \ code; \ return true; \ } static bool static_input_setter(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); - if (JS::Prefs::experimental_legacy_regexp()) { - // Step 1. Assert C is an object that has an internal slot named - // internalSlotName. - JSObject* regexpCtor = - GlobalObject::getOrCreateRegExpConstructor(cx, cx->global()); - if (!regexpCtor) { - return false; - } - - // Step 2. If SameValue(C, thisValue) is false, throw a TypeError exception. - bool same = false; - if (!args.thisv().isObject() || - !SameValue(cx, args.thisv(), ObjectValue(*regexpCtor), &same) || - !same) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, - JSMSG_INCOMPATIBLE_RECEIVER, - InformalValueTypeName(args.thisv())); - return false; - } - } - RegExpStatics* res = GlobalObject::getRegExpStatics(cx, cx->global()); if (!res) { return false; } - // Step 3. Let strVal be ? ToString(val). RootedString str(cx, ToString<CanGC>(cx, args.get(0))); if (!str) { return false; } - // Step 4. Set the value of the internal slot of C named internalSlotName to - // strVal. res->setPendingInput(str); args.rval().setString(str); return true; } -#ifdef NIGHTLY_BUILD -const JSPropertySpec js::regexp_static_props[] = { - JS_PSGS("input", static_input_getter, static_input_setter, 0), - JS_PSG("lastMatch", static_lastMatch_getter, 0), - JS_PSG("lastParen", static_lastParen_getter, 0), - JS_PSG("leftContext", static_leftContext_getter, 0), - JS_PSG("rightContext", static_rightContext_getter, 0), - JS_PSG("$1", static_paren1_getter, 0), - JS_PSG("$2", static_paren2_getter, 0), - JS_PSG("$3", static_paren3_getter, 0), - JS_PSG("$4", static_paren4_getter, 0), - JS_PSG("$5", static_paren5_getter, 0), - JS_PSG("$6", static_paren6_getter, 0), - JS_PSG("$7", static_paren7_getter, 0), - JS_PSG("$8", static_paren8_getter, 0), - JS_PSG("$9", static_paren9_getter, 0), - JS_PSGS("$_", static_input_getter, static_input_setter, 0), - JS_PSG("$&", static_lastMatch_getter, 0), - JS_PSG("$+", static_lastParen_getter, 0), - JS_PSG("$`", static_leftContext_getter, 0), - JS_PSG("$'", static_rightContext_getter, 0), - JS_SELF_HOSTED_SYM_GET(species, "$RegExpSpecies", 0), - JS_PS_END, -}; -#else const JSPropertySpec js::regexp_static_props[] = { JS_PSGS("input", static_input_getter, static_input_setter, JSPROP_PERMANENT | JSPROP_ENUMERATE), @@ -1533,7 +1386,6 @@ const JSPropertySpec js::regexp_static_props[] = { JS_SELF_HOSTED_SYM_GET(species, "$RegExpSpecies", 0), JS_PS_END, }; -#endif const JSFunctionSpec js::regexp_static_methods[] = { JS_FN("escape", regexp_escape, 1, 0), @@ -1578,12 +1430,13 @@ static RegExpRunStatus ExecuteRegExp(JSContext* cx, HandleObject regexp, /* Steps 3, 10-14, except 12.a.i, 12.c.i.1. */ RegExpRunStatus status = - ExecuteRegExpImpl(cx, res, &re, input, lastIndex, matches, reobj); + ExecuteRegExpImpl(cx, res, &re, input, lastIndex, matches); if (status == RegExpRunStatus::Error) { return RegExpRunStatus::Error; } /* Steps 12.a.i, 12.c.i.i, 15 are done by Self-hosted function. */ + return status; } @@ -2292,10 +2145,6 @@ bool js::RegExpBuiltinExec(JSContext* cx, Handle<RegExpObject*> regexp, static_assert(JSString::MAX_LENGTH <= INT32_MAX, "lastIndex fits in int32_t"); // Steps 6, 8-35. - RegExpStatics* res = GlobalObject::getRegExpStatics(cx, cx->global()); - if (!res) { - return false; - } if (forTest) { bool result; @@ -2303,7 +2152,6 @@ bool js::RegExpBuiltinExec(JSContext* cx, Handle<RegExpObject*> regexp, &result)) { return false; } - rval.setBoolean(result); return true; } diff --git a/js/src/builtin/RegExp.h b/js/src/builtin/RegExp.h @@ -114,8 +114,7 @@ JSObject* InitRegExpClass(JSContext* cx, HandleObject obj); [[nodiscard]] extern bool RegExpCreate(JSContext* cx, HandleValue pattern, HandleValue flags, - MutableHandleValue rval, - HandleObject newTarget); + MutableHandleValue rval); [[nodiscard]] extern bool IsRegExpPrototypeOptimizable(JSContext* cx, unsigned argc, diff --git a/js/src/jit-test/tests/basic/testCrossCompartmentTransparency.js b/js/src/jit-test/tests/basic/testCrossCompartmentTransparency.js @@ -76,6 +76,7 @@ if (String.prototype.toSource) { test("new String('one')", s => String.prototype.toString.call(s)); test("new RegExp('1')", r => RegExp.prototype.exec.call(r, '1').toString()); test("new RegExp('1')", r => RegExp.prototype.test.call(r, '1')); +test("new RegExp('1')", r => RegExp.prototype.compile.call(r, '1').toString()); test("new RegExp('1')", r => assertEq("a1".search(r), 1)); test("new RegExp('1')", r => assertEq("a1".match(r)[0], '1')); test("new RegExp('1')", r => assertEq("a1".replace(r, 'A'), 'aA')); diff --git a/js/src/jit-test/tests/regexp/legacy-features-enabled.js b/js/src/jit-test/tests/regexp/legacy-features-enabled.js @@ -1,43 +0,0 @@ -// |jit-test| --enable-legacy-regexp -function testLegacyFeaturesEnabled(re, str) { - for (let i = 0; i < 100; i++){ - re.test(str); - } -} - -{ - class MyRegExp extends RegExp {} - - var re1 = /a(b)c/; - testLegacyFeaturesEnabled(re1, "abc"); - assertEq(RegExp.$1, "b"); - - var re2 = new MyRegExp("d(e)f"); - testLegacyFeaturesEnabled(re2, "def"); - - var threw = false; - try { - RegExp.$1; - } catch(e) { - threw = true; - assertEq(e instanceof TypeError, true); - } -} - -{ - var other = newGlobal(); - other.eval("var re = /x(y)z/;"); - - var re = other.re; - testLegacyFeaturesEnabled(re, "xyz"); - - var threw = false; - try { - RegExp.$1; - } catch(e) { - threw = true; - assertEq(e instanceof TypeError, true); - } - - assertEq(threw, true); -} diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp @@ -2227,19 +2227,6 @@ static void UpdateRegExpStatics(MacroAssembler& masm, Register regexp, RegExpStatics::offsetOfMatchesInput()); Address lazySourceAddress(staticsReg, RegExpStatics::offsetOfLazySource()); Address lazyIndexAddress(staticsReg, RegExpStatics::offsetOfLazyIndex()); -#ifdef DEBUG - if (JS::Prefs::experimental_legacy_regexp()) { - Label legacyFeaturesEnabled; - masm.unboxNonDouble(Address(regexp, NativeObject::getFixedSlotOffset( - RegExpObject::flagsSlot())), - temp1, JSVAL_TYPE_INT32); - masm.branchTest32(Assembler::NonZero, temp1, - Imm32(RegExpObject::LegacyFeaturesEnabledBit), - &legacyFeaturesEnabled); - masm.assumeUnreachable("Non-legacy-enabled regexp in RegExp stub"); - masm.bind(&legacyFeaturesEnabled); - } -#endif masm.guardedCallPreBarrier(pendingInputAddress, MIRType::String); masm.guardedCallPreBarrier(matchesInputAddress, MIRType::String); diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp @@ -13282,9 +13282,7 @@ bool InitOptionParser(OptionParser& op) { !op.addBoolOption('\0', "enable-arraybuffer-immutable", "Enable immutable ArrayBuffers") || !op.addBoolOption('\0', "enable-iterator-chunking", - "Enable Iterator Chunking") || - !op.addBoolOption('\0', "enable-legacy-regexp", - "Enable Legacy RegExp features")) { + "Enable Iterator Chunking")) { return false; } @@ -13341,9 +13339,6 @@ bool SetGlobalOptionsPreJSInit(const OptionParser& op) { JS::Prefs::setAtStartup_experimental_symbols_as_weakmap_keys( symbolsAsWeakMapKeys); - if (op.getBoolOption("enable-legacy-regexp")) { - JS::Prefs::set_experimental_legacy_regexp(true); - } #ifdef NIGHTLY_BUILD if (op.getBoolOption("enable-async-iterator-helpers")) { JS::Prefs::setAtStartup_experimental_async_iterator_helpers(true); diff --git a/js/src/tests/non262/regress/regress-591846.js b/js/src/tests/non262/regress/regress-591846.js @@ -1,13 +1,11 @@ -// |reftest| shell-option(--enable-legacy-regexp) skip-if(release_or_beta||!xulRuntime.shell) -- legacy-regexp is not released yet, requires shell-options /* * Any copyright is dedicated to the Public Domain. * http://creativecommons.org/licenses/publicdomain/ */ // SKIP test262 export -// This test verifies that RegExp legacy static properties match TC39's expected -// attributes: non-enumerable and configurable. -// See: https://github.com/tc39/proposal-regexp-legacy-features +// Note that the values for enumerable/configurable are inconsistent with +// https://github.com/tc39/proposal-regexp-legacy-features // Reset RegExp.leftContext to the empty string. /x/.test('x'); @@ -15,9 +13,8 @@ var d = Object.getOwnPropertyDescriptor(RegExp, "leftContext"); assertEq(d.set, undefined); assertEq(typeof d.get, "function"); -let regexpLegacyFeatures = getPrefValue('experimental.legacy_regexp'); -assertEq(d.enumerable, !regexpLegacyFeatures); -assertEq(d.configurable, regexpLegacyFeatures); +assertEq(d.enumerable, true); +assertEq(d.configurable, false); assertEq(d.get.call(RegExp), ""); reportCompare(0, 0, "ok"); diff --git a/js/src/tests/test262-update.py b/js/src/tests/test262-update.py @@ -18,6 +18,7 @@ UNSUPPORTED_FEATURES = set( [ "tail-call-optimization", "Intl.Locale-info", # Bug 1693576 + "legacy-regexp", # Bug 1306461 "source-phase-imports", "source-phase-imports-module-source", "import-defer", @@ -38,7 +39,7 @@ FEATURE_CHECK_NEEDED = { "upsert": "!Map.prototype.getOrInsertComputed", # Bug 1986668 "immutable-arraybuffer": "!ArrayBuffer.prototype.sliceToImmutable", # Bug 1952253 } -RELEASE_OR_BETA = set(["legacy-regexp"]) +RELEASE_OR_BETA = set() SHELL_OPTIONS = { "ShadowRealm": "--enable-shadow-realms", "symbols-as-weakmap-keys": "--enable-symbols-as-weakmap-keys", diff --git a/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/index/prop-desc.js b/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/index/prop-desc.js @@ -1,4 +1,4 @@ -// |reftest| skip-if(release_or_beta) -- legacy-regexp is not released yet +// |reftest| skip -- legacy-regexp is not supported // Copyright (C) 2020 ExE Boss. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/index/this-cross-realm-constructor.js b/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/index/this-cross-realm-constructor.js @@ -1,4 +1,4 @@ -// |reftest| skip-if(release_or_beta) -- legacy-regexp is not released yet +// |reftest| skip -- legacy-regexp is not supported // Copyright (C) 2020 ExE Boss. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/index/this-not-regexp-constructor.js b/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/index/this-not-regexp-constructor.js @@ -1,4 +1,4 @@ -// |reftest| skip-if(release_or_beta) -- legacy-regexp is not released yet +// |reftest| skip -- legacy-regexp is not supported // Copyright (C) 2020 ExE Boss. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/index/this-subclass-constructor.js b/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/index/this-subclass-constructor.js @@ -1,4 +1,4 @@ -// |reftest| skip-if(release_or_beta) -- legacy-regexp is not released yet +// |reftest| skip -- legacy-regexp is not supported // Copyright (C) 2020 ExE Boss. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/input/prop-desc.js b/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/input/prop-desc.js @@ -1,4 +1,4 @@ -// |reftest| skip-if(release_or_beta) -- legacy-regexp is not released yet +// |reftest| skip -- legacy-regexp is not supported // Copyright (C) 2020 ExE Boss. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/input/this-cross-realm-constructor.js b/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/input/this-cross-realm-constructor.js @@ -1,4 +1,4 @@ -// |reftest| skip-if(release_or_beta) -- legacy-regexp is not released yet +// |reftest| skip -- legacy-regexp is not supported // Copyright (C) 2020 ExE Boss. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/input/this-not-regexp-constructor.js b/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/input/this-not-regexp-constructor.js @@ -1,4 +1,4 @@ -// |reftest| skip-if(release_or_beta) -- legacy-regexp is not released yet +// |reftest| skip -- legacy-regexp is not supported // Copyright (C) 2020 ExE Boss. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/input/this-subclass-constructor.js b/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/input/this-subclass-constructor.js @@ -1,4 +1,4 @@ -// |reftest| skip-if(release_or_beta) -- legacy-regexp is not released yet +// |reftest| skip -- legacy-regexp is not supported // Copyright (C) 2020 ExE Boss. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/lastMatch/prop-desc.js b/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/lastMatch/prop-desc.js @@ -1,4 +1,4 @@ -// |reftest| skip-if(release_or_beta) -- legacy-regexp is not released yet +// |reftest| skip -- legacy-regexp is not supported // Copyright (C) 2020 ExE Boss. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/lastMatch/this-cross-realm-constructor.js b/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/lastMatch/this-cross-realm-constructor.js @@ -1,4 +1,4 @@ -// |reftest| skip-if(release_or_beta) -- legacy-regexp is not released yet +// |reftest| skip -- legacy-regexp is not supported // Copyright (C) 2020 ExE Boss. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/lastMatch/this-not-regexp-constructor.js b/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/lastMatch/this-not-regexp-constructor.js @@ -1,4 +1,4 @@ -// |reftest| skip-if(release_or_beta) -- legacy-regexp is not released yet +// |reftest| skip -- legacy-regexp is not supported // Copyright (C) 2020 ExE Boss. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/lastMatch/this-subclass-constructor.js b/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/lastMatch/this-subclass-constructor.js @@ -1,4 +1,4 @@ -// |reftest| skip-if(release_or_beta) -- legacy-regexp is not released yet +// |reftest| skip -- legacy-regexp is not supported // Copyright (C) 2020 ExE Boss. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/lastParen/prop-desc.js b/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/lastParen/prop-desc.js @@ -1,4 +1,4 @@ -// |reftest| skip-if(release_or_beta) -- legacy-regexp is not released yet +// |reftest| skip -- legacy-regexp is not supported // Copyright (C) 2020 ExE Boss. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/lastParen/this-cross-realm-constructor.js b/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/lastParen/this-cross-realm-constructor.js @@ -1,4 +1,4 @@ -// |reftest| skip-if(release_or_beta) -- legacy-regexp is not released yet +// |reftest| skip -- legacy-regexp is not supported // Copyright (C) 2020 ExE Boss. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/lastParen/this-not-regexp-constructor.js b/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/lastParen/this-not-regexp-constructor.js @@ -1,4 +1,4 @@ -// |reftest| skip-if(release_or_beta) -- legacy-regexp is not released yet +// |reftest| skip -- legacy-regexp is not supported // Copyright (C) 2020 ExE Boss. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/lastParen/this-subclass-constructor.js b/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/lastParen/this-subclass-constructor.js @@ -1,4 +1,4 @@ -// |reftest| skip-if(release_or_beta) -- legacy-regexp is not released yet +// |reftest| skip -- legacy-regexp is not supported // Copyright (C) 2020 ExE Boss. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/leftContext/prop-desc.js b/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/leftContext/prop-desc.js @@ -1,4 +1,4 @@ -// |reftest| skip-if(release_or_beta) -- legacy-regexp is not released yet +// |reftest| skip -- legacy-regexp is not supported // Copyright (C) 2020 ExE Boss. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/leftContext/this-cross-realm-constructor.js b/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/leftContext/this-cross-realm-constructor.js @@ -1,4 +1,4 @@ -// |reftest| skip-if(release_or_beta) -- legacy-regexp is not released yet +// |reftest| skip -- legacy-regexp is not supported // Copyright (C) 2020 ExE Boss. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/leftContext/this-not-regexp-constructor.js b/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/leftContext/this-not-regexp-constructor.js @@ -1,4 +1,4 @@ -// |reftest| skip-if(release_or_beta) -- legacy-regexp is not released yet +// |reftest| skip -- legacy-regexp is not supported // Copyright (C) 2020 ExE Boss. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/leftContext/this-subclass-constructor.js b/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/leftContext/this-subclass-constructor.js @@ -1,4 +1,4 @@ -// |reftest| skip-if(release_or_beta) -- legacy-regexp is not released yet +// |reftest| skip -- legacy-regexp is not supported // Copyright (C) 2020 ExE Boss. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/rightContext/prop-desc.js b/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/rightContext/prop-desc.js @@ -1,4 +1,4 @@ -// |reftest| skip-if(release_or_beta) -- legacy-regexp is not released yet +// |reftest| skip -- legacy-regexp is not supported // Copyright (C) 2020 ExE Boss. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/rightContext/this-cross-realm-constructor.js b/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/rightContext/this-cross-realm-constructor.js @@ -1,4 +1,4 @@ -// |reftest| skip-if(release_or_beta) -- legacy-regexp is not released yet +// |reftest| skip -- legacy-regexp is not supported // Copyright (C) 2020 ExE Boss. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/rightContext/this-not-regexp-constructor.js b/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/rightContext/this-not-regexp-constructor.js @@ -1,4 +1,4 @@ -// |reftest| skip-if(release_or_beta) -- legacy-regexp is not released yet +// |reftest| skip -- legacy-regexp is not supported // Copyright (C) 2020 ExE Boss. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/rightContext/this-subclass-constructor.js b/js/src/tests/test262/annexB/built-ins/RegExp/legacy-accessors/rightContext/this-subclass-constructor.js @@ -1,4 +1,4 @@ -// |reftest| skip-if(release_or_beta) -- legacy-regexp is not released yet +// |reftest| skip -- legacy-regexp is not supported // Copyright (C) 2020 ExE Boss. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/annexB/built-ins/RegExp/prototype/compile/this-cross-realm-instance.js b/js/src/tests/test262/annexB/built-ins/RegExp/prototype/compile/this-cross-realm-instance.js @@ -1,4 +1,4 @@ -// |reftest| skip-if(release_or_beta) -- legacy-regexp is not released yet +// |reftest| skip -- legacy-regexp is not supported // Copyright (C) 2020 ExE Boss. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/tests/test262/annexB/built-ins/RegExp/prototype/compile/this-subclass-instance.js b/js/src/tests/test262/annexB/built-ins/RegExp/prototype/compile/this-subclass-instance.js @@ -1,4 +1,4 @@ -// |reftest| skip-if(release_or_beta) -- legacy-regexp is not released yet +// |reftest| skip -- legacy-regexp is not supported // Copyright (C) 2020 ExE Boss. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- diff --git a/js/src/vm/RegExpObject.cpp b/js/src/vm/RegExpObject.cpp @@ -62,12 +62,9 @@ static_assert(RegExpFlag::UnicodeSets == REGEXP_UNICODESETS_FLAG, "self-hosted JS and /v flag bits must agree"); static_assert(RegExpFlag::Sticky == REGEXP_STICKY_FLAG, "self-hosted JS and /y flag bits must agree"); -/* - * RegExpAlloc ( newTarget ) - * https://github.com/tc39/proposal-regexp-legacy-features?tab=readme-ov-file - */ + RegExpObject* js::RegExpAlloc(JSContext* cx, NewObjectKind newKind, - HandleObject proto, HandleObject newTarget) { + HandleObject proto /* = nullptr */) { Rooted<RegExpObject*> regexp( cx, NewObjectWithClassProtoAndKind<RegExpObject>(cx, proto, newKind)); if (!regexp) { @@ -77,34 +74,10 @@ RegExpObject* js::RegExpAlloc(JSContext* cx, NewObjectKind newKind, if (!SharedShape::ensureInitialCustomShape<RegExpObject>(cx, regexp)) { return nullptr; } - // Step 1. Let obj be ? OrdinaryCreateFromConstructor(newTarget, - // "%RegExpPrototype%", «[[RegExpMatcher]], [[OriginalSource]], - // [[OriginalFlags]], [[Realm]], [[LegacyFeaturesEnabled]]»). - // Set default newTarget if not provided - bool legacyFeaturesEnabled = false; - if (JS::Prefs::experimental_legacy_regexp()) { - // Step 2. Let thisRealm be the current Realm Record. - // Step 3. Set the value of obj’s [[Realm]] internal slot to thisRealm. - JS::Realm* thisRealm = regexp->nonCCWRealm(); - - JSObject* thisRealmRegExp = - &thisRealm->maybeGlobal()->getConstructor(JSProto_RegExp); - - // Step 4. If SameValue(newTarget, thisRealm.[[Intrinsics]].[[%RegExp%]]) is - // true, Step 4.i then Set the value of obj’s [[LegacyFeaturesEnabled]] - // internal slot to true. Step 5. Else, Step 5.i. Set the value of obj’s - // [[LegacyFeaturesEnabled]] internal slot to false. - legacyFeaturesEnabled = (!newTarget || newTarget == thisRealmRegExp); - } - regexp->setLegacyFeaturesEnabled(legacyFeaturesEnabled); - - // Step 6: Perform ! DefinePropertyOrThrow(obj, "lastIndex", - // PropertyDescriptor {[[Writable]]: true, [Enumerable]]: false, - // [[Configurable]]: false}). + MOZ_ASSERT(regexp->lookupPure(cx->names().lastIndex)->slot() == RegExpObject::lastIndexSlot()); - // Step 7: Return obj. return regexp; } @@ -172,8 +145,7 @@ const JSClass RegExpObject::protoClass_ = { template <typename CharT> RegExpObject* RegExpObject::create(JSContext* cx, const CharT* chars, size_t length, RegExpFlags flags, - NewObjectKind newKind, - HandleObject newTarget) { + NewObjectKind newKind) { static_assert(std::is_same_v<CharT, char16_t>, "this code may need updating if/when CharT encodes UTF-8"); @@ -182,21 +154,19 @@ RegExpObject* RegExpObject::create(JSContext* cx, const CharT* chars, return nullptr; } - return create(cx, source, flags, newKind, newTarget); + return create(cx, source, flags, newKind); } template RegExpObject* RegExpObject::create(JSContext* cx, const char16_t* chars, size_t length, RegExpFlags flags, - NewObjectKind newKind, - HandleObject newTarget); + NewObjectKind newKind); RegExpObject* RegExpObject::createSyntaxChecked(JSContext* cx, Handle<JSAtom*> source, RegExpFlags flags, - NewObjectKind newKind, - HandleObject newTarget) { - RegExpObject* regexp = RegExpAlloc(cx, newKind, nullptr, newTarget); + NewObjectKind newKind) { + RegExpObject* regexp = RegExpAlloc(cx, newKind); if (!regexp) { return nullptr; } @@ -207,8 +177,7 @@ RegExpObject* RegExpObject::createSyntaxChecked(JSContext* cx, } RegExpObject* RegExpObject::create(JSContext* cx, Handle<JSAtom*> source, - RegExpFlags flags, NewObjectKind newKind, - HandleObject newTarget) { + RegExpFlags flags, NewObjectKind newKind) { Rooted<RegExpObject*> regexp(cx); { AutoReportFrontendContext fc(cx); @@ -221,7 +190,7 @@ RegExpObject* RegExpObject::create(JSContext* cx, Handle<JSAtom*> source, return nullptr; } - regexp = RegExpAlloc(cx, newKind, nullptr, newTarget); + regexp = RegExpAlloc(cx, newKind); if (!regexp) { return nullptr; } @@ -1119,9 +1088,7 @@ JSObject* js::CloneRegExpObject(JSContext* cx, Handle<RegExpObject*> regex) { clone->initAndZeroLastIndex(shared->getSource(), shared->getFlags(), cx); clone->setShared(shared); - if (JS::Prefs::experimental_legacy_regexp()) { - clone->setLegacyFeaturesEnabled(regex->legacyFeaturesEnabled()); - } + return clone; } diff --git a/js/src/vm/RegExpObject.h b/js/src/vm/RegExpObject.h @@ -36,8 +36,7 @@ class GenericPrinter; class JSONPrinter; extern RegExpObject* RegExpAlloc(JSContext* cx, NewObjectKind newKind, - HandleObject proto = nullptr, - HandleObject newTarget = nullptr); + HandleObject proto = nullptr); extern JSObject* CloneRegExpObject(JSContext* cx, Handle<RegExpObject*> regex); @@ -62,32 +61,23 @@ class RegExpObject : public NativeObject { static const JSClass class_; static const JSClass protoClass_; - static const size_t RegExpFlagsMask = JS::RegExpFlag::AllFlags; - static const size_t LegacyFeaturesEnabledBit = Bit(8); - - static_assert((RegExpFlagsMask & LegacyFeaturesEnabledBit) == 0, - "LegacyFeaturesEnabledBit must not overlap"); - // The maximum number of pairs a MatchResult can have, without having to // allocate a bigger MatchResult. static const size_t MaxPairCount = 14; template <typename CharT> static RegExpObject* create(JSContext* cx, const CharT* chars, size_t length, - JS::RegExpFlags flags, NewObjectKind newKind, - HandleObject newTarget = nullptr); + JS::RegExpFlags flags, NewObjectKind newKind); // This variant assumes that the characters have already previously been // syntax checked. static RegExpObject* createSyntaxChecked(JSContext* cx, Handle<JSAtom*> source, JS::RegExpFlags flags, - NewObjectKind newKind, - HandleObject newTarget = nullptr); + NewObjectKind newKind); static RegExpObject* create(JSContext* cx, Handle<JSAtom*> source, - JS::RegExpFlags flags, NewObjectKind newKind, - HandleObject newTarget = nullptr); + JS::RegExpFlags flags, NewObjectKind newKind); /* * Compute the initial shape to associate with fresh RegExp objects, @@ -149,35 +139,10 @@ class RegExpObject : public NativeObject { } JS::RegExpFlags getFlags() const { - uint32_t raw = getFixedSlot(FLAGS_SLOT).toInt32(); - return JS::RegExpFlags(raw & RegExpFlagsMask); + return JS::RegExpFlags(getFixedSlot(FLAGS_SLOT).toInt32()); } - void setFlags(JS::RegExpFlags flags) { - uint32_t raw = getFixedSlot(FLAGS_SLOT).toInt32(); - uint32_t newValue = flags.value() | (raw & ~RegExpFlagsMask); - setFixedSlot(FLAGS_SLOT, Int32Value(newValue)); - } - - bool legacyFeaturesEnabled() const { - if (!JS::Prefs::experimental_legacy_regexp()) { - return false; - } - return (getFixedSlot(FLAGS_SLOT).toInt32() & LegacyFeaturesEnabledBit); - } - - void setLegacyFeaturesEnabled(bool enabled) { - if (!JS::Prefs::experimental_legacy_regexp()) { - return; - } - Value flagsVal = getFixedSlot(FLAGS_SLOT); - uint32_t raw = flagsVal.isInt32() ? flagsVal.toInt32() : 0; - if (enabled) { - raw |= LegacyFeaturesEnabledBit; - } else { - raw &= ~LegacyFeaturesEnabledBit; - } - setFixedSlot(FLAGS_SLOT, Int32Value(raw)); + setFixedSlot(FLAGS_SLOT, Int32Value(flags.value())); } bool hasIndices() const { return getFlags().hasIndices(); } diff --git a/js/src/vm/RegExpStatics.h b/js/src/vm/RegExpStatics.h @@ -46,30 +46,6 @@ class RegExpStatics { inline void checkInvariants(); - // Legacy RegExp static properties support. - private: - bool invalidated_ = false; - - public: - bool isInvalidated() const { - if (!JS::Prefs::experimental_legacy_regexp()) { - return false; - } - return invalidated_; - } - - inline void invalidate() { - if (JS::Prefs::experimental_legacy_regexp()) { - invalidated_ = true; - } - } - - inline void clearInvalidation() { - if (JS::Prefs::experimental_legacy_regexp()) { - invalidated_ = false; - } - } - /* * Check whether a match for pair |pairNum| occurred. If so, allocate and * store the match string in |*out|; otherwise place |undefined| in |*out|. @@ -186,12 +162,6 @@ inline bool RegExpStatics::createLastMatch(JSContext* cx, if (!executeLazy(cx)) { return false; } - - if (isInvalidated()) { - out.setUndefined(); - return true; - } - return makeMatch(cx, 0, out); } @@ -201,11 +171,6 @@ inline bool RegExpStatics::createLastParen(JSContext* cx, return false; } - if (isInvalidated()) { - out.setUndefined(); - return true; - } - if (matches.empty() || matches.pairCount() == 1) { out.setString(cx->runtime()->emptyString); return true; @@ -227,11 +192,6 @@ inline bool RegExpStatics::createParen(JSContext* cx, size_t pairNum, return false; } - if (isInvalidated()) { - out.setUndefined(); - return true; - } - if (matches.empty() || pairNum >= matches.pairCount()) { out.setString(cx->runtime()->emptyString); return true; @@ -245,11 +205,6 @@ inline bool RegExpStatics::createLeftContext(JSContext* cx, return false; } - if (isInvalidated()) { - out.setUndefined(); - return true; - } - if (matches.empty()) { out.setString(cx->runtime()->emptyString); return true; @@ -267,11 +222,6 @@ inline bool RegExpStatics::createRightContext(JSContext* cx, return false; } - if (isInvalidated()) { - out.setUndefined(); - return true; - } - if (matches.empty()) { out.setString(cx->runtime()->emptyString); return true; @@ -300,7 +250,7 @@ inline bool RegExpStatics::updateFromMatchPairs(JSContext* cx, ReportOutOfMemory(cx); return false; } - clearInvalidation(); + return true; } diff --git a/js/src/vm/SelfHosting.cpp b/js/src/vm/SelfHosting.cpp @@ -1014,7 +1014,7 @@ static bool intrinsic_RegExpCreate(JSContext* cx, unsigned argc, Value* vp) { args[1].isString() || args[1].isUndefined()); MOZ_ASSERT(!args.isConstructing()); - return RegExpCreate(cx, args[0], args.get(1), args.rval(), nullptr); + return RegExpCreate(cx, args[0], args.get(1), args.rval()); } static bool intrinsic_RegExpGetSubstitution(JSContext* cx, unsigned argc, diff --git a/modules/libpref/init/StaticPrefList.yaml b/modules/libpref/init/StaticPrefList.yaml @@ -8999,13 +8999,6 @@ mirror: always set_spidermonkey_pref: startup -# Experimental support for Legacy RegExp in JavaScript. -- name: javascript.options.experimental.legacy_regexp - type: bool - value: @IS_NIGHTLY_BUILD@ - mirror: always - set_spidermonkey_pref: always - #ifdef NIGHTLY_BUILD # Experimental support for Async Iterator Helpers in JavaScript. - name: javascript.options.experimental.async_iterator_helpers