aboutsummaryrefslogtreecommitdiff
path: root/src/jdk/nashorn
diff options
context:
space:
mode:
Diffstat (limited to 'src/jdk/nashorn')
-rw-r--r--src/jdk/nashorn/api/scripting/NashornScriptEngine.java6
-rw-r--r--src/jdk/nashorn/api/scripting/ScriptObjectMirror.java178
-rw-r--r--src/jdk/nashorn/api/scripting/URLReader.java46
-rw-r--r--src/jdk/nashorn/internal/codegen/Attr.java90
-rw-r--r--src/jdk/nashorn/internal/codegen/FieldObjectCreator.java2
-rw-r--r--src/jdk/nashorn/internal/codegen/MapCreator.java2
-rw-r--r--src/jdk/nashorn/internal/ir/BlockLexicalContext.java1
-rw-r--r--src/jdk/nashorn/internal/ir/BreakableNode.java2
-rw-r--r--src/jdk/nashorn/internal/ir/Symbol.java34
-rw-r--r--src/jdk/nashorn/internal/objects/AccessorPropertyDescriptor.java10
-rw-r--r--src/jdk/nashorn/internal/objects/ArrayBufferView.java13
-rw-r--r--src/jdk/nashorn/internal/objects/DataPropertyDescriptor.java9
-rw-r--r--src/jdk/nashorn/internal/objects/GenericPropertyDescriptor.java5
-rw-r--r--src/jdk/nashorn/internal/objects/Global.java45
-rw-r--r--src/jdk/nashorn/internal/objects/NativeArguments.java91
-rw-r--r--src/jdk/nashorn/internal/objects/NativeArray.java98
-rw-r--r--src/jdk/nashorn/internal/objects/NativeError.java10
-rw-r--r--src/jdk/nashorn/internal/objects/NativeEvalError.java2
-rw-r--r--src/jdk/nashorn/internal/objects/NativeFunction.java13
-rw-r--r--src/jdk/nashorn/internal/objects/NativeJSON.java2
-rw-r--r--src/jdk/nashorn/internal/objects/NativeJavaImporter.java2
-rw-r--r--src/jdk/nashorn/internal/objects/NativeObject.java107
-rw-r--r--src/jdk/nashorn/internal/objects/NativeRangeError.java2
-rw-r--r--src/jdk/nashorn/internal/objects/NativeReferenceError.java2
-rw-r--r--src/jdk/nashorn/internal/objects/NativeRegExp.java59
-rw-r--r--src/jdk/nashorn/internal/objects/NativeString.java25
-rw-r--r--src/jdk/nashorn/internal/objects/NativeSyntaxError.java2
-rw-r--r--src/jdk/nashorn/internal/objects/NativeTypeError.java2
-rw-r--r--src/jdk/nashorn/internal/objects/NativeURIError.java2
-rw-r--r--src/jdk/nashorn/internal/parser/JSONParser.java99
-rw-r--r--src/jdk/nashorn/internal/parser/Lexer.java100
-rw-r--r--src/jdk/nashorn/internal/parser/Parser.java2
-rw-r--r--src/jdk/nashorn/internal/runtime/Context.java16
-rw-r--r--src/jdk/nashorn/internal/runtime/GlobalFunctions.java11
-rw-r--r--src/jdk/nashorn/internal/runtime/JSONFunctions.java22
-rw-r--r--src/jdk/nashorn/internal/runtime/NativeJavaPackage.java5
-rw-r--r--src/jdk/nashorn/internal/runtime/PropertyListenerManager.java10
-rw-r--r--src/jdk/nashorn/internal/runtime/PropertyMap.java5
-rw-r--r--src/jdk/nashorn/internal/runtime/ScriptEnvironment.java4
-rw-r--r--src/jdk/nashorn/internal/runtime/ScriptObject.java193
-rw-r--r--src/jdk/nashorn/internal/runtime/ScriptRuntime.java7
-rw-r--r--src/jdk/nashorn/internal/runtime/ScriptingFunctions.java7
-rw-r--r--src/jdk/nashorn/internal/runtime/Source.java83
-rw-r--r--src/jdk/nashorn/internal/runtime/arrays/ArrayIndex.java130
-rw-r--r--src/jdk/nashorn/internal/runtime/arrays/ArrayIterator.java2
-rw-r--r--src/jdk/nashorn/internal/runtime/arrays/ArrayLikeIterator.java9
-rw-r--r--src/jdk/nashorn/internal/runtime/arrays/IteratorAction.java13
-rw-r--r--src/jdk/nashorn/internal/runtime/arrays/ReverseScriptObjectMirrorIterator.java56
-rw-r--r--src/jdk/nashorn/internal/runtime/arrays/ScriptObjectMirrorIterator.java81
-rw-r--r--src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java8
-rw-r--r--src/jdk/nashorn/internal/runtime/resources/Messages.properties5
-rw-r--r--src/jdk/nashorn/internal/runtime/resources/Options.properties18
52 files changed, 1217 insertions, 531 deletions
diff --git a/src/jdk/nashorn/api/scripting/NashornScriptEngine.java b/src/jdk/nashorn/api/scripting/NashornScriptEngine.java
index 283e36e9..b05a4aee 100644
--- a/src/jdk/nashorn/api/scripting/NashornScriptEngine.java
+++ b/src/jdk/nashorn/api/scripting/NashornScriptEngine.java
@@ -34,6 +34,7 @@ import java.io.InputStreamReader;
import java.io.Reader;
import java.lang.reflect.Method;
import java.net.URL;
+import java.nio.charset.Charset;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
@@ -72,7 +73,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
private final ScriptObject global;
// default options passed to Nashorn Options object
- private static final String[] DEFAULT_OPTIONS = new String[] { "-scripting", "-af", "-doe" };
+ private static final String[] DEFAULT_OPTIONS = new String[] { "-scripting", "-doe" };
NashornScriptEngine(final NashornScriptEngineFactory factory, final ClassLoader appLoader) {
this(factory, DEFAULT_OPTIONS, appLoader);
@@ -121,7 +122,8 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C
try {
if (reader instanceof URLReader) {
final URL url = ((URLReader)reader).getURL();
- return evalImpl(compileImpl(new Source(url.toString(), url), ctxt), ctxt);
+ final Charset cs = ((URLReader)reader).getCharset();
+ return evalImpl(compileImpl(new Source(url.toString(), url, cs), ctxt), ctxt);
}
return evalImpl(Source.readFully(reader), ctxt);
} catch (final IOException e) {
diff --git a/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java b/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java
index 7428a8f6..79e908db 100644
--- a/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java
+++ b/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java
@@ -342,6 +342,184 @@ public final class ScriptObjectMirror extends JSObject implements Bindings {
});
}
+ // Support for ECMAScript Object API on mirrors
+
+ /**
+ * Return the __proto__ of this object.
+ * @return __proto__ object.
+ */
+ public Object getProto() {
+ return inGlobal(new Callable<Object>() {
+ @Override public Object call() {
+ return wrap(getScriptObject().getProto(), global);
+ }
+ });
+ }
+
+ /**
+ * ECMA 8.12.1 [[GetOwnProperty]] (P)
+ *
+ * @param key property key
+ *
+ * @return Returns the Property Descriptor of the named own property of this
+ * object, or undefined if absent.
+ */
+ public Object getOwnPropertyDescriptor(final String key) {
+ return inGlobal(new Callable<Object>() {
+ @Override public Object call() {
+ return wrap(getScriptObject().getOwnPropertyDescriptor(key), global);
+ }
+ });
+ }
+
+ /**
+ * return an array of own property keys associated with the object.
+ *
+ * @param all True if to include non-enumerable keys.
+ * @return Array of keys.
+ */
+ public String[] getOwnKeys(final boolean all) {
+ return inGlobal(new Callable<String[]>() {
+ @Override public String[] call() {
+ return getScriptObject().getOwnKeys(all);
+ }
+ });
+ }
+
+ /**
+ * Flag this script object as non extensible
+ *
+ * @return the object after being made non extensible
+ */
+ public ScriptObjectMirror preventExtensions() {
+ return inGlobal(new Callable<ScriptObjectMirror>() {
+ @Override public ScriptObjectMirror call() {
+ getScriptObject().preventExtensions();
+ return ScriptObjectMirror.this;
+ }
+ });
+ }
+
+ /**
+ * Check if this script object is extensible
+ * @return true if extensible
+ */
+ public boolean isExtensible() {
+ return inGlobal(new Callable<Boolean>() {
+ @Override public Boolean call() {
+ return getScriptObject().isExtensible();
+ }
+ });
+ }
+
+ /**
+ * ECMAScript 15.2.3.8 - seal implementation
+ * @return the sealed script object
+ */
+ public ScriptObjectMirror seal() {
+ return inGlobal(new Callable<ScriptObjectMirror>() {
+ @Override public ScriptObjectMirror call() {
+ getScriptObject().seal();
+ return ScriptObjectMirror.this;
+ }
+ });
+ }
+
+ /**
+ * Check whether this script object is sealed
+ * @return true if sealed
+ */
+ public boolean isSealed() {
+ return inGlobal(new Callable<Boolean>() {
+ @Override public Boolean call() {
+ return getScriptObject().isSealed();
+ }
+ });
+ }
+
+ /**
+ * ECMA 15.2.39 - freeze implementation. Freeze this script object
+ * @return the frozen script object
+ */
+ public ScriptObjectMirror freeze() {
+ return inGlobal(new Callable<ScriptObjectMirror>() {
+ @Override public ScriptObjectMirror call() {
+ getScriptObject().freeze();
+ return ScriptObjectMirror.this;
+ }
+ });
+ }
+
+ /**
+ * Check whether this script object is frozen
+ * @return true if frozen
+ */
+ public boolean isFrozen() {
+ return inGlobal(new Callable<Boolean>() {
+ @Override public Boolean call() {
+ return getScriptObject().isFrozen();
+ }
+ });
+ }
+
+ // ECMAScript instanceof check
+
+ /**
+ * Checking whether a script object is an instance of another by
+ * walking the proto chain
+ *
+ * @param instance instace to check
+ * @return true if 'instance' is an instance of this object
+ */
+ public boolean isInstance(final ScriptObjectMirror instance) {
+ // if not belongs to my global scope, return false
+ if (instance == null || global != instance.global) {
+ return false;
+ }
+
+ return inGlobal(new Callable<Boolean>() {
+ @Override public Boolean call() {
+ return getScriptObject().isInstance(instance.getScriptObject());
+ }
+ });
+ }
+
+ /**
+ * Utility to check if given object is ECMAScript undefined value
+ *
+ * @param obj object to check
+ * @return true if 'obj' is ECMAScript undefined value
+ */
+ public static boolean isUndefined(final Object obj) {
+ return obj == ScriptRuntime.UNDEFINED;
+ }
+
+ /**
+ * is this a function object?
+ *
+ * @return if this mirror wraps a ECMAScript function instance
+ */
+ public boolean isFunction() {
+ return getScriptObject() instanceof ScriptFunction;
+ }
+
+ /**
+ * is this a 'use strict' function object?
+ *
+ * @return true if this mirror represents a ECMAScript 'use strict' function
+ */
+ public boolean isStrictFunction() {
+ return isFunction() && ((ScriptFunction)getScriptObject()).isStrict();
+ }
+
+ /**
+ * is this an array object?
+ *
+ * @return if this mirror wraps a ECMAScript array object
+ */
+ public boolean isArray() {
+ return getScriptObject().isArray();
+ }
// These are public only so that Context can access these.
diff --git a/src/jdk/nashorn/api/scripting/URLReader.java b/src/jdk/nashorn/api/scripting/URLReader.java
index d21d6263..13f69843 100644
--- a/src/jdk/nashorn/api/scripting/URLReader.java
+++ b/src/jdk/nashorn/api/scripting/URLReader.java
@@ -25,10 +25,12 @@
package jdk.nashorn.api.scripting;
+import java.io.CharArrayReader;
import java.io.IOException;
-import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
+import java.nio.charset.Charset;
+import jdk.nashorn.internal.runtime.Source;
/**
* A Reader that reads from a URL. Used to make sure that the reader
@@ -36,7 +38,10 @@ import java.net.URL;
*/
public final class URLReader extends Reader {
// underlying URL
- private URL url;
+ private final URL url;
+ // Charset used to convert
+ private final Charset cs;
+
// lazily initialized underlying reader for URL
private Reader reader;
@@ -44,9 +49,35 @@ public final class URLReader extends Reader {
* Constructor
*
* @param url URL for this URLReader
+ * @throws NullPointerException if url is null
*/
public URLReader(final URL url) {
+ this(url, (Charset)null);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param url URL for this URLReader
+ * @param charsetName Name of the Charset used to convert bytes to chars
+ * @throws NullPointerException if url is null
+ */
+ public URLReader(final URL url, final String charsetName) {
+ this(url, Charset.forName(charsetName));
+ }
+
+ /**
+ * Constructor
+ *
+ * @param url URL for this URLReader
+ * @param cs Charset used to convert bytes to chars
+ * @throws NullPointerException if url is null
+ */
+ public URLReader(final URL url, final Charset cs) {
+ // null check
+ url.getClass();
this.url = url;
+ this.cs = cs;
}
@Override
@@ -67,11 +98,20 @@ public final class URLReader extends Reader {
return url;
}
+ /**
+ * Charset used by this reader
+ *
+ * @return the Chartset used to convert bytes to chars
+ */
+ public Charset getCharset() {
+ return cs;
+ }
+
// lazily initialize char array reader using URL content
private Reader getReader() throws IOException {
synchronized (lock) {
if (reader == null) {
- reader = new InputStreamReader(url.openStream());
+ reader = new CharArrayReader(Source.readFully(url, cs));
}
}
diff --git a/src/jdk/nashorn/internal/codegen/Attr.java b/src/jdk/nashorn/internal/codegen/Attr.java
index d0b5a00a..3a442a7d 100644
--- a/src/jdk/nashorn/internal/codegen/Attr.java
+++ b/src/jdk/nashorn/internal/codegen/Attr.java
@@ -35,6 +35,7 @@ import static jdk.nashorn.internal.codegen.CompilerConstants.SCOPE;
import static jdk.nashorn.internal.codegen.CompilerConstants.SWITCH_TAG_PREFIX;
import static jdk.nashorn.internal.codegen.CompilerConstants.THIS;
import static jdk.nashorn.internal.codegen.CompilerConstants.VARARGS;
+import static jdk.nashorn.internal.ir.Symbol.IS_ALWAYS_DEFINED;
import static jdk.nashorn.internal.ir.Symbol.IS_CONSTANT;
import static jdk.nashorn.internal.ir.Symbol.IS_FUNCTION_SELF;
import static jdk.nashorn.internal.ir.Symbol.IS_GLOBAL;
@@ -128,6 +129,8 @@ final class Attr extends NodeOperatorVisitor<LexicalContext> {
private final Deque<Type> returnTypes;
+ private int catchNestingLevel;
+
private static final DebugLogger LOG = new DebugLogger("attr");
private static final boolean DEBUG = LOG.isEnabled();
@@ -169,14 +172,14 @@ final class Attr extends NodeOperatorVisitor<LexicalContext> {
if (functionNode.isVarArg()) {
initCompileConstant(VARARGS, body, IS_PARAM | IS_INTERNAL, Type.OBJECT_ARRAY);
if (functionNode.needsArguments()) {
- initCompileConstant(ARGUMENTS, body, IS_VAR | IS_INTERNAL, Type.typeFor(ScriptObject.class));
+ initCompileConstant(ARGUMENTS, body, IS_VAR | IS_INTERNAL | IS_ALWAYS_DEFINED, Type.typeFor(ScriptObject.class));
addLocalDef(ARGUMENTS.symbolName());
}
}
initParameters(functionNode, body);
- initCompileConstant(SCOPE, body, IS_VAR | IS_INTERNAL, Type.typeFor(ScriptObject.class));
- initCompileConstant(RETURN, body, IS_VAR | IS_INTERNAL, Type.OBJECT);
+ initCompileConstant(SCOPE, body, IS_VAR | IS_INTERNAL | IS_ALWAYS_DEFINED, Type.typeFor(ScriptObject.class));
+ initCompileConstant(RETURN, body, IS_VAR | IS_INTERNAL | IS_ALWAYS_DEFINED, Type.OBJECT);
}
@@ -202,18 +205,52 @@ final class Attr extends NodeOperatorVisitor<LexicalContext> {
private void acceptDeclarations(final FunctionNode functionNode, final Block body) {
// This visitor will assign symbol to all declared variables, except function declarations (which are taken care
// in a separate step above) and "var" declarations in for loop initializers.
+ //
+ // It also handles the case that a variable can be undefined, e.g
+ // if (cond) {
+ // x = x.y;
+ // }
+ // var x = 17;
+ //
+ // by making sure that no identifier has been found earlier in the body than the
+ // declaration - if such is the case the identifier is flagged as caBeUndefined to
+ // be safe if it turns into a local var. Otherwise corrupt bytecode results
+
body.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+ private final Set<String> uses = new HashSet<>();
+ private final Set<String> canBeUndefined = new HashSet<>();
+
@Override
public boolean enterFunctionNode(final FunctionNode nestedFn) {
return false;
}
@Override
+ public Node leaveIdentNode(final IdentNode identNode) {
+ uses.add(identNode.getName());
+ return identNode;
+ }
+
+ @Override
+ public boolean enterVarNode(final VarNode varNode) {
+ final String name = varNode.getName().getName();
+ //if this is used the var node symbol needs to be tagged as can be undefined
+ if (uses.contains(name)) {
+ canBeUndefined.add(name);
+ }
+ return true;
+ }
+
+ @Override
public Node leaveVarNode(final VarNode varNode) {
// any declared symbols that aren't visited need to be typed as well, hence the list
if (varNode.isStatement()) {
final IdentNode ident = varNode.getName();
final Symbol symbol = defineSymbol(body, ident.getName(), IS_VAR);
+ if (canBeUndefined.contains(ident.getName())) {
+ symbol.setType(Type.OBJECT);
+ symbol.setCanBeUndefined();
+ }
functionNode.addDeclaredSymbol(symbol);
if (varNode.isFunctionDeclaration()) {
newType(symbol, FunctionNode.FUNCTION_TYPE);
@@ -286,10 +323,12 @@ final class Attr extends NodeOperatorVisitor<LexicalContext> {
final Block block = lc.getCurrentBlock();
start(catchNode);
+ catchNestingLevel++;
// define block-local exception variable
- final Symbol def = defineSymbol(block, exception.getName(), IS_VAR | IS_LET);
- newType(def, Type.OBJECT);
+ final Symbol def = defineSymbol(block, exception.getName(), IS_VAR | IS_LET | IS_ALWAYS_DEFINED);
+ newType(def, Type.OBJECT); //we can catch anything, not just ecma exceptions
+
addLocalDef(exception.getName());
return true;
@@ -300,6 +339,9 @@ final class Attr extends NodeOperatorVisitor<LexicalContext> {
final IdentNode exception = catchNode.getException();
final Block block = lc.getCurrentBlock();
final Symbol symbol = findSymbol(block, exception.getName());
+
+ catchNestingLevel--;
+
assert symbol != null;
return end(catchNode.setException((IdentNode)exception.setSymbol(lc, symbol)));
}
@@ -509,9 +551,19 @@ final class Attr extends NodeOperatorVisitor<LexicalContext> {
assert lc.getFunctionBody(functionNode).getExistingSymbol(CALLEE.symbolName()) != null;
lc.setFlag(functionNode.getBody(), Block.NEEDS_SELF_SYMBOL);
newType(symbol, FunctionNode.FUNCTION_TYPE);
- } else if (!identNode.isInitializedHere()) { // NASHORN-448
- // here is a use outside the local def scope
- if (!isLocalDef(name)) {
+ } else if (!identNode.isInitializedHere()) {
+ /*
+ * See NASHORN-448, JDK-8016235
+ *
+ * Here is a use outside the local def scope
+ * the inCatch check is a conservative approach to handle things that might have only been
+ * defined in the try block, but with variable declarations, which due to JavaScript rules
+ * have to be lifted up into the function scope outside the try block anyway, but as the
+ * flow can fault at almost any place in the try block and get us to the catch block, all we
+ * know is that we have a declaration, not a definition. This can be made better and less
+ * conservative once we superimpose a CFG onto the AST.
+ */
+ if (!isLocalDef(name) || inCatch()) {
newType(symbol, Type.OBJECT);
symbol.setCanBeUndefined();
}
@@ -538,6 +590,10 @@ final class Attr extends NodeOperatorVisitor<LexicalContext> {
return end(identNode.setSymbol(lc, symbol));
}
+ private boolean inCatch() {
+ return catchNestingLevel > 0;
+ }
+
/**
* If the symbol isn't already a scope symbol, and it is either not local to the current function, or it is being
* referenced from within a with block, we force it to be a scope symbol.
@@ -550,26 +606,26 @@ final class Attr extends NodeOperatorVisitor<LexicalContext> {
}
private boolean symbolNeedsToBeScope(Symbol symbol) {
- if(symbol.isThis() || symbol.isInternal()) {
+ if (symbol.isThis() || symbol.isInternal()) {
return false;
}
boolean previousWasBlock = false;
- for(final Iterator<LexicalContextNode> it = lc.getAllNodes(); it.hasNext();) {
+ for (final Iterator<LexicalContextNode> it = lc.getAllNodes(); it.hasNext();) {
final LexicalContextNode node = it.next();
- if(node instanceof FunctionNode) {
+ if (node instanceof FunctionNode) {
// We reached the function boundary without seeing a definition for the symbol - it needs to be in
// scope.
return true;
- } else if(node instanceof WithNode) {
- if(previousWasBlock) {
+ } else if (node instanceof WithNode) {
+ if (previousWasBlock) {
// We reached a WithNode; the symbol must be scoped. Note that if the WithNode was not immediately
// preceded by a block, this means we're currently processing its expression, not its body,
// therefore it doesn't count.
return true;
}
previousWasBlock = false;
- } else if(node instanceof Block) {
- if(((Block)node).getExistingSymbol(symbol.getName()) == symbol) {
+ } else if (node instanceof Block) {
+ if (((Block)node).getExistingSymbol(symbol.getName()) == symbol) {
// We reached the block that defines the symbol without reaching either the function boundary, or a
// WithNode. The symbol need not be scoped.
return false;
@@ -1666,8 +1722,8 @@ final class Attr extends NodeOperatorVisitor<LexicalContext> {
}
private void pushLocalsBlock() {
- localDefs.push(localDefs.isEmpty() ? new HashSet<String>() : new HashSet<>(localDefs.peek()));
- localUses.push(localUses.isEmpty() ? new HashSet<String>() : new HashSet<>(localUses.peek()));
+ localDefs.push(new HashSet<>(localDefs.peek()));
+ localUses.push(new HashSet<>(localUses.peek()));
}
private void popLocals() {
diff --git a/src/jdk/nashorn/internal/codegen/FieldObjectCreator.java b/src/jdk/nashorn/internal/codegen/FieldObjectCreator.java
index 16ad2709..974b5ba8 100644
--- a/src/jdk/nashorn/internal/codegen/FieldObjectCreator.java
+++ b/src/jdk/nashorn/internal/codegen/FieldObjectCreator.java
@@ -126,7 +126,7 @@ public abstract class FieldObjectCreator<T> extends ObjectCreator {
final T value = valueIter.next();
if (symbol != null && value != null) {
- final int index = ArrayIndex.getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
if (index < 0) {
putField(method, key, symbol.getFieldIndex(), value);
diff --git a/src/jdk/nashorn/internal/codegen/MapCreator.java b/src/jdk/nashorn/internal/codegen/MapCreator.java
index 153e0367..609fac9b 100644
--- a/src/jdk/nashorn/internal/codegen/MapCreator.java
+++ b/src/jdk/nashorn/internal/codegen/MapCreator.java
@@ -79,7 +79,7 @@ public class MapCreator {
final String key = keys[i];
final Symbol symbol = symbols[i];
- if (symbol != null && !ArrayIndex.isIndexKey(key)) {
+ if (symbol != null && !ArrayIndex.isIntArrayIndex(key)) {
properties.add(new AccessorProperty(key, getPropertyFlags(symbol, hasArguments), structure, symbol.getFieldIndex()));
}
}
diff --git a/src/jdk/nashorn/internal/ir/BlockLexicalContext.java b/src/jdk/nashorn/internal/ir/BlockLexicalContext.java
index a86a327e..71c80a6b 100644
--- a/src/jdk/nashorn/internal/ir/BlockLexicalContext.java
+++ b/src/jdk/nashorn/internal/ir/BlockLexicalContext.java
@@ -63,6 +63,7 @@ public class BlockLexicalContext extends LexicalContext {
return sstack.pop();
}
+ @SuppressWarnings("unchecked")
@Override
public <T extends LexicalContextNode> T pop(final T node) {
T expected = node;
diff --git a/src/jdk/nashorn/internal/ir/BreakableNode.java b/src/jdk/nashorn/internal/ir/BreakableNode.java
index ea07cb4b..171df8e3 100644
--- a/src/jdk/nashorn/internal/ir/BreakableNode.java
+++ b/src/jdk/nashorn/internal/ir/BreakableNode.java
@@ -86,7 +86,7 @@ public abstract class BreakableNode extends LexicalContextNode {
/**
* Return the labels associated with this node. Breakable nodes that
- * aren't LoopNodes only have a break label -> the location immediately
+ * aren't LoopNodes only have a break label - the location immediately
* afterwards the node in code
* @return list of labels representing locations around this node
*/
diff --git a/src/jdk/nashorn/internal/ir/Symbol.java b/src/jdk/nashorn/internal/ir/Symbol.java
index d26fe561..7c183902 100644
--- a/src/jdk/nashorn/internal/ir/Symbol.java
+++ b/src/jdk/nashorn/internal/ir/Symbol.java
@@ -55,23 +55,25 @@ public final class Symbol implements Comparable<Symbol> {
public static final int KINDMASK = (1 << 3) - 1; // Kinds are represented by lower three bits
/** Is this scope */
- public static final int IS_SCOPE = 1 << 4;
+ public static final int IS_SCOPE = 1 << 4;
/** Is this a this symbol */
- public static final int IS_THIS = 1 << 5;
+ public static final int IS_THIS = 1 << 5;
/** Can this symbol ever be undefined */
- public static final int CAN_BE_UNDEFINED = 1 << 6;
+ public static final int CAN_BE_UNDEFINED = 1 << 6;
+ /** Is this symbol always defined? */
+ public static final int IS_ALWAYS_DEFINED = 1 << 8;
/** Can this symbol ever have primitive types */
- public static final int CAN_BE_PRIMITIVE = 1 << 7;
+ public static final int CAN_BE_PRIMITIVE = 1 << 9;
/** Is this a let */
- public static final int IS_LET = 1 << 8;
+ public static final int IS_LET = 1 << 10;
/** Is this an internal symbol, never represented explicitly in source code */
- public static final int IS_INTERNAL = 1 << 9;
+ public static final int IS_INTERNAL = 1 << 11;
/** Is this a function self-reference symbol */
- public static final int IS_FUNCTION_SELF = 1 << 10;
+ public static final int IS_FUNCTION_SELF = 1 << 12;
/** Is this a specialized param? */
- public static final int IS_SPECIALIZED_PARAM = 1 << 11;
+ public static final int IS_SPECIALIZED_PARAM = 1 << 13;
/** Is this symbol a shared temporary? */
- public static final int IS_SHARED = 1 << 12;
+ public static final int IS_SHARED = 1 << 14;
/** Null or name identifying symbol. */
private final String name;
@@ -384,7 +386,7 @@ public final class Symbol implements Comparable<Symbol> {
* Mark this symbol as one being shared by multiple expressions. The symbol must be a temporary.
*/
public void setIsShared() {
- if(!isShared()) {
+ if (!isShared()) {
assert isTemp();
trace("SET IS SHARED");
flags |= IS_SHARED;
@@ -417,6 +419,14 @@ public final class Symbol implements Comparable<Symbol> {
}
/**
+ * Check if this symbol is always defined, which overrides all canBeUndefined tags
+ * @return true if always defined
+ */
+ public boolean isAlwaysDefined() {
+ return isParam() || (flags & IS_ALWAYS_DEFINED) == IS_ALWAYS_DEFINED;
+ }
+
+ /**
* Get the range for this symbol
* @return range for symbol
*/
@@ -462,7 +472,9 @@ public final class Symbol implements Comparable<Symbol> {
*/
public void setCanBeUndefined() {
assert type.isObject() : type;
- if(!canBeUndefined()) {
+ if (isAlwaysDefined()) {
+ return;
+ } else if (!canBeUndefined()) {
assert !isShared();
flags |= CAN_BE_UNDEFINED;
}
diff --git a/src/jdk/nashorn/internal/objects/AccessorPropertyDescriptor.java b/src/jdk/nashorn/internal/objects/AccessorPropertyDescriptor.java
index 73397b59..59660ae6 100644
--- a/src/jdk/nashorn/internal/objects/AccessorPropertyDescriptor.java
+++ b/src/jdk/nashorn/internal/objects/AccessorPropertyDescriptor.java
@@ -138,18 +138,16 @@ public final class AccessorPropertyDescriptor extends ScriptObject implements Pr
@Override
public PropertyDescriptor fillFrom(final ScriptObject sobj) {
- final boolean strict = isStrictContext();
-
if (sobj.has(CONFIGURABLE)) {
this.configurable = JSType.toBoolean(sobj.get(CONFIGURABLE));
} else {
- delete(CONFIGURABLE, strict);
+ delete(CONFIGURABLE, false);
}
if (sobj.has(ENUMERABLE)) {
this.enumerable = JSType.toBoolean(sobj.get(ENUMERABLE));
} else {
- delete(ENUMERABLE, strict);
+ delete(ENUMERABLE, false);
}
if (sobj.has(GET)) {
@@ -160,7 +158,7 @@ public final class AccessorPropertyDescriptor extends ScriptObject implements Pr
throw typeError("not.a.function", ScriptRuntime.safeToString(getter));
}
} else {
- delete(GET, strict);
+ delete(GET, false);
}
if (sobj.has(SET)) {
@@ -171,7 +169,7 @@ public final class AccessorPropertyDescriptor extends ScriptObject implements Pr
throw typeError("not.a.function", ScriptRuntime.safeToString(setter));
}
} else {
- delete(SET, strict);
+ delete(SET, false);
}
return this;
diff --git a/src/jdk/nashorn/internal/objects/ArrayBufferView.java b/src/jdk/nashorn/internal/objects/ArrayBufferView.java
index d85b31cb..2011daeb 100644
--- a/src/jdk/nashorn/internal/objects/ArrayBufferView.java
+++ b/src/jdk/nashorn/internal/objects/ArrayBufferView.java
@@ -33,6 +33,8 @@ import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
+import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError;
+
@ScriptClass("ArrayBufferView")
abstract class ArrayBufferView extends ScriptObject {
@@ -305,11 +307,11 @@ abstract class ArrayBufferView extends ScriptObject {
dst = factory.construct(length);
} else if (arg0 instanceof NativeArray) {
// Constructor(type[] array)
- length = (int) (((NativeArray) arg0).getArray().length() & 0x7fff_ffff);
+ length = lengthToInt(((NativeArray) arg0).getArray().length());
dst = factory.construct(length);
} else {
// Constructor(unsigned long length)
- length = JSType.toInt32(arg0);
+ length = lengthToInt(JSType.toInt64(arg0));
return factory.construct(length);
}
@@ -354,6 +356,13 @@ abstract class ArrayBufferView extends ScriptObject {
}
}
+ private static int lengthToInt(final long length) {
+ if (length > Integer.MAX_VALUE || length < 0) {
+ throw rangeError("inappropriate.array.buffer.length", JSType.toString(length));
+ }
+ return (int) (length & Integer.MAX_VALUE);
+ }
+
protected static Object subarrayImpl(final Object self, final Object begin0, final Object end0) {
final ArrayBufferView arrayView = ((ArrayBufferView)self);
final int elementLength = arrayView.elementLength();
diff --git a/src/jdk/nashorn/internal/objects/DataPropertyDescriptor.java b/src/jdk/nashorn/internal/objects/DataPropertyDescriptor.java
index e5f7de31..7ce4d85e 100644
--- a/src/jdk/nashorn/internal/objects/DataPropertyDescriptor.java
+++ b/src/jdk/nashorn/internal/objects/DataPropertyDescriptor.java
@@ -136,29 +136,28 @@ public final class DataPropertyDescriptor extends ScriptObject implements Proper
@Override
public PropertyDescriptor fillFrom(final ScriptObject sobj) {
- final boolean strict = isStrictContext();
if (sobj.has(CONFIGURABLE)) {
this.configurable = JSType.toBoolean(sobj.get(CONFIGURABLE));
} else {
- delete(CONFIGURABLE, strict);
+ delete(CONFIGURABLE, false);
}
if (sobj.has(ENUMERABLE)) {
this.enumerable = JSType.toBoolean(sobj.get(ENUMERABLE));
} else {
- delete(ENUMERABLE, strict);
+ delete(ENUMERABLE, false);
}
if (sobj.has(WRITABLE)) {
this.writable = JSType.toBoolean(sobj.get(WRITABLE));
} else {
- delete(WRITABLE, strict);
+ delete(WRITABLE, false);
}
if (sobj.has(VALUE)) {
this.value = sobj.get(VALUE);
} else {
- delete(VALUE, strict);
+ delete(VALUE, false);
}
return this;
diff --git a/src/jdk/nashorn/internal/objects/GenericPropertyDescriptor.java b/src/jdk/nashorn/internal/objects/GenericPropertyDescriptor.java
index 31afc307..8f2be7c8 100644
--- a/src/jdk/nashorn/internal/objects/GenericPropertyDescriptor.java
+++ b/src/jdk/nashorn/internal/objects/GenericPropertyDescriptor.java
@@ -124,17 +124,16 @@ public final class GenericPropertyDescriptor extends ScriptObject implements Pro
@Override
public PropertyDescriptor fillFrom(final ScriptObject sobj) {
- final boolean strict = isStrictContext();
if (sobj.has(CONFIGURABLE)) {
this.configurable = JSType.toBoolean(sobj.get(CONFIGURABLE));
} else {
- delete(CONFIGURABLE, strict);
+ delete(CONFIGURABLE, false);
}
if (sobj.has(ENUMERABLE)) {
this.enumerable = JSType.toBoolean(sobj.get(ENUMERABLE));
} else {
- delete(ENUMERABLE, strict);
+ delete(ENUMERABLE, false);
}
return this;
diff --git a/src/jdk/nashorn/internal/objects/Global.java b/src/jdk/nashorn/internal/objects/Global.java
index 04daa8b5..59a9dd34 100644
--- a/src/jdk/nashorn/internal/objects/Global.java
+++ b/src/jdk/nashorn/internal/objects/Global.java
@@ -37,6 +37,7 @@ import java.lang.ref.SoftReference;
import java.lang.reflect.Field;
import java.security.AccessController;
import java.security.PrivilegedAction;
+import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -372,7 +373,7 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
private static final MethodHandle PRINT = findOwnMH("print", Object.class, Object.class, Object[].class);
private static final MethodHandle PRINTLN = findOwnMH("println", Object.class, Object.class, Object[].class);
private static final MethodHandle LOAD = findOwnMH("load", Object.class, Object.class, Object.class);
- private static final MethodHandle LOADWITHNEWGLOBAL = findOwnMH("loadWithNewGlobal", Object.class, Object.class, Object.class);
+ private static final MethodHandle LOADWITHNEWGLOBAL = findOwnMH("loadWithNewGlobal", Object.class, Object.class, Object[].class);
private static final MethodHandle EXIT = findOwnMH("exit", Object.class, Object.class, Object.class);
private final Context context;
@@ -429,15 +430,6 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
return instance().context;
}
- /**
- * Script access check for strict mode
- *
- * @return true if strict mode enabled in {@link Global#getThisContext()}
- */
- static boolean isStrict() {
- return getEnv()._strict;
- }
-
// GlobalObject interface implementation
@Override
@@ -615,14 +607,12 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
public PropertyDescriptor newAccessorDescriptor(final Object get, final Object set, final boolean configurable, final boolean enumerable) {
final AccessorPropertyDescriptor desc = new AccessorPropertyDescriptor(configurable, enumerable, get == null ? UNDEFINED : get, set == null ? UNDEFINED : set);
- final boolean strict = context.getEnv()._strict;
-
if (get == null) {
- desc.delete(PropertyDescriptor.GET, strict);
+ desc.delete(PropertyDescriptor.GET, false);
}
if (set == null) {
- desc.delete(PropertyDescriptor.SET, strict);
+ desc.delete(PropertyDescriptor.SET, false);
}
return desc;
@@ -750,16 +740,21 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
/**
* Global loadWithNewGlobal implementation - Nashorn extension
*
- * @param self scope
- * @param source source to load
+ * @param self scope
+ * @param args from plus (optional) arguments to be passed to the loaded script
*
- * @return result of load (undefined)
+ * @return result of load (may be undefined)
*
* @throws IOException if source could not be read
*/
- public static Object loadWithNewGlobal(final Object self, final Object source) throws IOException {
+ public static Object loadWithNewGlobal(final Object self, final Object...args) throws IOException {
final Global global = Global.instance();
- return global.context.loadWithNewGlobal(source);
+ final int length = args.length;
+ final boolean hasArgs = 0 < length;
+ final Object from = hasArgs ? args[0] : UNDEFINED;
+ final Object[] arguments = hasArgs ? Arrays.copyOfRange(args, 1, length) : args;
+
+ return global.context.loadWithNewGlobal(from, arguments);
}
/**
@@ -1479,7 +1474,6 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
// Error objects
this.builtinError = (ScriptFunction)initConstructor("Error");
final ScriptObject errorProto = getErrorPrototype();
- final boolean strict = Global.isStrict();
// Nashorn specific accessors on Error.prototype - stack, lineNumber, columnNumber and fileName
final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", NativeError.GET_STACK);
@@ -1497,10 +1491,10 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
// ECMA 15.11.4.2 Error.prototype.name
// Error.prototype.name = "Error";
- errorProto.set(NativeError.NAME, "Error", strict);
+ errorProto.set(NativeError.NAME, "Error", false);
// ECMA 15.11.4.3 Error.prototype.message
// Error.prototype.message = "";
- errorProto.set(NativeError.MESSAGE, "", strict);
+ errorProto.set(NativeError.MESSAGE, "", false);
this.builtinEvalError = initErrorSubtype("EvalError", errorProto);
this.builtinRangeError = initErrorSubtype("RangeError", errorProto);
@@ -1513,9 +1507,8 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) {
final ScriptObject cons = initConstructor(name);
final ScriptObject prototype = ScriptFunction.getPrototype(cons);
- final boolean strict = Global.isStrict();
- prototype.set(NativeError.NAME, name, strict);
- prototype.set(NativeError.MESSAGE, "", strict);
+ prototype.set(NativeError.NAME, name, false);
+ prototype.set(NativeError.MESSAGE, "", false);
prototype.setProto(errorProto);
return (ScriptFunction)cons;
}
@@ -1724,7 +1717,7 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
// <anon-function>
builtinFunction.setProto(anon);
builtinFunction.setPrototype(anon);
- anon.set("constructor", builtinFunction, anon.isStrict());
+ anon.set("constructor", builtinFunction, false);
anon.deleteOwnProperty(anon.getMap().findProperty("prototype"));
// now initialize Object
diff --git a/src/jdk/nashorn/internal/objects/NativeArguments.java b/src/jdk/nashorn/internal/objects/NativeArguments.java
index efab674b..d92d7fb3 100644
--- a/src/jdk/nashorn/internal/objects/NativeArguments.java
+++ b/src/jdk/nashorn/internal/objects/NativeArguments.java
@@ -27,7 +27,6 @@ package jdk.nashorn.internal.objects;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
-import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndexNoThrow;
import static jdk.nashorn.internal.lookup.Lookup.MH;
import java.lang.invoke.MethodHandle;
@@ -132,103 +131,103 @@ public final class NativeArguments extends ScriptObject {
@Override
public int getInt(final Object key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) ? namedArgs.getInt(index) : super.getInt(key);
}
@Override
public int getInt(final double key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) ? namedArgs.getInt(index) : super.getInt(key);
}
@Override
public int getInt(final long key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) ? namedArgs.getInt(index) : super.getInt(key);
}
@Override
public int getInt(final int key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) ? namedArgs.getInt(index) : super.getInt(key);
}
@Override
public long getLong(final Object key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) ? namedArgs.getLong(index) : super.getLong(key);
}
@Override
public long getLong(final double key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) ? namedArgs.getLong(index) : super.getLong(key);
}
@Override
public long getLong(final long key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) ? namedArgs.getLong(index) : super.getLong(key);
}
@Override
public long getLong(final int key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) ? namedArgs.getLong(index) : super.getLong(key);
}
@Override
public double getDouble(final Object key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) ? namedArgs.getDouble(index) : super.getDouble(key);
}
@Override
public double getDouble(final double key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) ? namedArgs.getDouble(index) : super.getDouble(key);
}
@Override
public double getDouble(final long key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) ? namedArgs.getDouble(index) : super.getDouble(key);
}
@Override
public double getDouble(final int key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) ? namedArgs.getDouble(index) : super.getDouble(key);
}
@Override
public Object get(final Object key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) ? namedArgs.getObject(index) : super.get(key);
}
@Override
public Object get(final double key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) ? namedArgs.getObject(index) : super.get(key);
}
@Override
public Object get(final long key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) ? namedArgs.getObject(index) : super.get(key);
}
@Override
public Object get(final int key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) ? namedArgs.getObject(index) : super.get(key);
}
@Override
public void set(final Object key, final int value, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
if (isMapped(index)) {
namedArgs = namedArgs.set(index, value, strict);
} else {
@@ -238,7 +237,7 @@ public final class NativeArguments extends ScriptObject {
@Override
public void set(final Object key, final long value, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
if (isMapped(index)) {
namedArgs = namedArgs.set(index, value, strict);
} else {
@@ -248,7 +247,7 @@ public final class NativeArguments extends ScriptObject {
@Override
public void set(final Object key, final double value, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
if (isMapped(index)) {
namedArgs = namedArgs.set(index, value, strict);
} else {
@@ -258,7 +257,7 @@ public final class NativeArguments extends ScriptObject {
@Override
public void set(final Object key, final Object value, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
if (isMapped(index)) {
namedArgs = namedArgs.set(index, value, strict);
} else {
@@ -268,7 +267,7 @@ public final class NativeArguments extends ScriptObject {
@Override
public void set(final double key, final int value, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
if (isMapped(index)) {
namedArgs = namedArgs.set(index, value, strict);
} else {
@@ -278,7 +277,7 @@ public final class NativeArguments extends ScriptObject {
@Override
public void set(final double key, final long value, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
if (isMapped(index)) {
namedArgs = namedArgs.set(index, value, strict);
} else {
@@ -288,7 +287,7 @@ public final class NativeArguments extends ScriptObject {
@Override
public void set(final double key, final double value, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
if (isMapped(index)) {
namedArgs = namedArgs.set(index, value, strict);
} else {
@@ -298,7 +297,7 @@ public final class NativeArguments extends ScriptObject {
@Override
public void set(final double key, final Object value, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
if (isMapped(index)) {
namedArgs = namedArgs.set(index, value, strict);
} else {
@@ -308,7 +307,7 @@ public final class NativeArguments extends ScriptObject {
@Override
public void set(final long key, final int value, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
if (isMapped(index)) {
namedArgs = namedArgs.set(index, value, strict);
} else {
@@ -318,7 +317,7 @@ public final class NativeArguments extends ScriptObject {
@Override
public void set(final long key, final long value, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
if (isMapped(index)) {
namedArgs = namedArgs.set(index, value, strict);
} else {
@@ -328,7 +327,7 @@ public final class NativeArguments extends ScriptObject {
@Override
public void set(final long key, final double value, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
if (isMapped(index)) {
namedArgs = namedArgs.set(index, value, strict);
} else {
@@ -338,7 +337,7 @@ public final class NativeArguments extends ScriptObject {
@Override
public void set(final long key, final Object value, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
if (isMapped(index)) {
namedArgs = namedArgs.set(index, value, strict);
} else {
@@ -348,7 +347,7 @@ public final class NativeArguments extends ScriptObject {
@Override
public void set(final int key, final int value, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
if (isMapped(index)) {
namedArgs = namedArgs.set(index, value, strict);
} else {
@@ -358,7 +357,7 @@ public final class NativeArguments extends ScriptObject {
@Override
public void set(final int key, final long value, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
if (isMapped(index)) {
namedArgs = namedArgs.set(index, value, strict);
} else {
@@ -368,7 +367,7 @@ public final class NativeArguments extends ScriptObject {
@Override
public void set(final int key, final double value, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
if (isMapped(index)) {
namedArgs = namedArgs.set(index, value, strict);
} else {
@@ -378,7 +377,7 @@ public final class NativeArguments extends ScriptObject {
@Override
public void set(final int key, final Object value, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
if (isMapped(index)) {
namedArgs = namedArgs.set(index, value, strict);
} else {
@@ -388,55 +387,55 @@ public final class NativeArguments extends ScriptObject {
@Override
public boolean has(final Object key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) || super.has(key);
}
@Override
public boolean has(final double key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) || super.has(key);
}
@Override
public boolean has(final long key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) || super.has(key);
}
@Override
public boolean has(final int key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) || super.has(key);
}
@Override
public boolean hasOwnProperty(final Object key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) || super.hasOwnProperty(key);
}
@Override
public boolean hasOwnProperty(final int key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) || super.hasOwnProperty(key);
}
@Override
public boolean hasOwnProperty(final long key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) || super.hasOwnProperty(key);
}
@Override
public boolean hasOwnProperty(final double key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) || super.hasOwnProperty(key);
}
@Override
public boolean delete(final int key, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
final boolean success = super.delete(key, strict);
if (success && namedArgs.has(index)) {
setDeleted(index);
@@ -446,7 +445,7 @@ public final class NativeArguments extends ScriptObject {
@Override
public boolean delete(final long key, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
final boolean success = super.delete(key, strict);
if (success && namedArgs.has(index)) {
setDeleted(index);
@@ -456,7 +455,7 @@ public final class NativeArguments extends ScriptObject {
@Override
public boolean delete(final double key, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
final boolean success = super.delete(key, strict);
if (success && namedArgs.has(index)) {
setDeleted(index);
@@ -466,7 +465,7 @@ public final class NativeArguments extends ScriptObject {
@Override
public boolean delete(final Object key, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
final boolean success = super.delete(key, strict);
if (success && namedArgs.has(index)) {
setDeleted(index);
@@ -480,7 +479,7 @@ public final class NativeArguments extends ScriptObject {
*/
@Override
public boolean defineOwnProperty(final String key, final Object propertyDesc, final boolean reject) {
- final int index = ArrayIndex.getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
if (index >= 0) {
final boolean allowed = super.defineOwnProperty(key, propertyDesc, false);
if (!allowed) {
diff --git a/src/jdk/nashorn/internal/objects/NativeArray.java b/src/jdk/nashorn/internal/objects/NativeArray.java
index 9736376b..a480c590 100644
--- a/src/jdk/nashorn/internal/objects/NativeArray.java
+++ b/src/jdk/nashorn/internal/objects/NativeArray.java
@@ -39,6 +39,7 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
+import jdk.nashorn.api.scripting.ScriptObjectMirror;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Constructor;
import jdk.nashorn.internal.objects.annotations.Function;
@@ -118,7 +119,7 @@ public final class NativeArray extends ScriptObject {
if (value == ScriptRuntime.EMPTY) {
arrayData = arrayData.delete(index);
} else {
- arrayData = arrayData.set(index, value, isStrictContext());
+ arrayData = arrayData.set(index, value, false);
}
}
@@ -158,6 +159,11 @@ public final class NativeArray extends ScriptObject {
// Step 3
if ("length".equals(key)) {
+ // check for length being made non-writable
+ if (desc.has(WRITABLE) && !desc.isWritable()) {
+ setIsLengthNotWritable();
+ }
+
// Step 3a
if (!desc.has(VALUE)) {
return super.defineOwnProperty("length", desc, reject);
@@ -228,7 +234,7 @@ public final class NativeArray extends ScriptObject {
}
// Step 4a
- final int index = ArrayIndex.getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
if (ArrayIndex.isValidArrayIndex(index)) {
final long longIndex = ArrayIndex.toLongIndex(index);
// Step 4b
@@ -286,7 +292,8 @@ public final class NativeArray extends ScriptObject {
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
public static Object isArray(final Object self, final Object arg) {
return isArray(arg) || (arg == Global.instance().getArrayPrototype())
- || (arg instanceof NativeRegExpExecResult);
+ || (arg instanceof NativeRegExpExecResult)
+ || (arg instanceof ScriptObjectMirror && ((ScriptObjectMirror)arg).isArray());
}
/**
@@ -603,7 +610,6 @@ public final class NativeArray extends ScriptObject {
public static Object pop(final Object self) {
try {
final ScriptObject sobj = (ScriptObject)self;
- final boolean strict = sobj.isStrictContext();
if (bulkable(sobj)) {
return sobj.getArray().pop();
@@ -612,15 +618,15 @@ public final class NativeArray extends ScriptObject {
final long len = JSType.toUint32(sobj.getLength());
if (len == 0) {
- sobj.set("length", 0, strict);
+ sobj.set("length", 0, true);
return ScriptRuntime.UNDEFINED;
}
final long index = len - 1;
final Object element = sobj.get(index);
- sobj.delete(index, strict);
- sobj.set("length", index, strict);
+ sobj.delete(index, true);
+ sobj.set("length", index, true);
return element;
} catch (final ClassCastException | NullPointerException e) {
@@ -639,11 +645,10 @@ public final class NativeArray extends ScriptObject {
public static Object push(final Object self, final Object... args) {
try {
final ScriptObject sobj = (ScriptObject)self;
- final boolean strict = sobj.isStrictContext();
if (bulkable(sobj)) {
if (sobj.getArray().length() + args.length <= JSType.MAX_UINT) {
- final ArrayData newData = sobj.getArray().push(sobj.isStrictContext(), args);
+ final ArrayData newData = sobj.getArray().push(true, args);
sobj.setArray(newData);
return newData.length();
}
@@ -652,9 +657,9 @@ public final class NativeArray extends ScriptObject {
long len = JSType.toUint32(sobj.getLength());
for (final Object element : args) {
- sobj.set(len++, element, strict);
+ sobj.set(len++, element, true);
}
- sobj.set("length", len, strict);
+ sobj.set("length", len, true);
return len;
} catch (final ClassCastException | NullPointerException e) {
@@ -672,7 +677,6 @@ public final class NativeArray extends ScriptObject {
public static Object reverse(final Object self) {
try {
final ScriptObject sobj = (ScriptObject)self;
- final boolean strict = sobj.isStrictContext();
final long len = JSType.toUint32(sobj.getLength());
final long middle = len / 2;
@@ -684,14 +688,14 @@ public final class NativeArray extends ScriptObject {
final boolean upperExists = sobj.has(upper);
if (lowerExists && upperExists) {
- sobj.set(lower, upperValue, strict);
- sobj.set(upper, lowerValue, strict);
+ sobj.set(lower, upperValue, true);
+ sobj.set(upper, lowerValue, true);
} else if (!lowerExists && upperExists) {
- sobj.set(lower, upperValue, strict);
- sobj.delete(upper, strict);
+ sobj.set(lower, upperValue, true);
+ sobj.delete(upper, true);
} else if (lowerExists && !upperExists) {
- sobj.delete(lower, strict);
- sobj.set(upper, lowerValue, strict);
+ sobj.delete(lower, true);
+ sobj.set(upper, lowerValue, true);
}
}
return sobj;
@@ -717,7 +721,6 @@ public final class NativeArray extends ScriptObject {
}
final ScriptObject sobj = (ScriptObject) obj;
- final boolean strict = Global.isStrict();
long len = JSType.toUint32(sobj.getLength());
@@ -728,15 +731,15 @@ public final class NativeArray extends ScriptObject {
sobj.getArray().shiftLeft(1);
} else {
for (long k = 1; k < len; k++) {
- sobj.set(k - 1, sobj.get(k), strict);
+ sobj.set(k - 1, sobj.get(k), true);
}
}
- sobj.delete(--len, strict);
+ sobj.delete(--len, true);
} else {
len = 0;
}
- sobj.set("length", len, strict);
+ sobj.set("length", len, true);
return first;
}
@@ -770,7 +773,7 @@ public final class NativeArray extends ScriptObject {
final NativeArray copy = new NativeArray(0);
for (long n = 0; k < finale; n++, k++) {
- copy.defineOwnProperty((int) n, sobj.get(k));
+ copy.defineOwnProperty(ArrayIndex.getArrayIndex(n), sobj.get(k));
}
return copy;
@@ -833,30 +836,27 @@ public final class NativeArray extends ScriptObject {
public static Object sort(final Object self, final Object comparefn) {
try {
final ScriptObject sobj = (ScriptObject) self;
- final boolean strict = sobj.isStrictContext();
final long len = JSType.toUint32(sobj.getLength());
+ ArrayData array = sobj.getArray();
if (len > 1) {
// Get only non-missing elements. Missing elements go at the end
// of the sorted array. So, just don't copy these to sort input.
-
final ArrayList<Object> src = new ArrayList<>();
- for (int i = 0; i < (int)len; i++) {
- if (sobj.has(i)) {
- src.add(sobj.get(i));
+ for (long i = 0; i < len; i = array.nextIndex(i)) {
+ if (array.has((int) i)) {
+ src.add(array.getObject((int) i));
}
}
final Object[] sorted = sort(src.toArray(), comparefn);
for (int i = 0; i < sorted.length; i++) {
- sobj.set(i, sorted[i], strict);
+ array = array.set(i, sorted[i], true);
}
// delete missing elements - which are at the end of sorted array
- for (int j = sorted.length; j < (int)len; j++) {
- sobj.delete(j, strict);
- }
+ sobj.setArray(array.delete(sorted.length, len - 1));
}
return sobj;
@@ -893,7 +893,6 @@ public final class NativeArray extends ScriptObject {
}
final ScriptObject sobj = (ScriptObject)obj;
- final boolean strict = Global.isStrict();
final long len = JSType.toUint32(sobj.getLength());
final long relativeStart = JSType.toLong(start);
@@ -906,7 +905,7 @@ public final class NativeArray extends ScriptObject {
final long from = actualStart + k;
if (sobj.has(from)) {
- array.defineOwnProperty((int) k, sobj.get(from));
+ array.defineOwnProperty(ArrayIndex.getArrayIndex(k), sobj.get(from));
}
}
@@ -916,14 +915,14 @@ public final class NativeArray extends ScriptObject {
final long to = k + items.length;
if (sobj.has(from)) {
- sobj.set(to, sobj.get(from), strict);
+ sobj.set(to, sobj.get(from), true);
} else {
- sobj.delete(to, strict);
+ sobj.delete(to, true);
}
}
for (long k = len; k > (len - actualDeleteCount + items.length); k--) {
- sobj.delete(k - 1, strict);
+ sobj.delete(k - 1, true);
}
} else if (items.length > actualDeleteCount) {
for (long k = len - actualDeleteCount; k > actualStart; k--) {
@@ -932,20 +931,20 @@ public final class NativeArray extends ScriptObject {
if (sobj.has(from)) {
final Object fromValue = sobj.get(from);
- sobj.set(to, fromValue, strict);
+ sobj.set(to, fromValue, true);
} else {
- sobj.delete(to, strict);
+ sobj.delete(to, true);
}
}
}
long k = actualStart;
for (int i = 0; i < items.length; i++, k++) {
- sobj.set(k, items[i], strict);
+ sobj.set(k, items[i], true);
}
final long newLength = len - actualDeleteCount + items.length;
- sobj.set("length", newLength, strict);
+ sobj.set("length", newLength, true);
return array;
}
@@ -966,7 +965,6 @@ public final class NativeArray extends ScriptObject {
}
final ScriptObject sobj = (ScriptObject)obj;
- final boolean strict = Global.isStrict();
final long len = JSType.toUint32(sobj.getLength());
if (items == null) {
@@ -977,7 +975,7 @@ public final class NativeArray extends ScriptObject {
sobj.getArray().shiftRight(items.length);
for (int j = 0; j < items.length; j++) {
- sobj.setArray(sobj.getArray().set(j, items[j], sobj.isStrictContext()));
+ sobj.setArray(sobj.getArray().set(j, items[j], true));
}
} else {
for (long k = len; k > 0; k--) {
@@ -986,19 +984,19 @@ public final class NativeArray extends ScriptObject {
if (sobj.has(from)) {
final Object fromValue = sobj.get(from);
- sobj.set(to, fromValue, strict);
+ sobj.set(to, fromValue, true);
} else {
- sobj.delete(to, strict);
+ sobj.delete(to, true);
}
}
for (int j = 0; j < items.length; j++) {
- sobj.set(j, items[j], strict);
+ sobj.set(j, items[j], true);
}
}
final long newLength = len + items.length;
- sobj.set("length", newLength, strict);
+ sobj.set("length", newLength, true);
return newLength;
}
@@ -1143,7 +1141,7 @@ public final class NativeArray extends ScriptObject {
@Override
protected boolean forEach(final Object val, final long i) throws Throwable {
final Object r = MAP_CALLBACK_INVOKER.invokeExact(callbackfn, thisArg, val, i, self);
- result.defineOwnProperty((int)index, r);
+ result.defineOwnProperty(ArrayIndex.getArrayIndex(index), r);
return true;
}
@@ -1172,7 +1170,7 @@ public final class NativeArray extends ScriptObject {
@Override
protected boolean forEach(final Object val, final long i) throws Throwable {
if ((boolean)FILTER_CALLBACK_INVOKER.invokeExact(callbackfn, thisArg, val, i, self)) {
- result.defineOwnProperty((int)(to++), val);
+ result.defineOwnProperty(ArrayIndex.getArrayIndex(to++), val);
}
return true;
}
@@ -1241,7 +1239,7 @@ public final class NativeArray extends ScriptObject {
* @return true if optimizable
*/
private static boolean bulkable(final ScriptObject self) {
- return self.isArray() && !hasInheritedArrayEntries(self);
+ return self.isArray() && !hasInheritedArrayEntries(self) && !self.isLengthNotWritable();
}
private static boolean hasInheritedArrayEntries(final ScriptObject self) {
diff --git a/src/jdk/nashorn/internal/objects/NativeError.java b/src/jdk/nashorn/internal/objects/NativeError.java
index 5473c8ef..b10a1c40 100644
--- a/src/jdk/nashorn/internal/objects/NativeError.java
+++ b/src/jdk/nashorn/internal/objects/NativeError.java
@@ -90,7 +90,7 @@ public final class NativeError extends ScriptObject {
if (msg != UNDEFINED) {
this.instMessage = JSType.toString(msg);
} else {
- this.delete(NativeError.MESSAGE, Global.isStrict());
+ this.delete(NativeError.MESSAGE, false);
}
}
@@ -166,7 +166,7 @@ public final class NativeError extends ScriptObject {
public static Object setLineNumber(final Object self, final Object value) {
Global.checkObject(self);
final ScriptObject sobj = (ScriptObject)self;
- sobj.set(LINENUMBER, value, Global.isStrict());
+ sobj.set(LINENUMBER, value, false);
return value;
}
@@ -194,7 +194,7 @@ public final class NativeError extends ScriptObject {
public static Object setColumnNumber(final Object self, final Object value) {
Global.checkObject(self);
final ScriptObject sobj = (ScriptObject)self;
- sobj.set(COLUMNNUMBER, value, Global.isStrict());
+ sobj.set(COLUMNNUMBER, value, false);
return value;
}
@@ -222,7 +222,7 @@ public final class NativeError extends ScriptObject {
public static Object setFileName(final Object self, final Object value) {
Global.checkObject(self);
final ScriptObject sobj = (ScriptObject)self;
- sobj.set(FILENAME, value, Global.isStrict());
+ sobj.set(FILENAME, value, false);
return value;
}
@@ -278,7 +278,7 @@ public final class NativeError extends ScriptObject {
public static Object setStack(final Object self, final Object value) {
Global.checkObject(self);
final ScriptObject sobj = (ScriptObject)self;
- sobj.set(STACK, value, Global.isStrict());
+ sobj.set(STACK, value, false);
return value;
}
diff --git a/src/jdk/nashorn/internal/objects/NativeEvalError.java b/src/jdk/nashorn/internal/objects/NativeEvalError.java
index a33fb0db..c4fc838e 100644
--- a/src/jdk/nashorn/internal/objects/NativeEvalError.java
+++ b/src/jdk/nashorn/internal/objects/NativeEvalError.java
@@ -59,7 +59,7 @@ public final class NativeEvalError extends ScriptObject {
if (msg != UNDEFINED) {
this.instMessage = JSType.toString(msg);
} else {
- this.delete(NativeError.MESSAGE, Global.isStrict());
+ this.delete(NativeError.MESSAGE, false);
}
}
diff --git a/src/jdk/nashorn/internal/objects/NativeFunction.java b/src/jdk/nashorn/internal/objects/NativeFunction.java
index 528b120a..38ead325 100644
--- a/src/jdk/nashorn/internal/objects/NativeFunction.java
+++ b/src/jdk/nashorn/internal/objects/NativeFunction.java
@@ -29,6 +29,7 @@ import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
import java.util.List;
+import jdk.nashorn.api.scripting.ScriptObjectMirror;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Constructor;
import jdk.nashorn.internal.objects.annotations.Function;
@@ -102,6 +103,16 @@ public final class NativeFunction {
list.toArray(args = new Object[list.size()]);
} else if (array == null || array == UNDEFINED) {
args = ScriptRuntime.EMPTY_ARRAY;
+ } else if (array instanceof ScriptObjectMirror) {
+ // look for array-like ScriptObjectMirror object
+ final ScriptObjectMirror mirror = (ScriptObjectMirror)array;
+ final Object len = mirror.containsKey("length")? mirror.getMember("length") : Integer.valueOf(0);
+ final int n = (int)JSType.toUint32(len);
+
+ args = new Object[n];
+ for (int i = 0; i < args.length; i++) {
+ args[i] = mirror.containsKey(i)? mirror.getSlot(i) : UNDEFINED;
+ }
} else {
throw typeError("function.apply.expects.array");
}
@@ -216,7 +227,7 @@ public final class NativeFunction {
final Global global = Global.instance();
- return Global.directEval(global, sb.toString(), global, "<function>", Global.isStrict());
+ return Global.directEval(global, sb.toString(), global, "<function>", global.isStrictContext());
}
private static void checkFunctionParameters(final String params) {
diff --git a/src/jdk/nashorn/internal/objects/NativeJSON.java b/src/jdk/nashorn/internal/objects/NativeJSON.java
index b3d6d873..ec35fc4e 100644
--- a/src/jdk/nashorn/internal/objects/NativeJSON.java
+++ b/src/jdk/nashorn/internal/objects/NativeJSON.java
@@ -158,7 +158,7 @@ public final class NativeJSON extends ScriptObject {
state.gap = gap;
final ScriptObject wrapper = Global.newEmptyInstance();
- wrapper.set("", value, Global.isStrict());
+ wrapper.set("", value, false);
return str("", wrapper, state);
}
diff --git a/src/jdk/nashorn/internal/objects/NativeJavaImporter.java b/src/jdk/nashorn/internal/objects/NativeJavaImporter.java
index 88d0e6a3..82849172 100644
--- a/src/jdk/nashorn/internal/objects/NativeJavaImporter.java
+++ b/src/jdk/nashorn/internal/objects/NativeJavaImporter.java
@@ -121,7 +121,7 @@ public final class NativeJavaImporter extends ScriptObject {
final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
final Object value = createProperty(name);
if(value != null) {
- set(name, value, isStrictContext());
+ set(name, value, false);
return true;
}
return false;
diff --git a/src/jdk/nashorn/internal/objects/NativeObject.java b/src/jdk/nashorn/internal/objects/NativeObject.java
index 5162d89b..20a69039 100644
--- a/src/jdk/nashorn/internal/objects/NativeObject.java
+++ b/src/jdk/nashorn/internal/objects/NativeObject.java
@@ -28,11 +28,13 @@ package jdk.nashorn.internal.objects;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
+import jdk.nashorn.api.scripting.ScriptObjectMirror;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Constructor;
import jdk.nashorn.internal.objects.annotations.Function;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
import jdk.nashorn.internal.objects.annotations.Where;
+import jdk.nashorn.internal.runtime.ECMAException;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptObject;
@@ -54,6 +56,10 @@ public final class NativeObject {
private NativeObject() {
}
+ private static ECMAException notAnObject(final Object obj) {
+ return typeError("not.an.object", ScriptRuntime.safeToString(obj));
+ }
+
/**
* ECMA 15.2.3.2 Object.getPrototypeOf ( O )
*
@@ -63,9 +69,13 @@ public final class NativeObject {
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
public static Object getPrototypeOf(final Object self, final Object obj) {
- Global.checkObject(obj);
-
- return ((ScriptObject)obj).getProto();
+ if (obj instanceof ScriptObject) {
+ return ((ScriptObject)obj).getProto();
+ } else if (obj instanceof ScriptObjectMirror) {
+ return ((ScriptObjectMirror)obj).getProto();
+ } else {
+ throw notAnObject(obj);
+ }
}
/**
@@ -78,12 +88,19 @@ public final class NativeObject {
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
public static Object getOwnPropertyDescriptor(final Object self, final Object obj, final Object prop) {
- Global.checkObject(obj);
+ if (obj instanceof ScriptObject) {
+ final String key = JSType.toString(prop);
+ final ScriptObject sobj = (ScriptObject)obj;
- final String key = JSType.toString(prop);
- final ScriptObject sobj = (ScriptObject)obj;
+ return sobj.getOwnPropertyDescriptor(key);
+ } else if (obj instanceof ScriptObjectMirror) {
+ final String key = JSType.toString(prop);
+ final ScriptObjectMirror sobjMirror = (ScriptObjectMirror)obj;
- return sobj.getOwnPropertyDescriptor(key);
+ return sobjMirror.getOwnPropertyDescriptor(key);
+ } else {
+ throw notAnObject(obj);
+ }
}
/**
@@ -95,9 +112,13 @@ public final class NativeObject {
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
public static Object getOwnPropertyNames(final Object self, final Object obj) {
- Global.checkObject(obj);
-
- return new NativeArray(((ScriptObject)obj).getOwnKeys(true));
+ if (obj instanceof ScriptObject) {
+ return new NativeArray(((ScriptObject)obj).getOwnKeys(true));
+ } else if (obj instanceof ScriptObjectMirror) {
+ return new NativeArray(((ScriptObjectMirror)obj).getOwnKeys(true));
+ } else {
+ throw notAnObject(obj);
+ }
}
/**
@@ -175,8 +196,13 @@ public final class NativeObject {
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
public static Object seal(final Object self, final Object obj) {
- Global.checkObject(obj);
- return ((ScriptObject)obj).seal();
+ if (obj instanceof ScriptObject) {
+ return ((ScriptObject)obj).seal();
+ } else if (obj instanceof ScriptObjectMirror) {
+ return ((ScriptObjectMirror)obj).seal();
+ } else {
+ throw notAnObject(obj);
+ }
}
@@ -189,8 +215,13 @@ public final class NativeObject {
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
public static Object freeze(final Object self, final Object obj) {
- Global.checkObject(obj);
- return ((ScriptObject)obj).freeze();
+ if (obj instanceof ScriptObject) {
+ return ((ScriptObject)obj).freeze();
+ } else if (obj instanceof ScriptObjectMirror) {
+ return ((ScriptObjectMirror)obj).freeze();
+ } else {
+ throw notAnObject(obj);
+ }
}
/**
@@ -202,8 +233,13 @@ public final class NativeObject {
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
public static Object preventExtensions(final Object self, final Object obj) {
- Global.checkObject(obj);
- return ((ScriptObject)obj).preventExtensions();
+ if (obj instanceof ScriptObject) {
+ return ((ScriptObject)obj).preventExtensions();
+ } else if (obj instanceof ScriptObjectMirror) {
+ return ((ScriptObjectMirror)obj).preventExtensions();
+ } else {
+ throw notAnObject(obj);
+ }
}
/**
@@ -215,8 +251,13 @@ public final class NativeObject {
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
public static Object isSealed(final Object self, final Object obj) {
- Global.checkObject(obj);
- return ((ScriptObject)obj).isSealed();
+ if (obj instanceof ScriptObject) {
+ return ((ScriptObject)obj).isSealed();
+ } else if (obj instanceof ScriptObjectMirror) {
+ return ((ScriptObjectMirror)obj).isSealed();
+ } else {
+ throw notAnObject(obj);
+ }
}
/**
@@ -228,8 +269,13 @@ public final class NativeObject {
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
public static Object isFrozen(final Object self, final Object obj) {
- Global.checkObject(obj);
- return ((ScriptObject)obj).isFrozen();
+ if (obj instanceof ScriptObject) {
+ return ((ScriptObject)obj).isFrozen();
+ } else if (obj instanceof ScriptObjectMirror) {
+ return ((ScriptObjectMirror)obj).isFrozen();
+ } else {
+ throw notAnObject(obj);
+ }
}
/**
@@ -241,8 +287,13 @@ public final class NativeObject {
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
public static Object isExtensible(final Object self, final Object obj) {
- Global.checkObject(obj);
- return ((ScriptObject)obj).isExtensible();
+ if (obj instanceof ScriptObject) {
+ return ((ScriptObject)obj).isExtensible();
+ } else if (obj instanceof ScriptObjectMirror) {
+ return ((ScriptObjectMirror)obj).isExtensible();
+ } else {
+ throw notAnObject(obj);
+ }
}
/**
@@ -254,9 +305,15 @@ public final class NativeObject {
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
public static Object keys(final Object self, final Object obj) {
- Global.checkObject(obj);
- final ScriptObject sobj = (ScriptObject)obj;
- return new NativeArray(sobj.getOwnKeys(false));
+ if (obj instanceof ScriptObject) {
+ final ScriptObject sobj = (ScriptObject)obj;
+ return new NativeArray(sobj.getOwnKeys(false));
+ } else if (obj instanceof ScriptObjectMirror) {
+ final ScriptObjectMirror sobjMirror = (ScriptObjectMirror)obj;
+ return new NativeArray(sobjMirror.getOwnKeys(false));
+ } else {
+ throw notAnObject(obj);
+ }
}
/**
diff --git a/src/jdk/nashorn/internal/objects/NativeRangeError.java b/src/jdk/nashorn/internal/objects/NativeRangeError.java
index dcdd517e..1dcb4f27 100644
--- a/src/jdk/nashorn/internal/objects/NativeRangeError.java
+++ b/src/jdk/nashorn/internal/objects/NativeRangeError.java
@@ -59,7 +59,7 @@ public final class NativeRangeError extends ScriptObject {
if (msg != UNDEFINED) {
this.instMessage = JSType.toString(msg);
} else {
- this.delete(NativeError.MESSAGE, Global.isStrict());
+ this.delete(NativeError.MESSAGE, false);
}
}
diff --git a/src/jdk/nashorn/internal/objects/NativeReferenceError.java b/src/jdk/nashorn/internal/objects/NativeReferenceError.java
index a3ae89e8..7bff7796 100644
--- a/src/jdk/nashorn/internal/objects/NativeReferenceError.java
+++ b/src/jdk/nashorn/internal/objects/NativeReferenceError.java
@@ -59,7 +59,7 @@ public final class NativeReferenceError extends ScriptObject {
if (msg != UNDEFINED) {
this.instMessage = JSType.toString(msg);
} else {
- this.delete(NativeError.MESSAGE, Global.isStrict());
+ this.delete(NativeError.MESSAGE, false);
}
}
diff --git a/src/jdk/nashorn/internal/objects/NativeRegExp.java b/src/jdk/nashorn/internal/objects/NativeRegExp.java
index 8b469bc1..bbbd9791 100644
--- a/src/jdk/nashorn/internal/objects/NativeRegExp.java
+++ b/src/jdk/nashorn/internal/objects/NativeRegExp.java
@@ -641,26 +641,19 @@ public final class NativeRegExp extends ScriptObject {
return string;
}
- /*
- * $$ -> $
- * $& -> the matched substring
- * $` -> the portion of string that preceeds matched substring
- * $' -> the portion of string that follows the matched substring
- * $n -> the nth capture, where n is [1-9] and $n is NOT followed by a decimal digit
- * $nn -> the nnth capture, where nn is a two digit decimal number [01-99].
- */
- String replace = replacement;
-
if (!regexp.isGlobal()) {
if (!matcher.search(0)) {
return string;
}
final StringBuilder sb = new StringBuilder();
+ sb.append(string, 0, matcher.start());
+
if (function != null) {
- replace = callReplaceValue(function, matcher, string);
+ sb.append(callReplaceValue(function, matcher, string));
+ } else {
+ appendReplacement(matcher, string, replacement, sb);
}
- appendReplacement(matcher, string, replace, sb, 0);
sb.append(string, matcher.end(), string.length());
return sb.toString();
}
@@ -676,12 +669,13 @@ public final class NativeRegExp extends ScriptObject {
final StringBuilder sb = new StringBuilder();
do {
+ sb.append(string, thisIndex, matcher.start());
if (function != null) {
- replace = callReplaceValue(function, matcher, string);
+ sb.append(callReplaceValue(function, matcher, string));
+ } else {
+ appendReplacement(matcher, string, replacement, sb);
}
- appendReplacement(matcher, string, replace, sb, thisIndex);
-
// ECMA 15.5.4.10 String.prototype.match(regexp)
thisIndex = matcher.end();
if (thisIndex == previousLastIndex) {
@@ -697,10 +691,19 @@ public final class NativeRegExp extends ScriptObject {
return sb.toString();
}
- private void appendReplacement(final RegExpMatcher matcher, final String text, final String replacement, final StringBuilder sb, final int lastAppendPosition) {
- // Process substitution string to replace group references with groups
+ private void appendReplacement(final RegExpMatcher matcher, final String text, final String replacement, final StringBuilder sb) {
+ /*
+ * Process substitution patterns:
+ *
+ * $$ -> $
+ * $& -> the matched substring
+ * $` -> the portion of string that preceeds matched substring
+ * $' -> the portion of string that follows the matched substring
+ * $n -> the nth capture, where n is [1-9] and $n is NOT followed by a decimal digit
+ * $nn -> the nnth capture, where nn is a two digit decimal number [01-99].
+ */
+
int cursor = 0;
- final StringBuilder result = new StringBuilder();
Object[] groups = null;
while (cursor < replacement.length()) {
@@ -732,37 +735,33 @@ public final class NativeRegExp extends ScriptObject {
}
// Append group if matched.
if (groups[refNum] != UNDEFINED) {
- result.append((String) groups[refNum]);
+ sb.append((String) groups[refNum]);
}
} else { // $0. ignore.
assert refNum == 0;
- result.append("$0");
+ sb.append("$0");
}
} else if (nextChar == '$') {
- result.append('$');
+ sb.append('$');
cursor++;
} else if (nextChar == '&') {
- result.append(matcher.group());
+ sb.append(matcher.group());
cursor++;
} else if (nextChar == '`') {
- result.append(text.substring(0, matcher.start()));
+ sb.append(text, 0, matcher.start());
cursor++;
} else if (nextChar == '\'') {
- result.append(text.substring(matcher.end()));
+ sb.append(text, matcher.end(), text.length());
cursor++;
} else {
// unknown substitution or $n with n>m. skip.
- result.append('$');
+ sb.append('$');
}
} else {
- result.append(nextChar);
+ sb.append(nextChar);
cursor++;
}
}
- // Append the intervening text
- sb.append(text, lastAppendPosition, matcher.start());
- // Append the match substitution
- sb.append(result);
}
private String callReplaceValue(final ScriptFunction function, final RegExpMatcher matcher, final String string) {
diff --git a/src/jdk/nashorn/internal/objects/NativeString.java b/src/jdk/nashorn/internal/objects/NativeString.java
index df4aa1bf..fda265e6 100644
--- a/src/jdk/nashorn/internal/objects/NativeString.java
+++ b/src/jdk/nashorn/internal/objects/NativeString.java
@@ -29,7 +29,6 @@ import static jdk.nashorn.internal.lookup.Lookup.MH;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import static jdk.nashorn.internal.runtime.JSType.isRepresentableAsInt;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
-import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndexNoThrow;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
@@ -156,7 +155,7 @@ public final class NativeString extends ScriptObject {
@SuppressWarnings("unused")
private static Object get(final Object self, final Object key) {
final CharSequence cs = JSType.toCharSequence(self);
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
if (index >= 0 && index < cs.length()) {
return String.valueOf(cs.charAt(index));
}
@@ -191,7 +190,7 @@ public final class NativeString extends ScriptObject {
// String characters can be accessed with array-like indexing..
@Override
public Object get(final Object key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
if (index >= 0 && index < value.length()) {
return String.valueOf(value.charAt(index));
}
@@ -284,7 +283,7 @@ public final class NativeString extends ScriptObject {
@Override
public boolean has(final Object key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
return isValid(index) || super.has(key);
}
@@ -295,19 +294,19 @@ public final class NativeString extends ScriptObject {
@Override
public boolean has(final long key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
return isValid(index) || super.has(key);
}
@Override
public boolean has(final double key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
return isValid(index) || super.has(key);
}
@Override
public boolean hasOwnProperty(final Object key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
return isValid(index) || super.hasOwnProperty(key);
}
@@ -318,13 +317,13 @@ public final class NativeString extends ScriptObject {
@Override
public boolean hasOwnProperty(final long key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
return isValid(index) || super.hasOwnProperty(key);
}
@Override
public boolean hasOwnProperty(final double key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
return isValid(index) || super.hasOwnProperty(key);
}
@@ -335,19 +334,19 @@ public final class NativeString extends ScriptObject {
@Override
public boolean delete(final long key, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
return checkDeleteIndex(index, strict)? false : super.delete(key, strict);
}
@Override
public boolean delete(final double key, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
return checkDeleteIndex(index, strict)? false : super.delete(key, strict);
}
@Override
public boolean delete(final Object key, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
return checkDeleteIndex(index, strict)? false : super.delete(key, strict);
}
@@ -364,7 +363,7 @@ public final class NativeString extends ScriptObject {
@Override
public Object getOwnPropertyDescriptor(final String key) {
- final int index = ArrayIndex.getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
if (index >= 0 && index < value.length()) {
final Global global = Global.instance();
return global.newDataDescriptor(String.valueOf(value.charAt(index)), false, true, false);
diff --git a/src/jdk/nashorn/internal/objects/NativeSyntaxError.java b/src/jdk/nashorn/internal/objects/NativeSyntaxError.java
index db54c483..e9ec3050 100644
--- a/src/jdk/nashorn/internal/objects/NativeSyntaxError.java
+++ b/src/jdk/nashorn/internal/objects/NativeSyntaxError.java
@@ -59,7 +59,7 @@ public final class NativeSyntaxError extends ScriptObject {
if (msg != UNDEFINED) {
this.instMessage = JSType.toString(msg);
} else {
- this.delete(NativeError.MESSAGE, Global.isStrict());
+ this.delete(NativeError.MESSAGE, false);
}
}
diff --git a/src/jdk/nashorn/internal/objects/NativeTypeError.java b/src/jdk/nashorn/internal/objects/NativeTypeError.java
index 5e87fbb2..bbec5ad3 100644
--- a/src/jdk/nashorn/internal/objects/NativeTypeError.java
+++ b/src/jdk/nashorn/internal/objects/NativeTypeError.java
@@ -59,7 +59,7 @@ public final class NativeTypeError extends ScriptObject {
if (msg != UNDEFINED) {
this.instMessage = JSType.toString(msg);
} else {
- delete(NativeError.MESSAGE, Global.isStrict());
+ delete(NativeError.MESSAGE, false);
}
}
diff --git a/src/jdk/nashorn/internal/objects/NativeURIError.java b/src/jdk/nashorn/internal/objects/NativeURIError.java
index 958c14ac..e6c91525 100644
--- a/src/jdk/nashorn/internal/objects/NativeURIError.java
+++ b/src/jdk/nashorn/internal/objects/NativeURIError.java
@@ -58,7 +58,7 @@ public final class NativeURIError extends ScriptObject {
if (msg != UNDEFINED) {
this.instMessage = JSType.toString(msg);
} else {
- this.delete(NativeError.MESSAGE, Global.isStrict());
+ this.delete(NativeError.MESSAGE, false);
}
}
diff --git a/src/jdk/nashorn/internal/parser/JSONParser.java b/src/jdk/nashorn/internal/parser/JSONParser.java
index aa9234ef..f1e68f66 100644
--- a/src/jdk/nashorn/internal/parser/JSONParser.java
+++ b/src/jdk/nashorn/internal/parser/JSONParser.java
@@ -54,10 +54,9 @@ public class JSONParser extends AbstractParser {
* Constructor
* @param source the source
* @param errors the error manager
- * @param strict are we in strict mode
*/
- public JSONParser(final Source source, final ErrorManager errors, final boolean strict) {
- super(source, errors, strict);
+ public JSONParser(final Source source, final ErrorManager errors) {
+ super(source, errors, false);
}
/**
@@ -135,6 +134,7 @@ public class JSONParser extends AbstractParser {
return ch == '\"';
}
+ // ECMA 15.12.1.1 The JSON Lexical Grammar - JSONWhiteSpace
@Override
protected boolean isWhitespace(final char ch) {
return Lexer.isJsonWhitespace(ch);
@@ -144,6 +144,99 @@ public class JSONParser extends AbstractParser {
protected boolean isEOL(final char ch) {
return Lexer.isJsonEOL(ch);
}
+
+ // ECMA 15.12.1.1 The JSON Lexical Grammar - JSONNumber
+ @Override
+ protected void scanNumber() {
+ // Record beginning of number.
+ final int startPosition = position;
+ // Assume value is a decimal.
+ TokenType valueType = TokenType.DECIMAL;
+
+ // floating point can't start with a "." with no leading digit before
+ if (ch0 == '.') {
+ error(Lexer.message("json.invalid.number"), STRING, position, limit);
+ }
+
+ // First digit of number.
+ int digit = convertDigit(ch0, 10);
+
+ // skip first digit
+ skip(1);
+
+ if (digit != 0) {
+ // Skip over remaining digits.
+ while (convertDigit(ch0, 10) != -1) {
+ skip(1);
+ }
+ }
+
+ if (ch0 == '.' || ch0 == 'E' || ch0 == 'e') {
+ // Must be a double.
+ if (ch0 == '.') {
+ // Skip period.
+ skip(1);
+
+ boolean mantissa = false;
+ // Skip mantissa.
+ while (convertDigit(ch0, 10) != -1) {
+ mantissa = true;
+ skip(1);
+ }
+
+ if (! mantissa) {
+ // no digit after "."
+ error(Lexer.message("json.invalid.number"), STRING, position, limit);
+ }
+ }
+
+ // Detect exponent.
+ if (ch0 == 'E' || ch0 == 'e') {
+ // Skip E.
+ skip(1);
+ // Detect and skip exponent sign.
+ if (ch0 == '+' || ch0 == '-') {
+ skip(1);
+ }
+ boolean exponent = false;
+ // Skip exponent.
+ while (convertDigit(ch0, 10) != -1) {
+ exponent = true;
+ skip(1);
+ }
+
+ if (! exponent) {
+ // no digit after "E"
+ error(Lexer.message("json.invalid.number"), STRING, position, limit);
+ }
+ }
+
+ valueType = TokenType.FLOATING;
+ }
+
+ // Add number token.
+ add(valueType, startPosition);
+ }
+
+ // ECMA 15.12.1.1 The JSON Lexical Grammar - JSONEscapeCharacter
+ @Override
+ protected boolean isEscapeCharacter(final char ch) {
+ switch (ch) {
+ case '"':
+ case '/':
+ case '\\':
+ case 'b':
+ case 'f':
+ case 'n':
+ case 'r':
+ case 't':
+ // could be unicode escape
+ case 'u':
+ return true;
+ default:
+ return false;
+ }
+ }
};
k = -1;
diff --git a/src/jdk/nashorn/internal/parser/Lexer.java b/src/jdk/nashorn/internal/parser/Lexer.java
index d9ebb365..ecf67962 100644
--- a/src/jdk/nashorn/internal/parser/Lexer.java
+++ b/src/jdk/nashorn/internal/parser/Lexer.java
@@ -648,7 +648,7 @@ public class Lexer extends Scanner {
*
* @return The converted digit or -1 if invalid.
*/
- private static int convertDigit(final char ch, final int base) {
+ protected static int convertDigit(final char ch, final int base) {
int digit;
if ('0' <= ch && ch <= '9') {
@@ -666,37 +666,24 @@ public class Lexer extends Scanner {
/**
- * Get the value of a numeric sequence.
- *
- * @param base Numeric base.
- * @param max Maximum number of digits.
- * @param skip Skip over escape first.
- * @param check Tells whether to throw error if a digit is invalid for the given base.
- * @param type Type of token to report against.
+ * Get the value of a hexadecimal numeric sequence.
*
+ * @param length Number of digits.
+ * @param type Type of token to report against.
* @return Value of sequence or < 0 if no digits.
*/
- private int valueOfSequence(final int base, final int max, final boolean skip, final boolean check, final TokenType type) {
- assert base == 16 || base == 8 : "base other than 16 or 8";
- final boolean isHex = base == 16;
- final int shift = isHex ? 4 : 3;
+ private int hexSequence(final int length, final TokenType type) {
int value = 0;
- if (skip) {
- skip(2);
- }
-
- for (int i = 0; i < max; i++) {
- final int digit = convertDigit(ch0, base);
+ for (int i = 0; i < length; i++) {
+ final int digit = convertDigit(ch0, 16);
if (digit == -1) {
- if (check) {
- error(Lexer.message("invalid." + (isHex ? "hex" : "octal")), type, position, limit);
- }
+ error(Lexer.message("invalid.hex"), type, position, limit);
return i == 0 ? -1 : value;
}
- value = value << shift | digit;
+ value = digit | value << 4;
skip(1);
}
@@ -704,6 +691,30 @@ public class Lexer extends Scanner {
}
/**
+ * Get the value of an octal numeric sequence. This parses up to 3 digits with a maximum value of 255.
+ *
+ * @return Value of sequence.
+ */
+ private int octalSequence() {
+ int value = 0;
+
+ for (int i = 0; i < 3; i++) {
+ final int digit = convertDigit(ch0, 8);
+
+ if (digit == -1) {
+ break;
+ }
+ value = digit | value << 3;
+ skip(1);
+
+ if (i == 1 && value >= 32) {
+ break;
+ }
+ }
+ return value;
+ }
+
+ /**
* Convert a string to a JavaScript identifier.
*
* @param start Position in source content.
@@ -724,7 +735,8 @@ public class Lexer extends Scanner {
while (!atEOF() && position < end && !isEOL(ch0)) {
// If escape character.
if (ch0 == '\\' && ch1 == 'u') {
- final int ch = valueOfSequence(16, 4, true, true, TokenType.IDENT);
+ skip(2);
+ final int ch = hexSequence(4, TokenType.IDENT);
if (isWhitespace((char)ch)) {
return null;
}
@@ -815,7 +827,7 @@ public class Lexer extends Scanner {
}
reset(afterSlash);
// Octal sequence.
- final int ch = valueOfSequence(8, 3, false, false, STRING);
+ final int ch = octalSequence();
if (ch < 0) {
sb.append('\\');
@@ -862,7 +874,7 @@ public class Lexer extends Scanner {
break;
case 'x': {
// Hex sequence.
- final int ch = valueOfSequence(16, 2, false, true, STRING);
+ final int ch = hexSequence(2, STRING);
if (ch < 0) {
sb.append('\\');
@@ -874,7 +886,7 @@ public class Lexer extends Scanner {
break;
case 'u': {
// Unicode sequence.
- final int ch = valueOfSequence(16, 4, false, true, STRING);
+ final int ch = hexSequence(4, STRING);
if (ch < 0) {
sb.append('\\');
@@ -907,8 +919,9 @@ public class Lexer extends Scanner {
/**
* Scan over a string literal.
+ * @param add true if we nare not just scanning but should actually modify the token stream
*/
- private void scanString(final boolean add) {
+ protected void scanString(final boolean add) {
// Type of string.
TokenType type = STRING;
// Record starting quote.
@@ -925,6 +938,9 @@ public class Lexer extends Scanner {
if (ch0 == '\\') {
type = ESCSTRING;
skip(1);
+ if (! isEscapeCharacter(ch0)) {
+ error(Lexer.message("invalid.escape.char"), STRING, position, limit);
+ }
if (isEOL(ch0)) {
// Multiline string literal
skipEOL(false);
@@ -979,6 +995,16 @@ public class Lexer extends Scanner {
}
/**
+ * Is the given character a valid escape char after "\" ?
+ *
+ * @param ch character to be checked
+ * @return if the given character is valid after "\"
+ */
+ protected boolean isEscapeCharacter(final char ch) {
+ return true;
+ }
+
+ /**
* Convert string to number.
*
* @param valueString String to convert.
@@ -1024,7 +1050,7 @@ public class Lexer extends Scanner {
/**
* Scan a number.
*/
- private void scanNumber() {
+ protected void scanNumber() {
// Record beginning of number.
final int start = position;
// Assume value is a decimal.
@@ -1090,6 +1116,10 @@ public class Lexer extends Scanner {
}
}
+ if (Character.isJavaIdentifierStart(ch0)) {
+ error(Lexer.message("missing.space.after.number"), type, position, 1);
+ }
+
// Add number token.
add(type, start);
}
@@ -1178,7 +1208,8 @@ public class Lexer extends Scanner {
// Make sure first character is valid start character.
if (ch0 == '\\' && ch1 == 'u') {
- final int ch = valueOfSequence(16, 4, true, true, TokenType.IDENT);
+ skip(2);
+ final int ch = hexSequence(4, TokenType.IDENT);
if (!Character.isJavaIdentifierStart(ch)) {
error(Lexer.message("illegal.identifier.character"), TokenType.IDENT, start, position);
@@ -1191,7 +1222,8 @@ public class Lexer extends Scanner {
// Make sure remaining characters are valid part characters.
while (!atEOF()) {
if (ch0 == '\\' && ch1 == 'u') {
- final int ch = valueOfSequence(16, 4, true, true, TokenType.IDENT);
+ skip(2);
+ final int ch = hexSequence(4, TokenType.IDENT);
if (!Character.isJavaIdentifierPart(ch)) {
error(Lexer.message("illegal.identifier.character"), TokenType.IDENT, start, position);
@@ -1583,7 +1615,13 @@ public class Lexer extends Scanner {
return null;
}
- private static String message(final String msgId, final String... args) {
+ /**
+ * Get the correctly localized error message for a given message id format arguments
+ * @param msgId message id
+ * @param args format arguments
+ * @return message
+ */
+ protected static String message(final String msgId, final String... args) {
return ECMAErrors.getMessage("lexer.error." + msgId, args);
}
diff --git a/src/jdk/nashorn/internal/parser/Parser.java b/src/jdk/nashorn/internal/parser/Parser.java
index ee90b8d9..0c2c1633 100644
--- a/src/jdk/nashorn/internal/parser/Parser.java
+++ b/src/jdk/nashorn/internal/parser/Parser.java
@@ -2403,7 +2403,7 @@ loop:
verifyStrictIdent(name, "function name");
} else if (isStatement) {
// Nashorn extension: anonymous function statements
- if (env._no_syntax_extensions || !env._anon_functions) {
+ if (env._no_syntax_extensions) {
expect(IDENT);
}
}
diff --git a/src/jdk/nashorn/internal/runtime/Context.java b/src/jdk/nashorn/internal/runtime/Context.java
index d0e3b020..5b89ec2c 100644
--- a/src/jdk/nashorn/internal/runtime/Context.java
+++ b/src/jdk/nashorn/internal/runtime/Context.java
@@ -46,6 +46,7 @@ import java.security.CodeSource;
import java.security.Permissions;
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
+import java.util.Map;
import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.org.objectweb.asm.util.CheckClassAdapter;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
@@ -188,7 +189,7 @@ public final class Context {
private final ScriptEnvironment env;
/** is this context in strict mode? Cached from env. as this is used heavily. */
- public final boolean _strict;
+ final boolean _strict;
/** class loader to resolve classes from script. */
private final ClassLoader appLoader;
@@ -482,6 +483,13 @@ public final class Context {
final String name = JSType.toString(sobj.get("name"));
source = new Source(name, script);
}
+ } else if (src instanceof Map) {
+ final Map map = (Map)src;
+ if (map.containsKey("script") && map.containsKey("name")) {
+ final String script = JSType.toString(map.get("script"));
+ final String name = JSType.toString(map.get("name"));
+ source = new Source(name, script);
+ }
}
if (source != null) {
@@ -496,12 +504,13 @@ public final class Context {
* expression, after creating a new global scope.
*
* @param from source expression for script
+ * @param args (optional) arguments to be passed to the loaded script
*
* @return return value for load call (undefined)
*
* @throws IOException if source cannot be found or loaded
*/
- public Object loadWithNewGlobal(final Object from) throws IOException {
+ public Object loadWithNewGlobal(final Object from, final Object...args) throws IOException {
final ScriptObject oldGlobal = getGlobalTrusted();
final ScriptObject newGlobal = AccessController.doPrivileged(new PrivilegedAction<ScriptObject>() {
@Override
@@ -518,6 +527,9 @@ public final class Context {
});
setGlobalTrusted(newGlobal);
+ final Object[] wrapped = args == null? ScriptRuntime.EMPTY_ARRAY : ScriptObjectMirror.wrapArray(args, newGlobal);
+ newGlobal.put("arguments", ((GlobalObject)newGlobal).wrapAsObject(wrapped));
+
try {
return ScriptObjectMirror.wrap(load(newGlobal, from), newGlobal);
} finally {
diff --git a/src/jdk/nashorn/internal/runtime/GlobalFunctions.java b/src/jdk/nashorn/internal/runtime/GlobalFunctions.java
index 98b79150..04211fc6 100644
--- a/src/jdk/nashorn/internal/runtime/GlobalFunctions.java
+++ b/src/jdk/nashorn/internal/runtime/GlobalFunctions.java
@@ -373,11 +373,16 @@ loop:
sb.append(ch);
} else if (ch < 256) {
sb.append('%');
- final byte b = (byte)ch;
- sb.append(Integer.toHexString(b & 0xFF).toUpperCase(Locale.ENGLISH));
+ if (ch < 16) {
+ sb.append('0');
+ }
+ sb.append(Integer.toHexString(ch).toUpperCase(Locale.ENGLISH));
} else {
sb.append("%u");
- sb.append(Integer.toHexString(ch & 0xFFFF).toUpperCase(Locale.ENGLISH));
+ if (ch < 4096) {
+ sb.append('0');
+ }
+ sb.append(Integer.toHexString(ch).toUpperCase(Locale.ENGLISH));
}
}
diff --git a/src/jdk/nashorn/internal/runtime/JSONFunctions.java b/src/jdk/nashorn/internal/runtime/JSONFunctions.java
index c296a87a..2895cb85 100644
--- a/src/jdk/nashorn/internal/runtime/JSONFunctions.java
+++ b/src/jdk/nashorn/internal/runtime/JSONFunctions.java
@@ -25,9 +25,6 @@
package jdk.nashorn.internal.runtime;
-import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndexNoThrow;
-import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex;
-
import java.lang.invoke.MethodHandle;
import java.util.Iterator;
import jdk.nashorn.internal.ir.LiteralNode;
@@ -37,6 +34,7 @@ import jdk.nashorn.internal.ir.PropertyNode;
import jdk.nashorn.internal.ir.UnaryNode;
import jdk.nashorn.internal.parser.JSONParser;
import jdk.nashorn.internal.parser.TokenType;
+import jdk.nashorn.internal.runtime.arrays.ArrayIndex;
import jdk.nashorn.internal.runtime.linker.Bootstrap;
/**
@@ -66,13 +64,9 @@ public final class JSONFunctions {
*/
public static Object parse(final Object text, final Object reviver) {
final String str = JSType.toString(text);
- final Context context = Context.getContextTrusted();
final JSONParser parser = new JSONParser(
new Source("<json>", str),
- new Context.ThrowErrorManager(),
- (context != null) ?
- context.getEnv()._strict :
- false);
+ new Context.ThrowErrorManager());
Node node;
@@ -107,7 +101,6 @@ public final class JSONFunctions {
final Object val = holder.get(name);
if (val instanceof ScriptObject) {
final ScriptObject valueObj = (ScriptObject)val;
- final boolean strict = valueObj.isStrictContext();
final Iterator<String> iter = valueObj.propertyIterator();
while (iter.hasNext()) {
@@ -115,9 +108,9 @@ public final class JSONFunctions {
final Object newElement = walk(valueObj, key, reviver);
if (newElement == ScriptRuntime.UNDEFINED) {
- valueObj.delete(key, strict);
+ valueObj.delete(key, false);
} else {
- setPropertyValue(valueObj, key, newElement, strict);
+ setPropertyValue(valueObj, key, newElement, false);
}
}
}
@@ -170,14 +163,13 @@ public final class JSONFunctions {
} else if (node instanceof ObjectNode) {
final ObjectNode objNode = (ObjectNode) node;
final ScriptObject object = ((GlobalObject)global).newObject();
- final boolean strict = global.isStrictContext();
for (final PropertyNode pNode: objNode.getElements()) {
final Node valueNode = pNode.getValue();
final String name = pNode.getKeyName();
final Object value = convertNode(global, valueNode);
- setPropertyValue(object, name, value, strict);
+ setPropertyValue(object, name, value, false);
}
return object;
@@ -192,8 +184,8 @@ public final class JSONFunctions {
// add a new property if does not exist already, or else set old property
private static void setPropertyValue(final ScriptObject sobj, final String name, final Object value, final boolean strict) {
- final int index = getArrayIndexNoThrow(name);
- if (isValidArrayIndex(index)) {
+ final int index = ArrayIndex.getArrayIndex(name);
+ if (ArrayIndex.isValidArrayIndex(index)) {
// array index key
sobj.defineOwnProperty(index, value);
} else if (sobj.getMap().findProperty(name) != null) {
diff --git a/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java b/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java
index 883ff85c..145afac6 100644
--- a/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java
+++ b/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java
@@ -199,7 +199,6 @@ public final class NativeJavaPackage extends ScriptObject {
final String fullName = name.isEmpty() ? propertyName : name + "." + propertyName;
final Context context = getContext();
- final boolean strict = context._strict;
Class<?> javaClass = null;
try {
@@ -209,9 +208,9 @@ public final class NativeJavaPackage extends ScriptObject {
}
if (javaClass == null) {
- set(propertyName, new NativeJavaPackage(fullName, getProto()), strict);
+ set(propertyName, new NativeJavaPackage(fullName, getProto()), false);
} else {
- set(propertyName, StaticClass.forClass(javaClass), strict);
+ set(propertyName, StaticClass.forClass(javaClass), false);
}
return super.lookup(desc, request);
diff --git a/src/jdk/nashorn/internal/runtime/PropertyListenerManager.java b/src/jdk/nashorn/internal/runtime/PropertyListenerManager.java
index a0c2f823..34db0cb3 100644
--- a/src/jdk/nashorn/internal/runtime/PropertyListenerManager.java
+++ b/src/jdk/nashorn/internal/runtime/PropertyListenerManager.java
@@ -61,7 +61,7 @@ public class PropertyListenerManager implements PropertyListener {
*
* @param listener The property listener that is added.
*/
- public final void addPropertyListener(final PropertyListener listener) {
+ public synchronized final void addPropertyListener(final PropertyListener listener) {
if (listeners == null) {
listeners = new WeakHashMap<>();
}
@@ -77,7 +77,7 @@ public class PropertyListenerManager implements PropertyListener {
*
* @param listener The property listener that is removed.
*/
- public final void removePropertyListener(final PropertyListener listener) {
+ public synchronized final void removePropertyListener(final PropertyListener listener) {
if (listeners != null) {
if (Context.DEBUG) {
listenersRemoved++;
@@ -92,7 +92,7 @@ public class PropertyListenerManager implements PropertyListener {
* @param object The ScriptObject to which property was added.
* @param prop The property being added.
*/
- protected final void notifyPropertyAdded(final ScriptObject object, final Property prop) {
+ protected synchronized final void notifyPropertyAdded(final ScriptObject object, final Property prop) {
if (listeners != null) {
for (PropertyListener listener : listeners.keySet()) {
listener.propertyAdded(object, prop);
@@ -106,7 +106,7 @@ public class PropertyListenerManager implements PropertyListener {
* @param object The ScriptObject from which property was deleted.
* @param prop The property being deleted.
*/
- protected final void notifyPropertyDeleted(final ScriptObject object, final Property prop) {
+ protected synchronized final void notifyPropertyDeleted(final ScriptObject object, final Property prop) {
if (listeners != null) {
for (PropertyListener listener : listeners.keySet()) {
listener.propertyDeleted(object, prop);
@@ -121,7 +121,7 @@ public class PropertyListenerManager implements PropertyListener {
* @param oldProp The old property being replaced.
* @param newProp The new property that replaces the old property.
*/
- protected final void notifyPropertyModified(final ScriptObject object, final Property oldProp, final Property newProp) {
+ protected synchronized final void notifyPropertyModified(final ScriptObject object, final Property oldProp, final Property newProp) {
if (listeners != null) {
for (PropertyListener listener : listeners.keySet()) {
listener.propertyModified(object, oldProp, newProp);
diff --git a/src/jdk/nashorn/internal/runtime/PropertyMap.java b/src/jdk/nashorn/internal/runtime/PropertyMap.java
index 077218d3..b7248166 100644
--- a/src/jdk/nashorn/internal/runtime/PropertyMap.java
+++ b/src/jdk/nashorn/internal/runtime/PropertyMap.java
@@ -95,7 +95,6 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
*/
private PropertyMap(final PropertyHashMap properties, final int fieldCount, final int fieldMaximum) {
this.properties = properties;
- this.hashCode = computeHashCode();
this.fieldCount = fieldCount;
this.fieldMaximum = fieldMaximum;
@@ -125,7 +124,6 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
this.spillLength = propertyMap.spillLength;
this.fieldCount = propertyMap.fieldCount;
this.fieldMaximum = propertyMap.fieldMaximum;
- this.hashCode = computeHashCode();
if (Context.DEBUG) {
count++;
@@ -610,6 +608,9 @@ public final class PropertyMap implements Iterable<Object>, PropertyListener {
@Override
public int hashCode() {
+ if (hashCode == 0 && !properties.isEmpty()) {
+ hashCode = computeHashCode();
+ }
return hashCode;
}
diff --git a/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java b/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java
index 2ca897db..f04dedf0 100644
--- a/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java
+++ b/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java
@@ -56,9 +56,6 @@ public final class ScriptEnvironment {
/** Current Options object. */
private final Options options;
- /** Always allow functions as statements */
- public final boolean _anon_functions;
-
/** Size of the per-global Class cache size */
public final int _class_cache_size;
@@ -192,7 +189,6 @@ public final class ScriptEnvironment {
this.namespace = new Namespace();
this.options = options;
- _anon_functions = options.getBoolean("anon.functions");
_class_cache_size = options.getInteger("class.cache.size");
_compile_only = options.getBoolean("compile.only");
_debug_lines = options.getBoolean("debug.lines");
diff --git a/src/jdk/nashorn/internal/runtime/ScriptObject.java b/src/jdk/nashorn/internal/runtime/ScriptObject.java
index 331687ad..0a2337f4 100644
--- a/src/jdk/nashorn/internal/runtime/ScriptObject.java
+++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java
@@ -37,8 +37,6 @@ import static jdk.nashorn.internal.runtime.PropertyDescriptor.SET;
import static jdk.nashorn.internal.runtime.PropertyDescriptor.VALUE;
import static jdk.nashorn.internal.runtime.PropertyDescriptor.WRITABLE;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
-import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndexNoThrow;
-import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
@@ -65,6 +63,7 @@ import jdk.nashorn.internal.lookup.MethodHandleFactory;
import jdk.nashorn.internal.objects.AccessorPropertyDescriptor;
import jdk.nashorn.internal.objects.DataPropertyDescriptor;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
+import jdk.nashorn.internal.runtime.arrays.ArrayIndex;
import jdk.nashorn.internal.runtime.linker.Bootstrap;
import jdk.nashorn.internal.runtime.linker.LinkerCallSite;
import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
@@ -106,6 +105,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
/** Is this a prototype PropertyMap? */
public static final int IS_PROTOTYPE = 0b0000_1000;
+ /** Is length property not-writable? */
+ public static final int IS_LENGTH_NOT_WRITABLE = 0b0001_0000;
+
/** Spill growth rate - by how many elements does {@link ScriptObject#spill} when full */
public static final int SPILL_RATE = 8;
@@ -333,7 +335,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
return global.newDataDescriptor(getWithProperty(property), configurable, enumerable, writable);
}
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
final ArrayData array = getArray();
if (array.has(index)) {
@@ -444,7 +446,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
if (newValue && property != null) {
// Temporarily clear flags.
property = modifyOwnProperty(property, 0);
- set(key, value, getContext()._strict);
+ set(key, value, false);
}
if (property == null) {
@@ -533,21 +535,23 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
* from any object in proto chain such as Array.prototype, Object.prototype.
* This method directly sets a particular element value in the current object.
*
- * @param index index key for property
+ * @param index key for property
* @param value value to define
*/
protected final void defineOwnProperty(final int index, final Object value) {
- if (index >= getArray().length()) {
+ assert ArrayIndex.isValidArrayIndex(index) : "invalid array index";
+ final long longIndex = ArrayIndex.toLongIndex(index);
+ if (longIndex >= getArray().length()) {
// make array big enough to hold..
- setArray(getArray().ensure(index));
+ setArray(getArray().ensure(longIndex));
}
setArray(getArray().set(index, value, false));
}
private void checkIntegerKey(final String key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
- if (isValidArrayIndex(index)) {
+ if (ArrayIndex.isValidArrayIndex(index)) {
final ArrayData data = getArray();
if (data.has(index)) {
@@ -557,7 +561,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
}
private void removeArraySlot(final String key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
final ArrayData array = getArray();
if (array.has(index)) {
@@ -997,7 +1001,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
* @param value the value to write at the given index
*/
public void setArgument(final int key, final Object value) {
- set(key, value, getContext()._strict);
+ set(key, value, false);
}
/**
@@ -1104,7 +1108,8 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
}
/**
- * return a List of own keys associated with the object.
+ * return an array of own property keys associated with the object.
+ *
* @param all True if to include non-enumerable keys.
* @return Array of keys.
*/
@@ -1205,7 +1210,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
* the proto chain
*
* @param instance instace to check
- * @return true if instance of instance
+ * @return true if 'instance' is an instance of this object
*/
public boolean isInstance(final ScriptObject instance) {
return false;
@@ -1276,14 +1281,14 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
*
* @return {@code true} if is prototype
*/
- public boolean isPrototype() {
+ public final boolean isPrototype() {
return (flags & IS_PROTOTYPE) != 0;
}
/**
* Flag this object as having a prototype.
*/
- public void setIsPrototype() {
+ public final void setIsPrototype() {
if (proto != null && !isPrototype()) {
proto.addPropertyListener(this);
}
@@ -1291,6 +1296,22 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
}
/**
+ * Check if this object has non-writable length property
+ *
+ * @return {@code true} if 'length' property is non-writable
+ */
+ public final boolean isLengthNotWritable() {
+ return (flags & IS_LENGTH_NOT_WRITABLE) != 0;
+ }
+
+ /**
+ * Flag this object as having non-writable length property
+ */
+ public void setIsLengthNotWritable() {
+ flags |= IS_LENGTH_NOT_WRITABLE;
+ }
+
+ /**
* Get the {@link ArrayData} for this ScriptObject if it is an array
* @return array data
*/
@@ -1362,7 +1383,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
/**
* Check whether this ScriptObject is frozen
- * @return true if frozed
+ * @return true if frozen
*/
public boolean isFrozen() {
return getMap().isFrozen();
@@ -1392,7 +1413,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
* (java.util.Map-like method to help ScriptObjectMirror implementation)
*/
public void clear() {
- final boolean strict = getContext()._strict;
+ final boolean strict = isStrictContext();
final Iterator<String> iter = propertyIterator();
while (iter.hasNext()) {
delete(iter.next(), strict);
@@ -1480,7 +1501,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
*/
public Object put(final Object key, final Object value) {
final Object oldValue = get(key);
- set(key, value, getContext()._strict);
+ set(key, value, isStrictContext());
return oldValue;
}
@@ -1492,7 +1513,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
* @param otherMap a {@literal <key,value>} map of properties to add
*/
public void putAll(final Map<?, ?> otherMap) {
- final boolean strict = getContext()._strict;
+ final boolean strict = isStrictContext();
for (final Map.Entry<?, ?> entry : otherMap.entrySet()) {
set(entry.getKey(), entry.getValue(), strict);
}
@@ -1507,7 +1528,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
*/
public Object remove(final Object key) {
final Object oldValue = get(key);
- delete(key, getContext()._strict);
+ delete(key, isStrictContext());
return oldValue;
}
@@ -1519,7 +1540,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
* @return if the delete was successful or not
*/
public boolean delete(final Object key) {
- return delete(key, getContext()._strict);
+ return delete(key, isStrictContext());
}
/**
@@ -2221,7 +2242,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
return;
}
- final boolean isStrict = getContext()._strict;
+ final boolean isStrict = isStrictContext();
if (newLength > arrayLength) {
setArray(getArray().ensure(newLength - 1));
@@ -2238,7 +2259,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
}
private int getInt(final int index, final String key) {
- if (isValidArrayIndex(index)) {
+ if (ArrayIndex.isValidArrayIndex(index)) {
for (ScriptObject object = this; ; ) {
final FindProperty find = object.findProperty(key, false, false, this);
@@ -2269,7 +2290,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override
public int getInt(final Object key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
final ArrayData array = getArray();
if (array.has(index)) {
@@ -2281,7 +2302,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override
public int getInt(final double key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
final ArrayData array = getArray();
if (array.has(index)) {
@@ -2293,7 +2314,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override
public int getInt(final long key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
final ArrayData array = getArray();
if (array.has(index)) {
@@ -2315,7 +2336,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
}
private long getLong(final int index, final String key) {
- if (isValidArrayIndex(index)) {
+ if (ArrayIndex.isValidArrayIndex(index)) {
for (ScriptObject object = this; ; ) {
final FindProperty find = object.findProperty(key, false, false, this);
@@ -2346,7 +2367,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override
public long getLong(final Object key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
final ArrayData array = getArray();
if (array.has(index)) {
@@ -2358,7 +2379,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override
public long getLong(final double key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
final ArrayData array = getArray();
if (array.has(index)) {
@@ -2370,7 +2391,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override
public long getLong(final long key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
final ArrayData array = getArray();
if (array.has(index)) {
@@ -2392,7 +2413,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
}
private double getDouble(final int index, final String key) {
- if (isValidArrayIndex(index)) {
+ if (ArrayIndex.isValidArrayIndex(index)) {
for (ScriptObject object = this; ; ) {
final FindProperty find = object.findProperty(key, false, false, this);
@@ -2423,7 +2444,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override
public double getDouble(final Object key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
final ArrayData array = getArray();
if (array.has(index)) {
@@ -2435,7 +2456,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override
public double getDouble(final double key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
final ArrayData array = getArray();
if (array.has(index)) {
@@ -2447,7 +2468,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override
public double getDouble(final long key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
final ArrayData array = getArray();
if (array.has(index)) {
@@ -2469,7 +2490,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
}
private Object get(final int index, final String key) {
- if (isValidArrayIndex(index)) {
+ if (ArrayIndex.isValidArrayIndex(index)) {
for (ScriptObject object = this; ; ) {
final FindProperty find = object.findProperty(key, false, false, this);
@@ -2500,7 +2521,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override
public Object get(final Object key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
final ArrayData array = getArray();
if (array.has(index)) {
@@ -2512,7 +2533,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override
public Object get(final double key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
final ArrayData array = getArray();
if (array.has(index)) {
@@ -2524,7 +2545,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override
public Object get(final long key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
final ArrayData array = getArray();
if (array.has(index)) {
@@ -2640,9 +2661,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override
public void set(final Object key, final int value, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
- if (isValidArrayIndex(index)) {
+ if (ArrayIndex.isValidArrayIndex(index)) {
if (getArray().has(index)) {
setArray(getArray().set(index, value, strict));
} else {
@@ -2657,9 +2678,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override
public void set(final Object key, final long value, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
- if (isValidArrayIndex(index)) {
+ if (ArrayIndex.isValidArrayIndex(index)) {
if (getArray().has(index)) {
setArray(getArray().set(index, value, strict));
} else {
@@ -2674,9 +2695,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override
public void set(final Object key, final double value, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
- if (isValidArrayIndex(index)) {
+ if (ArrayIndex.isValidArrayIndex(index)) {
if (getArray().has(index)) {
setArray(getArray().set(index, value, strict));
} else {
@@ -2691,9 +2712,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override
public void set(final Object key, final Object value, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
- if (isValidArrayIndex(index)) {
+ if (ArrayIndex.isValidArrayIndex(index)) {
if (getArray().has(index)) {
setArray(getArray().set(index, value, strict));
} else {
@@ -2711,9 +2732,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override
public void set(final double key, final int value, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
- if (isValidArrayIndex(index)) {
+ if (ArrayIndex.isValidArrayIndex(index)) {
if (getArray().has(index)) {
setArray(getArray().set(index, value, strict));
} else {
@@ -2728,9 +2749,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override
public void set(final double key, final long value, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
- if (isValidArrayIndex(index)) {
+ if (ArrayIndex.isValidArrayIndex(index)) {
if (getArray().has(index)) {
setArray(getArray().set(index, value, strict));
} else {
@@ -2745,9 +2766,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override
public void set(final double key, final double value, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
- if (isValidArrayIndex(index)) {
+ if (ArrayIndex.isValidArrayIndex(index)) {
if (getArray().has(index)) {
setArray(getArray().set(index, value, strict));
} else {
@@ -2762,9 +2783,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override
public void set(final double key, final Object value, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
- if (isValidArrayIndex(index)) {
+ if (ArrayIndex.isValidArrayIndex(index)) {
if (getArray().has(index)) {
setArray(getArray().set(index, value, strict));
} else {
@@ -2779,9 +2800,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override
public void set(final long key, final int value, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
- if (isValidArrayIndex(index)) {
+ if (ArrayIndex.isValidArrayIndex(index)) {
if (getArray().has(index)) {
setArray(getArray().set(index, value, strict));
} else {
@@ -2796,9 +2817,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override
public void set(final long key, final long value, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
- if (isValidArrayIndex(index)) {
+ if (ArrayIndex.isValidArrayIndex(index)) {
if (getArray().has(index)) {
setArray(getArray().set(index, value, strict));
} else {
@@ -2813,9 +2834,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override
public void set(final long key, final double value, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
- if (isValidArrayIndex(index)) {
+ if (ArrayIndex.isValidArrayIndex(index)) {
if (getArray().has(index)) {
setArray(getArray().set(index, value, strict));
} else {
@@ -2830,9 +2851,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override
public void set(final long key, final Object value, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
- if (isValidArrayIndex(index)) {
+ if (ArrayIndex.isValidArrayIndex(index)) {
if (getArray().has(index)) {
setArray(getArray().set(index, value, strict));
} else {
@@ -2847,9 +2868,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override
public void set(final int key, final int value, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
- if (isValidArrayIndex(index)) {
+ if (ArrayIndex.isValidArrayIndex(index)) {
if (getArray().has(index)) {
setArray(getArray().set(index, value, strict));
} else {
@@ -2864,9 +2885,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override
public void set(final int key, final long value, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
- if (isValidArrayIndex(index)) {
+ if (ArrayIndex.isValidArrayIndex(index)) {
if (getArray().has(index)) {
setArray(getArray().set(index, value, strict));
} else {
@@ -2881,9 +2902,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override
public void set(final int key, final double value, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
- if (isValidArrayIndex(index)) {
+ if (ArrayIndex.isValidArrayIndex(index)) {
if (getArray().has(index)) {
setArray(getArray().set(index, value, strict));
} else {
@@ -2898,9 +2919,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override
public void set(final int key, final Object value, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
- if (isValidArrayIndex(index)) {
+ if (ArrayIndex.isValidArrayIndex(index)) {
if (getArray().has(index)) {
setArray(getArray().set(index, value, strict));
} else {
@@ -2915,9 +2936,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override
public boolean has(final Object key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
- if (isValidArrayIndex(index)) {
+ if (ArrayIndex.isValidArrayIndex(index)) {
for (ScriptObject self = this; self != null; self = self.getProto()) {
if (self.getArray().has(index)) {
return true;
@@ -2932,9 +2953,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override
public boolean has(final double key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
- if (isValidArrayIndex(index)) {
+ if (ArrayIndex.isValidArrayIndex(index)) {
for (ScriptObject self = this; self != null; self = self.getProto()) {
if (self.getArray().has(index)) {
return true;
@@ -2949,9 +2970,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override
public boolean has(final long key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
- if (isValidArrayIndex(index)) {
+ if (ArrayIndex.isValidArrayIndex(index)) {
for (ScriptObject self = this; self != null; self = self.getProto()) {
if (self.getArray().has(index)) {
return true;
@@ -2966,9 +2987,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override
public boolean has(final int key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
- if (isValidArrayIndex(index)) {
+ if (ArrayIndex.isValidArrayIndex(index)) {
for (ScriptObject self = this; self != null; self = self.getProto()) {
if (self.getArray().has(index)) {
return true;
@@ -2983,7 +3004,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override
public boolean hasOwnProperty(final Object key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
if (getArray().has(index)) {
return true;
@@ -2996,7 +3017,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override
public boolean hasOwnProperty(final int key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
if (getArray().has(index)) {
return true;
@@ -3009,7 +3030,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override
public boolean hasOwnProperty(final long key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
if (getArray().has(index)) {
return true;
@@ -3022,7 +3043,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override
public boolean hasOwnProperty(final double key) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
if (getArray().has(index)) {
return true;
@@ -3035,7 +3056,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override
public boolean delete(final int key, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
final ArrayData array = getArray();
if (array.has(index)) {
@@ -3051,7 +3072,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override
public boolean delete(final long key, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
final ArrayData array = getArray();
if (array.has(index)) {
@@ -3067,7 +3088,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override
public boolean delete(final double key, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
final ArrayData array = getArray();
if (array.has(index)) {
@@ -3083,7 +3104,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
@Override
public boolean delete(final Object key, final boolean strict) {
- final int index = getArrayIndexNoThrow(key);
+ final int index = ArrayIndex.getArrayIndex(key);
final ArrayData array = getArray();
if (array.has(index)) {
diff --git a/src/jdk/nashorn/internal/runtime/ScriptRuntime.java b/src/jdk/nashorn/internal/runtime/ScriptRuntime.java
index d5ab68b2..f1febc0c 100644
--- a/src/jdk/nashorn/internal/runtime/ScriptRuntime.java
+++ b/src/jdk/nashorn/internal/runtime/ScriptRuntime.java
@@ -825,6 +825,13 @@ public final class ScriptRuntime {
return ((StaticClass)clazz).getRepresentedClass().isInstance(obj);
}
+ if (clazz instanceof ScriptObjectMirror) {
+ if (obj instanceof ScriptObjectMirror) {
+ return ((ScriptObjectMirror)clazz).isInstance((ScriptObjectMirror)obj);
+ }
+ return false;
+ }
+
throw typeError("instanceof.on.non.object");
}
diff --git a/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java b/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java
index ee1639d0..6bd0479f 100644
--- a/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java
+++ b/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java
@@ -221,10 +221,9 @@ public final class ScriptingFunctions {
final String err = errBuffer.toString();
// Set globals for secondary results.
- final boolean isStrict = global.isStrictContext();
- global.set(OUT_NAME, out, isStrict);
- global.set(ERR_NAME, err, isStrict);
- global.set(EXIT_NAME, exit, isStrict);
+ global.set(OUT_NAME, out, false);
+ global.set(ERR_NAME, err, false);
+ global.set(EXIT_NAME, exit, false);
// Propagate exception if present.
for (int i = 0; i < exception.length; i++) {
diff --git a/src/jdk/nashorn/internal/runtime/Source.java b/src/jdk/nashorn/internal/runtime/Source.java
index 24c041a8..b5033e95 100644
--- a/src/jdk/nashorn/internal/runtime/Source.java
+++ b/src/jdk/nashorn/internal/runtime/Source.java
@@ -116,7 +116,20 @@ public final class Source {
* @throws IOException if source cannot be loaded
*/
public Source(final String name, final URL url) throws IOException {
- this(name, baseURL(url, null), readFully(url.openStream()), url);
+ this(name, baseURL(url, null), readFully(url), url);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param name source name
+ * @param url url from which source can be loaded
+ * @param cs Charset used to convert bytes to chars
+ *
+ * @throws IOException if source cannot be loaded
+ */
+ public Source(final String name, final URL url, final Charset cs) throws IOException {
+ this(name, baseURL(url, null), readFully(url, cs), url);
}
/**
@@ -131,6 +144,19 @@ public final class Source {
this(name, dirName(file, null), readFully(file), getURLFromFile(file));
}
+ /**
+ * Constructor
+ *
+ * @param name source name
+ * @param file file from which source can be loaded
+ * @param cs Charset used to convert bytes to chars
+ *
+ * @throws IOException if source cannot be loaded
+ */
+ public Source(final String name, final File file, final Charset cs) throws IOException {
+ this(name, dirName(file, null), readFully(file, cs), getURLFromFile(file));
+ }
+
@Override
public boolean equals(final Object obj) {
if (this == obj) {
@@ -344,6 +370,53 @@ public final class Source {
}
/**
+ * Read all of the source until end of file. Return it as char array
+ *
+ * @param file source file
+ * @param cs Charset used to convert bytes to chars
+ * @return source as content
+ *
+ * @throws IOException if source could not be read
+ */
+ public static char[] readFully(final File file, final Charset cs) throws IOException {
+ if (!file.isFile()) {
+ throw new IOException(file + " is not a file"); //TODO localize?
+ }
+
+ final byte[] buf = Files.readAllBytes(file.toPath());
+ if (cs != null) {
+ return new String(buf, cs).toCharArray();
+ } else {
+ return byteToCharArray(buf);
+ }
+ }
+
+ /**
+ * Read all of the source until end of stream from the given URL. Return it as char array
+ *
+ * @param url URL to read content from
+ * @return source as content
+ *
+ * @throws IOException if source could not be read
+ */
+ public static char[] readFully(final URL url) throws IOException {
+ return readFully(url.openStream());
+ }
+
+ /**
+ * Read all of the source until end of file. Return it as char array
+ *
+ * @param url URL to read content from
+ * @param cs Charset used to convert bytes to chars
+ * @return source as content
+ *
+ * @throws IOException if source could not be read
+ */
+ public static char[] readFully(final URL url, final Charset cs) throws IOException {
+ return readFully(url.openStream(), cs);
+ }
+
+ /**
* Get the base url. This is currently used for testing only
* @param url a URL
* @return base URL for url
@@ -391,6 +464,14 @@ public final class Source {
return (idx != -1)? name.substring(0, idx + 1) : defaultValue;
}
+ private static char[] readFully(final InputStream is, final Charset cs) throws IOException {
+ if (cs != null) {
+ return new String(readBytes(is), cs).toCharArray();
+ } else {
+ return readFully(is);
+ }
+ }
+
private static char[] readFully(final InputStream is) throws IOException {
return byteToCharArray(readBytes(is));
}
diff --git a/src/jdk/nashorn/internal/runtime/arrays/ArrayIndex.java b/src/jdk/nashorn/internal/runtime/arrays/ArrayIndex.java
index 531c56b5..f59229c4 100644
--- a/src/jdk/nashorn/internal/runtime/arrays/ArrayIndex.java
+++ b/src/jdk/nashorn/internal/runtime/arrays/ArrayIndex.java
@@ -44,7 +44,7 @@ public final class ArrayIndex {
/**
* Fast conversion of non-negative integer string to long.
* @param key Key as a string.
- * @return long value of string or -1.
+ * @return long value of string or {@code -1} if string does not represent a valid index.
*/
private static long fromString(final String key) {
long value = 0;
@@ -52,7 +52,7 @@ public final class ArrayIndex {
// Check for empty string or leading 0
if (length == 0 || (length > 1 && key.charAt(0) == '0')) {
- return -1;
+ return INVALID_ARRAY_INDEX;
}
// Fast toNumber.
@@ -61,7 +61,7 @@ public final class ArrayIndex {
// If not a digit.
if (digit < '0' || digit > '9') {
- return -1;
+ return INVALID_ARRAY_INDEX;
}
// Insert digit.
@@ -69,7 +69,7 @@ public final class ArrayIndex {
// Check for overflow (need to catch before wrap around.)
if (value > MAX_ARRAY_INDEX) {
- return -1;
+ return INVALID_ARRAY_INDEX;
}
}
@@ -81,137 +81,79 @@ public final class ArrayIndex {
* routine needs to perform quickly since all keys are tested with it.
*
* @param key key to check for array index
- * @return valid array index, or negative value if not valid
+ * @return the array index, or {@code -1} if {@code key} does not represent a valid index.
+ * Note that negative return values other than {@code -1} are considered valid and can be converted to
+ * the actual index using {@link #toLongIndex(int)}.
*/
- public static int getArrayIndexNoThrow(final Object key) {
+ public static int getArrayIndex(final Object key) {
if (key instanceof Integer) {
- return getArrayIndexNoThrow(((Integer)key).intValue());
+ return getArrayIndex(((Integer) key).intValue());
} else if (key instanceof Number) {
- return getArrayIndexNoThrow(((Number)key).doubleValue());
+ return getArrayIndex(((Number) key).doubleValue());
} else if (key instanceof String) {
- return (int)fromString((String)key);
+ return (int)fromString((String) key);
} else if (key instanceof ConsString) {
return (int)fromString(key.toString());
}
- return -1;
+ return INVALID_ARRAY_INDEX;
}
/**
- * Returns a valid array index in an int, if the object represents one
+ * Returns a valid array index in an int, if the long represents one.
*
* @param key key to check
- * @return array index for key
- * @throws InvalidArrayIndexException if not a valid array index key
+ * @return the array index, or {@code -1} if long is not a valid array index.
+ * Note that negative return values other than {@code -1} are considered valid and can be converted to
+ * the actual index using {@link #toLongIndex(int)}.
*/
- public static int getArrayIndex(final Object key) throws InvalidArrayIndexException {
- final int index = getArrayIndexNoThrow(key);
- if (index != -1) {
- return index;
- }
-
- throw new InvalidArrayIndexException(key);
- }
-
- /**
- * Returns a valid array index in an int, if the long represents one
- *
- * @param key key to check
- * @return valid index or a negative value if long is not a valid array index
- */
- public static int getArrayIndexNoThrow(final long key) {
+ public static int getArrayIndex(final long key) {
if (key >= 0 && key <= MAX_ARRAY_INDEX) {
return (int)key;
}
- return -1;
- }
-
- /**
- * Returns a valid array index in an int, if the long represents one
- *
- * @param key key to check
- * @return valid index for the long
- * @throws InvalidArrayIndexException if long is not a valid array index
- */
- public static int getArrayIndex(final long key) throws InvalidArrayIndexException {
- final int index = getArrayIndexNoThrow(key);
- if (index != -1) {
- return index;
- }
-
- throw new InvalidArrayIndexException(key);
+ return INVALID_ARRAY_INDEX;
}
/**
- * Return a valid index for this double, if it represents one
+ * Return a valid index for this double, if it represents one.
*
* Doubles that aren't representable exactly as longs/ints aren't working
* array indexes, however, array[1.1] === array["1.1"] in JavaScript.
*
* @param key the key to check
- * @return the array index this double represents or a negative value if this isn't an index
+ * @return the array index this double represents or {@code -1} if this isn't a valid index.
+ * Note that negative return values other than {@code -1} are considered valid and can be converted to
+ * the actual index using {@link #toLongIndex(int)}.
*/
- public static int getArrayIndexNoThrow(final double key) {
+ public static int getArrayIndex(final double key) {
if (JSType.isRepresentableAsInt(key)) {
final int intKey = (int)key;
if (intKey >= 0) {
return intKey;
}
} else if (JSType.isRepresentableAsLong(key)) {
- return getArrayIndexNoThrow((long)key);
+ return getArrayIndex((long) key);
}
- return -1;
+ return INVALID_ARRAY_INDEX;
}
- /**
- * Return a valid array index for this double, if it represents one
- *
- * Doubles that aren't representable exactly as longs/ints aren't working
- * array indexes, however, array[1.1] === array["1.1"] in JavaScript.
- *
- * @param key the key to check
- * @return the array index this double represents
- * @throws InvalidArrayIndexException if this isn't an array index
- */
- public static int getArrayIndex(final double key) throws InvalidArrayIndexException {
- final int index = getArrayIndexNoThrow(key);
- if (index != -1) {
- return index;
- }
-
- throw new InvalidArrayIndexException(key);
- }
/**
- * Return a valid array index for this string, if it represents one
+ * Return a valid array index for this string, if it represents one.
*
* @param key the key to check
- * @return the array index this string represents or a negative value if this isn't an index
+ * @return the array index this string represents or {@code -1} if this isn't a valid index.
+ * Note that negative return values other than {@code -1} are considered valid and can be converted to
+ * the actual index using {@link #toLongIndex(int)}.
*/
- public static int getArrayIndexNoThrow(final String key) {
+ public static int getArrayIndex(final String key) {
return (int)fromString(key);
}
/**
- * Return a valid array index for this string, if it represents one
- *
- * @param key the key to check
- * @return the array index this string represents
- * @throws InvalidArrayIndexException if the string isn't an array index
- */
- public static int getArrayIndex(final String key) throws InvalidArrayIndexException {
- final int index = getArrayIndexNoThrow(key);
- if (index != -1) {
- return index;
- }
-
- throw new InvalidArrayIndexException(key);
- }
-
- /**
* Check whether an index is valid as an array index. This check only tests if
* it is the special "invalid array index" type, not if it is e.g. less than zero
* or corrupt in some other way
@@ -226,7 +168,7 @@ public final class ArrayIndex {
/**
* Convert an index to a long value. This basically amounts to ANDing it
* with {@link JSType#MAX_UINT}, as the maximum array index in JavaScript
- * is 0xffffffff
+ * is 0xfffffffe
*
* @param index index to convert to long form
* @return index as uint32 in a long
@@ -236,14 +178,14 @@ public final class ArrayIndex {
}
/**
- * Check whether a key string can be used as a valid numeric array index in
- * JavaScript
+ * Check whether a key string represents a valid array index in JavaScript and is small enough
+ * to fit into a positive int.
*
* @param key the key
- * @return true if key works as a valid numeric array index
+ * @return true if key works as a valid int array index
*/
- public static boolean isIndexKey(final String key) {
- return ArrayIndex.getArrayIndexNoThrow(key) >= 0;
+ public static boolean isIntArrayIndex(final String key) {
+ return getArrayIndex(key) >= 0;
}
}
diff --git a/src/jdk/nashorn/internal/runtime/arrays/ArrayIterator.java b/src/jdk/nashorn/internal/runtime/arrays/ArrayIterator.java
index e250c748..71d4d152 100644
--- a/src/jdk/nashorn/internal/runtime/arrays/ArrayIterator.java
+++ b/src/jdk/nashorn/internal/runtime/arrays/ArrayIterator.java
@@ -83,6 +83,6 @@ public class ArrayIterator extends ArrayLikeIterator<Object> {
@Override
public void remove() {
- array.delete(index, array.isStrictContext());
+ array.delete(index, false);
}
}
diff --git a/src/jdk/nashorn/internal/runtime/arrays/ArrayLikeIterator.java b/src/jdk/nashorn/internal/runtime/arrays/ArrayLikeIterator.java
index 48505f44..70f74d8e 100644
--- a/src/jdk/nashorn/internal/runtime/arrays/ArrayLikeIterator.java
+++ b/src/jdk/nashorn/internal/runtime/arrays/ArrayLikeIterator.java
@@ -26,6 +26,7 @@
package jdk.nashorn.internal.runtime.arrays;
import java.util.Iterator;
+import jdk.nashorn.api.scripting.ScriptObjectMirror;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.ScriptObject;
@@ -125,6 +126,10 @@ abstract public class ArrayLikeIterator<T> implements Iterator<T> {
return new MapIterator((ScriptObject)obj, includeUndefined);
}
+ if (obj instanceof ScriptObjectMirror) {
+ return new ScriptObjectMirrorIterator((ScriptObjectMirror)obj, includeUndefined);
+ }
+
return new EmptyArrayLikeIterator();
}
@@ -146,6 +151,10 @@ abstract public class ArrayLikeIterator<T> implements Iterator<T> {
return new ReverseMapIterator((ScriptObject)obj, includeUndefined);
}
+ if (obj instanceof ScriptObjectMirror) {
+ return new ReverseScriptObjectMirrorIterator((ScriptObjectMirror)obj, includeUndefined);
+ }
+
assert !obj.getClass().isArray();
return new EmptyArrayLikeIterator();
diff --git a/src/jdk/nashorn/internal/runtime/arrays/IteratorAction.java b/src/jdk/nashorn/internal/runtime/arrays/IteratorAction.java
index 7568f41b..91b20e5d 100644
--- a/src/jdk/nashorn/internal/runtime/arrays/IteratorAction.java
+++ b/src/jdk/nashorn/internal/runtime/arrays/IteratorAction.java
@@ -27,6 +27,7 @@ package jdk.nashorn.internal.runtime.arrays;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
+import jdk.nashorn.api.scripting.ScriptObjectMirror;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptRuntime;
@@ -96,12 +97,18 @@ public abstract class IteratorAction<T> {
* @return result of apply
*/
public final T apply() {
- if (!(callbackfn instanceof ScriptFunction)) {
+ final boolean strict;
+ if (callbackfn instanceof ScriptFunction) {
+ strict = ((ScriptFunction)callbackfn).isStrict();
+ } else if (callbackfn instanceof ScriptObjectMirror &&
+ ((ScriptObjectMirror)callbackfn).isFunction()) {
+ strict = ((ScriptObjectMirror)callbackfn).isStrictFunction();
+ } else {
throw typeError("not.a.function", ScriptRuntime.safeToString(callbackfn));
}
- final ScriptFunction func = ((ScriptFunction)callbackfn);
+
// for non-strict callback, need to translate undefined thisArg to be global object
- thisArg = (thisArg == ScriptRuntime.UNDEFINED && !func.isStrict()) ? Context.getGlobal() : thisArg;
+ thisArg = (thisArg == ScriptRuntime.UNDEFINED && !strict)? Context.getGlobal() : thisArg;
applyLoopBegin(iter);
final boolean reverse = iter.isReverse();
diff --git a/src/jdk/nashorn/internal/runtime/arrays/ReverseScriptObjectMirrorIterator.java b/src/jdk/nashorn/internal/runtime/arrays/ReverseScriptObjectMirrorIterator.java
new file mode 100644
index 00000000..1e3e4000
--- /dev/null
+++ b/src/jdk/nashorn/internal/runtime/arrays/ReverseScriptObjectMirrorIterator.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.runtime.arrays;
+
+import jdk.nashorn.api.scripting.ScriptObjectMirror;
+import jdk.nashorn.internal.runtime.JSType;
+
+/**
+ * Reverse iterator over a ScriptObjectMirror
+ */
+final class ReverseScriptObjectMirrorIterator extends ScriptObjectMirrorIterator {
+
+ ReverseScriptObjectMirrorIterator(final ScriptObjectMirror obj, final boolean includeUndefined) {
+ super(obj, includeUndefined);
+ this.index = JSType.toUint32(obj.containsKey("length")? obj.getMember("length") : 0) - 1;
+ }
+
+ @Override
+ public boolean isReverse() {
+ return true;
+ }
+
+ @Override
+ protected boolean indexInArray() {
+ return index >= 0;
+ }
+
+ @Override
+ protected long bumpIndex() {
+ return index--;
+ }
+}
+
diff --git a/src/jdk/nashorn/internal/runtime/arrays/ScriptObjectMirrorIterator.java b/src/jdk/nashorn/internal/runtime/arrays/ScriptObjectMirrorIterator.java
new file mode 100644
index 00000000..a7bef158
--- /dev/null
+++ b/src/jdk/nashorn/internal/runtime/arrays/ScriptObjectMirrorIterator.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.runtime.arrays;
+
+import java.util.NoSuchElementException;
+import jdk.nashorn.api.scripting.ScriptObjectMirror;
+import jdk.nashorn.internal.runtime.JSType;
+
+/**
+ * Iterator over a ScriptObjectMirror
+ */
+class ScriptObjectMirrorIterator extends ArrayLikeIterator<Object> {
+
+ protected final ScriptObjectMirror obj;
+ private final long length;
+
+ ScriptObjectMirrorIterator(final ScriptObjectMirror obj, final boolean includeUndefined) {
+ super(includeUndefined);
+ this.obj = obj;
+ this.length = JSType.toUint32(obj.containsKey("length")? obj.getMember("length") : 0);
+ this.index = 0;
+ }
+
+ protected boolean indexInArray() {
+ return index < length;
+ }
+
+ @Override
+ public long getLength() {
+ return length;
+ }
+
+ @Override
+ public boolean hasNext() {
+ if (length == 0L) {
+ return false; //return empty string if toUint32(length) == 0
+ }
+
+ while (indexInArray()) {
+ if (obj.containsKey(index) || includeUndefined) {
+ break;
+ }
+ bumpIndex();
+ }
+
+ return indexInArray();
+ }
+
+ @Override
+ public Object next() {
+ if (indexInArray()) {
+ return obj.get(bumpIndex());
+ }
+
+ throw new NoSuchElementException();
+ }
+}
+
diff --git a/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java b/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java
index 04ac661f..fd52f22d 100644
--- a/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java
+++ b/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java
@@ -61,13 +61,15 @@ class SparseArrayData extends ArrayData {
@Override
public Object[] asObjectArray() {
- final Object[] objArray = new Object[Math.min((int) length(), Integer.MAX_VALUE)];
+ final int length = (int) Math.min(length(), Integer.MAX_VALUE);
+ final int underlyingLength = (int) Math.min(length, underlying.length());
+ final Object[] objArray = new Object[length];
- for (int i = 0; i < underlying.length(); i++) {
+ for (int i = 0; i < underlyingLength; i++) {
objArray[i] = underlying.getObject(i);
}
- Arrays.fill(objArray, (int) underlying.length(), objArray.length, ScriptRuntime.UNDEFINED);
+ Arrays.fill(objArray, underlyingLength, length, ScriptRuntime.UNDEFINED);
for (final Map.Entry<Long, Object> entry : sparseMap.entrySet()) {
final long key = entry.getKey();
diff --git a/src/jdk/nashorn/internal/runtime/resources/Messages.properties b/src/jdk/nashorn/internal/runtime/resources/Messages.properties
index b8d9e5e3..f058fa33 100644
--- a/src/jdk/nashorn/internal/runtime/resources/Messages.properties
+++ b/src/jdk/nashorn/internal/runtime/resources/Messages.properties
@@ -25,9 +25,11 @@
lexer.error.edit.string.missing.brace=Edit string expression missing closing brace
lexer.error.here.missing.end.marker=Here string missing end marker "{0}"
lexer.error.missing.close.quote=Missing close quote
+lexer.error.missing.space.after.number=Missing space after numeric literal
lexer.error.invalid.hex=Invalid hex digit
-lexer.error.invalid.octal=Invalid octal digit
lexer.error.strict.no.octal=cannot use octal escapes in strict mode
+lexer.error.json.invalid.number=Invalid JSON number format
+lexer.error.invalid.escape.char=Invalid escape character
lexer.error.illegal.identifier.character=Illegal character in identifier
parser.error.illegal.continue.stmt=Illegal continue statement
@@ -127,6 +129,7 @@ type.error.method.not.constructor=Java method {0} can't be used as a constructor
type.error.env.not.object=$ENV must be an Object.
type.error.unsupported.java.to.type=Unsupported Java.to target type {0}.
range.error.inappropriate.array.length=inappropriate array length: {0}
+range.error.inappropriate.array.buffer.length=inappropriate array buffer length: {0}
range.error.invalid.fraction.digits=fractionDigits argument to {0} must be in [0, 20]
range.error.invalid.precision=precision argument toPrecision() must be in [1, 21]
range.error.invalid.radix=radix argument must be in [2, 36]
diff --git a/src/jdk/nashorn/internal/runtime/resources/Options.properties b/src/jdk/nashorn/internal/runtime/resources/Options.properties
index 4dd6df6f..4d7be62b 100644
--- a/src/jdk/nashorn/internal/runtime/resources/Options.properties
+++ b/src/jdk/nashorn/internal/runtime/resources/Options.properties
@@ -59,7 +59,7 @@ nashorn.options.D.key = nashorn.option.D
## is_undocumented - should this option never appear in the online help. defaults to no.
## desc - description of what the option does
## default - default value of the option. e.g. debug.lines is true by default. Not set means option not available by default
-## dependency - does this arg imply another arg, e.g. scripting -> anon-functions
+## dependency - does this arg imply another arg.
## confict - does this arg conflict with another arg e.g trace && instrument
## value_next_arg - is the opton's value passed as next argument in command line?
##
@@ -77,16 +77,9 @@ nashorn.option.xhelp = { \
desc="Print extended help for command line flags." \
}
-nashorn.option.anon.functions = { \
- name="--anon-functions", \
- short_name="-af", \
- is_undocumented=true, \
- desc="Always allow functions as statements." \
-}
-
nashorn.option.class.cache.size ={ \
name="--class-cache-size", \
- short_name="--ccs", \
+ short_name="-ccs", \
desc="Size of the Class cache size per global scope.", \
is_undocumented=true, \
type=Integer, \
@@ -201,10 +194,10 @@ nashorn.option.loader.per.compile = { \
nashorn.option.no.syntax.extensions = { \
name="--no-syntax-extensions", \
- short_name="--nse", \
+ short_name="-nse", \
is_undocumented=true, \
desc="No non-standard syntax extensions", \
- default=-anon-functions=false \
+ default=false \
}
nashorn.option.package = { \
@@ -296,8 +289,7 @@ nashorn.option.strict = { \
nashorn.option.scripting = { \
name="-scripting", \
- desc="Enable scripting features.", \
- dependency="--anon-functions=true" \
+ desc="Enable scripting features." \
}
nashorn.option.specialize.calls = { \