Skip to content

Commit

Permalink
Fix String.prototype.match
Browse files Browse the repository at this point in the history
As per the spec, it is simply supposed to invoke the Symbol.match
of the regexp.
  • Loading branch information
balajirrao committed Feb 19, 2025
1 parent a3371fc commit eba34cf
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 5 deletions.
48 changes: 46 additions & 2 deletions rhino/src/main/java/org/mozilla/javascript/NativeString.java
Original file line number Diff line number Diff line change
Expand Up @@ -624,8 +624,6 @@ public Object execIdCall(
return ScriptRuntime.wrapBoolean(
(id == Id_equals) ? s1.equals(s2) : s1.equalsIgnoreCase(s2));
}

case Id_match:
case Id_search:
case Id_replace:
case Id_replaceAll:
Expand Down Expand Up @@ -864,6 +862,9 @@ else if (Normalizer.Form.NFC.name().equals(formStr))
case SymbolId_iterator:
return new NativeStringIterator(scope, requireObjectCoercible(cx, thisObj, f));

case Id_match:
return js_match(f, cx, scope, thisObj, args);

case Id_matchAll:
{
// See ECMAScript spec 22.1.3.14
Expand Down Expand Up @@ -1041,6 +1042,49 @@ private ScriptableObject defaultIndexPropertyDescriptor(Object value) {
return desc;
}

/*
*
* See ECMA 22.1.3.13
*
*/
private static Object js_match(
IdFunctionObject f, Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
Object o = requireObjectCoercible(cx, thisObj, f);
Object regexp = args.length > 0 ? args[0] : Undefined.instance;
RegExpProxy regExpProxy = ScriptRuntime.checkRegExpProxy(cx);
if (regexp != null && !Undefined.isUndefined(regexp)) {
Object matcher = ScriptRuntime.getObjectElem(regexp, SymbolKey.MATCH, cx, scope);
// If method is not undefined, it should be a Callable
if (matcher != null && !Undefined.isUndefined(matcher)) {
if (!(matcher instanceof Callable)) {
throw ScriptRuntime.notFunctionError(
regexp, matcher, SymbolKey.MATCH.getName());
}
return ((Callable) matcher)
.call(cx, scope, ScriptRuntime.toObject(scope, regexp), new Object[] {o});
}
}

String s = ScriptRuntime.toString(o);
String regexpToString = Undefined.isUndefined(regexp) ? "" : ScriptRuntime.toString(regexp);

String flags = null;

// Not standard; Done for backward compatibility
if (cx.getLanguageVersion() < Context.VERSION_1_6 && args.length > 1) {
flags = ScriptRuntime.toString(args[1]);
}

Object compiledRegExp = regExpProxy.compileRegExp(cx, regexpToString, flags);
Scriptable rx = regExpProxy.wrapRegExp(cx, scope, compiledRegExp);

Object method = ScriptRuntime.getObjectElem(rx, SymbolKey.MATCH, cx, scope);
if (!(method instanceof Callable)) {
throw ScriptRuntime.notFunctionError(rx, method, SymbolKey.MATCH.getName());
}
return ((Callable) method).call(cx, scope, rx, new Object[] {s});
}

/*
*
* See ECMA 15.5.4.6. Uses Java String.indexOf()
Expand Down
4 changes: 1 addition & 3 deletions tests/testsrc/test262.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2008,7 +2008,7 @@ built-ins/SetIteratorPrototype 0/11 (0.0%)

~built-ins/SharedArrayBuffer

built-ins/String 92/1182 (7.78%)
built-ins/String 90/1182 (7.61%)
fromCharCode/not-a-constructor.js
fromCodePoint/not-a-constructor.js
prototype/charAt/not-a-constructor.js
Expand All @@ -2032,11 +2032,9 @@ built-ins/String 92/1182 (7.78%)
prototype/matchAll/not-a-constructor.js
prototype/matchAll/regexp-matchAll-invocation.js
prototype/matchAll/regexp-prototype-matchAll-invocation.js
prototype/match/cstm-matcher-get-err.js
prototype/match/cstm-matcher-invocation.js
prototype/match/duplicate-named-groups-properties.js
prototype/match/duplicate-named-indices-groups-properties.js
prototype/match/invoke-builtin-match.js
prototype/match/not-a-constructor.js
prototype/normalize/not-a-constructor.js
prototype/padEnd/not-a-constructor.js
Expand Down

0 comments on commit eba34cf

Please sign in to comment.