This commit is contained in:
Lana Steuck 2016-04-28 09:38:42 -07:00
commit b66d02e59c
38 changed files with 3633 additions and 409 deletions

View File

@ -4310,7 +4310,7 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
* @param ident identifier for block or function where applicable
*/
private void printSymbols(final Block block, final FunctionNode function, final String ident) {
if (compiler.getScriptEnvironment()._print_symbols || function.getFlag(FunctionNode.IS_PRINT_SYMBOLS)) {
if (compiler.getScriptEnvironment()._print_symbols || function.getDebugFlag(FunctionNode.DEBUG_PRINT_SYMBOLS)) {
final PrintWriter out = compiler.getScriptEnvironment().getErr();
out.println("[BLOCK in '" + ident + "']");
if (!block.printSymbols(out)) {

View File

@ -278,12 +278,12 @@ abstract class CompilationPhase {
final PrintWriter err = senv.getErr();
//TODO separate phase for the debug printouts for abstraction and clarity
if (senv._print_lower_ast || fn.getFlag(FunctionNode.IS_PRINT_LOWER_AST)) {
if (senv._print_lower_ast || fn.getDebugFlag(FunctionNode.DEBUG_PRINT_LOWER_AST)) {
err.println("Lower AST for: " + quote(newFunctionNode.getName()));
err.println(new ASTWriter(newFunctionNode));
}
if (senv._print_lower_parse || fn.getFlag(FunctionNode.IS_PRINT_LOWER_PARSE)) {
if (senv._print_lower_parse || fn.getDebugFlag(FunctionNode.DEBUG_PRINT_LOWER_PARSE)) {
err.println("Lower AST for: " + quote(newFunctionNode.getName()));
err.println(new PrintVisitor(newFunctionNode));
}

View File

@ -175,7 +175,9 @@ final class SplitIntoFunctions extends NodeVisitor<BlockLexicalContext> {
// we still use IS_SPLIT as the criteria in CompilationPhase.SERIALIZE_SPLIT_PHASE.
FunctionNode.IS_ANONYMOUS | FunctionNode.USES_ANCESTOR_SCOPE | FunctionNode.IS_SPLIT,
body,
null
null,
originalFn.getModule(),
originalFn.getDebugFlags()
)
.setCompileUnit(lc, splitNode.getCompileUnit());

View File

@ -435,7 +435,7 @@ final class WeighNodes extends NodeOperatorVisitor<LexicalContext> {
}
@Override
public Node leaveBIND(final BinaryNode binaryNode) {
public Node leaveARROW(final BinaryNode binaryNode) {
return binaryNodeWeight(binaryNode);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2010, 2016, 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
@ -48,12 +48,13 @@ public final class AccessNode extends BaseNode {
* @param property property
*/
public AccessNode(final long token, final int finish, final Expression base, final String property) {
super(token, finish, base, false);
super(token, finish, base, false, false);
this.property = property;
}
private AccessNode(final AccessNode accessNode, final Expression base, final String property, final boolean isFunction, final Type type, final int id) {
super(accessNode, base, isFunction, type, id);
private AccessNode(final AccessNode accessNode, final Expression base, final String property, final boolean isFunction,
final Type type, final int id, final boolean isSuper) {
super(accessNode, base, isFunction, type, id, isSuper);
this.property = property;
}
@ -105,7 +106,7 @@ public final class AccessNode extends BaseNode {
if (this.base == base) {
return this;
}
return new AccessNode(this, base, property, isFunction(), type, programPoint);
return new AccessNode(this, base, property, isFunction(), type, programPoint, isSuper());
}
@Override
@ -113,7 +114,7 @@ public final class AccessNode extends BaseNode {
if (this.type == type) {
return this;
}
return new AccessNode(this, base, property, isFunction(), type, programPoint);
return new AccessNode(this, base, property, isFunction(), type, programPoint, isSuper());
}
@Override
@ -121,7 +122,7 @@ public final class AccessNode extends BaseNode {
if (this.programPoint == programPoint) {
return this;
}
return new AccessNode(this, base, property, isFunction(), type, programPoint);
return new AccessNode(this, base, property, isFunction(), type, programPoint, isSuper());
}
@Override
@ -129,6 +130,14 @@ public final class AccessNode extends BaseNode {
if (isFunction()) {
return this;
}
return new AccessNode(this, base, property, true, type, programPoint);
return new AccessNode(this, base, property, true, type, programPoint, isSuper());
}
@Override
public AccessNode setIsSuper() {
if (isSuper()) {
return this;
}
return new AccessNode(this, base, property, isFunction(), type, programPoint, true);
}
}

View File

@ -52,6 +52,9 @@ public abstract class BaseNode extends Expression implements FunctionCall, Optim
/** Program point id */
protected final int programPoint;
/** Super property access. */
private final boolean isSuper;
/**
* Constructor
*
@ -59,13 +62,15 @@ public abstract class BaseNode extends Expression implements FunctionCall, Optim
* @param finish finish
* @param base base node
* @param isFunction is this a function
* @param isSuper is this a super property access
*/
public BaseNode(final long token, final int finish, final Expression base, final boolean isFunction) {
public BaseNode(final long token, final int finish, final Expression base, final boolean isFunction, final boolean isSuper) {
super(token, base.getStart(), finish);
this.base = base;
this.isFunction = isFunction;
this.type = null;
this.programPoint = INVALID_PROGRAM_POINT;
this.isSuper = isSuper;
}
/**
@ -75,13 +80,15 @@ public abstract class BaseNode extends Expression implements FunctionCall, Optim
* @param isFunction is this a function
* @param callSiteType the callsite type for this base node, either optimistic or conservative
* @param programPoint program point id
* @param isSuper is this a super property access
*/
protected BaseNode(final BaseNode baseNode, final Expression base, final boolean isFunction, final Type callSiteType, final int programPoint) {
protected BaseNode(final BaseNode baseNode, final Expression base, final boolean isFunction, final Type callSiteType, final int programPoint, final boolean isSuper) {
super(baseNode);
this.base = base;
this.isFunction = isFunction;
this.type = callSiteType;
this.programPoint = programPoint;
this.isSuper = isSuper;
}
/**
@ -136,4 +143,17 @@ public abstract class BaseNode extends Expression implements FunctionCall, Optim
*/
public abstract BaseNode setIsFunction();
/**
* @return {@code true} if a SuperProperty access.
*/
public boolean isSuper() {
return isSuper;
}
/**
* Mark this node as being a SuperProperty access.
*
* @return a base node identical to this one in all aspects except with its super flag set.
*/
public abstract BaseNode setIsSuper();
}

View File

@ -65,24 +65,39 @@ public class Block extends Node implements BreakableNode, Terminal, Flags<Block>
private final LocalVariableConversion conversion;
/** Flag indicating that this block needs scope */
public static final int NEEDS_SCOPE = 1 << 0;
public static final int NEEDS_SCOPE = 1 << 0;
/**
* Is this block tagged as terminal based on its contents
* (usually the last statement)
*/
public static final int IS_TERMINAL = 1 << 2;
public static final int IS_TERMINAL = 1 << 2;
/**
* Is this block the eager global scope - i.e. the original program. This isn't true for the
* outermost level of recompiles
*/
public static final int IS_GLOBAL_SCOPE = 1 << 3;
public static final int IS_GLOBAL_SCOPE = 1 << 3;
/**
* Is this block a synthetic one introduced by Parser?
*/
public static final int IS_SYNTHETIC = 1 << 4;
public static final int IS_SYNTHETIC = 1 << 4;
/**
* Is this the function body block? May not be the first, if parameter list contains expressions.
*/
public static final int IS_BODY = 1 << 5;
/**
* Is this the parameter initialization block? If present, must be the first block, immediately wrapping the function body block.
*/
public static final int IS_PARAMETER_BLOCK = 1 << 6;
/**
* Marks the variable declaration block for case clauses of a switch statement.
*/
public static final int IS_SWITCH_BLOCK = 1 << 7;
/**
* Constructor
@ -489,4 +504,31 @@ public class Block extends Node implements BreakableNode, Terminal, Flags<Block>
public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
return Acceptor.accept(this, visitor);
}
/**
* Checks if this is a function body.
*
* @return true if the function body flag is set
*/
public boolean isFunctionBody() {
return getFlag(IS_BODY);
}
/**
* Checks if this is a parameter block.
*
* @return true if the parameter block flag is set
*/
public boolean isParameterBlock() {
return getFlag(IS_PARAMETER_BLOCK);
}
/**
* Checks whether this is a switch block.
*
* @return true if this is a switch block
*/
public boolean isSwitchBlock() {
return getFlag(IS_SWITCH_BLOCK);
}
}

View File

@ -0,0 +1,147 @@
/*
* Copyright (c) 2015, 2016, 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.ir;
import java.util.Collections;
import java.util.List;
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
/**
* IR representation for class definitions.
*/
public class ClassNode extends Expression {
private static final long serialVersionUID = 1L;
private final IdentNode ident;
private final Expression classHeritage;
private final PropertyNode constructor;
private final List<PropertyNode> classElements;
private final int line;
/**
* Constructor.
*
* @param line line number
* @param token token
* @param finish finish
* @param ident ident
* @param classHeritage class heritage
* @param constructor constructor
* @param classElements class elements
*/
public ClassNode(final int line, final long token, final int finish, final IdentNode ident, final Expression classHeritage, final PropertyNode constructor,
final List<PropertyNode> classElements) {
super(token, finish);
this.line = line;
this.ident = ident;
this.classHeritage = classHeritage;
this.constructor = constructor;
this.classElements = classElements;
}
/**
* Class identifier. Optional.
*
* @return the class identifier
*/
public IdentNode getIdent() {
return ident;
}
/**
* The expression of the {@code extends} clause. Optional.
*
* @return the class heritage
*/
public Expression getClassHeritage() {
return classHeritage;
}
/**
* Get the constructor method definition.
*
* @return the constructor
*/
public PropertyNode getConstructor() {
return constructor;
}
/**
* Get method definitions except the constructor.
*
* @return the class elements
*/
public List<PropertyNode> getClassElements() {
return Collections.unmodifiableList(classElements);
}
/**
* Returns the line number.
*
* @return the line number
*/
public int getLineNumber() {
return line;
}
@Override
public Type getType() {
return Type.OBJECT;
}
@Override
public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterClassNode(this)) {
return visitor.leaveClassNode(this);
}
return this;
}
@Override
public void toString(final StringBuilder sb, final boolean printType) {
sb.append("class");
if (ident != null) {
sb.append(' ');
ident.toString(sb, printType);
}
if (classHeritage != null) {
sb.append(" extends");
classHeritage.toString(sb, printType);
}
sb.append(" {");
if (constructor != null) {
constructor.toString(sb, printType);
}
for (final PropertyNode classElement : classElements) {
sb.append(" ");
classElement.toString(sb, printType);
}
sb.append("}");
}
}

View File

@ -0,0 +1,87 @@
/*
* Copyright (c) 2015, 2016, 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.ir;
import java.util.Collections;
import java.util.List;
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
/**
* IR for CoverParenthesizedExpressionAndArrowParameterList, used only during parsing.
*/
public final class ExpressionList extends Expression {
private static final long serialVersionUID = 1L;
private final List<Expression> expressions;
/**
* Constructor.
*
* @param token token
* @param finish finish
* @param expressions expression
*/
public ExpressionList(final long token, final int finish, final List<Expression> expressions) {
super(token, finish);
this.expressions = expressions;
}
/**
* Get the list of expressions.
*
* @return the list of expressions
*/
public List<Expression> getExpressions() {
return Collections.unmodifiableList(expressions);
}
@Override
public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
throw new UnsupportedOperationException();
}
@Override
public Type getType() {
return null;
}
@Override
public void toString(StringBuilder sb, boolean printType) {
sb.append("(");
boolean first = true;
for (Expression expression : expressions) {
if (first) {
first = false;
} else {
sb.append(", ");
}
expression.toString(sb, printType);
}
sb.append(")");
}
}

View File

@ -90,7 +90,6 @@ public final class ForNode extends LoopNode {
this.init = init;
this.modify = modify;
this.iterator = null;
}
private ForNode(final ForNode forNode, final Expression init, final JoinPredecessorExpression test,

View File

@ -69,7 +69,13 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
/** a getter, @see {@link UserAccessorProperty} */
GETTER,
/** a setter, @see {@link UserAccessorProperty} */
SETTER
SETTER,
/** an arrow function */
ARROW,
/** a generator function */
GENERATOR,
/** a module function */
MODULE
}
/** Source of entity. */
@ -122,6 +128,12 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
/** Root class for function */
private final Class<?> rootClass;
/** The ES6 module */
private final Module module;
/** The debug flags */
private final int debugFlags;
/** Is anonymous function flag. */
public static final int IS_ANONYMOUS = 1 << 0;
@ -172,49 +184,21 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
/**
* Is this function the top-level program?
*/
public static final int IS_PROGRAM = 1 << 13;
public static final int IS_PROGRAM = 1 << 13;
/**
* Flag indicating whether this function uses the local variable symbol for itself. Only named function expressions
* can have this flag set if they reference themselves (e.g. "(function f() { return f })". Declared functions will
* use the symbol in their parent scope instead when they reference themselves by name.
*/
public static final int USES_SELF_SYMBOL = 1 << 14;
public static final int USES_SELF_SYMBOL = 1 << 14;
/** Does this function use the "this" keyword? */
public static final int USES_THIS = 1 << 15;
public static final int USES_THIS = 1 << 15;
/** Is this declared in a dynamic context */
public static final int IN_DYNAMIC_CONTEXT = 1 << 16;
public static final int IN_DYNAMIC_CONTEXT = 1 << 16;
/**
* The following flags are derived from directive comments within this function.
* Note that even IS_STRICT is one such flag but that requires special handling.
*/
/** parser, print parse tree */
public static final int IS_PRINT_PARSE = 1 << 17;
/** parser, print lower parse tree */
public static final int IS_PRINT_LOWER_PARSE = 1 << 18;
/** parser, print AST */
public static final int IS_PRINT_AST = 1 << 19;
/** parser, print lower AST */
public static final int IS_PRINT_LOWER_AST = 1 << 20;
/** parser, print symbols */
public static final int IS_PRINT_SYMBOLS = 1 << 21;
// callsite tracing, profiling within this function
/** profile callsites in this function? */
public static final int IS_PROFILE = 1 << 22;
/** trace callsite enterexit in this function? */
public static final int IS_TRACE_ENTEREXIT = 1 << 23;
/** trace callsite misses in this function? */
public static final int IS_TRACE_MISSES = 1 << 24;
/** trace callsite values in this function? */
public static final int IS_TRACE_VALUES = 1 << 25;
/**
* Whether this function needs the callee {@link ScriptFunction} instance passed to its code as a
@ -222,18 +206,41 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
* Rather, it is always calculated (see {@link #needsCallee()}). {@link RecompilableScriptFunctionData}
* will, however, cache the value of this flag.
*/
public static final int NEEDS_CALLEE = 1 << 26;
public static final int NEEDS_CALLEE = 1 << 17;
/**
* Is the function node cached?
*/
public static final int IS_CACHED = 1 << 27;
public static final int IS_CACHED = 1 << 18;
/** extension callsite flags mask */
public static final int EXTENSION_CALLSITE_FLAGS = IS_PRINT_PARSE |
IS_PRINT_LOWER_PARSE | IS_PRINT_AST | IS_PRINT_LOWER_AST |
IS_PRINT_SYMBOLS | IS_PROFILE | IS_TRACE_ENTEREXIT |
IS_TRACE_MISSES | IS_TRACE_VALUES;
/**
* Does this function contain a super call? (cf. ES6 14.3.5 Static Semantics: HasDirectSuper)
*/
public static final int ES6_HAS_DIRECT_SUPER = 1 << 19;
/**
* Does this function use the super binding?
*/
public static final int ES6_USES_SUPER = 1 << 20;
/**
* Is this function a (class or object) method?
*/
public static final int ES6_IS_METHOD = 1 << 21;
/**
* Is this the constructor method?
*/
public static final int ES6_IS_CLASS_CONSTRUCTOR = 1 << 22;
/** Is this the constructor of a subclass (i.e., a class with an extends declaration)? */
public static final int ES6_IS_SUBCLASS_CONSTRUCTOR = 1 << 23;
/** is this a strong mode function? */
public static final int ES6_IS_STRONG = 1 << 24;
/** Does this function use new.target? */
public static final int ES6_USES_NEW_TARGET = 1 << 25;
/** Does this function or any nested functions contain an eval? */
private static final int HAS_DEEP_EVAL = HAS_EVAL | HAS_NESTED_EVAL;
@ -247,8 +254,44 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
/** Does this function need the parent scope? It needs it if either it or its descendants use variables from it, or have a deep eval, or it's the program. */
public static final int NEEDS_PARENT_SCOPE = USES_ANCESTOR_SCOPE | HAS_DEEP_EVAL | IS_PROGRAM;
/**
* The following flags are derived from directive comments within this function.
* Note that even IS_STRICT is one such flag but that requires special handling.
*/
/** parser, print parse tree */
public static final int DEBUG_PRINT_PARSE = 1 << 0;
/** parser, print lower parse tree */
public static final int DEBUG_PRINT_LOWER_PARSE = 1 << 1;
/** parser, print AST */
public static final int DEBUG_PRINT_AST = 1 << 2;
/** parser, print lower AST */
public static final int DEBUG_PRINT_LOWER_AST = 1 << 3;
/** parser, print symbols */
public static final int DEBUG_PRINT_SYMBOLS = 1 << 4;
// callsite tracing, profiling within this function
/** profile callsites in this function? */
public static final int DEBUG_PROFILE = 1 << 5;
/** trace callsite enterexit in this function? */
public static final int DEBUG_TRACE_ENTEREXIT = 1 << 6;
/** trace callsite misses in this function? */
public static final int DEBUG_TRACE_MISSES = 1 << 7;
/** trace callsite values in this function? */
public static final int DEBUG_TRACE_VALUES = 1 << 8;
/** extension callsite flags mask */
public static final int DEBUG_CALLSITE_FLAGS = DEBUG_PRINT_PARSE |
DEBUG_PRINT_LOWER_PARSE | DEBUG_PRINT_AST | DEBUG_PRINT_LOWER_AST |
DEBUG_PRINT_SYMBOLS | DEBUG_PROFILE | DEBUG_TRACE_ENTEREXIT |
DEBUG_TRACE_MISSES | DEBUG_TRACE_VALUES;
/** What is the return type of this function? */
private Type returnType = Type.UNKNOWN;
public Type returnType = Type.UNKNOWN;
/**
* Constructor
@ -267,6 +310,8 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
* @param flags initial flags
* @param body body of the function
* @param endParserState The parser state at the end of the parsing.
* @param module the module
* @param debugFlags the debug flags
*/
public FunctionNode(
final Source source,
@ -282,7 +327,9 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
final FunctionNode.Kind kind,
final int flags,
final Block body,
final Object endParserState) {
final Object endParserState,
final Module module,
final int debugFlags) {
super(token, finish);
this.source = source;
@ -299,7 +346,9 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
this.body = body;
this.thisProperties = 0;
this.rootClass = null;
this.endParserState = endParserState;
this.endParserState = endParserState;
this.module = module;
this.debugFlags = debugFlags;
}
private FunctionNode(
@ -335,6 +384,8 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
this.ident = functionNode.ident;
this.kind = functionNode.kind;
this.firstToken = functionNode.firstToken;
this.module = functionNode.module;
this.debugFlags = functionNode.debugFlags;
}
@Override
@ -366,23 +417,23 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
}
// quick check for extension callsite flags turned on by directives.
if ((flags & EXTENSION_CALLSITE_FLAGS) == 0) {
if ((debugFlags & DEBUG_CALLSITE_FLAGS) == 0) {
return callsiteFlags;
}
if (getFlag(IS_PROFILE)) {
if (getDebugFlag(DEBUG_PROFILE)) {
callsiteFlags |= CALLSITE_PROFILE;
}
if (getFlag(IS_TRACE_MISSES)) {
if (getDebugFlag(DEBUG_TRACE_MISSES)) {
callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_MISSES;
}
if (getFlag(IS_TRACE_VALUES)) {
if (getDebugFlag(DEBUG_TRACE_VALUES)) {
callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_ENTEREXIT | CALLSITE_TRACE_VALUES;
}
if (getFlag(IS_TRACE_ENTEREXIT)) {
if (getDebugFlag(DEBUG_TRACE_ENTEREXIT)) {
callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_ENTEREXIT;
}
@ -466,23 +517,23 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
public static int getDirectiveFlag(final String directive) {
switch (directive) {
case "nashorn callsite trace enterexit":
return IS_TRACE_ENTEREXIT;
return DEBUG_TRACE_ENTEREXIT;
case "nashorn callsite trace misses":
return IS_TRACE_MISSES;
return DEBUG_TRACE_MISSES;
case "nashorn callsite trace objects":
return IS_TRACE_VALUES;
return DEBUG_TRACE_VALUES;
case "nashorn callsite profile":
return IS_PROFILE;
return DEBUG_PROFILE;
case "nashorn print parse":
return IS_PRINT_PARSE;
return DEBUG_PRINT_PARSE;
case "nashorn print lower parse":
return IS_PRINT_LOWER_PARSE;
return DEBUG_PRINT_LOWER_PARSE;
case "nashorn print ast":
return IS_PRINT_AST;
return DEBUG_PRINT_AST;
case "nashorn print lower ast":
return IS_PRINT_LOWER_AST;
return DEBUG_PRINT_LOWER_AST;
case "nashorn print symbols":
return IS_PRINT_SYMBOLS;
return DEBUG_PRINT_SYMBOLS;
default:
// unknown/unsupported directive
return 0;
@ -578,6 +629,25 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
return setFlags(lc, flags | flag);
}
/**
* Returns the debug flags for this function.
*
* @return the debug flags
*/
public int getDebugFlags() {
return debugFlags;
}
/**
* Checks whether a debug flag is set for this function.
*
* @param debugFlag the debug flag
* @return true if the flag is set
*/
public boolean getDebugFlag(final int debugFlag) {
return (debugFlags & debugFlag) != 0;
}
/**
* Returns true if the function is the top-level program.
* @return True if this function node represents the top-level program.
@ -1065,6 +1135,86 @@ public final class FunctionNode extends LexicalContextExpression implements Flag
return setFlag(lc, IS_CACHED);
}
/**
* Checks if the function is generated in strong mode.
*
* @return true if strong mode enabled for function
*/
public boolean isStrong() {
return getFlag(ES6_IS_STRONG);
}
/**
* Checks if this is an ES6 method.
*
* @return true if the ES6 method flag is set
*/
public boolean isMethod() {
return getFlag(ES6_IS_METHOD);
}
/**
* Checks if this function uses the ES6 super binding.
*
* @return true if the ES6 super flag is set
*/
public boolean usesSuper() {
return getFlag(ES6_USES_SUPER);
}
/**
* Checks if this function directly uses the super binding.
*
* @return true if the ES6 has-direct-super flag is set
*/
public boolean hasDirectSuper() {
return getFlag(ES6_HAS_DIRECT_SUPER);
}
/**
* Checks if this is an ES6 class constructor.
*
* @return true if the ES6 class constructor flag is set
*/
public boolean isClassConstructor() {
return getFlag(ES6_IS_CLASS_CONSTRUCTOR);
}
/**
* Checks if this is an ES6 subclass constructor.
*
* @return true if the ES6 subclass constructor flag is set
*/
public boolean isSubclassConstructor() {
return getFlag(ES6_IS_SUBCLASS_CONSTRUCTOR);
}
/**
* Checks if this function uses the ES6 new-targert.
*
* @return true if the ES6 new-target flag is set
*/
public boolean usesNewTarget() {
return getFlag(ES6_USES_NEW_TARGET);
}
/**
* Checks if this is an ES6 module.
*
* @return true if this is an ES6 module
*/
public boolean isModule() {
return kind == Kind.MODULE;
}
/**
* Returns the functions's ES6 module.
*
* @return the module, or null if this function is not part of one
*/
public Module getModule() {
return module;
}
/**
* Get the compile unit used to compile this function

View File

@ -49,6 +49,11 @@ public final class IdentNode extends Expression implements PropertyKey, Function
private static final int FUTURESTRICT_NAME = 1 << 3;
private static final int IS_DECLARED_HERE = 1 << 4;
private static final int IS_DEAD = 1 << 5;
private static final int DIRECT_SUPER = 1 << 6;
private static final int REST_PARAMETER = 1 << 7;
private static final int PROTO_PROPERTY = 1 << 8;
private static final int DEFAULT_PARAMETER = 1 << 9;
private static final int DESTRUCTURED_PARAMETER = 1 << 10;
/** Identifier. */
private final String name;
@ -382,4 +387,94 @@ public final class IdentNode extends Expression implements PropertyKey, Function
public LocalVariableConversion getLocalVariableConversion() {
return conversion;
}
/**
* Checks if this is a direct super identifier
*
* @return true if the direct super flag is set
*/
public boolean isDirectSuper() {
return (flags & DIRECT_SUPER) != 0;
}
/**
* Return a new identifier with the direct super flag set.
*
* @return the new identifier
*/
public IdentNode setIsDirectSuper() {
return new IdentNode(this, name, type, flags | DIRECT_SUPER, programPoint, conversion);
}
/**
* Checks if this is a rest parameter
*
* @return true if the rest parameter flag is set
*/
public boolean isRestParameter() {
return (flags & REST_PARAMETER) != 0;
}
/**
* Return a new identifier with the rest parameter flag set.
*
* @return the new identifier
*/
public IdentNode setIsRestParameter() {
return new IdentNode(this, name, type, flags | REST_PARAMETER, programPoint, conversion);
}
/**
* Checks if this is a proto property name.
*
* @return true if this is the proto property name
*/
public boolean isProtoPropertyName() {
return (flags & PROTO_PROPERTY) != 0;
}
/**
* Return a new identifier with the proto property name flag set.
*
* @return the new identifier
*/
public IdentNode setIsProtoPropertyName() {
return new IdentNode(this, name, type, flags | PROTO_PROPERTY, programPoint, conversion);
}
/**
* Checks whether this is a default parameter.
*
* @return true if this is a default parameter
*/
public boolean isDefaultParameter() {
return (flags & DEFAULT_PARAMETER) != 0;
}
/**
* Return a new identifier with the default parameter flag set.
*
* @return the new identifier
*/
public IdentNode setIsDefaultParameter() {
return new IdentNode(this, name, type, flags | DEFAULT_PARAMETER, programPoint, conversion);
}
/**
* Checks whether this is a destructured parameter.
*
* @return true if this is a destructured parameter
*/
public boolean isDestructuredParameter() {
return (flags & DESTRUCTURED_PARAMETER) != 0;
}
/**
* Return a new identifier with the destructured parameter flag set.
*
* @return the new identifier
*/
public IdentNode setIsDestructuredParameter() {
return new IdentNode(this, name, type, flags | DESTRUCTURED_PARAMETER, programPoint, conversion);
}
}

View File

@ -47,12 +47,13 @@ public final class IndexNode extends BaseNode {
* @param index index for access
*/
public IndexNode(final long token, final int finish, final Expression base, final Expression index) {
super(token, finish, base, false);
super(token, finish, base, false, false);
this.index = index;
}
private IndexNode(final IndexNode indexNode, final Expression base, final Expression index, final boolean isFunction, final Type type, final int programPoint) {
super(indexNode, base, isFunction, type, programPoint);
private IndexNode(final IndexNode indexNode, final Expression base, final Expression index, final boolean isFunction,
final Type type, final int programPoint, final boolean isSuper) {
super(indexNode, base, isFunction, type, programPoint, isSuper);
this.index = index;
}
@ -101,7 +102,7 @@ public final class IndexNode extends BaseNode {
if (this.base == base) {
return this;
}
return new IndexNode(this, base, index, isFunction(), type, programPoint);
return new IndexNode(this, base, index, isFunction(), type, programPoint, isSuper());
}
/**
@ -113,7 +114,7 @@ public final class IndexNode extends BaseNode {
if(this.index == index) {
return this;
}
return new IndexNode(this, base, index, isFunction(), type, programPoint);
return new IndexNode(this, base, index, isFunction(), type, programPoint, isSuper());
}
@Override
@ -121,7 +122,7 @@ public final class IndexNode extends BaseNode {
if (this.type == type) {
return this;
}
return new IndexNode(this, base, index, isFunction(), type, programPoint);
return new IndexNode(this, base, index, isFunction(), type, programPoint, isSuper());
}
@Override
@ -129,7 +130,7 @@ public final class IndexNode extends BaseNode {
if (isFunction()) {
return this;
}
return new IndexNode(this, base, index, true, type, programPoint);
return new IndexNode(this, base, index, true, type, programPoint, isSuper());
}
@Override
@ -137,6 +138,14 @@ public final class IndexNode extends BaseNode {
if (this.programPoint == programPoint) {
return this;
}
return new IndexNode(this, base, index, isFunction(), type, programPoint);
return new IndexNode(this, base, index, isFunction(), type, programPoint, isSuper());
}
@Override
public IndexNode setIsSuper() {
if (isSuper()) {
return this;
}
return new IndexNode(this, base, index, isFunction(), type, programPoint, true);
}
}

View File

@ -0,0 +1,338 @@
/*
* Copyright (c) 2015, 2016, 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.ir;
import java.util.List;
/**
* ES6 Module information.
*/
public final class Module {
/** The synthetic binding name assigned to export default declarations with unnamed expressions. */
public static final String DEFAULT_EXPORT_BINDING_NAME = "*default*";
/** The {@code export default} name. */
public static final String DEFAULT_NAME = "default";
/** The {@code export *} name. */
public static final String STAR_NAME = "*";
/**
* A module ExportEntry record.
*
* @link http://www.ecma-international.org/ecma-262/6.0/#sec-source-text-module-records
*/
public static final class ExportEntry {
private final String exportName;
private final String moduleRequest;
private final String importName;
private final String localName;
private ExportEntry(final String exportName, final String moduleRequest, final String importName, final String localName) {
this.exportName = exportName;
this.moduleRequest = moduleRequest;
this.importName = importName;
this.localName = localName;
}
/**
* Creates a {@code export *} export entry.
*
* @param moduleRequest the module request
* @return the export entry
*/
public static ExportEntry exportStarFrom(final String moduleRequest) {
return new ExportEntry(null, moduleRequest, STAR_NAME, null);
}
/**
* Creates a {@code export default} export entry.
*
* @return the export entry
*/
public static ExportEntry exportDefault() {
return exportDefault(DEFAULT_EXPORT_BINDING_NAME);
}
/**
* Creates a {@code export default} export entry with a local name.
*
* @param localName the local name
* @return the export entry
*/
public static ExportEntry exportDefault(final String localName) {
return new ExportEntry(DEFAULT_NAME, null, null, localName);
}
/**
* Creates a export entry with a local name and export name.
*
* @param exportName the export name
* @param localName the local name
* @return the export entry
*/
public static ExportEntry exportSpecifier(final String exportName, final String localName) {
return new ExportEntry(exportName, null, null, localName);
}
/**
* Creates a export entry with an export name.
*
* @param exportName the export name
* @return the export entry
*/
public static ExportEntry exportSpecifier(final String exportName) {
return exportSpecifier(exportName, exportName);
}
/**
* Create a copy of this entry with the specified {@code module request} string.
*
* @param moduleRequest the module request
* @return the new export entry
*/
public ExportEntry withFrom(@SuppressWarnings("hiding") final String moduleRequest) {
return new ExportEntry(exportName, moduleRequest, localName, null);
}
/**
* Returns the entry's export name.
*
* @return the export name
*/
public String getExportName() {
return exportName;
}
/**
* Returns the entry's module request.
*
* @return the module request
*/
public String getModuleRequest() {
return moduleRequest;
}
/**
* Returns the entry's import name.
*
* @return the import name
*/
public String getImportName() {
return importName;
}
/**
* Returns the entry's local name.
*
* @return the local name
*/
public String getLocalName() {
return localName;
}
@Override
public String toString() {
return "ExportEntry [exportName=" + exportName + ", moduleRequest=" + moduleRequest + ", importName=" + importName + ", localName=" + localName + "]";
}
}
/**
* An ImportEntry record.
*
* @link http://www.ecma-international.org/ecma-262/6.0/#sec-source-text-module-records
*/
public static final class ImportEntry {
private final String moduleRequest;
private final String importName;
private final String localName;
private ImportEntry(final String moduleRequest, final String importName, final String localName) {
this.moduleRequest = moduleRequest;
this.importName = importName;
this.localName = localName;
}
/**
* Creates an import entry with default name.
*
* @param localName the local name
* @return the import entry
*/
public static ImportEntry importDefault(final String localName) {
return new ImportEntry(null, DEFAULT_NAME, localName);
}
/**
* Creates an import entry with {@code *} import name.
*
* @param localName the local name
* @return the import entry
*/
public static ImportEntry importStarAsNameSpaceFrom(final String localName) {
return new ImportEntry(null, STAR_NAME, localName);
}
/**
* Creates an import entry with the given import and local names.
*
* @param importName the import name
* @param localName the local name
* @return the import entry
*/
public static ImportEntry importSpecifier(final String importName, final String localName) {
return new ImportEntry(null, importName, localName);
}
/**
* Creates a new import entry with the given import name.
*
* @param importName the import name
* @return the import entry
*/
public static ImportEntry importSpecifier(final String importName) {
return importSpecifier(importName, importName);
}
/**
* Returns a copy of this import entry with the given module request.
*
* @param moduleRequest the module request
* @return the new import entry
*/
public ImportEntry withFrom(@SuppressWarnings("hiding") final String moduleRequest) {
return new ImportEntry(moduleRequest, importName, localName);
}
/**
* Returns the entry's module request.
*
* @return the module request
*/
public String getModuleRequest() {
return moduleRequest;
}
/**
* Returns the entry's import name.
*
* @return the import name
*/
public String getImportName() {
return importName;
}
/**
* Returns the entry's local name.
*
* @return the local name
*/
public String getLocalName() {
return localName;
}
@Override
public String toString() {
return "ImportEntry [moduleRequest=" + moduleRequest + ", importName=" + importName + ", localName=" + localName + "]";
}
}
private final List<String> requestedModules;
private final List<ImportEntry> importEntries;
private final List<ExportEntry> localExportEntries;
private final List<ExportEntry> indirectExportEntries;
private final List<ExportEntry> starExportEntries;
/**
* Creates a module with the specified requested modules and import and export entries.
*
* @param requestedModules the requested modules
* @param importEntries the import entries
* @param localExportEntries local export entries
* @param indirectExportEntries indirect export entries
* @param starExportEntries star export entries
*/
public Module(final List<String> requestedModules, final List<ImportEntry> importEntries, final List<ExportEntry> localExportEntries,
final List<ExportEntry> indirectExportEntries, final List<ExportEntry> starExportEntries) {
this.requestedModules = requestedModules;
this.importEntries = importEntries;
this.localExportEntries = localExportEntries;
this.indirectExportEntries = indirectExportEntries;
this.starExportEntries = starExportEntries;
}
/**
* Returns the list of requested modules.
*
* @return the requested modules
*/
public List<String> getRequestedModules() {
return requestedModules;
}
/**
* Returns the list of import entries.
*
* @return the import entries
*/
public List<ImportEntry> getImportEntries() {
return importEntries;
}
/**
* Returns the list of local export entries.
*
* @return the local export entries
*/
public List<ExportEntry> getLocalExportEntries() {
return localExportEntries;
}
/**
* Returns the list of indirect export entries.
*
* @return the indirect export entries
*/
public List<ExportEntry> getIndirectExportEntries() {
return indirectExportEntries;
}
/**
* Returns the list of star export entries.
*
* @return the star export entries
*/
public List<ExportEntry> getStarExportEntries() {
return starExportEntries;
}
@Override
public String toString() {
return "Module [requestedModules=" + requestedModules + ", importEntries=" + importEntries + ", localExportEntries=" + localExportEntries + ", indirectExportEntries=" +
indirectExportEntries + ", starExportEntries=" + starExportEntries + "]";
}
}

View File

@ -36,7 +36,7 @@ public final class PropertyNode extends Node {
private static final long serialVersionUID = 1L;
/** Property key. */
private final PropertyKey key;
private final Expression key;
/** Property value. */
private final Expression value;
@ -47,6 +47,12 @@ public final class PropertyNode extends Node {
/** Property getter. */
private final FunctionNode setter;
/** static property flag */
private final boolean isStatic;
/** Computed property flag */
private final boolean computed;
/**
* Constructor
*
@ -56,21 +62,27 @@ public final class PropertyNode extends Node {
* @param value the value of this property
* @param getter getter function body
* @param setter setter function body
* @param isStatic is this a static property?
* @param computed is this a computed property?
*/
public PropertyNode(final long token, final int finish, final PropertyKey key, final Expression value, final FunctionNode getter, final FunctionNode setter) {
public PropertyNode(final long token, final int finish, final Expression key, final Expression value, final FunctionNode getter, final FunctionNode setter, final boolean isStatic, final boolean computed) {
super(token, finish);
this.key = key;
this.value = value;
this.getter = getter;
this.setter = setter;
this.isStatic = isStatic;
this.computed = computed;
}
private PropertyNode(final PropertyNode propertyNode, final PropertyKey key, final Expression value, final FunctionNode getter, final FunctionNode setter) {
private PropertyNode(final PropertyNode propertyNode, final Expression key, final Expression value, final FunctionNode getter, final FunctionNode setter, final boolean isStatic, final boolean computed) {
super(propertyNode);
this.key = key;
this.value = value;
this.getter = getter;
this.setter = setter;
this.isStatic = isStatic;
this.computed = computed;
}
/**
@ -78,14 +90,14 @@ public final class PropertyNode extends Node {
* @return key name
*/
public String getKeyName() {
return key.getPropertyName();
return key instanceof PropertyKey ? ((PropertyKey) key).getPropertyName() : null;
}
@Override
public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterPropertyNode(this)) {
return visitor.leavePropertyNode(
setKey((PropertyKey)((Node)key).accept(visitor)).
setKey((Expression) key.accept(visitor)).
setValue(value == null ? null : (Expression)value.accept(visitor)).
setGetter(getter == null ? null : (FunctionNode)getter.accept(visitor)).
setSetter(setter == null ? null : (FunctionNode)setter.accept(visitor)));
@ -134,7 +146,7 @@ public final class PropertyNode extends Node {
if (this.getter == getter) {
return this;
}
return new PropertyNode(this, key, value, getter, setter);
return new PropertyNode(this, key, value, getter, setter, isStatic, computed);
}
/**
@ -142,14 +154,14 @@ public final class PropertyNode extends Node {
* @return the key
*/
public Expression getKey() {
return (Expression)key;
return key;
}
private PropertyNode setKey(final PropertyKey key) {
private PropertyNode setKey(final Expression key) {
if (this.key == key) {
return this;
}
return new PropertyNode(this, key, value, getter, setter);
return new PropertyNode(this, key, value, getter, setter, isStatic, computed);
}
/**
@ -169,7 +181,7 @@ public final class PropertyNode extends Node {
if (this.setter == setter) {
return this;
}
return new PropertyNode(this, key, value, getter, setter);
return new PropertyNode(this, key, value, getter, setter, isStatic, computed);
}
/**
@ -189,6 +201,24 @@ public final class PropertyNode extends Node {
if (this.value == value) {
return this;
}
return new PropertyNode(this, key, value, getter, setter);
}
return new PropertyNode(this, key, value, getter, setter, isStatic, computed);
}
/**
* Returns true if this is a static property.
*
* @return true if static flag is set
*/
public boolean isStatic() {
return isStatic;
}
/**
* Returns true if this is a computed property.
*
* @return true if the computed flag is set
*/
public boolean isComputed() {
return computed;
}
}

View File

@ -133,8 +133,8 @@ public abstract class NodeOperatorVisitor<T extends LexicalContext> extends Node
return enterASSIGN_SHR(binaryNode);
case ASSIGN_SUB:
return enterASSIGN_SUB(binaryNode);
case BIND:
return enterBIND(binaryNode);
case ARROW:
return enterARROW(binaryNode);
case BIT_AND:
return enterBIT_AND(binaryNode);
case BIT_OR:
@ -217,8 +217,8 @@ public abstract class NodeOperatorVisitor<T extends LexicalContext> extends Node
return leaveASSIGN_SHR(binaryNode);
case ASSIGN_SUB:
return leaveASSIGN_SUB(binaryNode);
case BIND:
return leaveBIND(binaryNode);
case ARROW:
return leaveARROW(binaryNode);
case BIT_AND:
return leaveBIT_AND(binaryNode);
case BIT_OR:
@ -735,22 +735,22 @@ public abstract class NodeOperatorVisitor<T extends LexicalContext> extends Node
}
/**
* Binary enter - callback for entering a bind operator
* Binary enter - callback for entering a arrow operator
*
* @param binaryNode the node
* @return true if traversal should continue and node children be traversed, false otherwise
*/
public boolean enterBIND(final BinaryNode binaryNode) {
public boolean enterARROW(final BinaryNode binaryNode) {
return enterDefault(binaryNode);
}
/**
* Binary leave - callback for leaving a bind operator
* Binary leave - callback for leaving a arrow operator
*
* @param binaryNode the node
* @return processed node, which will replace the original one, or the original node
*/
public Node leaveBIND(final BinaryNode binaryNode) {
public Node leaveARROW(final BinaryNode binaryNode) {
return leaveDefault(binaryNode);
}

View File

@ -33,6 +33,7 @@ import jdk.nashorn.internal.ir.BreakNode;
import jdk.nashorn.internal.ir.CallNode;
import jdk.nashorn.internal.ir.CaseNode;
import jdk.nashorn.internal.ir.CatchNode;
import jdk.nashorn.internal.ir.ClassNode;
import jdk.nashorn.internal.ir.ContinueNode;
import jdk.nashorn.internal.ir.DebuggerNode;
import jdk.nashorn.internal.ir.EmptyNode;
@ -897,5 +898,23 @@ public abstract class NodeVisitor<T extends LexicalContext> {
return leaveDefault(withNode);
}
/**
* Callback for entering a ClassNode
*
* @param classNode the node
* @return true if traversal should continue and node children be traversed, false otherwise
*/
public boolean enterClassNode(final ClassNode classNode) {
return enterDefault(classNode);
}
/**
* Callback for leaving a ClassNode
*
* @param classNode the node
* @return processed node, which will replace the original one, or the original node
*/
public Node leaveClassNode(final ClassNode classNode) {
return leaveDefault(classNode);
}
}

View File

@ -278,7 +278,12 @@ class ParserContext {
return new NodeIterator<>(ParserContextFunctionNode.class);
}
private class NodeIterator <T extends ParserContextNode> implements Iterator<T> {
public ParserContextModuleNode getCurrentModule() {
final Iterator<ParserContextModuleNode> iter = new NodeIterator<>(ParserContextModuleNode.class, getCurrentFunction());
return iter.hasNext() ? iter.next() : null;
}
private class NodeIterator<T extends ParserContextNode> implements Iterator<T> {
private int index;
private T next;
private final Class<T> clazz;

View File

@ -24,10 +24,12 @@
*/
package jdk.nashorn.internal.parser;
import java.util.HashSet;
import java.util.List;
import jdk.nashorn.internal.codegen.Namespace;
import jdk.nashorn.internal.ir.FunctionNode;
import jdk.nashorn.internal.ir.IdentNode;
import jdk.nashorn.internal.ir.Module;
/**
* ParserContextNode that represents a function that is currently being parsed
@ -46,11 +48,11 @@ class ParserContextFunctionNode extends ParserContextBaseNode {
/** Line number for function declaration */
private final int line;
/** Function node kind, see {@link FunctionNode#Kind} */
/** Function node kind, see {@link FunctionNode.Kind} */
private final FunctionNode.Kind kind;
/** List of parameter identifiers for function */
private final List<IdentNode> parameters;
private List<IdentNode> parameters;
/** Token for function start */
private final long token;
@ -61,6 +63,14 @@ class ParserContextFunctionNode extends ParserContextBaseNode {
/** Opaque node for parser end state, see {@link Parser} */
private Object endParserState;
private HashSet<String> parameterBoundNames;
private IdentNode duplicateParameterBinding;
private boolean simpleParameterList = true;
private Module module;
private int debugFlags;
/**
* @param token The token for the function
* @param ident External function name
@ -155,6 +165,10 @@ class ParserContextFunctionNode extends ParserContextBaseNode {
return parameters;
}
void setParameters(List<IdentNode> parameters) {
this.parameters = parameters;
}
/**
* Set last token
* @param token New last token
@ -194,4 +208,70 @@ class ParserContextFunctionNode extends ParserContextBaseNode {
public int getId() {
return isProgram() ? -1 : Token.descPosition(token);
}
/**
* Returns the debug flags for this function.
*
* @return the debug flags
*/
int getDebugFlags() {
return debugFlags;
}
/**
* Sets a debug flag for this function.
*
* @param debugFlag the debug flag
*/
void setDebugFlag(final int debugFlag) {
debugFlags |= debugFlag;
}
public boolean isMethod() {
return getFlag(FunctionNode.ES6_IS_METHOD) != 0;
}
public boolean isClassConstructor() {
return getFlag(FunctionNode.ES6_IS_CLASS_CONSTRUCTOR) != 0;
}
public boolean isSubclassConstructor() {
return getFlag(FunctionNode.ES6_IS_SUBCLASS_CONSTRUCTOR) != 0;
}
boolean addParameterBinding(final IdentNode bindingIdentifier) {
if (Parser.isArguments(bindingIdentifier)) {
setFlag(FunctionNode.DEFINES_ARGUMENTS);
}
if (parameterBoundNames == null) {
parameterBoundNames = new HashSet<>();
}
if (parameterBoundNames.add(bindingIdentifier.getName())) {
return true;
} else {
duplicateParameterBinding = bindingIdentifier;
return false;
}
}
public IdentNode getDuplicateParameterBinding() {
return duplicateParameterBinding;
}
public boolean isSimpleParameterList() {
return simpleParameterList;
}
public void setSimpleParameterList(final boolean simpleParameterList) {
this.simpleParameterList = simpleParameterList;
}
public Module getModule() {
return module;
}
public void setModule(final Module module) {
this.module = module;
}
}

View File

@ -0,0 +1,90 @@
/*
* Copyright (c) 2015, 2016, 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.parser;
import java.util.ArrayList;
import java.util.List;
import jdk.nashorn.internal.ir.Module;
import jdk.nashorn.internal.ir.Module.ExportEntry;
import jdk.nashorn.internal.ir.Module.ImportEntry;
/**
* ParserContextNode that represents a module.
*/
class ParserContextModuleNode extends ParserContextBaseNode {
/** Module name. */
private final String name;
private List<String> requestedModules = new ArrayList<>();
private List<ImportEntry> importEntries = new ArrayList<>();
private List<ExportEntry> localExportEntries = new ArrayList<>();
private List<ExportEntry> indirectExportEntries = new ArrayList<>();
private List<ExportEntry> starExportEntries = new ArrayList<>();
/**
* Constructor.
*
* @param name name of the module
*/
ParserContextModuleNode(final String name) {
this.name = name;
}
/**
* Returns the name of the module.
*
* @return name of the module
*/
public String getModuleName() {
return name;
}
public void addModuleRequest(final String moduleRequest) {
requestedModules.add(moduleRequest);
}
public void addImportEntry(final ImportEntry importEntry) {
importEntries.add(importEntry);
}
public void addLocalExportEntry(final ExportEntry exportEntry) {
localExportEntries.add(exportEntry);
}
public void addIndirectExportEntry(final ExportEntry exportEntry) {
indirectExportEntries.add(exportEntry);
}
public void addStarExportEntry(final ExportEntry exportEntry) {
starExportEntries.add(exportEntry);
}
public Module createModule() {
return new Module(requestedModules, importEntries, localExportEntries, indirectExportEntries, starExportEntries);
}
}

View File

@ -82,7 +82,7 @@ public enum TokenType {
ASSIGN (BINARY, "=", 2, false),
EQ (BINARY, "==", 9, true),
EQ_STRICT (BINARY, "===", 9, true),
BIND (BINARY, "=>", 9, true),
ARROW (BINARY, "=>", 2, true),
GT (BINARY, ">", 10, true),
GE (BINARY, ">=", 10, true),
SAR (BINARY, ">>", 11, true),
@ -100,6 +100,7 @@ public enum TokenType {
OR (BINARY, "||", 4, true),
RBRACE (BRACKET, "}"),
BIT_NOT (UNARY, "~", 14, false),
ELLIPSIS (UNARY, "..."),
// ECMA 7.6.1.1 Keywords, 7.6.1.2 Future Reserved Words.
// All other Java keywords are commented out.
@ -190,7 +191,10 @@ public enum TokenType {
COMMALEFT (IR, null),
DECPOSTFIX (IR, null),
INCPOSTFIX (IR, null);
INCPOSTFIX (IR, null),
SPREAD_ARGUMENT(IR, null),
SPREAD_ARRAY (IR, null),
YIELD_STAR (IR, null);
/** Next token kind in token lookup table. */
private TokenType next;
@ -251,7 +255,6 @@ public enum TokenType {
return kind == BINARY && (!noIn || this != IN) && precedence != 0;
}
public int getLength() {
assert name != null : "Token name not set";
return name.length();

View File

@ -1403,11 +1403,11 @@ public final class Context {
return null;
}
if (env._print_ast || functionNode.getFlag(FunctionNode.IS_PRINT_AST)) {
if (env._print_ast || functionNode.getDebugFlag(FunctionNode.DEBUG_PRINT_AST)) {
getErr().println(new ASTWriter(functionNode));
}
if (env._print_parse || functionNode.getFlag(FunctionNode.IS_PRINT_PARSE)) {
if (env._print_parse || functionNode.getDebugFlag(FunctionNode.DEBUG_PRINT_PARSE)) {
getErr().println(new PrintVisitor(functionNode, true, false));
}
}

View File

@ -176,6 +176,8 @@ public class DtoaBuffer {
buffer.append('0');
}
buffer.append(chars, 0, length);
} else {
decimalPoint = 1;
}
} else if (decimalPoint >= length) {
// large integer, add trailing zeroes

View File

@ -63,6 +63,27 @@ parser.error.trailing.comma.in.json=Trailing comma is not allowed in JSON
parser.error.missing.const.assignment=Missing assignment to constant "{0}"
parser.error.unterminated.template.expression=Expected } after expression in template literal
# ES6 mode error messages
parser.error.multiple.constructors=Class contains more than one constructor
parser.error.generator.constructor=Class constructor must not be a generator
parser.error.accessor.constructor=Class constructor must not be an accessor
parser.error.static.prototype.method=Static class method must not be named 'prototype'
parser.error.missing.destructuring.assignment=Missing assignment in destructuring declaration
parser.error.let.binding.for='let' is not a valid binding name in a for loop
parser.error.invalid.export=invalid export declaration
parser.error.expected.binding=expected BindingIdentifier or BindingPattern
parser.error.multiple.proto.key=property name __proto__ appears more than once in object literal
parser.error.new.target.in.function=new.target expression is only allowed in functions
parser.error.expected.target=expected 'target'
parser.error.invalid.super=invalid use of keyword super
parser.error.expected.arrow.parameter=expected arrow function parameter list
parser.error.invalid.arrow.parameter=invalid arrow function parameter
parser.error.expected.named.import=expected NameSpaceImport or NamedImports
parser.error.expected.import=expected ImportClause or ModuleSpecifier
parser.error.expected.as=expected 'as'
parser.error.expected.binding.identifier=expected BindingIdentifier
parser.error.expected.from=expected 'from'
# strict mode error messages
parser.error.strict.no.with="with" statement cannot be used in strict mode
parser.error.strict.name="{0}" cannot be used as {1} in strict mode

View File

@ -438,6 +438,9 @@ public class Shell implements PartialParser {
final File file = new File(fileName);
final ScriptFunction script = context.compileScript(sourceFor(fileName, file), global);
if (script == null || errors.getNumberOfErrors() != 0) {
if (context.getEnv()._parse_only && !errors.hasErrors()) {
continue; // No error, continue to consume all files in list
}
return COMPILATION_ERROR;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 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
@ -21,14 +21,17 @@
* questions.
*/
/**
* Check yield keyword is parsed and yield statement does nothing (yet).
* JDK-8155025: 0.001.toFixed(2) should return "0.00" not "0"
*
* @test
* @run
*/
function func() {
yield 2;
for (var i = 0, zeros=""; i <= 9; i++, zeros += "0") {
var n = Number("0." + zeros + "1");
for (var j = 1; j <= i + 3; j++) {
print(n + ".toFixed(" + j + ")=" + n.toFixed(j));
}
}

View File

@ -0,0 +1,75 @@
0.1.toFixed(1)=0.1
0.1.toFixed(2)=0.10
0.1.toFixed(3)=0.100
0.01.toFixed(1)=0.0
0.01.toFixed(2)=0.01
0.01.toFixed(3)=0.010
0.01.toFixed(4)=0.0100
0.001.toFixed(1)=0.0
0.001.toFixed(2)=0.00
0.001.toFixed(3)=0.001
0.001.toFixed(4)=0.0010
0.001.toFixed(5)=0.00100
0.0001.toFixed(1)=0.0
0.0001.toFixed(2)=0.00
0.0001.toFixed(3)=0.000
0.0001.toFixed(4)=0.0001
0.0001.toFixed(5)=0.00010
0.0001.toFixed(6)=0.000100
0.00001.toFixed(1)=0.0
0.00001.toFixed(2)=0.00
0.00001.toFixed(3)=0.000
0.00001.toFixed(4)=0.0000
0.00001.toFixed(5)=0.00001
0.00001.toFixed(6)=0.000010
0.00001.toFixed(7)=0.0000100
0.000001.toFixed(1)=0.0
0.000001.toFixed(2)=0.00
0.000001.toFixed(3)=0.000
0.000001.toFixed(4)=0.0000
0.000001.toFixed(5)=0.00000
0.000001.toFixed(6)=0.000001
0.000001.toFixed(7)=0.0000010
0.000001.toFixed(8)=0.00000100
1e-7.toFixed(1)=0.0
1e-7.toFixed(2)=0.00
1e-7.toFixed(3)=0.000
1e-7.toFixed(4)=0.0000
1e-7.toFixed(5)=0.00000
1e-7.toFixed(6)=0.000000
1e-7.toFixed(7)=0.0000001
1e-7.toFixed(8)=0.00000010
1e-7.toFixed(9)=0.000000100
1e-8.toFixed(1)=0.0
1e-8.toFixed(2)=0.00
1e-8.toFixed(3)=0.000
1e-8.toFixed(4)=0.0000
1e-8.toFixed(5)=0.00000
1e-8.toFixed(6)=0.000000
1e-8.toFixed(7)=0.0000000
1e-8.toFixed(8)=0.00000001
1e-8.toFixed(9)=0.000000010
1e-8.toFixed(10)=0.0000000100
1e-9.toFixed(1)=0.0
1e-9.toFixed(2)=0.00
1e-9.toFixed(3)=0.000
1e-9.toFixed(4)=0.0000
1e-9.toFixed(5)=0.00000
1e-9.toFixed(6)=0.000000
1e-9.toFixed(7)=0.0000000
1e-9.toFixed(8)=0.00000000
1e-9.toFixed(9)=0.000000001
1e-9.toFixed(10)=0.0000000010
1e-9.toFixed(11)=0.00000000100
1e-10.toFixed(1)=0.0
1e-10.toFixed(2)=0.00
1e-10.toFixed(3)=0.000
1e-10.toFixed(4)=0.0000
1e-10.toFixed(5)=0.00000
1e-10.toFixed(6)=0.000000
1e-10.toFixed(7)=0.0000000
1e-10.toFixed(8)=0.00000000
1e-10.toFixed(9)=0.000000000
1e-10.toFixed(10)=0.0000000001
1e-10.toFixed(11)=0.00000000010
1e-10.toFixed(12)=0.000000000100

View File

@ -0,0 +1,94 @@
/*
* Copyright (c) 2016, 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-8134503: support ES6 parsing in Nashorn
*
* @test
* @option --language=es6
* @option --parse-only
*/
[].map(v => v + 1);
class A extends B.C {
constructor(a, b) {
super(a, b);
}
someMethod(c) {
super.someMethod();
}
get g() {
return this.g;
}
set s(t) {
this.t = t;
}
static m() {
return k;
}
}
var obj = {
__proto__: theProtoObj,
handler,
r() {
return super.m();
},
[ '__' + (() => 'x')() ]: 1,
*q (x, y) {
yield 1;
}
};
var [a, , b] = [1, 2, 3];
var { x: a, y: { z: b }, w: c } = abc();
var {a, b, c} = abc();
var o = { x, y };
function g({name: x}) {
return x;
}
foo(a, ...b);
var c = [ ...s ];
var [a] = [];
var [a = 1] = [];
var f = {
[Symbol.iterator]: function*() {
var cur = 1;
for (;;) {
yield cur;
}
}
};

View File

@ -1,3 +1,3 @@
test/script/error/NASHORN-154/function_mult_params_in_strict.js:38:14 strict mode function cannot have duplicate parameter name "x"
test/script/error/NASHORN-154/function_mult_params_in_strict.js:38:17 strict mode function cannot have duplicate parameter name "x"
function func(x, x) {}
^
^

View File

@ -100,7 +100,7 @@
"startPosition": "1181",
"properties": [
{
"endPosition": "1185",
"endPosition": "1187",
"kind": "PROPERTY",
"value": {
"endPosition": "1187",
@ -2386,7 +2386,7 @@
"startPosition": "1139",
"properties": [
{
"endPosition": "1143",
"endPosition": "1146",
"kind": "PROPERTY",
"value": {
"endPosition": "1146",
@ -2403,7 +2403,7 @@
}
},
{
"endPosition": "1150",
"endPosition": "1152",
"kind": "PROPERTY",
"value": {
"endPosition": "1152",
@ -2443,7 +2443,7 @@
"startPosition": "1160",
"properties": [
{
"endPosition": "1166",
"endPosition": "1169",
"kind": "PROPERTY",
"value": {
"endPosition": "1169",
@ -2460,7 +2460,7 @@
}
},
{
"endPosition": "1175",
"endPosition": "1177",
"kind": "PROPERTY",
"value": {
"endPosition": "1177",
@ -2914,7 +2914,7 @@
"startPosition": "1178",
"properties": [
{
"endPosition": "1182",
"endPosition": "1184",
"kind": "PROPERTY",
"value": {
"endPosition": "1184",
@ -3395,7 +3395,7 @@
"startPosition": "1200",
"properties": [
{
"endPosition": "1206",
"endPosition": "1214",
"kind": "PROPERTY",
"value": {
"endPosition": "1214",
@ -4709,11 +4709,11 @@
,
{
"fileName": "parsernegativetests/strict_repeatparam.js",
"code": "ident (1119, 1)",
"columnNumber": "14",
"code": "ident (1122, 1)",
"columnNumber": "17",
"kind": "ERROR",
"position": "1119",
"message": "parsernegativetests/strict_repeatparam.js:31:14 strict mode function cannot have duplicate parameter name \"x\"\nfunction func(x, x) {}\n ^",
"position": "1122",
"message": "parsernegativetests/strict_repeatparam.js:31:17 strict mode function cannot have duplicate parameter name \"x\"\nfunction func(x, x) {}\n ^",
"lineNumber": "31"
}
,

View File

@ -6,10 +6,10 @@ with_stat.js:2:7 Expected ; but found )
with({}) {}
^
repeat_param.js:2:15 strict mode function cannot have duplicate parameter name "x"
repeat_param.js:2:18 strict mode function cannot have duplicate parameter name "x"
function func(x, x) {}
^
^
repeat_prop.js:2:22 Property "foo" already defined
var obj = { foo: 34, foo: 'hello' };

View File

@ -74,7 +74,7 @@
"properties": [
{
"getter": "null",
"endPosition": "74",
"endPosition": "76",
"kind": "PROPERTY",
"setter": "null",
"value": {

View File

@ -6,7 +6,7 @@
"properties": [
{
"getter": "null",
"endPosition": "8",
"endPosition": "12",
"kind": "PROPERTY",
"setter": "null",
"value": {
@ -38,7 +38,7 @@
"properties": [
{
"getter": "null",
"endPosition": "34",
"endPosition": "37",
"kind": "PROPERTY",
"setter": "null",
"value": {
@ -57,7 +57,7 @@
},
{
"getter": "null",
"endPosition": "41",
"endPosition": "43",
"kind": "PROPERTY",
"setter": "null",
"value": {
@ -83,7 +83,7 @@
"properties": [
{
"getter": "null",
"endPosition": "57",
"endPosition": "60",
"kind": "PROPERTY",
"setter": "null",
"value": {
@ -102,7 +102,7 @@
},
{
"getter": "null",
"endPosition": "66",
"endPosition": "68",
"kind": "PROPERTY",
"setter": "null",
"value": {

View File

@ -1,7 +1,7 @@
[
{
"getter": "null",
"endPosition": "17",
"endPosition": "22",
"kind": "PROPERTY",
"setter": "null",
"value": {
@ -20,7 +20,7 @@
},
{
"getter": "null",
"endPosition": "31",
"endPosition": "38",
"kind": "PROPERTY",
"setter": "null",
"value": {
@ -45,7 +45,7 @@
},
{
"getter": "null",
"endPosition": "46",
"endPosition": "61",
"kind": "PROPERTY",
"setter": "null",
"value": {
@ -72,7 +72,7 @@
},
{
"getter": "null",
"endPosition": "69",
"endPosition": "72",
"kind": "PROPERTY",
"setter": "null",
"value": {

View File

@ -80,7 +80,7 @@
"properties": [
{
"getter": "null",
"endPosition": "97",
"endPosition": "105",
"kind": "PROPERTY",
"setter": "null",
"value": {

View File

@ -49,7 +49,7 @@
"properties": [
{
"getter": "null",
"endPosition": "34",
"endPosition": "39",
"kind": "PROPERTY",
"setter": "null",
"value": {

View File

@ -194,9 +194,9 @@ public final class ScriptRunnable extends AbstractScriptRunnable implements ITes
pb.redirectError(errorFileHandle);
final Process process = pb.start();
process.waitFor();
final int exitCode = process.waitFor();
if (errorFileHandle.length() > 0) {
if (exitCode != 0 || errorFileHandle.length() > 0) {
if (expectRunFailure) {
return;
}