This commit is contained in:
Athijegannathan Sundararajan 2013-06-18 13:25:24 +05:30
commit 70cc4e755b
59 changed files with 9485 additions and 275 deletions

View File

@ -193,7 +193,8 @@ test262-test-sys-prop.test.js.enable.strict.mode=true
# list of test262 test dirs to be excluded
test262-test-sys-prop.test.js.exclude.dir=\
${test262.suite.dir}/intl402/
${test262.suite.dir}/intl402/ \
${test262.suite.dir}/bestPractice/
test262-test-sys-prop.test.failed.list.file=${build.dir}/test/failedTests

View File

@ -1,21 +1,21 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
@ -30,3 +30,4 @@
*/
print("Hello World");

View File

@ -72,7 +72,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);

View File

@ -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.

View File

@ -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);
}
@ -320,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;
@ -334,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)));
}
@ -543,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();
}
@ -572,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.
@ -584,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;
@ -1700,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() {

View File

@ -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
*/

View File

@ -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;
@ -416,6 +418,14 @@ public final class Symbol implements Comparable<Symbol> {
return (flags & KINDMASK) == IS_PARAM;
}
/**
* 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 (!isParam() && !canBeUndefined()) {//parameters are never undefined
if (isAlwaysDefined()) {
return;
} else if (!canBeUndefined()) {
assert !isShared();
flags |= CAN_BE_UNDEFINED;
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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, 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,17 +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 args (optional) arguments to be passed to the loaded script
* @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, final Object...args) throws IOException {
public static Object loadWithNewGlobal(final Object self, final Object...args) throws IOException {
final Global global = Global.instance();
return global.context.loadWithNewGlobal(source, args);
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);
}
/**
@ -1480,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);
@ -1498,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);
@ -1514,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;
}
@ -1725,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

View File

@ -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);
@ -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;
}
@ -833,7 +836,6 @@ 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();
@ -850,7 +852,7 @@ public final class NativeArray extends ScriptObject {
final Object[] sorted = sort(src.toArray(), comparefn);
for (int i = 0; i < sorted.length; i++) {
array = array.set(i, sorted[i], strict);
array = array.set(i, sorted[i], true);
}
// delete missing elements - which are at the end of sorted array
@ -891,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);
@ -914,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--) {
@ -930,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;
}
@ -964,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) {
@ -975,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--) {
@ -984,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;
}
@ -1239,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) {

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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) {

View File

@ -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);
}

View File

@ -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;

View File

@ -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);
}
}
/**

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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) {

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -149,9 +149,9 @@ public class JSONParser extends AbstractParser {
@Override
protected void scanNumber() {
// Record beginning of number.
final int start = position;
final int startPosition = position;
// Assume value is a decimal.
TokenType type = TokenType.DECIMAL;
TokenType valueType = TokenType.DECIMAL;
// floating point can't start with a "." with no leading digit before
if (ch0 == '.') {
@ -211,11 +211,11 @@ public class JSONParser extends AbstractParser {
}
}
type = TokenType.FLOATING;
valueType = TokenType.FLOATING;
}
// Add number token.
add(type, start);
add(valueType, startPosition);
}
// ECMA 15.12.1.1 The JSON Lexical Grammar - JSONEscapeCharacter

View File

@ -666,43 +666,54 @@ 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);
}
return value;
}
/**
* 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.
*
@ -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,6 +919,7 @@ 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
*/
protected void scanString(final boolean add) {
// Type of string.
@ -1103,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);
}
@ -1191,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);
@ -1204,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);
@ -1596,6 +1615,12 @@ public class Lexer extends Scanner {
return null;
}
/**
* 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);
}

View File

@ -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);
}
}

View File

@ -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) {

View File

@ -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));
}
}

View File

@ -101,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()) {
@ -109,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);
}
}
}
@ -164,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;

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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");

View File

@ -105,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;
@ -443,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) {
@ -998,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);
}
/**
@ -1105,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.
*/
@ -1206,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;
@ -1277,20 +1281,36 @@ 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);
}
flags |= IS_PROTOTYPE;
}
/**
* 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
@ -1363,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();
@ -1393,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);
@ -1481,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;
}
@ -1493,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);
}
@ -1508,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;
}
@ -1520,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());
}
/**
@ -2222,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));

View File

@ -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");
}

View File

@ -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++) {

View File

@ -83,6 +83,6 @@ public class ArrayIterator extends ArrayLikeIterator<Object> {
@Override
public void remove() {
array.delete(index, array.isStrictContext());
array.delete(index, false);
}
}

View File

@ -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();

View File

@ -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();

View File

@ -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--;
}
}

View File

@ -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();
}
}

View File

@ -25,8 +25,8 @@
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

View File

@ -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 = { \

View File

@ -0,0 +1,51 @@
/*
* 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.
*
* 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.
*/
/**
* JDK-8011893: JS Object builtin prototype is not thread safe
*
* @test
* @run
*/
var a = {};
var thread = new java.lang.Thread(new java.lang.Runnable() {
run: function() {
print("Thread starts");
for (var i = 0; i < 1000000; i++) {
// Unsubscribe to builtin, subscribe to new proto
var b = Object.create(a);
}
print("Thread done");
}
});
print("Main starts");
thread.start();
for (var j = 0; j < 1000000; j++) {
// Subscribe to builtin prototype.
a = {};
}
thread.join();
print("Main done");

