Package com.google.caja.parser.js

Examples of com.google.caja.parser.js.Operator


          if (rnd.nextBoolean()) { out.append('m'); }
          if (rnd.nextBoolean()) { out.append('i'); }
          tok = out.toString();
          break;
        case PUNCTUATION:
          Operator op = OPERATORS[rnd.nextInt(OPERATORS.length)];
          if (op.getClosingSymbol() != null) {
            tok = rnd.nextBoolean()
                ? op.getOpeningSymbol()
                : op.getClosingSymbol();
          } else {
            tok = op.getSymbol();
          }
          if (tok.startsWith("/")) {
            // Make sure / operators follow numbers so they're not interpreted
            // as regular expressions.
            tokens.add("3");
View Full Code Here


      out.add(new Use(ac.cast(Reference.class)));
      return;
    }

    if (ac.node instanceof Operation) {
      Operator op = ac.cast(Operation.class).node.getOperator();
      if (op == Operator.MEMBER_ACCESS) {
        findUses(AncestorChain.instance(ac, ac.node.children().get(0)), out);
        // Do not recurse to member name
        return;
      }
View Full Code Here

    private static boolean isObjectInMemberAccess(AncestorChain<?> ac) {
      if (ac.parent == null || !(ac.parent.node instanceof Operation)) {
        return false;
      }
      Operator op = ac.parent.cast(Operation.class).node.getOperator();
      return op == Operator.MEMBER_ACCESS || op == Operator.SQUARE_BRACKET
          && ac.node == ac.parent.node.children().get(0);
    }
View Full Code Here

        case GREATER_THAN:
          if (fact.isTruthy()) {
            // If (a < b) the a != b, and !(a > b).
            Expression left = operands.get(0);
            Expression right = operands.get(1);
            Operator included = op.getOperator() == Operator.LESS_THAN
                ? Operator.LESS_EQUALS : Operator.GREATER_EQUALS;
            addFactInt(Operation.create(UNK, included, left, right), Fact.TRUE);
            addFactInt(
                Operation.create(UNK, Operator.STRICTLY_NOT_EQUAL, left, right),
                Fact.TRUE);
            // Incomparable values like NaN means we can conclude nothing if
            // !(a < b).
          }
          break;
        case LESS_EQUALS:
        case GREATER_EQUALS:
          if (fact.isFalsey()) {
            // if !(a <= b) then a !== b.
            Expression left = operands.get(0);
            Expression right = operands.get(1);
            addFactInt(
                Operation.create(UNK, Operator.STRICTLY_NOT_EQUAL, left, right),
                Fact.TRUE);
          }
          break;
        case INSTANCE_OF:
          // if (x instanceof y) does not throw, then y must be a function.
          // if it's true, then x must be an object.
          // Note: primitives are not instances of their wrapper class.
          addFactInt(
              Operation.create(UNK, Operator.TYPEOF, operands.get(1)),
              Fact.is(StringLiteral.valueOf(UNK, "function")));
          if (fact.isTruthy()) {
            addFactInt(operands.get(0), Fact.TRUTHY);
          }
          break;
        case EQUAL:
          addFactInt(
              Operation.create(
                  UNK, Operator.NOT_EQUAL, operands.get(0), operands.get(1)),
              fact.isTruthy() ? Fact.FALSE : Fact.TRUE);
          break;
        case NOT_EQUAL:
          addFactInt(
              Operation.create(
                  UNK, Operator.EQUAL, operands.get(0), operands.get(1)),
              fact.isTruthy() ? Fact.FALSE : Fact.TRUE);
          break;
        case STRICTLY_EQUAL:
          if (fact.isTruthy()) {
            Expression lhs = operands.get(0);
            Expression rhs = operands.get(1);
            addFactInt(Operation.create(UNK, Operator.EQUAL, lhs, rhs),
                       Fact.TRUE);
            if (rhs instanceof Literal) {
              // TODO(mikesamuel): what do we do about the fact that (0 === -0)?
              // Instead of inferring that the value IS 0, we could infer that
              // it's falsey, and the typeof is number.
              addFactInt(lhs, Fact.is((Literal) rhs));

            // (this.global === this) -> global aliases the global object.
            } else if (isThis(rhs) && lhs instanceof Reference) {
              addFactInt(lhs, Fact.GLOBAL);
            } else {
              String typeOf = rhs.typeOf();
              if (typeOf != null && lhs.typeOf() == null) {
                addFactInt(
                    Operation.create(UNK, Operator.TYPEOF, lhs),
                    Fact.is(StringLiteral.valueOf(UNK, typeOf)));
              }
              // TODO(mikesamuel): Is this useful?  When, in a comparison,
              // do we know that something is truthy or falsey, but not what
              // literal value it is.  The expressions:
              //    x === function () {}
              //    y === [1,2,3]
              //    z === {}
              // are never true, so control wouldn't reach here.
              Boolean truthiness = rhs.conditionResult();
              if (truthiness != null) {
                addFuzzyFact(lhs, truthiness);
              }
            }
          } else {
            Expression lhs = operands.get(0);
            Expression rhs = operands.get(1);
            if (ParseTreeNodes.deepEquals(lhs, rhs)) {
              addFactInt(lhs, Fact.is(new RealLiteral(UNK, Double.NaN)));
            }
          }
          addFactInt(
              Operation.create(
                  UNK, Operator.STRICTLY_NOT_EQUAL,
                  operands.get(0), operands.get(1)),
              fact.isTruthy() ? Fact.FALSE : Fact.TRUE);
          break;
        case STRICTLY_NOT_EQUAL:
          addFactInt(Operation.create(
              UNK, Operator.STRICTLY_EQUAL, operands.get(0), operands.get(1)),
              fact.isTruthy() ? Fact.FALSE : Fact.TRUE);
          break;
        case LOGICAL_AND:
        case LOGICAL_OR:
          boolean isAnd = op.getOperator() == Operator.LOGICAL_AND;
          if (fact.isTruthy() == isAnd) {
            addFuzzyFact(operands.get(0), isAnd);
            addFactInt(operands.get(1), fact)// Second value is result
          }
          break;
        case MEMBER_ACCESS:
        case SQUARE_BRACKET:
          // If foo.bar is truthy, then so is foo.
          if (fact.isTruthy()) {
            addFuzzyFact(operands.get(0), true);
          }
          break;
        case TYPEOF:
          if (fact.type == Fact.Type.IS
              && fact.value instanceof StringLiteral) {
            String s = ((StringLiteral) fact.value).getUnquotedValue();
            Expression op0 = operands.get(0);
            if ("undefined".equals(s)) {
              addFactInt(op0, Fact.UNDEFINED);
            } else {
              if ("function".equals(s)) { addFactInt(op0, Fact.TRUTHY); }
              // undefined is a commonly tested value, so infer its absence
              // for other types.
              addFactInt(
                  Operation.create(
                      UNK, Operator.STRICTLY_EQUAL, op0, Fact.UNDEFINED.value),
                  Fact.FALSE);
            }
          }
          break;
        default:
          break;
      }
      // (a < b) -> (b > a) since we know (a) and (b) are pure
      if (operands.size() == 2) {
        Operator swapped = WITH_REVERSE_ORDER.get(op.getOperator());
        if (swapped != null) {
          addFactInt(
              Operation.create(
                  op.getFilePosition(), swapped,
                  operands.get(1), operands.get(0)),
View Full Code Here

    }
    if (!globals.isEmpty()) {
      for (Pair<Expression, Fact> fe : factList) {
        if (fe.b == Fact.GLOBAL) { continue; }
        Expression e = fe.a;
        Operator op = null;
        if (Operation.is(e, Operator.TYPEOF)) {
          op = Operator.TYPEOF;
          e = (Expression) e.children().get(0);
        }
        String topRef = topRef(e);
View Full Code Here

      // Handle conditionals specially since the goal of this code is to cut
      // bits out of them.
      optimizeConditional(s, (Conditional) node, 0, out);
      return;
    } else if (node instanceof Operation) {
      Operator op = ((Operation) node).getOperator();
      if (Operator.MEMBER_ACCESS == op) {
        // The reference that is the second argument should not be treated as
        // an optimization target.
        optimizeMemberAccess(
            s, (Operation) node, isFuzzy, isLhs, throwsOnUndefined, out);
        return;
      }
    }

    // Stores the digest as it is built.
    StringBuilder sb = new StringBuilder();
    sb.append('(');

    if (node instanceof Reference) {
      // Set the digest to null if node is a non-global reference, so that
      // this node and ancestors cannot possibly match any facts in the
      // knowledge base.
      if (!s.isOuter(((Reference) node).getIdentifierName())) { sb = null; }
    } else if (node instanceof FunctionConstructor) {
      s = Scope.fromFunctionConstructor(s, (FunctionConstructor) node);
    } else if (node instanceof CatchStmt) {
      s = Scope.fromCatchStmt(s, (CatchStmt) node);
    }

    List<? extends ParseTreeNode> children = node.children();
    int n = children.size();
    if (n != 0) {
      // The number of operands for which we only care about the truthiness of
      // the result.
      int fuzzyLimit = 0;
      // The number of operands that are left hand side expressions.
      int lhsLimit = 0;
      // The number of operands that will cause the exception to fail with
      // an error if undefined.
      int touLimit = 0;
      // The number of operands that are functions.
      int fnLimit = 0;

      if (node instanceof Operation) {
        Operator op = ((Operation) node).getOperator();
        switch (op) {
          case LOGICAL_OR: case LOGICAL_AND:
            fuzzyLimit = isFuzzy ? 2 : 0;
            break;
          case TERNARY:
            fuzzyLimit = isFuzzy ? 3 : 1;
            break;
          case NOT:
            fuzzyLimit = 1;
            break;
          case FUNCTION_CALL:
            fnLimit = 1;
            // $FALL-THROUGH$
          case MEMBER_ACCESS: case CONSTRUCTOR:
          case SQUARE_BRACKET:
            touLimit = 1;
            break;
          default: break;
        }
        if (op.getCategory() == OperatorCategory.ASSIGNMENT) {
          // Don't optimize left-hand sides of assignments.  We allow code to
          // modify the environment after its sampled, as long as nothing is
          // deleted or replaced with a less functional replacement.
          lhsLimit = 1;
        }
View Full Code Here

  }

  private Fact foldComparisonToFalsey(ParseTreeNode n) {
    if (!(n instanceof Operation)) { return null; }
    Operation op = (Operation) n;
    Operator o = op.getOperator();
    boolean eq;
    boolean strict;
    switch (o) {
      case EQUAL: case STRICTLY_EQUAL: eq = true; break;
      case NOT_EQUAL: case STRICTLY_NOT_EQUAL: eq = false; break;
View Full Code Here

    if (n instanceof Reference) {
      // Now that we're done with all the declaration in the scope, we can
      // tell whether a use corresponds to a declaration in the scope.
      String symbolName = id.node.getName();
      ScopeTree<S> defSite = definingSite(symbolName, s);
      Operator assignOperator = assignOperator(id);
      if (assignOperator == null) {
        listener.read(id, s.scopeImpl, scopeImpl(defSite));
      } else if (assignOperator == Operator.ASSIGN) {
        listener.assigned(id, s.scopeImpl, scopeImpl(defSite));
      } else // ++foo, foo++, foo += 1 all read before assignment
View Full Code Here

    AncestorChain<?> grandparent = ac.parent.parent;
    if (grandparent == null) { return null; }
    if (grandparent.node instanceof Operation) {
      // Handles ++ac, ac += ..., ac = ...
      Operation op = grandparent.cast(Operation.class).node;
      Operator operator = op.getOperator();
      return (operator.getCategory() == OperatorCategory.ASSIGNMENT
              && ac.parent.node == op.children().get(0)) ? operator : null;
    } else if (grandparent.node instanceof ExpressionStmt
               && grandparent.parent != null
               && grandparent.parent.node instanceof ForEachLoop) {
      // Handle
View Full Code Here

          newOperands = operands.toArray(new Expression[n]);
        }
        newOperands[i] = newOperand;
      }
    }
    Operator oper = op.getOperator();
    FilePosition pos = e.getFilePosition();
    if (oper != Operator.TERNARY) {
      return newOperands == null ? e : Operation.create(pos, oper, newOperands);
    }
    // (c ? x,z : y,z) -> (c ? x:y),z
    Expression[] ternaryOperands = newOperands != null
        ? newOperands : operands.toArray(new Expression[3]);
    Expression c = ternaryOperands[0];
    Expression x = ternaryOperands[1];
    Expression y = ternaryOperands[2];
    while (Operation.is(c, Operator.NOT)) {
      c = ((Operation) c).children().get(0);
      Expression t = x;
      x = y;
      y = t;
    }
    if (ParseTreeNodes.deepEquals(x, y)) {
      if (c.simplifyForSideEffect() == null) { return x; }
      return commaOp(pos, c, x);
    }
    if (isSimple(c)) {
      // If a reference fails with an exception because it is undefined, then
      // control would never reach the second identical expression.
      if (ParseTreeNodes.deepEquals(c, x)) {
        // (c ? c : y) -> c || y     if c not side effecting
        return Operation.create(pos, Operator.LOGICAL_OR, c, y);
      } else if (ParseTreeNodes.deepEquals(c, y)) {
        // (c ? x : c) -> c && x     if c not side effecting
        return Operation.create(pos, Operator.LOGICAL_AND, c, x);
      }
    }
    // TODO(mikesamuel): if c is simple and not a global reference, optimize
    // out he common head as well.
    CommaCommonalities opt = commaCommonalities(x, y);
    if (opt != null) {
      // Both reduced sides can't be null since we checked above whether
      // x and y are structurally identical.
      if (opt.aReduced == null) {
        // (c ? z: y,z)  ->  (c || y),z
        return commaOp(
            pos,
            Operation.createInfix(Operator.LOGICAL_OR, c, opt.bReduced),
            opt.commonTail);
      } else if (opt.bReduced == null) {
        // (c ? x,z : z)  ->  (c && x),z
        return commaOp(
            pos,
            Operation.createInfix(Operator.LOGICAL_AND, c, opt.aReduced),
            opt.commonTail);
      } else {
        // (c ? x,z : y,z) -> (c ? x : y),z
        return commaOp(
            pos,
            optimizeExpressionFlow(
                Operation.createTernary(c, opt.aReduced, opt.bReduced)),
            opt.commonTail);
      }
    }
    ternaryOperands[0] = c;
    ternaryOperands[1] = x;
    ternaryOperands[2] = y;
    if (x instanceof Operation && y instanceof Operation) {
      Operation xop = (Operation) x;
      Operation yop = (Operation) y;
      Operator xoper = xop.getOperator();
      if (xoper == yop.getOperator()) {
        List<? extends Expression> xoperands = xop.children();
        List<? extends Expression> yoperands = yop.children();
        int nOperands = xoperands.size();
        if (nOperands == yoperands.size()) {
          Expression xoperand0 = xoperands.get(0);
          // We can often pull the rightmost operand out since it would be
          // evaluated last regardless.
          if (nOperands == 2
              && ParseTreeNodes.deepEquals(xoperands.get(1), yoperands.get(1))
              && xoper.getCategory() != OperatorCategory.ASSIGNMENT
              && (xoper != Operator.FUNCTION_CALL
                  || !(Operation.is(xoperand0, Operator.MEMBER_ACCESS)
                       || Operation.is(xoperand0, Operator.SQUARE_BRACKET)))) {
            // c ? foo(myNode) : bar(myNode)  =>  (c ? foo : bar)(myNode)
            return Operation.create(
View Full Code Here

TOP

Related Classes of com.google.caja.parser.js.Operator

Copyright © 2018 www.massapicom. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.