Buggy code:
//*  * Copyright 2004 The Closure Compiler Authors.  *  * Licensed under the Apache License, Version 2.0 (the "License");  * you may not use this file except in compliance with the License.  * You may obtain a copy of the License at  *  *     http: *  * Unless required by applicable law or agreed to in writing, software  * distributed under the License is distributed on an "AS IS" BASIS,  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  * See the License for the specific language governing permissions and  * limitations under the License.  *//  package com.google.javascript.jscomp;  import com.google.common.base.Charsets; import com.google.common.base.Preconditions; import com.google.common.collect.Maps; import com.google.javascript.jscomp.CompilerOptions.LanguageMode; import com.google.javascript.rhino.Node; import com.google.javascript.rhino.Token; import com.google.javascript.rhino.TokenStream;  import java.io.IOException; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import java.util.Map;  //**  * CodeGenerator generates codes from a parse tree, sending it to the specified  * CodeConsumer.  *  *// class CodeGenerator {   private static final String LT_ESCAPED = "\\x3c";   private static final String GT_ESCAPED = "\\x3e";      private final Map<String, String> escapedJsStrings = Maps.newHashMap();    private static final char[] HEX_CHARS       = { '0', '1', '2', '3', '4', '5', '6', '7',           '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };    private final CodeConsumer cc;    private final CharsetEncoder outputCharsetEncoder;    private final boolean preferSingleQuotes;   private final boolean trustedStrings;   private final LanguageMode languageMode;    private CodeGenerator(CodeConsumer consumer) {     cc = consumer;     outputCharsetEncoder = null;     preferSingleQuotes = false;     trustedStrings = true;     languageMode = LanguageMode.ECMASCRIPT5;   }    static CodeGenerator forCostEstimation(CodeConsumer consumer) {     return new CodeGenerator(consumer);   }    CodeGenerator(       CodeConsumer consumer,       CompilerOptions options) {     cc = consumer;      Charset outputCharset = options.getOutputCharset();     if (outputCharset == null || outputCharset == Charsets.US_ASCII) {                               this.outputCharsetEncoder = null;     } else {       this.outputCharsetEncoder = outputCharset.newEncoder();     }     this.preferSingleQuotes = options.preferSingleQuotes;     this.trustedStrings = options.trustedStrings;     this.languageMode = options.getLanguageOut();   }    //**    * Insert a ECMASCRIPT 5 strict annotation.    *//   public void tagAsStrict() {     add("'use strict';");   }    void add(String str) {     cc.add(str);   }    private void addIdentifier(String identifier) {     cc.addIdentifier(identifierEscape(identifier));   }    void add(Node n) {     add(n, Context.OTHER);   }    void add(Node n, Context context) {     if (!cc.continueProcessing()) {       return;     }      int type = n.getType();     String opstr = NodeUtil.opToStr(type);     int childCount = n.getChildCount();     Node first = n.getFirstChild();     Node last = n.getLastChild();          if (opstr != null && first != last) {       Preconditions.checkState(           childCount == 2,           "Bad binary operator \"%s\": expected 2 arguments but got %s",           opstr, childCount);       int p = NodeUtil.precedence(type);                    Context rhsContext = getContextForNoInOperator(context);                          if (last.getType() == type &&           NodeUtil.isAssociative(type)) {         addExpr(first, p, context);         cc.addOp(opstr, true);         addExpr(last, p, rhsContext);       } else if (NodeUtil.isAssignmentOp(n) && NodeUtil.isAssignmentOp(last)) {                 addExpr(first, p, context);         cc.addOp(opstr, true);         addExpr(last, p, rhsContext);       } else {         unrollBinaryOperator(n, type, opstr, context, rhsContext, p, p + 1);       }       return;     }      cc.startSourceMapping(n);      switch (type) {       case Token.TRY: {         Preconditions.checkState(first.getNext().isBlock() &&                 !first.getNext().hasMoreThanOneChild());         Preconditions.checkState(childCount >= 2 && childCount <= 3);          add("try");         add(first, Context.PRESERVE_BLOCK);                          Node catchblock = first.getNext().getFirstChild();         if (catchblock != null) {           add(catchblock);         }          if (childCount == 3) {           add("finally");           add(last, Context.PRESERVE_BLOCK);         }         break;       }        case Token.CATCH:         Preconditions.checkState(childCount == 2);         add("catch(");         add(first);         add(")");         add(last, Context.PRESERVE_BLOCK);         break;        case Token.THROW:         Preconditions.checkState(childCount == 1);         add("throw");         add(first);                          cc.endStatement(true);         break;        case Token.RETURN:         add("return");         if (childCount == 1) {           add(first);         } else {           Preconditions.checkState(childCount == 0);         }         cc.endStatement();         break;        case Token.VAR:         if (first != null) {           add("var ");           addList(first, false, getContextForNoInOperator(context));         }         break;        case Token.LABEL_NAME:         Preconditions.checkState(!n.getString().isEmpty());         addIdentifier(n.getString());         break;        case Token.NAME:         if (first == null || first.isEmpty()) {           addIdentifier(n.getString());         } else {           Preconditions.checkState(childCount == 1);           addIdentifier(n.getString());           cc.addOp("=", true);           if (first.isComma()) {             addExpr(first, NodeUtil.precedence(Token.ASSIGN), Context.OTHER);           } else {                                     addExpr(first, 0, getContextForNoInOperator(context));           }         }         break;        case Token.ARRAYLIT:         add("[");         addArrayList(first);         add("]");         break;        case Token.PARAM_LIST:         add("(");         addList(first);         add(")");         break;        case Token.COMMA:         Preconditions.checkState(childCount == 2);         unrollBinaryOperator(n, Token.COMMA, ",", context,             getContextForNoInOperator(context), 0, 0);         break;        case Token.NUMBER:         Preconditions.checkState(childCount == 0);         cc.addNumber(n.getDouble());         break;        case Token.TYPEOF:       case Token.VOID:       case Token.NOT:       case Token.BITNOT:       case Token.POS: {                 Preconditions.checkState(childCount == 1);         cc.addOp(NodeUtil.opToStrNoFail(type), false);         addExpr(first, NodeUtil.precedence(type), Context.OTHER);         break;       }        case Token.NEG: {         Preconditions.checkState(childCount == 1);                                  if (n.getFirstChild().isNumber()) {           cc.addNumber(-n.getFirstChild().getDouble());         } else {           cc.addOp(NodeUtil.opToStrNoFail(type), false);           addExpr(first, NodeUtil.precedence(type), Context.OTHER);         }          break;       }        case Token.HOOK: {         Preconditions.checkState(childCount == 3);         int p = NodeUtil.precedence(type);        <START_BUG> Context rhsContext = Context.OTHER; <END_BUG>         addExpr(first, p + 1, context);         cc.addOp("?", true);         addExpr(first.getNext(), 1, rhsContext);         cc.addOp(":", true);         addExpr(last, 1, rhsContext);         break;       }        case Token.REGEXP:         if (!first.isString() ||             !last.isString()) {           throw new Error("Expected children to be strings");         }          String regexp = regexpEscape(first.getString(), outputCharsetEncoder);                  if (childCount == 2) {           add(regexp + last.getString());         } else {           Preconditions.checkState(childCount == 1);           add(regexp);         }         break;        case Token.FUNCTION:         if (n.getClass() != Node.class) {           throw new Error("Unexpected Node subclass.");         }         Preconditions.checkState(childCount == 3);         boolean funcNeedsParens = (context == Context.START_OF_EXPR);         if (funcNeedsParens) {           add("(");         }          add("function");         add(first);          add(first.getNext());         add(last, Context.PRESERVE_BLOCK);         cc.endFunction(context == Context.STATEMENT);          if (funcNeedsParens) {           add(")");         }         break;        case Token.GETTER_DEF:       case Token.SETTER_DEF:         Preconditions.checkState(n.getParent().isObjectLit());         Preconditions.checkState(childCount == 1);         Preconditions.checkState(first.isFunction());                  Preconditions.checkState(first.getFirstChild().getString().isEmpty());         if (type == Token.GETTER_DEF) {                     Preconditions.checkState(!first.getChildAtIndex(1).hasChildren());           add("get ");         } else {                     Preconditions.checkState(first.getChildAtIndex(1).hasOneChild());           add("set ");         }                  String name = n.getString();         Node fn = first;         Node parameters = fn.getChildAtIndex(1);         Node body = fn.getLastChild();                  if (!n.isQuotedString() &&             TokenStream.isJSIdentifier(name) &&                                     NodeUtil.isLatin(name)) {           add(name);         } else {                     double d = getSimpleNumber(name);           if (!Double.isNaN(d)) {             cc.addNumber(d);           } else {             addJsString(n);           }         }          add(parameters);         add(body, Context.PRESERVE_BLOCK);         break;        case Token.SCRIPT:       case Token.BLOCK: {         if (n.getClass() != Node.class) {           throw new Error("Unexpected Node subclass.");         }         boolean preserveBlock = context == Context.PRESERVE_BLOCK;         if (preserveBlock) {           cc.beginBlock();         }          boolean preferLineBreaks =             type == Token.SCRIPT ||             (type == Token.BLOCK &&                 !preserveBlock &&                 n.getParent() != null &&                 n.getParent().isScript());         for (Node c = first; c != null; c = c.getNext()) {           add(c, Context.STATEMENT);                      if (c.isVar()) {             cc.endStatement();           }            if (c.isFunction()) {             cc.maybeLineBreak();           }                                if (preferLineBreaks) {             cc.notePreferredLineBreak();           }         }         if (preserveBlock) {           cc.endBlock(cc.breakAfterBlockFor(n, context == Context.STATEMENT));         }         break;       }        case Token.FOR:         if (childCount == 4) {           add("for(");           if (first.isVar()) {             add(first, Context.IN_FOR_INIT_CLAUSE);           } else {             addExpr(first, 0, Context.IN_FOR_INIT_CLAUSE);           }           add(";");           add(first.getNext());           add(";");           add(first.getNext().getNext());           add(")");           addNonEmptyStatement(               last, getContextForNonEmptyExpression(context), false);         } else {           Preconditions.checkState(childCount == 3);           add("for(");           add(first);           add("in");           add(first.getNext());           add(")");           addNonEmptyStatement(               last, getContextForNonEmptyExpression(context), false);         }         break;        case Token.DO:         Preconditions.checkState(childCount == 2);         add("do");         addNonEmptyStatement(first, Context.OTHER, false);         add("while(");         add(last);         add(")");         cc.endStatement();         break;        case Token.WHILE:         Preconditions.checkState(childCount == 2);         add("while(");         add(first);         add(")");         addNonEmptyStatement(             last, getContextForNonEmptyExpression(context), false);         break;        case Token.EMPTY:         Preconditions.checkState(childCount == 0);         break;        case Token.GETPROP: {         Preconditions.checkState(             childCount == 2,             "Bad GETPROP: expected 2 children, but got %s", childCount);         Preconditions.checkState(             last.isString(),             "Bad GETPROP: RHS should be STRING");         boolean needsParens = (first.isNumber());         if (needsParens) {           add("(");         }         addExpr(first, NodeUtil.precedence(type), context);         if (needsParens) {           add(")");         }         if (this.languageMode == LanguageMode.ECMASCRIPT3             && TokenStream.isKeyword(last.getString())) {                     add("[");           add(last);           add("]");         } else {           add(".");           addIdentifier(last.getString());         }         break;       }        case Token.GETELEM:         Preconditions.checkState(             childCount == 2,             "Bad GETELEM: expected 2 children but got %s", childCount);         addExpr(first, NodeUtil.precedence(type), context);         add("[");         add(first.getNext());         add("]");         break;        case Token.WITH:         Preconditions.checkState(childCount == 2);         add("with(");         add(first);         add(")");         addNonEmptyStatement(             last, getContextForNonEmptyExpression(context), false);         break;        case Token.INC:       case Token.DEC: {         Preconditions.checkState(childCount == 1);         String o = type == Token.INC ? "++" : "--";         int postProp = n.getIntProp(Node.INCRDECR_PROP);                         if (postProp != 0) {           addExpr(first, NodeUtil.precedence(type), context);           cc.addOp(o, false);         } else {           cc.addOp(o, false);           add(first);         }         break;       }        case Token.CALL:                                                                                 if (isIndirectEval(first)             || n.getBooleanProp(Node.FREE_CALL) && NodeUtil.isGet(first)) {           add("(0,");           addExpr(first, NodeUtil.precedence(Token.COMMA), Context.OTHER);           add(")");         } else {           addExpr(first, NodeUtil.precedence(type), context);         }         add("(");         addList(first.getNext());         add(")");         break;        case Token.IF:         boolean hasElse = childCount == 3;         boolean ambiguousElseClause =             context == Context.BEFORE_DANGLING_ELSE && !hasElse;         if (ambiguousElseClause) {           cc.beginBlock();         }          add("if(");         add(first);         add(")");          if (hasElse) {           addNonEmptyStatement(               first.getNext(), Context.BEFORE_DANGLING_ELSE, false);           add("else");           addNonEmptyStatement(               last, getContextForNonEmptyExpression(context), false);         } else {           addNonEmptyStatement(first.getNext(), Context.OTHER, false);           Preconditions.checkState(childCount == 2);         }          if (ambiguousElseClause) {           cc.endBlock();         }         break;        case Token.NULL:         Preconditions.checkState(childCount == 0);         cc.addConstant("null");         break;        case Token.THIS:         Preconditions.checkState(childCount == 0);         add("this");         break;        case Token.FALSE:         Preconditions.checkState(childCount == 0);         cc.addConstant("false");         break;        case Token.TRUE:         Preconditions.checkState(childCount == 0);         cc.addConstant("true");         break;        case Token.CONTINUE:         Preconditions.checkState(childCount <= 1);         add("continue");         if (childCount == 1) {           if (!first.isLabelName()) {             throw new Error("Unexpected token type. Should be LABEL_NAME.");           }           add(" ");           add(first);         }         cc.endStatement();         break;        case Token.DEBUGGER:         Preconditions.checkState(childCount == 0);         add("debugger");         cc.endStatement();         break;        case Token.BREAK:         Preconditions.checkState(childCount <= 1);         add("break");         if (childCount == 1) {           if (!first.isLabelName()) {             throw new Error("Unexpected token type. Should be LABEL_NAME.");           }           add(" ");           add(first);         }         cc.endStatement();         break;        case Token.EXPR_RESULT:         Preconditions.checkState(childCount == 1);         add(first, Context.START_OF_EXPR);         cc.endStatement();         break;        case Token.NEW:         add("new ");         int precedence = NodeUtil.precedence(type);                                  if (NodeUtil.containsType(             first, Token.CALL, NodeUtil.MATCH_NOT_FUNCTION)) {           precedence = NodeUtil.precedence(first.getType()) + 1;         }         addExpr(first, precedence, Context.OTHER);                  Node next = first.getNext();         if (next != null) {           add("(");           addList(next);           add(")");         }         break;        case Token.STRING_KEY:         Preconditions.checkState(             childCount == 1, "Object lit key must have 1 child");         addJsString(n);         break;        case Token.STRING:         Preconditions.checkState(             childCount == 0, "A string may not have children");         addJsString(n);         break;        case Token.DELPROP:         Preconditions.checkState(childCount == 1);         add("delete ");         add(first);         break;        case Token.OBJECTLIT: {         boolean needsParens = (context == Context.START_OF_EXPR);         if (needsParens) {           add("(");         }         add("{");         for (Node c = first; c != null; c = c.getNext()) {           if (c != first) {             cc.listSeparator();           }            if (c.isGetterDef() || c.isSetterDef()) {             add(c);           } else {             Preconditions.checkState(c.isStringKey());             String key = c.getString();                                     if (!c.isQuotedString()                 && !(languageMode == LanguageMode.ECMASCRIPT3                     && TokenStream.isKeyword(key))                 && TokenStream.isJSIdentifier(key)                                                 && NodeUtil.isLatin(key)) {               add(key);             } else {                             double d = getSimpleNumber(key);               if (!Double.isNaN(d)) {                 cc.addNumber(d);               } else {                 addExpr(c, 1, Context.OTHER);               }             }             add(":");             addExpr(c.getFirstChild(), 1, Context.OTHER);           }         }         add("}");         if (needsParens) {           add(")");         }         break;       }        case Token.SWITCH:         add("switch(");         add(first);         add(")");         cc.beginBlock();         addAllSiblings(first.getNext());         cc.endBlock(context == Context.STATEMENT);         break;        case Token.CASE:         Preconditions.checkState(childCount == 2);         add("case ");         add(first);         addCaseBody(last);         break;        case Token.DEFAULT_CASE:         Preconditions.checkState(childCount == 1);         add("default");         addCaseBody(first);         break;        case Token.LABEL:         Preconditions.checkState(childCount == 2);         if (!first.isLabelName()) {           throw new Error("Unexpected token type. Should be LABEL_NAME.");         }         add(first);         add(":");         addNonEmptyStatement(             last, getContextForNonEmptyExpression(context), true);         break;        case Token.CAST:         add("(");         add(first);         add(")");         break;        default:         throw new Error("Unknown type " + type + "\n" + n.toStringTree());     }      cc.endSourceMapping(n);   }    //**    * We could use addList recursively here, but sometimes we produce    * very deeply nested operators and run out of stack space, so we    * just unroll the recursion when possible.    *    * We assume nodes are left-recursive.    *//   private void unrollBinaryOperator(       Node n, int op, String opStr, Context context,       Context rhsContext, int leftPrecedence, int rightPrecedence) {     Node firstNonOperator = n.getFirstChild();     while (firstNonOperator.getType() == op) {       firstNonOperator = firstNonOperator.getFirstChild();     }      addExpr(firstNonOperator, leftPrecedence, context);      Node current = firstNonOperator;     do {       current = current.getParent();       cc.addOp(opStr, true);       addExpr(current.getFirstChild().getNext(), rightPrecedence, rhsContext);     } while (current != n);   }    static boolean isSimpleNumber(String s) {     int len = s.length();     if (len == 0) {       return false;     }     for (int index = 0; index < len; index++) {       char c = s.charAt(index);       if (c < '0' || c > '9') {         return false;       }     }     return len == 1 || s.charAt(0) != '0';   }    static double getSimpleNumber(String s) {     if (isSimpleNumber(s)) {       try {         long l = Long.parseLong(s);         if (l < NodeUtil.MAX_POSITIVE_INTEGER_NUMBER) {           return l;         }       } catch (NumberFormatException e) {               }     }     return Double.NaN;   }    //**    * @return Whether the name is an indirect eval.    *//   private boolean isIndirectEval(Node n) {     return n.isName() && "eval".equals(n.getString()) &&         !n.getBooleanProp(Node.DIRECT_EVAL);   }    //**    * Adds a block or expression, substituting a VOID with an empty statement.    * This is used for "for (...);" and "if (...);" type statements.    *    * @param n The node to print.    * @param context The context to determine how the node should be printed.    *//   private void addNonEmptyStatement(       Node n, Context context, boolean allowNonBlockChild) {     Node nodeToProcess = n;      if (!allowNonBlockChild && !n.isBlock()) {       throw new Error("Missing BLOCK child.");     }              if (n.isBlock()) {       int count = getNonEmptyChildCount(n, 2);       if (count == 0) {         if (cc.shouldPreserveExtraBlocks()) {           cc.beginBlock();           cc.endBlock(cc.breakAfterBlockFor(n, context == Context.STATEMENT));         } else {           cc.endStatement(true);         }         return;       }        if (count == 1) {                                 Node firstAndOnlyChild = getFirstNonEmptyChild(n);         boolean alwaysWrapInBlock = cc.shouldPreserveExtraBlocks();         if (alwaysWrapInBlock || isOneExactlyFunctionOrDo(firstAndOnlyChild)) {           cc.beginBlock();           add(firstAndOnlyChild, Context.STATEMENT);           cc.maybeLineBreak();           cc.endBlock(cc.breakAfterBlockFor(n, context == Context.STATEMENT));           return;         } else {                     nodeToProcess = firstAndOnlyChild;         }       }        if (count > 1) {         context = Context.PRESERVE_BLOCK;       }     }      if (nodeToProcess.isEmpty()) {       cc.endStatement(true);     } else {       add(nodeToProcess, context);                    if (nodeToProcess.isVar()) {         cc.endStatement();       }     }   }    //**    * @return Whether the Node is a DO or FUNCTION (with or without    * labels).    *//   private boolean isOneExactlyFunctionOrDo(Node n) {     if (n.isLabel()) {       Node labeledStatement = n.getLastChild();       if (!labeledStatement.isBlock()) {         return isOneExactlyFunctionOrDo(labeledStatement);       } else {                                 if (getNonEmptyChildCount(n, 2) == 1) {           return isOneExactlyFunctionOrDo(getFirstNonEmptyChild(n));         } else {                               return false;         }       }     } else {       return (n.isFunction() || n.isDo());     }   }    private void addExpr(Node n, int minPrecedence, Context context) {     if ((NodeUtil.precedence(n.getType()) < minPrecedence) ||         ((context == Context.IN_FOR_INIT_CLAUSE) && n.isIn())){       add("(");       add(n, Context.OTHER);       add(")");     } else {       add(n, context);     }   }    void addList(Node firstInList) {     addList(firstInList, true, Context.OTHER);   }    void addList(Node firstInList, boolean isArrayOrFunctionArgument) {     addList(firstInList, isArrayOrFunctionArgument, Context.OTHER);   }    void addList(Node firstInList, boolean isArrayOrFunctionArgument,                Context lhsContext) {     for (Node n = firstInList; n != null; n = n.getNext()) {       boolean isFirst = n == firstInList;       if (isFirst) {         addExpr(n, isArrayOrFunctionArgument ? 1 : 0, lhsContext);       } else {         cc.listSeparator();         addExpr(n, isArrayOrFunctionArgument ? 1 : 0,             getContextForNoInOperator(lhsContext));       }     }   }    //**    * This function adds a comma-separated list as is specified by an ARRAYLIT    * node with the associated skipIndexes array.  This is a space optimization    * since we avoid creating a whole Node object for each empty array literal    * slot.    * @param firstInList The first in the node list (chained through the next    * property).    *//   void addArrayList(Node firstInList) {     boolean lastWasEmpty = false;     for (Node n = firstInList; n != null; n = n.getNext()) {       if (n != firstInList) {         cc.listSeparator();       }       addExpr(n, 1, Context.OTHER);       lastWasEmpty = n.isEmpty();     }      if (lastWasEmpty) {       cc.listSeparator();     }   }    void addCaseBody(Node caseBody) {     cc.beginCaseBody();     add(caseBody);     cc.endCaseBody();   }    void addAllSiblings(Node n) {     for (Node c = n; c != null; c = c.getNext()) {       add(c);     }   }    //** Outputs a JS string, using the optimal (single//double) quote character *//   private void addJsString(Node n) {     String s = n.getString();     boolean useSlashV = n.getBooleanProp(Node.SLASH_V);     if (useSlashV) {       add(jsString(n.getString(), useSlashV));     } else {       String cached = escapedJsStrings.get(s);       if (cached == null) {         cached = jsString(n.getString(), useSlashV);         escapedJsStrings.put(s, cached);       }       add(cached);     }   }    private String jsString(String s, boolean useSlashV) {     int singleq = 0, doubleq = 0;          for (int i = 0; i < s.length(); i++) {       switch (s.charAt(i)) {         case '"': doubleq++; break;         case '\'': singleq++; break;       }     }      String doublequote, singlequote;     char quote;     if (preferSingleQuotes ?         (singleq <= doubleq) : (singleq < doubleq)) {             quote = '\'';       doublequote = "\"";       singlequote = "\\\'";     } else {             quote = '\"';       doublequote = "\\\"";       singlequote = "\'";     }      return strEscape(s, quote, doublequote, singlequote, "\\\\",         outputCharsetEncoder, useSlashV, false);   }    //** Escapes regular expression *//   String regexpEscape(String s, CharsetEncoder outputCharsetEncoder) {     return strEscape(s, '//', "\"", "'", "\\", outputCharsetEncoder, false, true);   }    //**    * Escapes the given string to a double quoted (") JavaScript//JSON string    *//   String escapeToDoubleQuotedJsString(String s) {     return strEscape(s, '"',  "\\\"", "\'", "\\\\", null, false, false);   }    //* If the user doesn't want to specify an output charset encoder, assume      they want Latin//ASCII characters only.    *//   String regexpEscape(String s) {     return regexpEscape(s, null);   }    //** Helper to escape JavaScript string as well as regular expression *//   private String strEscape(       String s,       char quote,       String doublequoteEscape,       String singlequoteEscape,       String backslashEscape,       CharsetEncoder outputCharsetEncoder,       boolean useSlashV,       boolean isRegexp) {     StringBuilder sb = new StringBuilder(s.length() + 2);     sb.append(quote);     for (int i = 0; i < s.length(); i++) {       char c = s.charAt(i);       switch (c) {         case '\0': sb.append("\\x00"); break;         case '\u000B':           if (useSlashV) {             sb.append("\\v");           } else {             sb.append("\\x0B");           }           break;                 case '\b': sb.append("\\b"); break;         case '\f': sb.append("\\f"); break;         case '\n': sb.append("\\n"); break;         case '\r': sb.append("\\r"); break;         case '\t': sb.append("\\t"); break;         case '\\': sb.append(backslashEscape); break;         case '\"': sb.append(doublequoteEscape); break;         case '\'': sb.append(singlequoteEscape); break;                  case '\u2028': sb.append("\\u2028"); break;         case '\u2029': sb.append("\\u2029"); break;          case '=':                     if (trustedStrings || isRegexp) {             sb.append(c);           } else {             sb.append("\\x3d");           }           break;          case '&':           if (trustedStrings || isRegexp) {             sb.append(c);           } else {             sb.append("\\x26");           }           break;          case '>':           if (!trustedStrings && !isRegexp) {             sb.append(GT_ESCAPED);             break;           }                                                              if (i >= 2 &&               ((s.charAt(i - 1) == '-' && s.charAt(i - 2) == '-') ||                (s.charAt(i - 1) == ']' && s.charAt(i - 2) == ']'))) {             sb.append(GT_ESCAPED);           } else {             sb.append(c);           }           break;         case '<':           if (!trustedStrings && !isRegexp) {             sb.append(LT_ESCAPED);             break;           }                                          final String endScript = "//script";                      final String startComment = "!--";            if (s.regionMatches(true, i + 1, endScript, 0,                               endScript.length())) {             sb.append(LT_ESCAPED);           } else if (s.regionMatches(false, i + 1, startComment, 0,                                      startComment.length())) {             sb.append(LT_ESCAPED);           } else {             sb.append(c);           }           break;         default:                               if (outputCharsetEncoder != null) {             if (outputCharsetEncoder.canEncode(c)) {               sb.append(c);             } else {                             appendHexJavaScriptRepresentation(sb, c);             }           } else {                                                 if (c > 0x1f && c < 0x7f) {               sb.append(c);             } else {                                                         appendHexJavaScriptRepresentation(sb, c);             }           }       }     }     sb.append(quote);     return sb.toString();   }    static String identifierEscape(String s) {         if (NodeUtil.isLatin(s)) {       return s;     }          StringBuilder sb = new StringBuilder();     for (int i = 0; i < s.length(); i++) {       char c = s.charAt(i);                         if (c > 0x1F && c < 0x7F) {         sb.append(c);       } else {         appendHexJavaScriptRepresentation(sb, c);       }     }     return sb.toString();   }   //**    * @param maxCount The maximum number of children to look for.    * @return The number of children of this node that are non empty up to    * maxCount.    *//   private static int getNonEmptyChildCount(Node n, int maxCount) {     int i = 0;     Node c = n.getFirstChild();     for (; c != null && i < maxCount; c = c.getNext()) {       if (c.isBlock()) {         i += getNonEmptyChildCount(c, maxCount - i);       } else if (!c.isEmpty()) {         i++;       }     }     return i;   }    //** Gets the first non-empty child of the given node. *//   private static Node getFirstNonEmptyChild(Node n) {     for (Node c = n.getFirstChild(); c != null; c = c.getNext()) {       if (c.isBlock()) {         Node result = getFirstNonEmptyChild(c);         if (result != null) {           return result;         }       } else if (!c.isEmpty()) {         return c;       }     }     return null;   }          enum Context {     STATEMENT,     BEFORE_DANGLING_ELSE,     START_OF_EXPR,     PRESERVE_BLOCK,                 IN_FOR_INIT_CLAUSE,     OTHER   }    private Context getContextForNonEmptyExpression(Context currentContext) {     return currentContext == Context.BEFORE_DANGLING_ELSE ?         Context.BEFORE_DANGLING_ELSE : Context.OTHER;   }    //**    * If we're in a IN_FOR_INIT_CLAUSE, we can't permit in operators in the    * expression.  Pass on the IN_FOR_INIT_CLAUSE flag through subexpressions.    *//   private  Context getContextForNoInOperator(Context context) {     return (context == Context.IN_FOR_INIT_CLAUSE         ? Context.IN_FOR_INIT_CLAUSE : Context.OTHER);   }    //**    * @see #appendHexJavaScriptRepresentation(int, Appendable)    *//   private static void appendHexJavaScriptRepresentation(       StringBuilder sb, char c) {     try {       appendHexJavaScriptRepresentation(c, sb);     } catch (IOException ex) {             throw new RuntimeException(ex);     }   }    //**    * Returns a JavaScript representation of the character in a hex escaped    * format.    *    * @param codePoint The code point to append.    * @param out The buffer to which the hex representation should be appended.    *//   private static void appendHexJavaScriptRepresentation(       int codePoint, Appendable out)       throws IOException {     if (Character.isSupplementaryCodePoint(codePoint)) {                               char[] surrogates = Character.toChars(codePoint);       appendHexJavaScriptRepresentation(surrogates[0], out);       appendHexJavaScriptRepresentation(surrogates[1], out);       return;     }     out.append("\\u")         .append(HEX_CHARS[(codePoint >>> 12) & 0xf])         .append(HEX_CHARS[(codePoint >>> 8) & 0xf])         .append(HEX_CHARS[(codePoint >>> 4) & 0xf])         .append(HEX_CHARS[codePoint & 0xf]);   } } 


Fix:
Context rhsContext = getContextForNoInOperator(context);