commit 9af568d0c7aab14b4cc22b200036ba08c4648557
parent f5110adff3b8369a59534eb7fd253aa8845750d2
Author: Meg Ford <meg387@gmail.com>
Date: Wed, 29 Oct 2025 00:17:45 +0000
Bug 1898383 - Add new error message for RegExpExec r=dminor
Differential Revision: https://phabricator.services.mozilla.com/D268639
Diffstat:
6 files changed, 25 insertions(+), 10 deletions(-)
diff --git a/js/public/friend/ErrorNumbers.msg b/js/public/friend/ErrorNumbers.msg
@@ -681,6 +681,7 @@ MSG_DEF(JSMSG_DUPLICATE_CAPTURE_NAME, 0, JSEXN_SYNTAXERR, "duplicate captur
MSG_DEF(JSMSG_INVALID_NAMED_REF, 0, JSEXN_SYNTAXERR, "invalid named reference in regular expression")
MSG_DEF(JSMSG_INVALID_NAMED_CAPTURE_REF, 0, JSEXN_SYNTAXERR, "invalid named capture reference in regular expression")
MSG_DEF(JSMSG_INCOMPATIBLE_REGEXP_GETTER, 2, JSEXN_TYPEERR, "RegExp.prototype.{0} getter called on non-RegExp object: {1}")
+MSG_DEF(JSMSG_INCOMPATIBLE_REGEXP_METHOD, 2, JSEXN_TYPEERR, "RegExp.prototype.{0} called on incompatible receiver: {1}")
MSG_DEF(JSMSG_INVALID_CLASS_SET_OP, 0, JSEXN_SYNTAXERR, "invalid class set operation in regular expression")
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")
diff --git a/js/src/builtin/RegExp.cpp b/js/src/builtin/RegExp.cpp
@@ -2212,7 +2212,8 @@ bool js::RegExpExec(JSContext* cx, Handle<JSObject*> regexp,
// unwrap.
if (!regexp->canUnwrapAs<RegExpObject>()) {
Rooted<Value> thisv(cx, ObjectValue(*regexp));
- return ReportIncompatibleSelfHostedMethod(cx, thisv);
+ return ReportIncompatibleSelfHostedMethod(
+ cx, thisv, IncompatibleContext::RegExpExec);
}
// Call RegExpBuiltinExec in the regular expression's realm.
diff --git a/js/src/jit-test/tests/regexp/RegExpExec-errors.js b/js/src/jit-test/tests/regexp/RegExpExec-errors.js
@@ -1,6 +1,6 @@
load(libdir + "asserts.js");
assertErrorMessage(() => RegExp.prototype.test.call({}), TypeError,
- /test method called on incompatible Object/);
+ /RegExp.prototype.test called on incompatible receiver: Object/);
assertErrorMessage(() => RegExp.prototype[Symbol.match].call([]), TypeError,
- /\[Symbol\.match\] method called on incompatible Array/);
+ /RegExp.prototype.\[Symbol\.match\] called on incompatible receiver: Array/);
+\ No newline at end of file
diff --git a/js/src/vm/CallNonGenericMethod.cpp b/js/src/vm/CallNonGenericMethod.cpp
@@ -27,7 +27,8 @@ bool JS::detail::CallMethodIfWrapped(JSContext* cx, IsAcceptableThis test,
}
if (IsCallSelfHostedNonGenericMethod(impl)) {
- return ReportIncompatibleSelfHostedMethod(cx, thisv);
+ return ReportIncompatibleSelfHostedMethod(cx, thisv,
+ IncompatibleContext::Regular);
}
ReportIncompatible(cx, args);
diff --git a/js/src/vm/SelfHosting.cpp b/js/src/vm/SelfHosting.cpp
@@ -1228,8 +1228,9 @@ bool js::IsCallSelfHostedNonGenericMethod(NativeImpl impl) {
return impl == CallSelfHostedNonGenericMethod;
}
-bool js::ReportIncompatibleSelfHostedMethod(JSContext* cx,
- Handle<Value> thisValue) {
+bool js::ReportIncompatibleSelfHostedMethod(
+ JSContext* cx, Handle<Value> thisValue,
+ IncompatibleContext incompatibleContext) {
// The contract for this function is the same as
// CallSelfHostedNonGenericMethod. The normal ReportIncompatible function
// doesn't work for selfhosted functions, because they always call the
@@ -1264,9 +1265,15 @@ bool js::ReportIncompatibleSelfHostedMethod(JSContext* cx,
if (std::all_of(
std::begin(internalNames), std::end(internalNames),
[funName](auto* name) { return strcmp(funName, name) != 0; })) {
- JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr,
- JSMSG_INCOMPATIBLE_METHOD, funName, "method",
- InformalValueTypeName(thisValue));
+ if (incompatibleContext == IncompatibleContext::RegExpExec) {
+ JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr,
+ JSMSG_INCOMPATIBLE_REGEXP_METHOD, funName,
+ InformalValueTypeName(thisValue));
+ } else {
+ JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr,
+ JSMSG_INCOMPATIBLE_METHOD, funName, "method",
+ InformalValueTypeName(thisValue));
+ }
return false;
}
++iter;
diff --git a/js/src/vm/SelfHosting.h b/js/src/vm/SelfHosting.h
@@ -255,7 +255,11 @@ void SetUnclonedSelfHostedCanonicalName(JSFunction* fun, JSAtom* name);
bool IsCallSelfHostedNonGenericMethod(NativeImpl impl);
-bool ReportIncompatibleSelfHostedMethod(JSContext* cx, Handle<Value> thisValue);
+enum class IncompatibleContext { Regular, RegExpExec };
+
+bool ReportIncompatibleSelfHostedMethod(
+ JSContext* cx, Handle<Value> thisValue,
+ IncompatibleContext incompatibleContext);
/* Get the compile options used when compiling self hosted code. */
void FillSelfHostingCompileOptions(JS::CompileOptions& options);