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

Add a new context flag for experimental features #1706

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
58 changes: 36 additions & 22 deletions rhino/src/main/java/org/mozilla/javascript/Context.java
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ public class Context implements Closeable {
* identifier. See ECMAScript-262, section 11.2 for definition of memberExpression. By default
* {@link #hasFeature(int)} returns false.
*/
public static final int FEATURE_MEMBER_EXPR_AS_FUNCTION_NAME = 2;
public static final int FEATURE_MEMBER_EXPR_AS_FUNCTION_NAME = FEATURE_NON_ECMA_GET_YEAR + 1;

/**
* Control if reserved keywords are treated as identifiers. If <code>
Expand All @@ -130,7 +130,8 @@ public class Context implements Closeable {
*
* <p>By default {@link #hasFeature(int)} returns false.
*/
public static final int FEATURE_RESERVED_KEYWORD_AS_IDENTIFIER = 3;
public static final int FEATURE_RESERVED_KEYWORD_AS_IDENTIFIER =
FEATURE_MEMBER_EXPR_AS_FUNCTION_NAME + 1;

/**
* Control if <code>toString()</code> should returns the same result as <code>toSource()</code>
Expand All @@ -143,7 +144,8 @@ public class Context implements Closeable {
* <p>By default {@link #hasFeature(int)} returns true only if the current JS version is set to
* {@link #VERSION_1_2}.
*/
public static final int FEATURE_TO_STRING_AS_SOURCE = 4;
public static final int FEATURE_TO_STRING_AS_SOURCE =
FEATURE_RESERVED_KEYWORD_AS_IDENTIFIER + 1;

/**
* Control if properties <code>__proto__</code> and <code>__parent__</code> are treated
Expand All @@ -159,12 +161,13 @@ public class Context implements Closeable {
*
* <p>By default {@link #hasFeature(int)} returns true.
*/
public static final int FEATURE_PARENT_PROTO_PROPERTIES = 5;
public static final int FEATURE_PARENT_PROTO_PROPERTIES = FEATURE_TO_STRING_AS_SOURCE + 1;

/**
* @deprecated In previous releases, this name was given to FEATURE_PARENT_PROTO_PROPERTIES.
*/
@Deprecated public static final int FEATURE_PARENT_PROTO_PROPRTIES = 5;
@Deprecated
public static final int FEATURE_PARENT_PROTO_PROPRTIES = FEATURE_PARENT_PROTO_PROPERTIES;

/**
* Control if support for E4X(ECMAScript for XML) extension is available. If
Expand All @@ -175,7 +178,7 @@ public class Context implements Closeable {
*
* @since 1.6 Release 1
*/
public static final int FEATURE_E4X = 6;
public static final int FEATURE_E4X = FEATURE_PARENT_PROTO_PROPERTIES + 1;

/**
* Control if dynamic scope should be used for name access. If hasFeature(FEATURE_DYNAMIC_SCOPE)
Expand All @@ -191,7 +194,7 @@ public class Context implements Closeable {
*
* @since 1.6 Release 1
*/
public static final int FEATURE_DYNAMIC_SCOPE = 7;
public static final int FEATURE_DYNAMIC_SCOPE = FEATURE_E4X + 1;

/**
* Control if strict variable mode is enabled. When the feature is on Rhino reports runtime
Expand All @@ -202,7 +205,7 @@ public class Context implements Closeable {
*
* @since 1.6 Release 1
*/
public static final int FEATURE_STRICT_VARS = 8;
public static final int FEATURE_STRICT_VARS = FEATURE_DYNAMIC_SCOPE + 1;

/**
* Control if strict eval mode is enabled. When the feature is on Rhino reports runtime errors
Expand All @@ -213,7 +216,7 @@ public class Context implements Closeable {
*
* @since 1.6 Release 1
*/
public static final int FEATURE_STRICT_EVAL = 9;
public static final int FEATURE_STRICT_EVAL = FEATURE_STRICT_VARS + 1;

/**
* When the feature is on Rhino will add a "fileName" and "lineNumber" properties to Error
Expand All @@ -228,7 +231,7 @@ public class Context implements Closeable {
*
* @since 1.6 Release 6
*/
public static final int FEATURE_LOCATION_INFORMATION_IN_ERROR = 10;
public static final int FEATURE_LOCATION_INFORMATION_IN_ERROR = FEATURE_STRICT_EVAL + 1;

/**
* Controls whether JS 1.5 'strict mode' is enabled. When the feature is on, Rhino reports more
Expand All @@ -239,14 +242,14 @@ public class Context implements Closeable {
*
* @since 1.6 Release 6
*/
public static final int FEATURE_STRICT_MODE = 11;
public static final int FEATURE_STRICT_MODE = FEATURE_LOCATION_INFORMATION_IN_ERROR + 1;

/**
* Controls whether a warning should be treated as an error.
*
* @since 1.6 Release 6
*/
public static final int FEATURE_WARNING_AS_ERROR = 12;
public static final int FEATURE_WARNING_AS_ERROR = FEATURE_STRICT_MODE + 1;

/**
* Enables enhanced access to Java. Specifically, controls whether private and protected members
Expand All @@ -258,7 +261,7 @@ public class Context implements Closeable {
*
* @since 1.7 Release 1
*/
public static final int FEATURE_ENHANCED_JAVA_ACCESS = 13;
public static final int FEATURE_ENHANCED_JAVA_ACCESS = FEATURE_WARNING_AS_ERROR + 1;

/**
* Enables access to JavaScript features from ECMAscript 6 that are present in JavaScript
Expand All @@ -267,7 +270,7 @@ public class Context implements Closeable {
*
* @since 1.7 Release 3
*/
public static final int FEATURE_V8_EXTENSIONS = 14;
public static final int FEATURE_V8_EXTENSIONS = FEATURE_ENHANCED_JAVA_ACCESS + 1;

/**
* Defines how an undefined "this" parameter is handled in certain calls. Previously Rhino would
Expand All @@ -276,7 +279,7 @@ public class Context implements Closeable {
*
* @since 1.7.7
*/
public static final int FEATURE_OLD_UNDEF_NULL_THIS = 15;
public static final int FEATURE_OLD_UNDEF_NULL_THIS = FEATURE_V8_EXTENSIONS + 1;

/**
* If set, then the order of property key enumeration will be first numeric keys in numeric
Expand All @@ -285,7 +288,7 @@ public class Context implements Closeable {
*
* @since 1.7.7.1
*/
public static final int FEATURE_ENUMERATE_IDS_FIRST = 16;
public static final int FEATURE_ENUMERATE_IDS_FIRST = FEATURE_OLD_UNDEF_NULL_THIS + 1;

/**
* If set, then all objects will have a thread-safe property map. (Note that this doesn't make
Expand All @@ -296,30 +299,30 @@ public class Context implements Closeable {
*
* @since 1.7.8
*/
public static final int FEATURE_THREAD_SAFE_OBJECTS = 17;
public static final int FEATURE_THREAD_SAFE_OBJECTS = FEATURE_ENUMERATE_IDS_FIRST + 1;

/**
* If set, then all integer numbers will be returned without decimal place. For instance assume
* there is a function like this: <code>function foo() {return 5;}</code> 5 will be returned if
* feature is set, 5.0 otherwise.
*/
public static final int FEATURE_INTEGER_WITHOUT_DECIMAL_PLACE = 18;
public static final int FEATURE_INTEGER_WITHOUT_DECIMAL_PLACE = FEATURE_THREAD_SAFE_OBJECTS + 1;

/**
* TypedArray buffer uses little/big endian depending on the platform. The default is big endian
* for Rhino.
*
* @since 1.7 Release 11
*/
public static final int FEATURE_LITTLE_ENDIAN = 19;
public static final int FEATURE_LITTLE_ENDIAN = FEATURE_INTEGER_WITHOUT_DECIMAL_PLACE + 1;

/**
* Configure the XMLProcessor to parse XML with security features or not. Security features
* include not fetching remote entity references and disabling XIncludes
*
* @since 1.7 Release 12
*/
public static final int FEATURE_ENABLE_XML_SECURE_PARSING = 20;
public static final int FEATURE_ENABLE_XML_SECURE_PARSING = FEATURE_LITTLE_ENDIAN + 1;

/**
* Configure whether the entries in a Java Map can be accessed by properties.
Expand All @@ -344,15 +347,26 @@ public class Context implements Closeable {
*
* @since 1.7 Release 14
*/
public static final int FEATURE_ENABLE_JAVA_MAP_ACCESS = 21;
public static final int FEATURE_ENABLE_JAVA_MAP_ACCESS = FEATURE_ENABLE_XML_SECURE_PARSING + 1;

/**
* Internationalization API implementation (see https://tc39.github.io/ecma402) can be activated
* using this feature.
*
* @since 1.7 Release 15
*/
public static final int FEATURE_INTL_402 = 22;
public static final int FEATURE_INTL_402 = FEATURE_ENABLE_JAVA_MAP_ACCESS + 1;

/**
* Configure whether experimental features are enabled. These will change from release to
* release, but this flag will always be used when a new feature is in development, but does not
* pass enough conformance tests to be enabled by default. An example would be a large new
* JavaScript language feature that has only been partially implemented. When each feature
* reaches enough maturity to be defined "feature complete," then the feature will be changed so
* that it is always implemented, rather than only when this flag is set. As such, different
* Rhino releases will have different behavior when this flag is set.
*/
public static final int FEATURE_EXPERIMENTAL_FEATURES = FEATURE_INTL_402 + 1;

public static final String languageVersionProperty = "language version";
public static final String errorReporterProperty = "error reporter";
Expand Down
133 changes: 68 additions & 65 deletions rhino/src/main/java/org/mozilla/javascript/ContextFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,13 @@ public class ContextFactory {
private volatile Object listeners;
private boolean disabledListening;
private ClassLoader applicationClassLoader;
private java.util.function.Function<Integer, Feature> featureTester;

public enum Feature {
DEFAULT,
ENABLED,
DISABLED
};

/** Listener of {@link Context} creation and release events. */
public interface Listener {
Expand Down Expand Up @@ -207,89 +214,77 @@ protected Context makeContext() {
* {@link Context} without introducing additional subclasses.
*/
protected boolean hasFeature(Context cx, int featureIndex) {
int version;
if (featureTester != null) {
switch (featureTester.apply(featureIndex)) {
case ENABLED:
return true;
case DISABLED:
return false;
default:
// Fall through
break;
}
}

switch (featureIndex) {
case Context.FEATURE_NON_ECMA_GET_YEAR:
/*
* During the great date rewrite of 1.3, we tried to track the
* evolving ECMA standard, which then had a definition of
* getYear which always subtracted 1900. Which we
* implemented, not realizing that it was incompatible with
* the old behavior... now, rather than thrash the behavior
* yet again, we've decided to leave it with the - 1900
* behavior and point people to the getFullYear method. But
* we try to protect existing scripts that have specified a
* version...
*/
version = cx.getLanguageVersion();
return (version == Context.VERSION_1_0
|| version == Context.VERSION_1_1
|| version == Context.VERSION_1_2);
{
/*
* During the great date rewrite of 1.3, we tried to track the
* evolving ECMA standard, which then had a definition of
* getYear which always subtracted 1900. Which we
* implemented, not realizing that it was incompatible with
* the old behavior... now, rather than thrash the behavior
* yet again, we've decided to leave it with the - 1900
* behavior and point people to the getFullYear method. But
* we try to protect existing scripts that have specified a
* version...
*/
int version = cx.getLanguageVersion();
return (version == Context.VERSION_1_0
|| version == Context.VERSION_1_1
|| version == Context.VERSION_1_2);
}

case Context.FEATURE_MEMBER_EXPR_AS_FUNCTION_NAME:
case Context.FEATURE_INTL_402:
case Context.FEATURE_ENABLE_JAVA_MAP_ACCESS:
case Context.FEATURE_LITTLE_ENDIAN:
case Context.FEATURE_INTEGER_WITHOUT_DECIMAL_PLACE:
case Context.FEATURE_THREAD_SAFE_OBJECTS:
case Context.FEATURE_ENHANCED_JAVA_ACCESS:
case Context.FEATURE_WARNING_AS_ERROR:
case Context.FEATURE_STRICT_MODE:
case Context.FEATURE_LOCATION_INFORMATION_IN_ERROR:
case Context.FEATURE_STRICT_EVAL:
case Context.FEATURE_STRICT_VARS:
case Context.FEATURE_DYNAMIC_SCOPE:
case Context.FEATURE_EXPERIMENTAL_FEATURES:
return false;

case Context.FEATURE_RESERVED_KEYWORD_AS_IDENTIFIER:
case Context.FEATURE_ENABLE_XML_SECURE_PARSING:
case Context.FEATURE_V8_EXTENSIONS:
case Context.FEATURE_PARENT_PROTO_PROPERTIES:
return true;

case Context.FEATURE_TO_STRING_AS_SOURCE:
version = cx.getLanguageVersion();
return version == Context.VERSION_1_2;

case Context.FEATURE_PARENT_PROTO_PROPERTIES:
return true;
{
int version = cx.getLanguageVersion();
return version == Context.VERSION_1_2;
}

case Context.FEATURE_E4X:
version = cx.getLanguageVersion();
return (version == Context.VERSION_DEFAULT || version >= Context.VERSION_1_6);

case Context.FEATURE_DYNAMIC_SCOPE:
return false;

case Context.FEATURE_STRICT_VARS:
return false;

case Context.FEATURE_STRICT_EVAL:
return false;

case Context.FEATURE_LOCATION_INFORMATION_IN_ERROR:
return false;

case Context.FEATURE_STRICT_MODE:
return false;

case Context.FEATURE_WARNING_AS_ERROR:
return false;

case Context.FEATURE_ENHANCED_JAVA_ACCESS:
return false;

case Context.FEATURE_V8_EXTENSIONS:
return true;
{
int version = cx.getLanguageVersion();
return (version == Context.VERSION_DEFAULT || version >= Context.VERSION_1_6);
}

case Context.FEATURE_OLD_UNDEF_NULL_THIS:
return cx.getLanguageVersion() <= Context.VERSION_1_7;

case Context.FEATURE_ENUMERATE_IDS_FIRST:
return cx.getLanguageVersion() >= Context.VERSION_ES6;

case Context.FEATURE_THREAD_SAFE_OBJECTS:
return false;

case Context.FEATURE_INTEGER_WITHOUT_DECIMAL_PLACE:
return false;

case Context.FEATURE_LITTLE_ENDIAN:
return false;

case Context.FEATURE_ENABLE_XML_SECURE_PARSING:
return true;

case Context.FEATURE_ENABLE_JAVA_MAP_ACCESS:
return false;

case Context.FEATURE_INTL_402:
return false;
}
// It is a bug to call the method with unknown featureIndex
throw new IllegalArgumentException(String.valueOf(featureIndex));
Expand Down Expand Up @@ -408,6 +403,14 @@ protected void onContextReleased(Context cx) {
}
}

/**
* Set a function that will be used to check whether a feature is enabled. This is an
* alternative to implementing a subclass of this class in order to enable an optional feature.
*/
public void setFeatureTester(java.util.function.Function<Integer, Feature> f) {
featureTester = f;
}

public final void addListener(Listener listener) {
checkNotSealed();
synchronized (listenersLock) {
Expand Down
Loading
Loading