Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change default version to VERSION_ES6 #1755

Merged
merged 4 commits into from
Dec 17, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Change default version to VERSION_ES6
This changes the version set when a Context object is created to
VERSION_ES6 by default.

It also adds language to the JavaDoc to indicate that:

* We will not be adding additional versions after VERSION_ES6, but
  instead will introduce new features in new versions of Rhino, like
  other JavaScript engines.
* Code that uses Rhino should plan on migrating to VERSION_ES6.
* Projects that use Rhino should, if possible, stop relying on older
  language versions, as these typically are features that are
  incompatible with modern JavaScript.

(Simply changing VERSION_DEFAULT is not sufficient -- VERSION_DEFAULT
unfortunately drives a number of odd behaviors that many tests and
probably many programs depend on.)
gbrail committed Dec 13, 2024
commit 1352fc263dbac8b136c67408070f5746823e4a1f
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@
public class CompilerEnvirons {
public CompilerEnvirons() {
errorReporter = DefaultErrorReporter.instance;
languageVersion = Context.VERSION_DEFAULT;
languageVersion = Context.VERSION_ES6;
generateDebugInfo = true;
reservedKeywordAsIdentifier = true;
allowMemberExprAsFunctionName = false;
36 changes: 30 additions & 6 deletions rhino/src/main/java/org/mozilla/javascript/Context.java
Original file line number Diff line number Diff line change
@@ -66,7 +66,8 @@ public class Context implements Closeable {
* The unknown version.
*
* <p>Be aware, this version will not support many of the newer language features and will not
* change in the future.
* change in the future. In practice, for historical reasons, this is an odd version that
* doesn't necessarily match any particular version of JavaScript and should not be used.
*
* <p>Please use one of the other constants like VERSION_ES6 to get support for recent language
* features.
@@ -103,7 +104,14 @@ public class Context implements Closeable {
/** JavaScript 1.8 */
public static final int VERSION_1_8 = 180;

/** ECMAScript 6. */
/**
* ECMAScript 6 and after. Since around version 1.7, this has been used to denote most new
* language features.
*
* <p>As of version 1.8, the Rhino community has no plans to continue adding new language
* versions, but instead plans to track the ECMAScript specification as it evolves and add new
* features in new versions of Rhino.
*/
public static final int VERSION_ES6 = 200;

/**
@@ -363,7 +371,11 @@ public class Context implements Closeable {

/**
* Creates a new Context. The context will be associated with the {@link
* ContextFactory#getGlobal() global context factory}.
* ContextFactory#getGlobal() global context factory}. By default, the new context will run in
* compiled mode and use the {@link #VERSION_ES6} language version, which supports features as
* defined in the most recent ECMAScript standard. This default behavior can be changed by
* overriding the ContextFactory class and installing the new implementation as the global
* ContextFactory.
*
* <p>Note that the Context must be associated with a thread before it can be used to execute a
* script.
@@ -380,7 +392,10 @@ public Context() {

/**
* Creates a new context. Provided as a preferred super constructor for subclasses in place of
* the deprecated default public constructor.
* the deprecated default public constructor. By default, the new context will run in compiled
* mode and use the {@link #VERSION_ES6} language version, which supports features as defined in
* the most recent ECMAScript standard. This default behavior can be changed by overriding the
* ContextFactory class
*
* @param factory the context factory associated with this context (most likely, the one that
* created the context). Can not be null. The context features are inherited from the
@@ -392,7 +407,7 @@ protected Context(ContextFactory factory) {
throw new IllegalArgumentException("factory == null");
}
this.factory = factory;
version = VERSION_DEFAULT;
version = VERSION_ES6;
optimizationLevel = codegenClass != null ? 0 : -1;
maximumInterpreterStackDepth = Integer.MAX_VALUE;
}
@@ -659,7 +674,16 @@ public final int getLanguageVersion() {
* Set the language version.
*
* <p>Setting the language version will affect functions and scripts compiled subsequently. See
* the overview documentation for version-specific behavior.
* the overview documentation for version-specific behavior. The default version is {@link
* #VERSION_ES6}, which represents the newest ECMAScript features implemented by Rhino, and this
* is the version that should be used unless a project needs backwards compatibility with older
* Rhino scripts that may depend on behaviors from the earlier history of JavaScript.
*
* <p>As of version 1.8, the Rhino community has no plans to continue to add new language
* versions, but instead plans to track the ECMAScript standard and add new features as the
* language evolves in new versions of Rhino, like other JavaScript engines. Projects that use
* Rhino are encouraged to migrate to the {@link #VERSION_ES6} version and stop relying on older
Copy link
Collaborator

@rbri rbri Dec 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{@link #VERSION_ES6} -> {@link #VERSION_ECMASCRIPT} ?

* behaviors of Rhino that are no longer compatible with ECMAScript.
*
* @param version the version as specified by VERSION_1_0, VERSION_1_1, etc.
*/
Original file line number Diff line number Diff line change
@@ -81,6 +81,7 @@ public void sameValueDifferentTopology() {
@Test
public void heterogenousScriptables() {
try (Context cx = Context.enter()) {
cx.setLanguageVersion(Context.VERSION_DEFAULT);
ScriptableObject top = cx.initStandardObjects();
ScriptRuntime.doTopCall(
(Callable)
Original file line number Diff line number Diff line change
@@ -25,6 +25,7 @@ private interface Action {

private static ContextAction<Void> action(final String fn, final Action a) {
return cx -> {
cx.setLanguageVersion(Context.VERSION_DEFAULT);
ScriptableObject scope1 = cx.initStandardObjects();
ScriptableObject scope2 = cx.initStandardObjects();
scope1.put("scope2", scope1, scope2);
Original file line number Diff line number Diff line change
@@ -31,6 +31,7 @@ public void test1() throws Exception {

private NativeContinuation createContinuation() throws Exception {
try (Context cx = Context.enter()) {
cx.setLanguageVersion(Context.VERSION_DEFAULT);
cx.setOptimizationLevel(-1); // interpreter for continuations
ScriptableObject global = cx.initStandardObjects();
final AtomicReference<NativeContinuation> captured = new AtomicReference<>();
Original file line number Diff line number Diff line change
@@ -90,6 +90,7 @@ public static Collection<Object[]> singleDoctest() throws IOException {
public void runDoctest() throws Exception {
ContextFactory factory = ContextFactory.getGlobal();
try (Context cx = factory.enterContext()) {
cx.setLanguageVersion(Context.VERSION_DEFAULT);
cx.setOptimizationLevel(optimizationLevel);
Global global = new Global(cx);
// global.runDoctest throws an exception on any failure
28 changes: 20 additions & 8 deletions tests/src/test/java/org/mozilla/javascript/tests/Evaluator.java
Original file line number Diff line number Diff line change
@@ -16,21 +16,33 @@ public static Object eval(String source) {
return eval(source, null);
}

public static Object eval(Context cx, String source) {
return eval(cx, source, null);
}

public static Object eval(String source, String id, Scriptable object) {
return eval(source, Collections.singletonMap(id, object));
}

public static Object eval(Context cx, String source, String id, Scriptable object) {
return eval(cx, source, Collections.singletonMap(id, object));
}

public static Object eval(String source, Map<String, Scriptable> bindings) {
try (Context cx = ContextFactory.getGlobal().enterContext()) {
Scriptable scope = cx.initStandardObjects();
if (bindings != null) {
for (Map.Entry<String, Scriptable> entry : bindings.entrySet()) {
final Scriptable object = entry.getValue();
object.setParentScope(scope);
scope.put(entry.getKey(), scope, object);
}
return eval(cx, source, bindings);
}
}

public static Object eval(Context cx, String source, Map<String, Scriptable> bindings) {
Scriptable scope = cx.initStandardObjects();
if (bindings != null) {
for (Map.Entry<String, Scriptable> entry : bindings.entrySet()) {
final Scriptable object = entry.getValue();
object.setParentScope(scope);
scope.put(entry.getKey(), scope, object);
}
return cx.evaluateString(scope, source, "source", 1, null);
}
return cx.evaluateString(scope, source, "source", 1, null);
}
}
Original file line number Diff line number Diff line change
@@ -566,6 +566,7 @@ private static void assertPrintMsg(String source, String expectedMsg) {
DummyConsolePrinter printer = new DummyConsolePrinter();

try (Context cx = Context.enter()) {
cx.setLanguageVersion(Context.VERSION_DEFAULT);
Scriptable scope = cx.initStandardObjects();
NativeConsole.init(scope, false, printer);
cx.evaluateString(scope, source, "source", 1, null);
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@
import static org.junit.Assert.assertThrows;

import org.junit.Test;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.EvaluatorException;
import org.mozilla.javascript.Scriptable;

@@ -11,6 +12,7 @@ public class NullishCoalescingOpTest {
public void testNullishCoalescingOperatorRequiresES6() {
Utils.runWithAllOptimizationLevels(
cx -> {
cx.setLanguageVersion(Context.VERSION_DEFAULT);
Scriptable scope = cx.initStandardObjects();
assertThrows(
EvaluatorException.class,
@@ -77,6 +79,7 @@ public void testNullishCoalescingDoesNotLeakVariables() {
public void testNullishAssignmentRequiresES6() {
Utils.runWithAllOptimizationLevels(
cx -> {
cx.setLanguageVersion(Context.VERSION_DEFAULT);
Scriptable scope = cx.initStandardObjects();
assertThrows(
EvaluatorException.class,
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@
import static org.junit.Assert.assertThrows;

import org.junit.Test;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.EvaluatorException;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.Undefined;
@@ -12,6 +13,7 @@ public class OptionalChainingOperatorTest {
public void requiresES6() {
Utils.runWithAllOptimizationLevels(
cx -> {
cx.setLanguageVersion(Context.VERSION_DEFAULT);
Scriptable scope = cx.initStandardObjects();
assertThrows(
EvaluatorException.class,
Original file line number Diff line number Diff line change
@@ -66,6 +66,7 @@ public class ParserTest {
@Before
public void setUp() throws Exception {
environment = new CompilerEnvirons();
environment.setLanguageVersion(Context.VERSION_DEFAULT);
}

@Test
Original file line number Diff line number Diff line change
@@ -40,6 +40,7 @@ public void setUp() throws Exception {
}

ctx = Context.enter();
ctx.setLanguageVersion(Context.VERSION_DEFAULT);
scope1 = ctx.newObject(sharedScope);
scope1.setPrototype(sharedScope);
scope1.setParentScope(null);
@@ -79,7 +80,7 @@ public void importClassWithImporter() throws Exception {
assertEquals(java.sql.Date.class, o);

o = evaluateString(scope1, "Date"); // JavaScript "Statement" function
assertEquals(IdFunctionObject.class, o.getClass());
assertTrue(o instanceof IdFunctionObject);

o = evaluateString(scope2, "typeof imp1"); // scope 2 has
// no imp1
@@ -104,7 +105,7 @@ public void importPackageWithImporter() throws Exception {
assertEquals(java.sql.Date.class, o);

o = evaluateString(scope1, "Date"); // JavaScript "Statement" function
assertEquals(IdFunctionObject.class, o.getClass());
assertTrue(o instanceof IdFunctionObject);

o = evaluateString(scope2, "typeof imp1 == 'undefined'"); // scope 2 has
// no imp1
Original file line number Diff line number Diff line change
@@ -40,7 +40,6 @@ public Object call(

@After
public void tearDown() throws Exception {
cx.setLanguageVersion(Context.VERSION_DEFAULT);
Context.exit();
}

@@ -106,6 +105,7 @@ public void whenVersionGt17ThenPassNullAsThisObjForApplyJS() {
NativeArray arr =
(NativeArray)
Evaluator.eval(
cx,
"function F2() {return this;};[this, F2.apply(), F2.apply(undefined)];");

assertNotEquals(arr.get(0), arr.get(1));
@@ -117,6 +117,7 @@ public void whenVersionGt17ThenPassNullAsThisObjForApplyJS() {
arr =
(NativeArray)
Evaluator.eval(
cx,
"function F2() {return this;};[this, F2.apply(), F2.apply(null)];");
assertNotEquals(arr.get(0), arr.get(1));
assertNotEquals(arr.get(0), arr.get(2));
@@ -126,6 +127,7 @@ public void whenVersionGt17ThenPassNullAsThisObjForApplyJS() {
arr =
(NativeArray)
Evaluator.eval(
cx,
"function F2() {return this;};[this, F2.apply(), F2.apply(undefined)];");

assertNotEquals(arr.get(0), arr.get(1));
@@ -137,6 +139,7 @@ public void whenVersionGt17ThenPassNullAsThisObjForApplyJS() {
arr =
(NativeArray)
Evaluator.eval(
cx,
"function F2() {return this;};[this, F2.apply(), F2.apply(null)];");
assertNotEquals(arr.get(0), arr.get(1));
assertNotEquals(arr.get(0), arr.get(2));
@@ -149,6 +152,7 @@ public void whenVersionLtEq17ThenPassGlobalThisObjForApplyJS() {
NativeArray arr =
(NativeArray)
Evaluator.eval(
cx,
"function F2() {return this;};[this, F2.apply(), F2.apply(undefined)];");

assertEquals(arr.get(0), arr.get(1));
@@ -158,6 +162,7 @@ public void whenVersionLtEq17ThenPassGlobalThisObjForApplyJS() {
arr =
(NativeArray)
Evaluator.eval(
cx,
"function F2() {return this;};[this, F2.apply(), F2.apply(null)];");

assertEquals(arr.get(0), arr.get(1));
@@ -171,6 +176,7 @@ public void whenVersionGt17ThenPassNullAsThisObjForCallJS() {
NativeArray arr =
(NativeArray)
Evaluator.eval(
cx,
"function F2() {return this;};[this, F2.call(), F2.call(undefined)];");

assertNotEquals(arr.get(0), arr.get(1));
@@ -182,6 +188,7 @@ public void whenVersionGt17ThenPassNullAsThisObjForCallJS() {
arr =
(NativeArray)
Evaluator.eval(
cx,
"function F2() {return this;};[this, F2.call(), F2.call(null)];");
assertNotEquals(arr.get(0), arr.get(1));
assertNotEquals(arr.get(0), arr.get(2));
@@ -191,6 +198,7 @@ public void whenVersionGt17ThenPassNullAsThisObjForCallJS() {
arr =
(NativeArray)
Evaluator.eval(
cx,
"function F2() {return this;};[this, F2.call(), F2.call(undefined)];");

assertNotEquals(arr.get(0), arr.get(1));
@@ -202,6 +210,7 @@ public void whenVersionGt17ThenPassNullAsThisObjForCallJS() {
arr =
(NativeArray)
Evaluator.eval(
cx,
"function F2() {return this;};[this, F2.call(), F2.call(null)];");
assertNotEquals(arr.get(0), arr.get(1));
assertNotEquals(arr.get(0), arr.get(2));
@@ -214,6 +223,7 @@ public void whenVersionLtEq17ThenPassGlobalThisObjForCallJS() {
NativeArray arr =
(NativeArray)
Evaluator.eval(
cx,
"function F2() {return this;};[this, F2.call(), F2.call(undefined)];");

assertEquals(arr.get(0), arr.get(1));
@@ -223,6 +233,7 @@ public void whenVersionLtEq17ThenPassGlobalThisObjForCallJS() {
arr =
(NativeArray)
Evaluator.eval(
cx,
"function F2() {return this;};[this, F2.call(), F2.call(null)];");

assertEquals(arr.get(0), arr.get(1));
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@
import static org.mozilla.javascript.tests.Evaluator.eval;

import org.junit.Test;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.NativeObject;

/**
@@ -19,8 +20,10 @@ public class StringMissingPropertyIsNotEnumerableTest {
public void stringMissingPropertyIsNotEnumerable() {
NativeObject object = new NativeObject();

Object result = eval("'s'.propertyIsEnumerable(0)", "obj", object);

assertFalse((Boolean) result);
try (Context cx = Context.enter()) {
cx.setLanguageVersion(Context.VERSION_DEFAULT);
Object result = eval("'s'.propertyIsEnumerable(0)", "obj", object);
assertFalse((Boolean) result);
}
}
}
Loading