View File

@ -0,0 +1,4 @@
Main starts
Thread starts
Thread done
Main done

View File

@ -0,0 +1,122 @@
/*
* 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.
*
* 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.
*/
/**
* JDK-8015355: Array.prototype functions don't honour non-writable length and / or index properties
*
* @test
* @run
*/
function fail(msg) {
print(msg);
}
function check(callback) {
try {
callback();
fail("TypeError expected for " + callback);
} catch (e) {
if (! (e instanceof TypeError)) {
fail("TypeError expected, got " + e);
}
}
}
var array = Object.defineProperty([],"length", { writable: false });
check(function() {
array.push(0)
});
check(function() {
array.pop()
});
check(function() {
Object.defineProperty([,,],"0",{ writable: false }).reverse();
});
check(function() {
array.shift()
});
check(function() {
array.splice(0)
});
check(function() {
array.unshift()
});
// try the above via call
check(function() {
Array.prototype.push.call(array, 0);
});
check(function() {
Array.prototype.pop.call(array);
});
check(function() {
Array.prototype.shift.call(array);
});
check(function() {
Array.prototype.unshift.call(array);
});
check(function() {
Array.prototype.splice.call(array, 0);
});
check(function() {
Array.prototype.reverse.call(Object.defineProperty([,,],"0",{ writable: false }));
});
// try the above via apply
check(function() {
Array.prototype.push.apply(array, [ 0 ]);
});
check(function() {
Array.prototype.pop.apply(array);
});
check(function() {
Array.prototype.shift.apply(array);
});
check(function() {
Array.prototype.unshift.apply(array);
});
check(function() {
Array.prototype.splice.apply(array, [ 0 ]);
});
check(function() {
Array.prototype.reverse.apply(Object.defineProperty([,,],"0",{ writable: false }));
});

View File

@ -0,0 +1,51 @@
/*
* 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.
*
* 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.
*/
/**
* JDK-8016235 : use before definition in catch block generated erroneous bytecode
* as there is no guarantee anything in the try block has executed.
*
* @test
* @run
*/
function f() {
try {
var parser = {};
} catch (e) {
parser = parser.context();
}
}
function g() {
try {
return "apa";
} catch (tmp) {
//for now, too conservative as var ex declaration exists on the function
//level, but at least the code does not break, and the analysis is driven
//from the catch block (the rare case), not the try block (the common case)
var ex = new Error("DOM Exception 5");
ex.code = ex.number = 5;
return ex;
}
}

View File

@ -0,0 +1,38 @@
/*
* 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.
*
* 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.
*/
/**
* JDK-8016518: Parsing of octal string escapes is broken
*
* @test
* @run
*/
print("\471".charCodeAt(0));
print("\471".charCodeAt(1));
print("\377".length);
print("\377".charCodeAt(0));
print("\400".length);
print("\400".charCodeAt(0));
print("\400".charCodeAt(1));

View File

@ -0,0 +1,7 @@
39
49
1
255
2
32
48

View File

