src/com/google/javascript/jscomp/NodeUtil.java
/**
   * Returns true if calls to this function have side effects.
   *
   * @param callNode The call node to inspected.
   * @param compiler A compiler object to provide program state changing
   *     context information. Can be null.
   */
Returns true if calls to this function have side effects.
@param callNode The call node to inspected.
@param compiler A compiler object to provide program state changing
context information. Can be null.
Returns true if calls to this function have side effects . @param callNode The call node to inspected . @param compiler A compiler object to provide program state changing context information . Can be null .
static boolean functionCallHasSideEffects(
      Node callNode, @Nullable AbstractCompiler compiler) {
    checkState(callNode.isCall() || callNode.isTaggedTemplateLit(), callNode);
    if (callNode.isNoSideEffectsCall()) {
      return false;
    }
    if (callNode.isOnlyModifiesArgumentsCall()
        && allArgsUnescapedLocal(callNode)) {
      return false;
    }
    Node callee = callNode.getFirstChild();
    if (callee.isName()) {
      String name = callee.getString();
      if (BUILTIN_FUNCTIONS_WITHOUT_SIDEEFFECTS.contains(name)) {
        return false;
      }
    } else if (callee.isGetProp()) {
      if (callNode.hasOneChild()
          && OBJECT_METHODS_WITHOUT_SIDEEFFECTS.contains(callee.getLastChild().getString())) {
        return false;
      }
      if (callNode.isOnlyModifiesThisCall()
          && evaluatesToLocalValue(callee.getFirstChild())) {
        return false;
      }
      if (callee.getFirstChild().isName() && callee.isQualifiedName()
          && callee.getFirstChild().getString().equals("Math")) {
        switch(callee.getLastChild().getString()) {
          case "abs":
          case "acos":
          case "acosh":
          case "asin":
          case "asinh":
          case "atan":
          case "atanh":
          case "atan2":
          case "cbrt":
          case "ceil":
          case "cos":
          case "cosh":
          case "exp":
          case "expm1":
          case "floor":
          case "hypot":
          case "log":
          case "log10":
          case "log1p":
          case "log2":
          case "max":
          case "min":
          case "pow":
          case "round":
          case "sign":
          case "sin":
          case "sinh":
          case "sqrt":
          case "tan":
          case "tanh":
          case "trunc":
            return false;
          case "random":
            return !callNode.hasOneChild(); 
          default:
        }
      }
      if (compiler != null && !compiler.hasRegExpGlobalReferences()) {
        if (callee.getFirstChild().isRegExp()
            && REGEXP_METHODS.contains(callee.getLastChild().getString())) {
          return false;
        } else if (isTypedAsString(callee.getFirstChild(), compiler)) {
          String method = callee.getLastChild().getString();
          Node param = callee.getNext();
          if (param != null) {
            if (param.isString()) {
              if (STRING_REGEXP_METHODS.contains(method)) {
                return false;
              }
            } else if (param.isRegExp()) {
              if ("replace".equals(method)) {
                return !param.getNext().isString();
              } else if (STRING_REGEXP_METHODS.contains(method)) {
                return false;
              }
            }
          }
        }
      }
    }
    return true;
  }
static boolean functionCallHasSideEffects ( Node callNode , @ Nullable AbstractCompiler compiler ) { checkState ( callNode . isCall ( ) || callNode . isTaggedTemplateLit ( ) , callNode ) ; if ( callNode . isNoSideEffectsCall ( ) ) { return false ; } if ( callNode . isOnlyModifiesArgumentsCall ( ) && allArgsUnescapedLocal ( callNode ) ) { return false ; } Node callee = callNode . getFirstChild ( ) ; if ( callee . isName ( ) ) { String name = callee . getString ( ) ; if ( BUILTIN_FUNCTIONS_WITHOUT_SIDEEFFECTS . contains ( name ) ) { return false ; } } else if ( callee . isGetProp ( ) ) { if ( callNode . hasOneChild ( ) && OBJECT_METHODS_WITHOUT_SIDEEFFECTS . contains ( callee . getLastChild ( ) . getString ( ) ) ) { return false ; } if ( callNode . isOnlyModifiesThisCall ( ) && evaluatesToLocalValue ( callee . getFirstChild ( ) ) ) { return false ; } if ( callee . getFirstChild ( ) . isName ( ) && callee . isQualifiedName ( ) && callee . getFirstChild ( ) . getString ( ) . equals ( "Math" ) ) { switch ( callee . getLastChild ( ) . getString ( ) ) { case "abs" : case "acos" : case "acosh" : case "asin" : case "asinh" : case "atan" : case "atanh" : case "atan2" : case "cbrt" : case "ceil" : case "cos" : case "cosh" : case "exp" : case "expm1" : case "floor" : case "hypot" : case "log" : case "log10" : case "log1p" : case "log2" : case "max" : case "min" : case "pow" : case "round" : case "sign" : case "sin" : case "sinh" : case "sqrt" : case "tan" : case "tanh" : case "trunc" : return false ; case "random" : return ! callNode . hasOneChild ( ) ; default : } } if ( compiler != null && ! compiler . hasRegExpGlobalReferences ( ) ) { if ( callee . getFirstChild ( ) . isRegExp ( ) && REGEXP_METHODS . contains ( callee . getLastChild ( ) . getString ( ) ) ) { return false ; } else if ( isTypedAsString ( callee . getFirstChild ( ) , compiler ) ) { String method = callee . getLastChild ( ) . getString ( ) ; Node param = callee . getNext ( ) ; if ( param != null ) { if ( param . isString ( ) ) { if ( STRING_REGEXP_METHODS . contains ( method ) ) { return false ; } } else if ( param . isRegExp ( ) ) { if ( "replace" . equals ( method ) ) { return ! param . getNext ( ) . isString ( ) ; } else if ( STRING_REGEXP_METHODS . contains ( method ) ) { return false ; } } } } } } return true ; }
Returns true if calls to this function have side effects.
Returns true if calls to this function have side effects .
// Built-in functions with no side effects. // Many common Math functions have no side-effects. // TODO(nicksantos): This is a terrible terrible hack, until // I create a definitionProvider that understands namespacing. // no parameters // Unknown Math.* function, so fall out of this switch statement. // Unlike regexs, string methods don't need to be hosted on a string literal // to avoid leaking mutating global state changes, it is just necessary that // the regex object can't be referenced. // Assume anything but a string constant has side-effects