Resolving bug 261278: strict mode implementation

This commit is contained in:
igor%mir2.org 2004-09-23 21:34:22 +00:00
parent d08552d8a1
commit 49a53cd5e9
7 changed files with 57 additions and 16 deletions

View File

@ -40,6 +40,11 @@ or <tt>140</tt>. See <a href="overview.html#versions">JavaScript Language
Versions</a> for more information on language versions. Versions</a> for more information on language versions.
</blockquote> </blockquote>
<tt>-strict</tt>
<blockquote>
Enable strict mode.
</blockquote>
<tt>-continuations</tt> <tt>-continuations</tt>
<blockquote> <blockquote>
Enable experiments support for continuations and set the optimization level to -1 to force interpretation mode. Enable experiments support for continuations and set the optimization level to -1 to force interpretation mode.

View File

@ -233,9 +233,9 @@ public class Context
public static final int FEATURE_DYNAMIC_SCOPE = 7; public static final int FEATURE_DYNAMIC_SCOPE = 7;
/** /**
* Control if highly experimental support for the continuation in the * Control if experimental support for the continuations in the
* interpreter is enabled. * interpreter is enabled.
* If Rhino embedding enables this highly experimental features, then * If Rhino embedding enables this experimental features, then
* <tt>Continuation</tt> object will be available to scripts. * <tt>Continuation</tt> object will be available to scripts.
* When used with pure interpretation mode (optimizatio level is -1) * When used with pure interpretation mode (optimizatio level is -1)
* <tt>Continuation</tt>it allows to capture and restore continuations. * <tt>Continuation</tt>it allows to capture and restore continuations.
@ -248,6 +248,21 @@ public class Context
*/ */
public static final int FEATURE_INTERPRETER_CONTINUATIONS = 8; public static final int FEATURE_INTERPRETER_CONTINUATIONS = 8;
/**
* Control if strict mode is enabled.
* With strict mode enabled Rhino reports runtime errors in the following
* cases:
* <ul>
* <li> Assignment to non-existing names which typically indicates missed
* <b>var</b> declaration.
* <li> Passing non-string arguments to the eval function.
* </ul>
* <p>
* By default {@link #hasFeature(int)} returns false.
* @since 1.6 Release 1
*/
public static final int FEATURE_STRICT_MODE = 9;
public static final String languageVersionProperty = "language version"; public static final String languageVersionProperty = "language version";
public static final String errorReporterProperty = "error reporter"; public static final String errorReporterProperty = "error reporter";
@ -2106,6 +2121,7 @@ public class Context
* @see #FEATURE_E4X * @see #FEATURE_E4X
* @see #FEATURE_DYNAMIC_SCOPE * @see #FEATURE_DYNAMIC_SCOPE
* @see #FEATURE_INTERPRETER_CONTINUATIONS * @see #FEATURE_INTERPRETER_CONTINUATIONS
* @see #FEATURE_STRICT_MODE
*/ */
public boolean hasFeature(int featureIndex) public boolean hasFeature(int featureIndex)
{ {

View File

@ -271,6 +271,9 @@ public class ContextFactory
case Context.FEATURE_INTERPRETER_CONTINUATIONS: case Context.FEATURE_INTERPRETER_CONTINUATIONS:
return false; return false;
case Context.FEATURE_STRICT_MODE:
return false;
} }
// It is a bug to call the method with unknown featureIndex // It is a bug to call the method with unknown featureIndex
throw new IllegalArgumentException(String.valueOf(featureIndex)); throw new IllegalArgumentException(String.valueOf(featureIndex));

View File