@ -0,0 +1,33 @@
/*
* 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.
*
* 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.
*/
/**
* JDK-8016528: Hex code from escape() should be padded
*
* @test
* @run
*/
for (var i = 0; i < 8192; i++) {
print(escape(String.fromCharCode(i)));
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,37 @@
/*
* 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.
*
* 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.
*/
/**
* JDK-8016542: String.prototype.replace called with function argument should not replace $ patterns
*
* @test
* @run
*/
print("abc".replace("a", "$&"));
print("abc".replace("b", "$&"));
print("abc".replace("c", "$&"));
print("abc".replace("a", function(){return "$&"}));
print("abc".replace("b", function(){return "$&"}));
print("abc".replace("c", function(){return "$&"}));

View File

@ -0,0 +1,6 @@
abc
abc
abc
$&bc
a$&c
ab$&

View File

@ -0,0 +1,132 @@
/*
* 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.
*
* 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.
*/
/**
* JDK-8016618: script mirror object access should be improved
*
* @test
* @option -scripting
* @option -strict
* @run
*/
var global = loadWithNewGlobal({
name: "code",
script: <<EOF
var x = 33;
function func(x, y) {
print('func.x = ' + x);
print('func.x = ' + y)
};
var obj = {
foo: 'hello',
bar: 42
};
Object.defineProperty(obj, "bar",
{ enumerable: false, writable: false });
// return global
this;
EOF
});
// load on mirror with local object as argument
global.load({
name: "code",
script: "print('x = ' + x)"
});
function f() {
// mirror function called with local arguments
global.func.apply(obj, arguments);
}
f(23, "hello");
var fObject = global.eval("Object");
// instanceof on mirrors
print("global instanceof fObject? " + (global instanceof fObject));
// Object API on mirrors
var desc = Object.getOwnPropertyDescriptor(global, "x");
print("x is wriable ? " + desc.writable);
print("x value = " + desc.value);
var proto = Object.getPrototypeOf(global);
print("global's __proto__ " + proto);
var obj = global.obj;
var keys = Object.keys(obj);
print("Object.keys on obj");
for (var i in keys) {
print(keys[i]);
}
print("Object.getOwnProperties on obj");
var keys = Object.getOwnPropertyNames(obj);
for (var i in keys) {
print(keys[i]);
}
// mirror array access
var array = global.eval("[334, 55, 65]");
Array.prototype.forEach.call(array, function(elem) {
print("forEach " + elem)
});
print("reduceRight " + Array.prototype.reduceRight.call(array,
function(previousValue, currentValue, index, array) {
print("reduceRight cur value " + currentValue);
return previousValue + currentValue;
}, 0));
print("reduce " + Array.prototype.reduce.call(array,
function(previousValue, currentValue, index, array) {
print("reduce cur value " + currentValue);
return previousValue + currentValue;
}, 0));
print("forEach");
Array.prototype.forEach.call(array, function(o) {
print(o);
});
print("Array.isArray(array)? " + Array.isArray(array));
// try to write to a non-writable property of mirror
try {
obj.bar = 33;
} catch (e) {
print(e);
}
// mirror function called with local callback
print("forEach on mirror");
array.forEach(function(toto) {
print(toto);
});

View File

@ -0,0 +1,33 @@
x = 33
func.x = 23
func.x = hello
global instanceof fObject? true
x is wriable ? true
x value = 33
global's __proto__ [object Object]
Object.keys on obj
foo
Object.getOwnProperties on obj
foo
bar
forEach 334
forEach 55
forEach 65
reduceRight cur value 65
reduceRight cur value 55
reduceRight cur value 334
reduceRight 454
reduce cur value 334
reduce cur value 55
reduce cur value 65
reduce 454
forEach
334
55
65
Array.isArray(array)? true
TypeError: "bar" is not a writable property of [object Object]
forEach on mirror
334
55
65

View File

@ -25,7 +25,6 @@
* This loads "module.js" and calls the anonymous top-level function from it.
*
* @test
* @option --anon-functions
* @run
*/

View File

@ -0,0 +1,30 @@
/*
* 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.
*
* 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.
*/
/**
* JDK-8016522: Numeric literal must not be followed by IdentifierStart
*
* @test/compile-error
*/
3in {};

View File

@ -0,0 +1,3 @@
test/script/error/JDK-8016522.js:30:1 Missing space after numeric literal
3in {};
^