This commit is contained in:
Athijegannathan Sundararajan 2013-06-05 13:33:33 +05:30
commit 424252851f
32 changed files with 829 additions and 177 deletions

View File

@ -31,7 +31,7 @@ import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@ -48,7 +48,7 @@ import jdk.nashorn.internal.runtime.ScriptRuntime;
* access ScriptObject via the javax.script.Bindings interface or
* netscape.javascript.JSObject interface.
*/
final class ScriptObjectMirror extends JSObject implements Bindings {
public final class ScriptObjectMirror extends JSObject implements Bindings {
private final ScriptObject sobj;
private final ScriptObject global;
@ -217,7 +217,7 @@ final class ScriptObjectMirror extends JSObject implements Bindings {
return inGlobal(new Callable<Set<Map.Entry<String, Object>>>() {
@Override public Set<Map.Entry<String, Object>> call() {
final Iterator<String> iter = sobj.propertyIterator();
final Set<Map.Entry<String, Object>> entries = new HashSet<>();
final Set<Map.Entry<String, Object>> entries = new LinkedHashSet<>();
while (iter.hasNext()) {
final String key = iter.next();
@ -253,7 +253,7 @@ final class ScriptObjectMirror extends JSObject implements Bindings {
return inGlobal(new Callable<Set<String>>() {
@Override public Set<String> call() {
final Iterator<String> iter = sobj.propertyIterator();
final Set<String> keySet = new HashSet<>();
final Set<String> keySet = new LinkedHashSet<>();
while (iter.hasNext()) {
keySet.add(iter.next());
@ -302,6 +302,21 @@ final class ScriptObjectMirror extends JSObject implements Bindings {
});
}
/**
* Delete a property from this object.
*
* @param key the property to be deleted
*
* @return if the delete was successful or not
*/
public boolean delete(final Object key) {
return inGlobal(new Callable<Boolean>() {
@Override public Boolean call() {
return sobj.delete(unwrap(key, global));
}
});
}
@Override
public int size() {
return inGlobal(new Callable<Integer>() {
@ -327,20 +342,28 @@ final class ScriptObjectMirror extends JSObject implements Bindings {
});
}
// package-privates below this.
ScriptObject getScriptObject() {
return sobj;
}
static Object translateUndefined(Object obj) {
return (obj == ScriptRuntime.UNDEFINED)? null : obj;
}
// These are public only so that Context can access these.
static Object wrap(final Object obj, final ScriptObject homeGlobal) {
/**
* Make a script object mirror on given object if needed.
*
* @param obj object to be wrapped
* @param homeGlobal global to which this object belongs
* @return wrapped object
*/
public static Object wrap(final Object obj, final ScriptObject homeGlobal) {
return (obj instanceof ScriptObject) ? new ScriptObjectMirror((ScriptObject)obj, homeGlobal) : obj;
}
static Object unwrap(final Object obj, final ScriptObject homeGlobal) {
/**
* Unwrap a script object mirror if needed.
*
* @param obj object to be unwrapped
* @param homeGlobal global to which this object belongs
* @return unwrapped object
*/
public static Object unwrap(final Object obj, final ScriptObject homeGlobal) {
if (obj instanceof ScriptObjectMirror) {
final ScriptObjectMirror mirror = (ScriptObjectMirror)obj;
return (mirror.global == homeGlobal)? mirror.sobj : obj;
@ -349,7 +372,14 @@ final class ScriptObjectMirror extends JSObject implements Bindings {
return obj;
}
static Object[] wrapArray(final Object[] args, final ScriptObject homeGlobal) {
/**
* Wrap an array of object to script object mirrors if needed.
*
* @param args array to be unwrapped
* @param homeGlobal global to which this object belongs
* @return wrapped array
*/
public static Object[] wrapArray(final Object[] args, final ScriptObject homeGlobal) {
if (args == null || args.length == 0) {
return args;
}
@ -363,7 +393,14 @@ final class ScriptObjectMirror extends JSObject implements Bindings {
return newArgs;
}
static Object[] unwrapArray(final Object[] args, final ScriptObject homeGlobal) {
/**
* Unwrap an array of script object mirrors if needed.
*
* @param args array to be unwrapped
* @param homeGlobal global to which this object belongs
* @return unwrapped array
*/
public static Object[] unwrapArray(final Object[] args, final ScriptObject homeGlobal) {
if (args == null || args.length == 0) {
return args;
}
@ -376,4 +413,13 @@ final class ScriptObjectMirror extends JSObject implements Bindings {
}
return newArgs;
}
// package-privates below this.
ScriptObject getScriptObject() {
return sobj;
}
static Object translateUndefined(Object obj) {
return (obj == ScriptRuntime.UNDEFINED)? null : obj;
}
}

View File

@ -84,13 +84,12 @@ import jdk.nashorn.internal.ir.TryNode;
import jdk.nashorn.internal.ir.UnaryNode;
import jdk.nashorn.internal.ir.VarNode;
import jdk.nashorn.internal.ir.WithNode;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
import jdk.nashorn.internal.parser.TokenType;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.Debug;
import jdk.nashorn.internal.runtime.DebugLogger;
import jdk.nashorn.internal.runtime.ECMAException;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.Property;
import jdk.nashorn.internal.runtime.PropertyMap;
@ -1323,7 +1322,7 @@ final class Attr extends NodeOperatorVisitor<LexicalContext> {
@Override
public Node leaveForNode(final ForNode forNode) {
if (forNode.isForIn()) {
forNode.setIterator(newInternal(lc.getCurrentFunction().uniqueName(ITERATOR_PREFIX.symbolName()), Type.OBJECT)); //NASHORN-73
forNode.setIterator(newInternal(lc.getCurrentFunction().uniqueName(ITERATOR_PREFIX.symbolName()), Type.typeFor(ITERATOR_PREFIX.type()))); //NASHORN-73
/*
* Iterators return objects, so we need to widen the scope of the
* init variable if it, for example, has been assigned double type
@ -1500,7 +1499,7 @@ final class Attr extends NodeOperatorVisitor<LexicalContext> {
}
private Symbol exceptionSymbol() {
return newInternal(lc.getCurrentFunction().uniqueName(EXCEPTION_PREFIX.symbolName()), Type.typeFor(ECMAException.class));
return newInternal(lc.getCurrentFunction().uniqueName(EXCEPTION_PREFIX.symbolName()), Type.typeFor(EXCEPTION_PREFIX.type()));
}
/**

View File

@ -60,7 +60,6 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.TreeMap;
import jdk.nashorn.internal.codegen.ClassEmitter.Flag;
import jdk.nashorn.internal.codegen.CompilerConstants.Call;
import jdk.nashorn.internal.codegen.RuntimeCallSite.SpecializedRuntimeNode;
@ -80,11 +79,11 @@ import jdk.nashorn.internal.ir.EmptyNode;
import jdk.nashorn.internal.ir.ExecuteNode;
import jdk.nashorn.internal.ir.ForNode;
import jdk.nashorn.internal.ir.FunctionNode;
import jdk.nashorn.internal.ir.LexicalContext;
import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
import jdk.nashorn.internal.ir.IdentNode;
import jdk.nashorn.internal.ir.IfNode;
import jdk.nashorn.internal.ir.IndexNode;
import jdk.nashorn.internal.ir.LexicalContext;
import jdk.nashorn.internal.ir.LexicalContextNode;
import jdk.nashorn.internal.ir.LiteralNode;
import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
@ -457,17 +456,18 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
}
private void initSymbols(final LinkedList<Symbol> symbols, final Type type) {
if (symbols.isEmpty()) {
return;
}
method.loadUndefined(type);
while (!symbols.isEmpty()) {
final Symbol symbol = symbols.removeFirst();
if (!symbols.isEmpty()) {
method.dup();
}
method.store(symbol);
final Iterator<Symbol> it = symbols.iterator();
if(it.hasNext()) {
method.loadUndefined(type);
boolean hasNext;
do {
final Symbol symbol = it.next();
hasNext = it.hasNext();
if(hasNext) {
method.dup();
}
method.store(symbol);
} while(hasNext);
}
}
@ -941,11 +941,6 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
* bootstrap code for object
*/
final FieldObjectCreator<Symbol> foc = new FieldObjectCreator<Symbol>(this, nameList, newSymbols, values, true, hasArguments) {
@Override
protected Type getValueType(final Symbol value) {
return value.getSymbolType();
}
@Override
protected void loadValue(final Symbol value) {
method.load(value);
@ -1356,11 +1351,6 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
}
new FieldObjectCreator<Node>(this, keys, symbols, values) {
@Override
protected Type getValueType(final Node node) {
return node.getType();
}
@Override
protected void loadValue(final Node node) {
load(node);

View File

@ -29,6 +29,7 @@ import static jdk.nashorn.internal.lookup.Lookup.MH;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.util.Iterator;
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptObject;
@ -105,13 +106,13 @@ public enum CompilerConstants {
ARGUMENTS("arguments", Object.class, 2),
/** prefix for iterators for for (x in ...) */
ITERATOR_PREFIX(":i"),
ITERATOR_PREFIX(":i", Iterator.class),
/** prefix for tag variable used for switch evaluation */
SWITCH_TAG_PREFIX(":s"),
/** prefix for all exceptions */
EXCEPTION_PREFIX(":e"),
EXCEPTION_PREFIX(":e", Throwable.class),
/** prefix for quick slots generated in Store */
QUICK_PREFIX(":q"),

View File

@ -144,15 +144,6 @@ public abstract class FieldObjectCreator<T> extends ObjectCreator {
*/
protected abstract void loadValue(T value);
/**
* Determine the type of a value. Defined by anonymous subclasses in code gen.
*
* @param value Value to inspect.
*
* @return Value type.
*/
protected abstract Type getValueType(T value);
/**
* Store a value in a field of the generated class object.
*
@ -165,13 +156,6 @@ public abstract class FieldObjectCreator<T> extends ObjectCreator {
method.dup();
loadValue(value);
final Type valueType = getValueType(value);
// for example when we have a with scope
if (valueType.isObject() || valueType.isBoolean()) {
method.convert(OBJECT);
}
method.convert(OBJECT);
method.putField(getClassName(), ObjectClassGenerator.getFieldName(fieldIndex, Type.OBJECT), typeDescriptor(Object.class));
}

View File

@ -59,12 +59,10 @@ import jdk.nashorn.internal.lookup.MethodHandleFactory;
public final class RuntimeCallSite extends MutableCallSite {
static final Call BOOTSTRAP = staticCallNoLookup(Bootstrap.class, "runtimeBootstrap", CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class);
private static final MethodHandle NEXT = findOwnMH("next", MethodHandle.class);
private static final MethodHandle NEXT = findOwnMH("next", MethodHandle.class, String.class);
private final RuntimeNode.Request request;
private String name;
/**
* A specialized runtime node, i.e. on where we know at least one more specific type than object
*/
@ -203,7 +201,6 @@ public final class RuntimeCallSite extends MutableCallSite {
*/
public RuntimeCallSite(final MethodType type, final String name) {
super(type);
this.name = name;
this.request = Request.valueOf(name.substring(0, name.indexOf(SpecializedRuntimeNode.REQUEST_SEPARATOR)));
setTarget(makeMethod(name));
}
@ -292,7 +289,7 @@ public final class RuntimeCallSite extends MutableCallSite {
mh = MH.explicitCastArguments(mh, type());
}
final MethodHandle fallback = MH.foldArguments(MethodHandles.exactInvoker(type()), MH.bindTo(NEXT, this));
final MethodHandle fallback = MH.foldArguments(MethodHandles.exactInvoker(type()), MH.insertArguments(NEXT, 0, this, requestName));
MethodHandle guard;
if (type().parameterType(0).isPrimitive()) {
@ -338,18 +335,12 @@ public final class RuntimeCallSite extends MutableCallSite {
*
* @return next wider specialization method for this RuntimeCallSite
*/
public MethodHandle next() {
this.name = nextName(name);
final MethodHandle next = makeMethod(name);
public MethodHandle next(final String name) {
final MethodHandle next = makeMethod(nextName(name));
setTarget(next);
return next;
}
@Override
public String toString() {
return super.toString() + " " + name;
}
/** Method cache */
private static final Map<String, MethodHandle> METHODS;

View File

@ -28,7 +28,6 @@ package jdk.nashorn.internal.ir;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import jdk.nashorn.internal.codegen.CompileUnit;
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.annotations.Immutable;
@ -242,8 +241,8 @@ public abstract class LiteralNode<T> extends Node implements PropertyKey {
*
* @return the new literal node
*/
public static LiteralNode<Node> newInstance(final long token, final int finish) {
return new NodeLiteralNode(token, finish);
public static LiteralNode<Object> newInstance(final long token, final int finish) {
return new NullLiteralNode(token, finish);
}
/**
@ -253,8 +252,8 @@ public abstract class LiteralNode<T> extends Node implements PropertyKey {
*
* @return the new literal node
*/
public static LiteralNode<?> newInstance(final Node parent) {
return new NodeLiteralNode(parent.getToken(), parent.getFinish());
public static LiteralNode<Object> newInstance(final Node parent) {
return new NullLiteralNode(parent.getToken(), parent.getFinish());
}
@Immutable
@ -496,33 +495,15 @@ public abstract class LiteralNode<T> extends Node implements PropertyKey {
return new LexerTokenLiteralNode(parent.getToken(), parent.getFinish(), value);
}
private static final class NodeLiteralNode extends LiteralNode<Node> {
private static final class NullLiteralNode extends LiteralNode<Object> {
private NodeLiteralNode(final long token, final int finish) {
this(token, finish, null);
}
private NodeLiteralNode(final long token, final int finish, final Node value) {
super(Token.recast(token, TokenType.OBJECT), finish, value);
}
private NodeLiteralNode(final LiteralNode<Node> literalNode) {
super(literalNode);
}
private NodeLiteralNode(final LiteralNode<Node> literalNode, final Node value) {
super(literalNode, value);
private NullLiteralNode(final long token, final int finish) {
super(Token.recast(token, TokenType.OBJECT), finish, null);
}
@Override
public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterLiteralNode(this)) {
if (value != null) {
final Node newValue = value.accept(visitor);
if(value != newValue) {
return visitor.leaveLiteralNode(new NodeLiteralNode(this, newValue));
}
}
return visitor.leaveLiteralNode(this);
}
@ -531,38 +512,13 @@ public abstract class LiteralNode<T> extends Node implements PropertyKey {
@Override
public Type getType() {
return value == null ? Type.OBJECT : super.getType();
return Type.OBJECT;
}
@Override
public Type getWidestOperationType() {
return value == null ? Type.OBJECT : value.getWidestOperationType();
return Type.OBJECT;
}
}
/**
* Create a new node literal for an arbitrary node
*
* @param token token
* @param finish finish
* @param value the literal value node
*
* @return the new literal node
*/
public static LiteralNode<Node> newInstance(final long token, final int finish, final Node value) {
return new NodeLiteralNode(token, finish, value);
}
/**
* Create a new node literal based on a parent node (source, token, finish)
*
* @param parent parent node
* @param value node value
*
* @return the new literal node
*/
public static LiteralNode<?> newInstance(final Node parent, final Node value) {
return new NodeLiteralNode(parent.getToken(), parent.getFinish(), value);
}
/**

View File

@ -119,6 +119,10 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
@Property(attributes = Attribute.NOT_ENUMERABLE)
public Object load;
/** Nashorn extension: global.loadWithNewGlobal */
@Property(attributes = Attribute.NOT_ENUMERABLE)
public Object loadWithNewGlobal;
/** Nashorn extension: global.exit */
@Property(attributes = Attribute.NOT_ENUMERABLE)
public Object exit;
@ -364,11 +368,12 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
// Used to store the last RegExp result to support deprecated RegExp constructor properties
private RegExpResult lastRegExpResult;
private static final MethodHandle EVAL = findOwnMH("eval", Object.class, Object.class, Object.class);
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 EXIT = findOwnMH("exit", Object.class, Object.class, Object.class);
private static final MethodHandle EVAL = findOwnMH("eval", Object.class, Object.class, Object.class);
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 EXIT = findOwnMH("exit", Object.class, Object.class, Object.class);
private final Context context;
@ -742,6 +747,21 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
return global.context.load(scope, source);
}
/**
* Global loadWithNewGlobal implementation - Nashorn extension
*
* @param self scope
* @param source source to load
*
* @return result of load (undefined)
*
* @throws IOException if source could not be read
*/
public static Object loadWithNewGlobal(final Object self, final Object source) throws IOException {
final Global global = Global.instance();
return global.context.loadWithNewGlobal(source);
}
/**
* Global exit and quit implementation - Nashorn extension: perform a {@code System.exit} call from the script
*
@ -1387,6 +1407,7 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
this.unescape = ScriptFunctionImpl.makeFunction("unescape", GlobalFunctions.UNESCAPE);
this.print = ScriptFunctionImpl.makeFunction("print", env._print_no_newline ? PRINT : PRINTLN);
this.load = ScriptFunctionImpl.makeFunction("load", LOAD);
this.loadWithNewGlobal = ScriptFunctionImpl.makeFunction("loadWithNewGlobal", LOADWITHNEWGLOBAL);
this.exit = ScriptFunctionImpl.makeFunction("exit", EXIT);
this.quit = ScriptFunctionImpl.makeFunction("quit", EXIT);
@ -1628,20 +1649,21 @@ public final class Global extends ScriptObject implements GlobalObject, Scope {
@SuppressWarnings("resource")
private static Object printImpl(final boolean newLine, final Object... objects) {
final PrintWriter out = Global.getEnv().getOut();
final StringBuilder sb = new StringBuilder();
boolean first = true;
for (final Object object : objects) {
if (first) {
first = false;
} else {
out.print(' ');
if (sb.length() != 0) {
sb.append(' ');
}
out.print(JSType.toString(object));
sb.append(JSType.toString(object));
}
// Print all at once to ensure thread friendly result.
if (newLine) {
out.println();
out.println(sb.toString());
} else {
out.print(sb.toString());
}
out.flush();

View File

@ -39,6 +39,7 @@ import jdk.nashorn.internal.objects.annotations.Function;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
import jdk.nashorn.internal.objects.annotations.SpecializedConstructor;
import jdk.nashorn.internal.objects.annotations.Where;
import jdk.nashorn.internal.parser.DateParser;
import jdk.nashorn.internal.runtime.ConsString;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.ScriptEnvironment;

View File

@ -32,6 +32,7 @@ import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.List;
import jdk.nashorn.internal.codegen.CompilerConstants;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Constructor;
import jdk.nashorn.internal.objects.annotations.Function;
@ -248,7 +249,13 @@ public final class NativeError extends ScriptObject {
final List<StackTraceElement> filtered = new ArrayList<>();
for (final StackTraceElement st : frames) {
if (ECMAErrors.isScriptFrame(st)) {
filtered.add(st);
final String className = "<" + st.getFileName() + ">";
String methodName = st.getMethodName();
if (methodName.equals(CompilerConstants.RUN_SCRIPT.symbolName())) {
methodName = "<program>";
}
filtered.add(new StackTraceElement(className, methodName,
st.getFileName(), st.getLineNumber()));
}
}
res = filtered.toArray();

View File

@ -33,10 +33,14 @@ 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.parser.Parser;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.ParserException;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
import jdk.nashorn.internal.runtime.Source;
/**
* ECMA 15.3 Function Objects
@ -187,16 +191,25 @@ public final class NativeFunction {
sb.append("(function (");
if (args.length > 0) {
final StringBuilder paramListBuf = new StringBuilder();
for (int i = 0; i < args.length - 1; i++) {
sb.append(JSType.toString(args[i]));
paramListBuf.append(JSType.toString(args[i]));
if (i < args.length - 2) {
sb.append(",");
paramListBuf.append(",");
}
}
final String paramList = paramListBuf.toString();
if (! paramList.isEmpty()) {
checkFunctionParameters(paramList);
sb.append(paramList);
}
}
sb.append(") {\n");
if (args.length > 0) {
sb.append(JSType.toString(args[args.length - 1]));
final String funcBody = JSType.toString(args[args.length - 1]);
checkFunctionBody(funcBody);
sb.append(funcBody);
sb.append('\n');
}
sb.append("})");
@ -205,4 +218,24 @@ public final class NativeFunction {
return Global.directEval(global, sb.toString(), global, "<function>", Global.isStrict());
}
private static void checkFunctionParameters(final String params) {
final Source src = new Source("<function>", params);
final Parser parser = new Parser(Global.getEnv(), src, new Context.ThrowErrorManager());
try {
parser.parseFormalParameterList();
} catch (final ParserException pe) {
pe.throwAsEcmaException();
}
}
private static void checkFunctionBody(final String funcBody) {
final Source src = new Source("<function>", funcBody);
final Parser parser = new Parser(Global.getEnv(), src, new Context.ThrowErrorManager());
try {
parser.parseFunctionBody();
} catch (final ParserException pe) {
pe.throwAsEcmaException();
}
}
}

View File

@ -23,7 +23,7 @@
* questions.
*/
package jdk.nashorn.internal.objects;
package jdk.nashorn.internal.parser;
import static java.lang.Character.DECIMAL_DIGIT_NUMBER;
import static java.lang.Character.LOWERCASE_LETTER;
@ -196,6 +196,11 @@ public class DateParser {
break;
case SIGN:
if (peek() == -1) {
// END after sign - wrong!
return false;
}
if (currentField == YEAR) {
yearSign = numValue;
} else if (currentField < SECOND || !setTimezone(readTimeZoneOffset(), true)) {
@ -297,6 +302,11 @@ public class DateParser {
break;
case SIGN:
if (peek() == -1) {
// END after sign - wrong!
return false;
}
if (!setTimezone(readTimeZoneOffset(), true)) {
return false;
}

View File

@ -192,36 +192,110 @@ public class Parser extends AbstractParser {
// Begin parse.
return program(scriptName);
} catch (final Exception e) {
// Extract message from exception. The message will be in error
// message format.
String message = e.getMessage();
// If empty message.
if (message == null) {
message = e.toString();
}
// Issue message.
if (e instanceof ParserException) {
errors.error((ParserException)e);
} else {
errors.error(message);
}
if (env._dump_on_error) {
e.printStackTrace(env.getErr());
}
handleParseException(e);
return null;
} finally {
final String end = this + " end '" + scriptName + "'";
if (Timing.isEnabled()) {
Timing.accumulateTime(toString(), System.currentTimeMillis() - t0);
LOG.info(end, "' in ", (System.currentTimeMillis() - t0), " ms");
} else {
LOG.info(end);
}
}
} finally {
final String end = this + " end '" + scriptName + "'";
if (Timing.isEnabled()) {
Timing.accumulateTime(toString(), System.currentTimeMillis() - t0);
LOG.info(end, "' in ", (System.currentTimeMillis() - t0), " ms");
} else {
LOG.info(end);
}
}
}
/**
* Parse and return the list of function parameter list. A comma
* separated list of function parameter identifiers is expected to be parsed.
* Errors will be thrown and the error manager will contain information
* if parsing should fail. This method is used to check if parameter Strings
* passed to "Function" constructor is a valid or not.
*
* @return the list of IdentNodes representing the formal parameter list
*/
public List<IdentNode> parseFormalParameterList() {
try {
stream = new TokenStream();
lexer = new Lexer(source, stream, scripting && !env._no_syntax_extensions);
// Set up first token (skips opening EOL.)
k = -1;
next();
return formalParameterList(TokenType.EOF);
} catch (final Exception e) {
handleParseException(e);
return null;
}
}
/**
* Execute parse and return the resulting function node.
* Errors will be thrown and the error manager will contain information
* if parsing should fail. This method is used to check if code String
* passed to "Function" constructor is a valid function body or not.
*
* @return function node resulting from successful parse
*/
public FunctionNode parseFunctionBody() {
try {
stream = new TokenStream();
lexer = new Lexer(source, stream, scripting && !env._no_syntax_extensions);
// Set up first token (skips opening EOL.)
k = -1;
next();
// Make a fake token for the function.
final long functionToken = Token.toDesc(FUNCTION, 0, source.getLength());
// Set up the function to append elements.
FunctionNode function = newFunctionNode(
functionToken,
new IdentNode(functionToken, Token.descPosition(functionToken), RUN_SCRIPT.symbolName()),
new ArrayList<IdentNode>(),
FunctionNode.Kind.NORMAL);
functionDeclarations = new ArrayList<>();
sourceElements();
addFunctionDeclarations(function);
functionDeclarations = null;
expect(EOF);
function.setFinish(source.getLength() - 1);
function = restoreFunctionNode(function, token); //commit code
function = function.setBody(lc, function.getBody().setNeedsScope(lc));
return function;
} catch (final Exception e) {
handleParseException(e);
return null;
}
}
private void handleParseException(final Exception e) {
// Extract message from exception. The message will be in error
// message format.
String message = e.getMessage();
// If empty message.
if (message == null) {
message = e.toString();
}
// Issue message.
if (e instanceof ParserException) {
errors.error((ParserException)e);
} else {
errors.error(message);
}
if (env._dump_on_error) {
e.printStackTrace(env.getErr());
}
}
/**
@ -2424,12 +2498,29 @@ loop:
* @return List of parameter nodes.
*/
private List<IdentNode> formalParameterList() {
return formalParameterList(RPAREN);
}
/**
* Same as the other method of the same name - except that the end
* token type expected is passed as argument to this method.
*
* FormalParameterList :
* Identifier
* FormalParameterList , Identifier
*
* See 13
*
* Parse function parameter list.
* @return List of parameter nodes.
*/
private List<IdentNode> formalParameterList(final TokenType endType) {
// Prepare to gather parameters.
final List<IdentNode> parameters = new ArrayList<>();
// Track commas.
boolean first = true;
while (type != RPAREN) {
while (type != endType) {
// Comma prior to every argument except the first.
if (!first) {
expect(COMMARIGHT);

View File

@ -48,6 +48,7 @@ import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.org.objectweb.asm.util.CheckClassAdapter;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
import jdk.nashorn.internal.codegen.Compiler;
import jdk.nashorn.internal.codegen.ObjectClassGenerator;
import jdk.nashorn.internal.ir.FunctionNode;
@ -490,6 +491,40 @@ public final class Context {
throw typeError("cant.load.script", ScriptRuntime.safeToString(from));
}
/**
* Implementation of {@code loadWithNewGlobal} Nashorn extension. Load a script file from a source
* expression, after creating a new global scope.
*
* @param from source expression for 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, RuntimeException {
final ScriptObject oldGlobal = getGlobalTrusted();
final ScriptObject newGlobal = AccessController.doPrivileged(new PrivilegedAction<ScriptObject>() {
@Override
public ScriptObject run() {
try {
return createGlobal();
} catch (final RuntimeException e) {
if (Context.DEBUG) {
e.printStackTrace();
}
throw e;
}
}
});
setGlobalTrusted(newGlobal);
try {
return ScriptObjectMirror.wrap(load(newGlobal, from), newGlobal);
} finally {
setGlobalTrusted(oldGlobal);
}
}
/**
* Load or get a structure class. Structure class names are based on the number of parameter fields
* and {@link AccessorProperty} fields in them. Structure classes are used to represent ScriptObjects

View File

@ -1511,6 +1511,17 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr
return oldValue;
}
/**
* Delete a property from the ScriptObject.
* (to help ScriptObjectMirror implementation)
*
* @param key the key of the property
* @return if the delete was successful or not
*/
public boolean delete(final Object key) {
return delete(key, getContext()._strict);
}
/**
* Return the size of the ScriptObject - i.e. the number of properties
* it contains

View File

@ -40,6 +40,7 @@ import java.util.Locale;
import java.util.NoSuchElementException;
import java.util.Objects;
import jdk.internal.dynalink.beans.StaticClass;
import jdk.nashorn.api.scripting.ScriptObjectMirror;
import jdk.nashorn.internal.codegen.CompilerConstants.Call;
import jdk.nashorn.internal.ir.debug.JSONWriter;
import jdk.nashorn.internal.parser.Lexer;
@ -240,6 +241,10 @@ public final class ScriptRuntime {
};
}
if (obj instanceof ScriptObjectMirror) {
return ((ScriptObjectMirror)obj).keySet().iterator();
}
return Collections.emptyIterator();
}
@ -280,6 +285,10 @@ public final class ScriptRuntime {
};
}
if (obj instanceof ScriptObjectMirror) {
return ((ScriptObjectMirror)obj).values().iterator();
}
if (obj instanceof Iterable) {
return ((Iterable<?>)obj).iterator();
}
@ -591,6 +600,10 @@ public final class ScriptRuntime {
throw typeError("cant.delete.property", safeToString(property), "null");
}
if (obj instanceof ScriptObjectMirror) {
return ((ScriptObjectMirror)obj).delete(property);
}
if (JSType.isPrimitive(obj)) {
return ((ScriptObject) JSType.toScriptObject(obj)).delete(property, Boolean.TRUE.equals(strict));
}

View File

@ -0,0 +1,55 @@
/*
* 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-8012164: Error.stack needs trimming
*
* @test
* @run
*/
function func() {
error();
}
function error() {
try {
throw new Error('foo');
} catch (e) {
for (i in e.stack) {
printFrame(e.stack[i]);
}
}
}
func();
// See JDK-8015855: test/script/basic/JDK-8012164.js fails on Windows
// Replace '\' to '/' in class and file names of StackFrameElement objects
function printFrame(stack) {
var fileName = stack.fileName.replace(/\\/g, '/');
var className = stack.className.replace(/\\/g, '/');
print(className + '.' + stack.methodName + '(' +
fileName + ':' + stack.lineNumber + ')');
}

View File

@ -0,0 +1,3 @@
<test/script/basic/JDK-8012164.js>.error(test/script/basic/JDK-8012164.js:38)
<test/script/basic/JDK-8012164.js>.func(test/script/basic/JDK-8012164.js:33)
<test/script/basic/JDK-8012164.js>.<program>(test/script/basic/JDK-8012164.js:46)

View File

@ -0,0 +1,64 @@
/*
* 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-8015345: Function("}),print('test'),({") should throw SyntaxError
*
* @test
* @run
*/
function checkFunction(code) {
try {
Function(code);
fail("should have thrown SyntaxError for :" + code);
} catch (e) {
if (! (e instanceof SyntaxError)) {
fail("SyntaxError expected, but got " + e);
}
print(e);
}
}
// invalid body
checkFunction("}),print('test'),({");
// invalid param list
checkFunction("x**y", "print('x')");
// invalid param identifier
checkFunction("in", "print('hello')");
//checkFunction("<>", "print('hello')")
// invalid param list and body
checkFunction("x--y", ")");
// check few valid cases as well
var f = Function("x", "return x*x");
print(f(10))
f = Function("x", "y", "return x+y");
print(f(33, 22));
f = Function("x,y", "return x/y");
print(f(24, 2));

View File

@ -0,0 +1,15 @@
SyntaxError: <function>:1:0 Expected eof but found }
}),print('test'),({
^
SyntaxError: <function>:1:2 Expected an operand but found *
x**y
^
SyntaxError: <function>:1:0 Expected an operand but found in
in
^
SyntaxError: <function>:1:3 Expected ; but found y
x--y
^
100
55
12

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-8015353: Date.parse illegal string parsing issues
*
* @test
* @run
*/
function checkDate(str) {
if (! isNaN(Date.parse(str))) {
fail(str + " is parsed as legal Date");
}
}
checkDate("2012-01-10T00:00:00.000-");
checkDate("2012-01-01T00:00+");

View File

@ -0,0 +1,57 @@
/*
* 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-8015741 : Need a global.load function that starts with a new global scope.
*
* @test
* @run
*/
var Thread = java.lang.Thread;
myGlobal = "#0";
var script1 = {name: "script 1", script: 'myGlobal = "#1"; print(myGlobal);'};
var script2 = {name: "script 2", script: 'myGlobal = "#2"; print(myGlobal);'};
var script3 = {name: "script 3", script: 'myGlobal = "#3"; print(myGlobal);'};
var script4 = {name: "script 4", script: 'myGlobal = "#4"; print(myGlobal);'};
print(myGlobal);
load(script1);
print(myGlobal);
print(myGlobal);
var thread1 = new Thread(function() { load(script2); });
thread1.start();
thread1.join();
print(myGlobal);
print(myGlobal);
loadWithNewGlobal(script3);
print(myGlobal);
print(myGlobal);
var thread2 = new Thread(function() { loadWithNewGlobal(script4); });
thread2.start();
thread2.join();
print(myGlobal);

View File

@ -0,0 +1,12 @@
#0
#1
#1
#1
#2
#2
#2
#3
#2
#2
#4
#2

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.
*
* 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-8015830: Javascript mapping of ScriptEngine bindings does not expose keys
*
* @test
* @run
*/
var m = new javax.script.ScriptEngineManager();
var engine = m.getEngineByName("nashorn");
engine.eval("x = 100; doit = function () { }");
var global = engine.getBindings(javax.script.ScriptContext.ENGINE_SCOPE);
for(k in global){
print(k + " = " + global[k]);
}
for each (k in global) {
print(k);
}
for(k in global) {
delete global[k];
}
for(k in global){
print(k + " = " + global[k]);
}
for each(k in global) {
print(k);
}

View File

@ -0,0 +1,4 @@
x = 100
doit = function () { }
100
function () { }

View File

@ -0,0 +1,55 @@
/*
* 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-8015945: loadWithNewGlobal return value has to be properly wrapped
*
* @test
* @option -scripting
* @run
*/
var global = loadWithNewGlobal({ name: "<code>",
script: <<EOF
function squares() {
var res = new Array(arguments.length);
for (var i in arguments) {
res[i] = arguments[i]*arguments[i]
}
return res;
}
this;
EOF
})
print("global an Object? " + (global instanceof Object));
var res = global.squares(2, 3, 4, 5);
print("global.squares returns Array? " + (res instanceof Array));
// still can access array index properties and length
print("result length " + res.length);
for (var i in res) {
print(i + " = " + res[i]);
}

View File

@ -0,0 +1,7 @@
global an Object? false
global.squares returns Array? false
result length 4
0 = 4
1 = 9
2 = 16
3 = 25

View File

@ -1,3 +1,3 @@
runScript 33
runScript 32
<program> 33
<program> 32
done

View File

@ -1,2 +1,2 @@
runScript 33
<program> 33
done

View File

@ -1,4 +1,4 @@
func3 : 40
func2 : 36
func1 : 32
runScript : 44
<program> : 44

View File

@ -4,7 +4,7 @@ function (x) {
print('anon func'); return x*x;
}
syntax error? true
SyntaxError: <function>:2:13 Missing close quote
SyntaxError: <function>:1:13 Missing close quote
print('hello)
^
done

View File

@ -0,0 +1,96 @@
/*
* 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.
*/
/**
* typedarray test.
*
* @test
* @run
*/
var typeDefinitions = [
Int8Array,
Uint8Array,
Uint8ClampedArray,
Int16Array,
Uint16Array,
Int32Array,
Uint32Array,
Float32Array,
Float64Array,
];
var mem1 = new ArrayBuffer(1024);
mem1.byteLength;
mem1.slice(512);
mem1.slice(512, 748);
var size = 128;
var arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
var arr2 = [99, 89];
var partial = [];
var all = [];
typeDefinitions.forEach(function(arrayDef) {
var p = arrayDef.prototype;
var sub = [];
sub.push(new arrayDef(mem1, arrayDef.BYTES_PER_ELEMENT, 3));
sub.push(new arrayDef(size));
sub.push(new arrayDef(arr));
//push the instances, they will be reused to do instance based construction
partial.push({
instances:sub,
type:arrayDef
});
all.concat(all, sub);
});
partial.forEach(function(inst) {
// build new instances with TypeArray instance as parameter.
partial.forEach(function(other) {
other.instances.forEach(function(otherInstance) {
var ii = new inst.type(otherInstance);
all.push(ii);
});
})
});
all.forEach(function(instance) {
// cover instance props and functions
var arr = Object.getOwnPropertyNames(instance);
arr.forEach(function(p) {
var val = instance[p];
if(!isNaN(p)){
val[p] = 99;
}
});
instance.set(instance, 0);
instance.set(instance);
instance.set(arr2);
instance.subarray(5, 9);
instance.subarray(5);
});