@ -1777,20 +1777,16 @@ public class ScriptRuntime {
} else { } else {
// "newname = 7;", where 'newname' has not yet // "newname = 7;", where 'newname' has not yet
// been defined, creates a new property in the // been defined, creates a new property in the
// global object. Find the global object by // top scope unless strict mode is specified.
// walking up the scope chain. if (cx.hasFeature(Context.FEATURE_STRICT_MODE)) {
throw Context.reportRuntimeError1("msg.assn.create.strict", id);
}
// Find the top scope by walking up the scope chain.
bound = ScriptableObject.getTopLevelScope(scope); bound = ScriptableObject.getTopLevelScope(scope);
if (cx.useDynamicScope) { if (cx.useDynamicScope) {
bound = locateDynamicScope(cx, bound); bound = locateDynamicScope(cx, bound);
} }
bound.put(id, bound, value); bound.put(id, bound, value);
/*
This code is causing immense performance problems in
scripts that assign to the variables as a way of creating them.
XXX need strict mode
String message = getMessage1("msg.assn.create", id);
Context.reportWarning(message);
*/
} }
return value; return value;
} }
@ -2213,6 +2209,9 @@ public class ScriptRuntime {
return Undefined.instance; return Undefined.instance;
Object x = args[0]; Object x = args[0];
if (!(x instanceof String)) { if (!(x instanceof String)) {
if (cx.hasFeature(Context.FEATURE_STRICT_MODE)) {
throw Context.reportRuntimeError0("msg.eval.nonstring.strict");
}
String message = Context.getMessage0("msg.eval.nonstring"); String message = Context.getMessage0("msg.eval.nonstring");
Context.reportWarning(message); Context.reportWarning(message);
return x; return x;

View File

@ -130,6 +130,10 @@ msg.eval.nonstring =\
Calling eval() with anything other than a primitive string value will \ Calling eval() with anything other than a primitive string value will \
simply return the value. Is this what you intended? simply return the value. Is this what you intended?
msg.eval.nonstring.strict =\
Calling eval() with anything other than a primitive string value is not \
allowed in the strict mode.
# NativeCall # NativeCall
msg.only.from.new =\ msg.only.from.new =\
"{0}" may only be invoked from a "new" expression. "{0}" may only be invoked from a "new" expression.
@ -401,9 +405,9 @@ mag.too.deep.parser.recursion =\
Too deep recursion while parsing Too deep recursion while parsing
# ScriptRuntime # ScriptRuntime
msg.assn.create =\ msg.assn.create.strict =\
Assignment to undefined "{0}" will create a new variable. \ Attempt to assign non-existing name "{0}" in the strict mode. \
Add a variable statement at the top level scope to remove this warning. It could indicate a missing variable statement.
msg.prop.not.found =\ msg.prop.not.found =\
Property {0} not found. Property {0} not found.
@ -452,7 +456,7 @@ msg.no.ref.to.get =\
msg.no.ref.to.set =\ msg.no.ref.to.set =\
{0} is not a reference to set reference value tpo {1}. {0} is not a reference to set reference value tpo {1}.
msg.no.ref.from.function =\ msg.no.ref.from.function =\
Function {0} can not be used as the left-hand side of assignment \ Function {0} can not be used as the left-hand side of assignment \
or as an operand of ++ or -- operator. or as an operand of ++ or -- operator.

View File

@ -192,6 +192,10 @@ public class Main
} }
continue; continue;
} }
if (arg.equals("-strict")) {
shellContextFactory.setStrictMode(true);
continue;
}
if (arg.equals("-continuations")) { if (arg.equals("-continuations")) {
shellContextFactory.setEnableContinuations(true); shellContextFactory.setEnableContinuations(true);
cx.setOptimizationLevel(-1); cx.setOptimizationLevel(-1);

View File

@ -40,10 +40,14 @@ import org.mozilla.javascript.*;
public class ShellContextFactory extends ContextFactory public class ShellContextFactory extends ContextFactory
{ {
private boolean enableContinuations; private boolean enableContinuations;
private boolean strictMode;
protected boolean hasFeature(Context cx, int featureIndex) protected boolean hasFeature(Context cx, int featureIndex)
{ {
if (featureIndex == Context.FEATURE_INTERPRETER_CONTINUATIONS) { switch (featureIndex) {
case Context.FEATURE_STRICT_MODE:
return strictMode;
case Context.FEATURE_INTERPRETER_CONTINUATIONS:
return enableContinuations; return enableContinuations;
} }
return super.hasFeature(cx, featureIndex); return super.hasFeature(cx, featureIndex);
@ -55,4 +59,10 @@ public class ShellContextFactory extends ContextFactory
this.enableContinuations = flag; this.enableContinuations = flag;
} }
public void setStrictMode(boolean flag)
{
checkNotSealed();
this.strictMode = flag;
}
} }