commit a6cac184cf434c0324f8e22994c923547b98cbcf
parent 3ceca4002d238c37211adcf88224938b15a5f620
Author: Daniel Minor <dminor@mozilla.com>
Date: Tue, 25 Nov 2025 19:12:07 +0000
Bug 1998177 - Don't call well-known Symbol methods for regexp on primitives; r=jandem
Differential Revision: https://phabricator.services.mozilla.com/D273154
Diffstat:
5 files changed, 18 insertions(+), 124 deletions(-)
diff --git a/js/src/builtin/String.js b/js/src/builtin/String.js
@@ -14,14 +14,10 @@ function String_match(regexp) {
}
// Step 2.
- var isPatternString = typeof regexp === "string";
- if (
- !(isPatternString && CanOptimizeStringProtoSymbolLookup()) &&
- !IsNullOrUndefined(regexp)
- ) {
+ if (IsObject(regexp)) {
// Fast path for regular expressions with the original
// RegExp.prototype[@@match] function.
- if (IsObject(regexp) && IsOptimizableRegExpObject(regexp)) {
+ if (IsOptimizableRegExpObject(regexp)) {
return callFunction(RegExpMatch, regexp, this);
}
@@ -30,9 +26,6 @@ function String_match(regexp) {
// Step 2.b.
if (matcher !== undefined) {
- if (!IsObject(regexp)) {
- RegExpSymbolProtocolOnPrimitiveCounter();
- }
return callContentFunction(matcher, regexp, this);
}
}
@@ -40,7 +33,7 @@ function String_match(regexp) {
// Step 3.
var S = ToString(this);
- if (isPatternString && IsRegExpPrototypeOptimizable()) {
+ if (typeof regexp === "string" && IsRegExpPrototypeOptimizable()) {
var flatResult = FlatStringMatch(S, regexp);
if (flatResult !== undefined) {
return flatResult;
@@ -69,7 +62,7 @@ function String_matchAll(regexp) {
}
// Step 2.
- if (!IsNullOrUndefined(regexp)) {
+ if (IsObject(regexp)) {
// Steps 2.a-b.
if (IsRegExp(regexp)) {
// Step 2.b.i.
@@ -88,7 +81,7 @@ function String_matchAll(regexp) {
// Fast path for regular expressions with the original
// RegExp.prototype[@@matchAll] function.
- if (IsObject(regexp) && IsOptimizableRegExpObject(regexp)) {
+ if (IsOptimizableRegExpObject(regexp)) {
return callFunction(RegExpMatchAll, regexp, this);
}
@@ -97,9 +90,6 @@ function String_matchAll(regexp) {
// Step 2.d.
if (matcher !== undefined) {
- if (!IsObject(regexp)) {
- RegExpSymbolProtocolOnPrimitiveCounter();
- }
return callContentFunction(matcher, regexp, this);
}
}
@@ -212,13 +202,10 @@ function String_replace(searchValue, replaceValue) {
}
// Step 2.
- if (
- !(typeof searchValue === "string" && CanOptimizeStringProtoSymbolLookup()) &&
- !IsNullOrUndefined(searchValue)
- ) {
+ if (IsObject(searchValue)) {
// Fast path for regular expressions with the original
// RegExp.prototype[@@replace] function.
- if (IsObject(searchValue) && IsOptimizableRegExpObject(searchValue)) {
+ if (IsOptimizableRegExpObject(searchValue)) {
return callFunction(RegExpReplace, searchValue, this, replaceValue);
}
@@ -227,9 +214,6 @@ function String_replace(searchValue, replaceValue) {
// Step 2.b.
if (replacer !== undefined) {
- if (!IsObject(searchValue)) {
- RegExpSymbolProtocolOnPrimitiveCounter();
- }
return callContentFunction(replacer, searchValue, this, replaceValue);
}
}
@@ -294,7 +278,7 @@ function String_replaceAll(searchValue, replaceValue) {
}
// Step 2.
- if (!IsNullOrUndefined(searchValue)) {
+ if (IsObject(searchValue)) {
// Steps 2.a-b.
if (IsRegExp(searchValue)) {
// Step 2.b.i.
@@ -313,7 +297,7 @@ function String_replaceAll(searchValue, replaceValue) {
// Fast path for regular expressions with the original
// RegExp.prototype[@@replace] function.
- if (IsObject(searchValue) && IsOptimizableRegExpObject(searchValue)) {
+ if (IsOptimizableRegExpObject(searchValue)) {
return callFunction(RegExpReplace, searchValue, this, replaceValue);
}
@@ -322,9 +306,6 @@ function String_replaceAll(searchValue, replaceValue) {
// Step 2.b.
if (replacer !== undefined) {
- if (!IsObject(searchValue)) {
- RegExpSymbolProtocolOnPrimitiveCounter();
- }
return callContentFunction(replacer, searchValue, this, replaceValue);
}
}
@@ -425,13 +406,10 @@ function String_search(regexp) {
// Step 2.
var isPatternString = typeof regexp === "string";
- if (
- !(isPatternString && CanOptimizeStringProtoSymbolLookup()) &&
- !IsNullOrUndefined(regexp)
- ) {
+ if (IsObject(regexp)) {
// Fast path for regular expressions with the original
// RegExp.prototype[@@search] function.
- if (IsObject(regexp) && IsOptimizableRegExpObject(regexp)) {
+ if (IsOptimizableRegExpObject(regexp)) {
return callFunction(RegExpSearch, regexp, this);
}
@@ -440,9 +418,6 @@ function String_search(regexp) {
// Step 2.b.
if (searcher !== undefined) {
- if (!IsObject(regexp)) {
- RegExpSymbolProtocolOnPrimitiveCounter();
- }
return callContentFunction(searcher, regexp, this);
}
}
@@ -479,25 +454,20 @@ function String_split(separator, limit) {
// are constants. Following sequence of if's cannot be put together in
// order that IonMonkey sees the constant if present (bug 1246141).
if (typeof this === "string") {
- if (CanOptimizeStringProtoSymbolLookup()) {
- if (typeof separator === "string") {
- if (limit === undefined) {
- // inlineConstantStringSplitString needs both arguments to
- // be MConstant, so pass them directly.
- return StringSplitString(this, separator);
- }
+ if (typeof separator === "string") {
+ if (limit === undefined) {
+ // inlineConstantStringSplitString needs both arguments to
+ // be MConstant, so pass them directly.
+ return StringSplitString(this, separator);
}
}
}
// Step 2.
- if (
- !(typeof separator === "string" && CanOptimizeStringProtoSymbolLookup()) &&
- !IsNullOrUndefined(separator)
- ) {
+ if (IsObject(separator)) {
// Fast path for regular expressions with the original
// RegExp.prototype[@@split] function.
- if (IsObject(separator) && IsOptimizableRegExpObject(separator)) {
+ if (IsOptimizableRegExpObject(separator)) {
return callFunction(RegExpSplit, separator, this, limit);
}
@@ -506,9 +476,6 @@ function String_split(separator, limit) {
// Step 2.b.
if (splitter !== undefined) {
- if (!IsObject(separator)) {
- RegExpSymbolProtocolOnPrimitiveCounter();
- }
return callContentFunction(splitter, separator, this, limit);
}
}
diff --git a/js/src/jit-test/tests/basic/bug1549035.js b/js/src/jit-test/tests/basic/bug1549035.js
@@ -1,11 +0,0 @@
-var expected = 2;
-for (var i = 0; i < 100; ++i) {
- if (i === 50) {
- expected = 0;
- String.prototype[Symbol.split] = function() {
- return [];
- };
- }
- var r = "ab".split("");
- assertEq(r.length, expected);
-}
diff --git a/js/src/jit-test/tests/fuses/string-proto-symbols-3.js b/js/src/jit-test/tests/fuses/string-proto-symbols-3.js
@@ -1,19 +0,0 @@
-// |jit-test| --fast-warmup; --no-threads
-
-// Test invalidation of Ion code when StringPrototypeSymbols fuse is popped.
-function test() {
- var s = "foobar";
- var count = 0;
- for (var i = 0; i < 200; i++) {
- s.replace("abc", "").replace("def", "");
- if (i === 150) {
- // Pop the fuse.
- Object.prototype[Symbol.replace] = function() {
- count++;
- return s;
- };
- }
- }
- assertEq(count, 98);
-}
-test();
diff --git a/js/src/jit-test/tests/ion/testStringMatch.js b/js/src/jit-test/tests/ion/testStringMatch.js
@@ -37,24 +37,6 @@ function testMod(apply, unapply) {
}
}
}
-testMod(() => {
- String.prototype[Symbol.match] = () => ["mod"];
-}, () => {
- delete String.prototype[Symbol.match];
-});
-testMod(() => {
- Object.prototype[Symbol.match] = () => ["mod"];
-}, () => {
- delete Object.prototype[Symbol.match];
-});
-
-testMod(() => {
- Object.setPrototypeOf(String.prototype, {
- [Symbol.match]: () => ["mod"]
- });
-}, () => {
- Object.setPrototypeOf(String.prototype, Object.prototype);
-});
var orig_exec = RegExp.prototype.exec;
testMod(() => {
diff --git a/js/src/tests/jstests.list b/js/src/tests/jstests.list
@@ -662,31 +662,6 @@ skip script test262/language/statements/with/set-mutable-binding-idref-compound-
skip script test262/built-ins/Iterator/concat/fresh-iterator-result.js
skip script test262/built-ins/Iterator/concat/next-method-returns-throwing-value.js
-# https://bugzilla.mozilla.org/show_bug.cgi?id=1950211
-skip script test262/built-ins/String/prototype/replace/cstm-replace-on-boolean-primitive.js
-skip script test262/built-ins/String/prototype/replace/cstm-replace-on-string-primitive.js
-skip script test262/built-ins/String/prototype/replace/cstm-replace-on-number-primitive.js
-skip script test262/built-ins/String/prototype/replace/cstm-replace-on-bigint-primitive.js
-skip script test262/built-ins/String/prototype/matchAll/cstm-matchall-on-number-primitive.js
-skip script test262/built-ins/String/prototype/matchAll/cstm-matchall-on-bigint-primitive.js
-skip script test262/built-ins/String/prototype/matchAll/cstm-matchall-on-string-primitive.js
-skip script test262/built-ins/String/prototype/replaceAll/cstm-replaceall-on-bigint-primitive.js
-skip script test262/built-ins/String/prototype/replaceAll/cstm-replaceall-on-number-primitive.js
-skip script test262/built-ins/String/prototype/replaceAll/cstm-replaceall-on-boolean-primitive.js
-skip script test262/built-ins/String/prototype/replaceAll/cstm-replaceall-on-string-primitive.js
-skip script test262/built-ins/String/prototype/split/cstm-split-on-boolean-primitive.js
-skip script test262/built-ins/String/prototype/split/cstm-split-on-string-primitive.js
-skip script test262/built-ins/String/prototype/split/cstm-split-on-number-primitive.js
-skip script test262/built-ins/String/prototype/split/cstm-split-on-bigint-primitive.js
-skip script test262/built-ins/String/prototype/match/cstm-matcher-on-boolean-primitive.js
-skip script test262/built-ins/String/prototype/match/cstm-matcher-on-bigint-primitive.js
-skip script test262/built-ins/String/prototype/match/cstm-matcher-on-number-primitive.js
-skip script test262/built-ins/String/prototype/match/cstm-matcher-on-string-primitive.js
-skip script test262/built-ins/String/prototype/search/cstm-search-on-bigint-primitive.js
-skip script test262/built-ins/String/prototype/search/cstm-search-on-string-primitive.js
-skip script test262/built-ins/String/prototype/search/cstm-search-on-boolean-primitive.js
-skip script test262/built-ins/String/prototype/search/cstm-search-on-number-primitive.js
-
# https://bugzilla.mozilla.org/show_bug.cgi?id=1970162
# https://github.com/tc39/ecma402/pull/989
skip script test262/intl402/PluralRules/constructor-options-throwing-getters.js