57 import java.util.List; |
57 import java.util.List; |
58 import java.util.ListIterator; |
58 import java.util.ListIterator; |
59 import java.util.Map; |
59 import java.util.Map; |
60 import java.util.Set; |
60 import java.util.Set; |
61 import jdk.nashorn.internal.ir.AccessNode; |
61 import jdk.nashorn.internal.ir.AccessNode; |
|
62 import jdk.nashorn.internal.ir.BaseNode; |
62 import jdk.nashorn.internal.ir.BinaryNode; |
63 import jdk.nashorn.internal.ir.BinaryNode; |
63 import jdk.nashorn.internal.ir.Block; |
64 import jdk.nashorn.internal.ir.Block; |
64 import jdk.nashorn.internal.ir.CatchNode; |
65 import jdk.nashorn.internal.ir.CatchNode; |
65 import jdk.nashorn.internal.ir.Expression; |
66 import jdk.nashorn.internal.ir.Expression; |
66 import jdk.nashorn.internal.ir.ForNode; |
67 import jdk.nashorn.internal.ir.ForNode; |
733 return binaryNode; |
734 return binaryNode; |
734 } |
735 } |
735 |
736 |
736 @Override |
737 @Override |
737 public Node leaveUnaryNode(final UnaryNode unaryNode) { |
738 public Node leaveUnaryNode(final UnaryNode unaryNode) { |
738 switch (unaryNode.tokenType()) { |
739 if (unaryNode.tokenType() == TokenType.TYPEOF) { |
739 case DELETE: |
|
740 return leaveDELETE(unaryNode); |
|
741 case TYPEOF: |
|
742 return leaveTYPEOF(unaryNode); |
740 return leaveTYPEOF(unaryNode); |
743 default: |
741 } else { |
744 return super.leaveUnaryNode(unaryNode); |
742 return super.leaveUnaryNode(unaryNode); |
745 } |
743 } |
746 } |
|
747 |
|
748 private Node leaveDELETE(final UnaryNode unaryNode) { |
|
749 final FunctionNode currentFunctionNode = lc.getCurrentFunction(); |
|
750 final boolean strictMode = currentFunctionNode.isStrict(); |
|
751 final Expression rhs = unaryNode.getExpression(); |
|
752 final Expression strictFlagNode = (Expression)LiteralNode.newInstance(unaryNode, strictMode).accept(this); |
|
753 |
|
754 Request request = Request.DELETE; |
|
755 final List<Expression> args = new ArrayList<>(); |
|
756 |
|
757 if (rhs instanceof IdentNode) { |
|
758 final IdentNode ident = (IdentNode)rhs; |
|
759 // If this is a declared variable or a function parameter, delete always fails (except for globals). |
|
760 final String name = ident.getName(); |
|
761 final Symbol symbol = ident.getSymbol(); |
|
762 |
|
763 if (symbol.isThis()) { |
|
764 // Can't delete "this", ignore and return true |
|
765 return LiteralNode.newInstance(unaryNode, true); |
|
766 } |
|
767 final Expression literalNode = LiteralNode.newInstance(unaryNode, name); |
|
768 final boolean failDelete = strictMode || (!symbol.isScope() && (symbol.isParam() || (symbol.isVar() && !symbol.isProgramLevel()))); |
|
769 |
|
770 if (!failDelete) { |
|
771 args.add(compilerConstantIdentifier(SCOPE)); |
|
772 } |
|
773 args.add(literalNode); |
|
774 args.add(strictFlagNode); |
|
775 |
|
776 if (failDelete) { |
|
777 request = Request.FAIL_DELETE; |
|
778 } else if ((symbol.isGlobal() && !symbol.isFunctionDeclaration()) || symbol.isProgramLevel()) { |
|
779 request = Request.SLOW_DELETE; |
|
780 } |
|
781 } else if (rhs instanceof AccessNode) { |
|
782 final Expression base = ((AccessNode)rhs).getBase(); |
|
783 final String property = ((AccessNode)rhs).getProperty(); |
|
784 |
|
785 args.add(base); |
|
786 args.add(LiteralNode.newInstance(unaryNode, property)); |
|
787 args.add(strictFlagNode); |
|
788 |
|
789 } else if (rhs instanceof IndexNode) { |
|
790 final IndexNode indexNode = (IndexNode)rhs; |
|
791 final Expression base = indexNode.getBase(); |
|
792 final Expression index = indexNode.getIndex(); |
|
793 |
|
794 args.add(base); |
|
795 args.add(index); |
|
796 args.add(strictFlagNode); |
|
797 |
|
798 } else { |
|
799 throw new AssertionError("Unexpected delete with " + rhs.getClass().getName() + " expression"); |
|
800 } |
|
801 return new RuntimeNode(unaryNode, request, args); |
|
802 } |
744 } |
803 |
745 |
804 @Override |
746 @Override |
805 public Node leaveForNode(final ForNode forNode) { |
747 public Node leaveForNode(final ForNode forNode) { |
806 if (forNode.isForInOrOf()) { |
748 if (forNode.isForInOrOf()) { |