Skip to content

Commit

Permalink
make sure to use only the RegExpProxy interface instead of some hardc…
Browse files Browse the repository at this point in the history
…oded instanceof
  • Loading branch information
rbri authored and gbrail committed Aug 23, 2024
1 parent c743a3f commit cd9aae7
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

import java.io.Serializable;
import java.util.Comparator;
import org.mozilla.javascript.regexp.NativeRegExp;

/** Contains implementation of shared methods useful for arrays and typed arrays. */
public class ArrayLikeAbstractOperations {
Expand Down Expand Up @@ -146,20 +145,23 @@ static Function getCallbackArg(Context cx, Object callbackArg) {
if (!(callbackArg instanceof Function)) {
throw ScriptRuntime.notFunctionError(callbackArg);
}
if (cx.getLanguageVersion() >= Context.VERSION_ES6
&& (callbackArg instanceof NativeRegExp)) {
// Previously, it was allowed to pass RegExp instance as a callback (it implements
// Function)
// But according to ES2015 21.2.6 Properties of RegExp Instances:
// > RegExp instances are ordinary objects that inherit properties from the RegExp
// prototype object.
// > RegExp instances have internal slots [[RegExpMatcher]], [[OriginalSource]], and
// [[OriginalFlags]].
// so, no [[Call]] for RegExp-s
throw ScriptRuntime.notFunctionError(callbackArg);
}

Function f = (Function) callbackArg;

if (cx.getLanguageVersion() >= Context.VERSION_ES6) {
RegExpProxy reProxy = ScriptRuntime.getRegExpProxy(cx);
if (reProxy != null && reProxy.isRegExp(f))
// Previously, it was allowed to pass RegExp instance as a callback (it implements
// Function)
// But according to ES2015 21.2.6 Properties of RegExp Instances:
// > RegExp instances are ordinary objects that inherit properties from the RegExp
// prototype object.
// > RegExp instances have internal slots [[RegExpMatcher]], [[OriginalSource]], and
// [[OriginalFlags]].
// so, no [[Call]] for RegExp-s
throw ScriptRuntime.notFunctionError(callbackArg);
}

return f;
}

Expand Down
24 changes: 14 additions & 10 deletions rhino/src/main/java/org/mozilla/javascript/NativeString.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import java.text.Normalizer;
import java.util.Locale;
import org.mozilla.javascript.ScriptRuntime.StringIdOrIndex;
import org.mozilla.javascript.regexp.NativeRegExp;

/**
* This class implements the String native object.
Expand Down Expand Up @@ -468,15 +467,20 @@ public Object execIdCall(
case Id_endsWith:
String thisString =
ScriptRuntime.toString(requireObjectCoercible(cx, thisObj, f));
if (args.length > 0 && args[0] instanceof NativeRegExp) {
if (ScriptableObject.isTrue(
ScriptableObject.getProperty(
ScriptableObject.ensureScriptable(args[0]),
SymbolKey.MATCH))) {
throw ScriptRuntime.typeErrorById(
"msg.first.arg.not.regexp",
String.class.getSimpleName(),
f.getFunctionName());

if (args.length > 0) {
RegExpProxy reProxy = ScriptRuntime.getRegExpProxy(cx);
if (reProxy != null && args[0] instanceof Scriptable) {
Scriptable arg0 = (Scriptable) args[0];
if (reProxy.isRegExp(arg0)) {
if (ScriptableObject.isTrue(
ScriptableObject.getProperty(arg0, SymbolKey.MATCH))) {
throw ScriptRuntime.typeErrorById(
"msg.first.arg.not.regexp",
String.class.getSimpleName(),
f.getFunctionName());
}
}
}
}

Expand Down
4 changes: 4 additions & 0 deletions tests/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ dependencies {
implementation project(':rhino')
implementation project(':rhino-tools')
implementation project(':rhino-xml')

testImplementation("com.tngtech.archunit:archunit-junit4:1.2.0") {
exclude group: 'junit'
}
}

test {
Expand Down
40 changes: 40 additions & 0 deletions tests/src/test/java/org/mozilla/archunit/ArchitectureTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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/. */

package org.mozilla.archunit;

import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;

import com.tngtech.archunit.core.importer.ImportOption;
import com.tngtech.archunit.junit.AnalyzeClasses;
import com.tngtech.archunit.junit.ArchTest;
import com.tngtech.archunit.junit.ArchUnitRunner;
import com.tngtech.archunit.lang.ArchRule;
import org.junit.runner.RunWith;

/**
* Architecture tests.
*
* @author Ronald Brill
*/
@RunWith(ArchUnitRunner.class)
@AnalyzeClasses(
packages = "org.mozilla.javascript",
importOptions = ImportOption.DoNotIncludeTests.class)
public class ArchitectureTest {

/** Use only the RegExpProxy. */
@ArchTest
public static final ArchRule regExpProxyRule =
noClasses()
.that()
.resideOutsideOfPackage("org.mozilla.javascript.regexp..")
.and()
.doNotHaveFullyQualifiedName("org.mozilla.javascript.RegExpProxy")
.should()
.dependOnClassesThat()
.resideInAnyPackage("org.mozilla.javascript.regexp..");
}

0 comments on commit cd9aae7

Please sign in to comment.