dist/scripts/vendor.min.js
function $ParseProvider() {
  var cache = createMap();
  var literals = {
    'true': true,
    'false': false,
    'null': null,
    'undefined': undefined
  };
  var identStart, identContinue;

  /**
   * @ngdoc method
   * @name $parseProvider#addLiteral
   * @description
   *
   * Configure $parse service to add literal values that will be present as literal at expressions.
   *
   * @param {string} literalName Token for the literal value. The literal name value must be a valid literal name.
   * @param {*} literalValue Value for this literal. All literal values must be primitives or `undefined`.
   *
   **/
  this.addLiteral = function(literalName, literalValue) {
    literals[literalName] = literalValue;
  };

 /**
  * @ngdoc method
  * @name $parseProvider#setIdentifierFns
  *
  * @description
  *
  * Allows defining the set of characters that are allowed in AngularJS expressions. The function
  * `identifierStart` will get called to know if a given character is a valid character to be the
  * first character for an identifier. The function `identifierContinue` will get called to know if
  * a given character is a valid character to be a follow-up identifier character. The functions
  * `identifierStart` and `identifierContinue` will receive as arguments the single character to be
  * identifier and the character code point. These arguments will be `string` and `numeric`. Keep in
  * mind that the `string` parameter can be two characters long depending on the character
  * representation. It is expected for the function to return `true` or `false`, whether that
  * character is allowed or not.
  *
  * Since this function will be called extensively, keep the implementation of these functions fast,
  * as the performance of these functions have a direct impact on the expressions parsing speed.
  *
  * @param {function=} identifierStart The function that will decide whether the given character is
  *   a valid identifier start character.
  * @param {function=} identifierContinue The function that will decide whether the given character is
  *   a valid identifier continue character.
  */
  this.setIdentifierFns = function(identifierStart, identifierContinue) {
    identStart = identifierStart;
    identContinue = identifierContinue;
    return this;
  };

  this.$get = ['$filter', function($filter) {
    var noUnsafeEval = csp().noUnsafeEval;
    var $parseOptions = {
          csp: noUnsafeEval,
          literals: copy(literals),
          isIdentifierStart: isFunction(identStart) && identStart,
          isIdentifierContinue: isFunction(identContinue) && identContinue
        };
    $parse.$$getAst = $$getAst;
    return $parse;

    function $parse(exp, interceptorFn) {
      var parsedExpression, cacheKey;

      switch (typeof exp) {
        case 'string':
          exp = exp.trim();
          cacheKey = exp;

          parsedExpression = cache[cacheKey];

          if (!parsedExpression) {
            var lexer = new Lexer($parseOptions);
            var parser = new Parser(lexer, $filter, $parseOptions);
            parsedExpression = parser.parse(exp);

            cache[cacheKey] = addWatchDelegate(parsedExpression);
          }
          return addInterceptor(parsedExpression, interceptorFn);

        case 'function':
          return addInterceptor(exp, interceptorFn);

        default:
          return addInterceptor(noop, interceptorFn);
      }
    }

    function $$getAst(exp) {
      var lexer = new Lexer($parseOptions);
      var parser = new Parser(lexer, $filter, $parseOptions);
      return parser.getAst(exp).ast;
    }

    function expressionInputDirtyCheck(newValue, oldValueOfValue, compareObjectIdentity) {

      if (newValue == null || oldValueOfValue == null) { // null/undefined
        return newValue === oldValueOfValue;
      }

      if (typeof newValue === 'object') {

        // attempt to convert the value to a primitive type
        // TODO(docs): add a note to docs that by implementing valueOf even objects and arrays can
        //             be cheaply dirty-checked
        newValue = getValueOf(newValue);

        if (typeof newValue === 'object' && !compareObjectIdentity) {
          // objects/arrays are not supported - deep-watching them would be too expensive
          return false;
        }

        // fall-through to the primitive equality check
      }

      //Primitive or NaN
      // eslint-disable-next-line no-self-compare
      return newValue === oldValueOfValue || (newValue !== newValue && oldValueOfValue !== oldValueOfValue);
    }

    function inputsWatchDelegate(scope, listener, objectEquality, parsedExpression, prettyPrintExpression) {
      var inputExpressions = parsedExpression.inputs;
      var lastResult;

      if (inputExpressions.length === 1) {
        var oldInputValueOf = expressionInputDirtyCheck; // init to something unique so that equals check fails
        inputExpressions = inputExpressions[0];
        return scope.$watch(function expressionInputWatch(scope) {
          var newInputValue = inputExpressions(scope);
          if (!expressionInputDirtyCheck(newInputValue, oldInputValueOf, inputExpressions.isPure)) {
            lastResult = parsedExpression(scope, undefined, undefined, [newInputValue]);
            oldInputValueOf = newInputValue && getValueOf(newInputValue);
          }
          return lastResult;
        }, listener, objectEquality, prettyPrintExpression);
      }

      var oldInputValueOfValues = [];
      var oldInputValues = [];
      for (var i = 0, ii = inputExpressions.length; i < ii; i++) {
        oldInputValueOfValues[i] = expressionInputDirtyCheck; // init to something unique so that equals check fails
        oldInputValues[i] = null;
      }

      return scope.$watch(function expressionInputsWatch(scope) {
        var changed = false;

        for (var i = 0, ii = inputExpressions.length; i < ii; i++) {
          var newInputValue = inputExpressions[i](scope);
          if (changed || (changed = !expressionInputDirtyCheck(newInputValue, oldInputValueOfValues[i], inputExpressions[i].isPure))) {
            oldInputValues[i] = newInputValue;
            oldInputValueOfValues[i] = newInputValue && getValueOf(newInputValue);
          }
        }

        if (changed) {
          lastResult = parsedExpression(scope, undefined, undefined, oldInputValues);
        }

        return lastResult;
      }, listener, objectEquality, prettyPrintExpression);
    }

    function oneTimeWatchDelegate(scope, listener, objectEquality, parsedExpression, prettyPrintExpression) {
      var isDone = parsedExpression.literal ? isAllDefined : isDefined;
      var unwatch, lastValue;

      var exp = parsedExpression.$$intercepted || parsedExpression;
      var post = parsedExpression.$$interceptor || identity;

      var useInputs = parsedExpression.inputs && !exp.inputs;

      // Propogate the literal/inputs/constant attributes
      // ... but not oneTime since we are handling it
      oneTimeWatch.literal = parsedExpression.literal;
      oneTimeWatch.constant = parsedExpression.constant;
      oneTimeWatch.inputs = parsedExpression.inputs;

      // Allow other delegates to run on this wrapped expression
      addWatchDelegate(oneTimeWatch);

      unwatch = scope.$watch(oneTimeWatch, listener, objectEquality, prettyPrintExpression);

      return unwatch;

      function unwatchIfDone() {
        if (isDone(lastValue)) {
          unwatch();
        }
      }

      function oneTimeWatch(scope, locals, assign, inputs) {
        lastValue = useInputs && inputs ? inputs[0] : exp(scope, locals, assign, inputs);
        if (isDone(lastValue)) {
          scope.$$postDigest(unwatchIfDone);
        }
        return post(lastValue);
      }
    }

    function isAllDefined(value) {
      var allDefined = true;
      forEach(value, function(val) {
        if (!isDefined(val)) allDefined = false;
      });
      return allDefined;
    }

    function constantWatchDelegate(scope, listener, objectEquality, parsedExpression) {
      var unwatch = scope.$watch(function constantWatch(scope) {
        unwatch();
        return parsedExpression(scope);
      }, listener, objectEquality);
      return unwatch;
    }

    function addWatchDelegate(parsedExpression) {
      if (parsedExpression.constant) {
        parsedExpression.$$watchDelegate = constantWatchDelegate;
      } else if (parsedExpression.oneTime) {
        parsedExpression.$$watchDelegate = oneTimeWatchDelegate;
      } else if (parsedExpression.inputs) {
        parsedExpression.$$watchDelegate = inputsWatchDelegate;
      }

      return parsedExpression;
    }

    function chainInterceptors(first, second) {
      function chainedInterceptor(value) {
        return second(first(value));
      }
      chainedInterceptor.$stateful = first.$stateful || second.$stateful;
      chainedInterceptor.$$pure = first.$$pure && second.$$pure;

      return chainedInterceptor;
    }

    function addInterceptor(parsedExpression, interceptorFn) {
      if (!interceptorFn) return parsedExpression;

      // Extract any existing interceptors out of the parsedExpression
      // to ensure the original parsedExpression is always the $$intercepted
      if (parsedExpression.$$interceptor) {
        interceptorFn = chainInterceptors(parsedExpression.$$interceptor, interceptorFn);
        parsedExpression = parsedExpression.$$intercepted;
      }

      var useInputs = false;

      var fn = function interceptedExpression(scope, locals, assign, inputs) {
        var value = useInputs && inputs ? inputs[0] : parsedExpression(scope, locals, assign, inputs);
        return interceptorFn(value);
      };

      // Maintain references to the interceptor/intercepted
      fn.$$intercepted = parsedExpression;
      fn.$$interceptor = interceptorFn;

      // Propogate the literal/oneTime/constant attributes
      fn.literal = parsedExpression.literal;
      fn.oneTime = parsedExpression.oneTime;
      fn.constant = parsedExpression.constant;

      // Treat the interceptor like filters.
      // If it is not $stateful then only watch its inputs.
      // If the expression itself has no inputs then use the full expression as an input.
      if (!interceptorFn.$stateful) {
        useInputs = !parsedExpression.inputs;
        fn.inputs = parsedExpression.inputs ? parsedExpression.inputs : [parsedExpression];

        if (!interceptorFn.$$pure) {
          fn.inputs = fn.inputs.map(function(e) {
              // Remove the isPure flag of inputs when it is not absolute because they are now wrapped in a
              // non-pure interceptor function.
              if (e.isPure === PURITY_RELATIVE) {
                return function depurifier(s) { return e(s); };
              }
              return e;
            });
        }
      }

      return addWatchDelegate(fn);
    }
  }];
}
function $ParseProvider() {
  var cache = createMap();
  var literals = {
    'true': true,
    'false': false,
    'null': null,
    'undefined': undefined
  };
  var identStart, identContinue;

  /**
   * @ngdoc method
   * @name $parseProvider#addLiteral
   * @description
   *
   * Configure $parse service to add literal values that will be present as literal at expressions.
   *
   * @param {string} literalName Token for the literal value. The literal name value must be a valid literal name.
   * @param {*} literalValue Value for this literal. All literal values must be primitives or `undefined`.
   *
   **/
  this.addLiteral = function(literalName, literalValue) {
    literals[literalName] = literalValue;
  };

 /**
  * @ngdoc method
  * @name $parseProvider#setIdentifierFns
  *
  * @description
  *
  * Allows defining the set of characters that are allowed in AngularJS expressions. The function
  * `identifierStart` will get called to know if a given character is a valid character to be the
  * first character for an identifier. The function `identifierContinue` will get called to know if
  * a given character is a valid character to be a follow-up identifier character. The functions
  * `identifierStart` and `identifierContinue` will receive as arguments the single character to be
  * identifier and the character code point. These arguments will be `string` and `numeric`. Keep in
  * mind that the `string` parameter can be two characters long depending on the character
  * representation. It is expected for the function to return `true` or `false`, whether that
  * character is allowed or not.
  *
  * Since this function will be called extensively, keep the implementation of these functions fast,
  * as the performance of these functions have a direct impact on the expressions parsing speed.
  *
  * @param {function=} identifierStart The function that will decide whether the given character is
  *   a valid identifier start character.
  * @param {function=} identifierContinue The function that will decide whether the given character is
  *   a valid identifier continue character.
  */
  this.setIdentifierFns = function(identifierStart, identifierContinue) {
    identStart = identifierStart;
    identContinue = identifierContinue;
    return this;
  };

  this.$get = ['$filter', function($filter) {
    var noUnsafeEval = csp().noUnsafeEval;
    var $parseOptions = {
          csp: noUnsafeEval,
          literals: copy(literals),
          isIdentifierStart: isFunction(identStart) && identStart,
          isIdentifierContinue: isFunction(identContinue) && identContinue
        };
    $parse.$$getAst = $$getAst;
    return $parse;

    function $parse(exp, interceptorFn) {
      var parsedExpression, cacheKey;

      switch (typeof exp) {
        case 'string':
          exp = exp.trim();
          cacheKey = exp;

          parsedExpression = cache[cacheKey];

          if (!parsedExpression) {
            var lexer = new Lexer($parseOptions);
            var parser = new Parser(lexer, $filter, $parseOptions);
            parsedExpression = parser.parse(exp);

            cache[cacheKey] = addWatchDelegate(parsedExpression);
          }
          return addInterceptor(parsedExpression, interceptorFn);

        case 'function':
          return addInterceptor(exp, interceptorFn);

        default:
          return addInterceptor(noop, interceptorFn);
      }
    }

    function $$getAst(exp) {
      var lexer = new Lexer($parseOptions);
      var parser = new Parser(lexer, $filter, $parseOptions);
      return parser.getAst(exp).ast;
    }

    function expressionInputDirtyCheck(newValue, oldValueOfValue, compareObjectIdentity) {

      if (newValue == null || oldValueOfValue == null) { // null/undefined
        return newValue === oldValueOfValue;
      }

      if (typeof newValue === 'object') {

        // attempt to convert the value to a primitive type
        // TODO(docs): add a note to docs that by implementing valueOf even objects and arrays can
        //             be cheaply dirty-checked
        newValue = getValueOf(newValue);

        if (typeof newValue === 'object' && !compareObjectIdentity) {
          // objects/arrays are not supported - deep-watching them would be too expensive
          return false;
        }

        // fall-through to the primitive equality check
      }

      //Primitive or NaN
      // eslint-disable-next-line no-self-compare
      return newValue === oldValueOfValue || (newValue !== newValue && oldValueOfValue !== oldValueOfValue);
    }

    function inputsWatchDelegate(scope, listener, objectEquality, parsedExpression, prettyPrintExpression) {
      var inputExpressions = parsedExpression.inputs;
      var lastResult;

      if (inputExpressions.length === 1) {
        var oldInputValueOf = expressionInputDirtyCheck; // init to something unique so that equals check fails
        inputExpressions = inputExpressions[0];
        return scope.$watch(function expressionInputWatch(scope) {
          var newInputValue = inputExpressions(scope);
          if (!expressionInputDirtyCheck(newInputValue, oldInputValueOf, inputExpressions.isPure)) {
            lastResult = parsedExpression(scope, undefined, undefined, [newInputValue]);
            oldInputValueOf = newInputValue && getValueOf(newInputValue);
          }
          return lastResult;
        }, listener, objectEquality, prettyPrintExpression);
      }

      var oldInputValueOfValues = [];
      var oldInputValues = [];
      for (var i = 0, ii = inputExpressions.length; i < ii; i++) {
        oldInputValueOfValues[i] = expressionInputDirtyCheck; // init to something unique so that equals check fails
        oldInputValues[i] = null;
      }

      return scope.$watch(function expressionInputsWatch(scope) {
        var changed = false;

        for (var i = 0, ii = inputExpressions.length; i < ii; i++) {
          var newInputValue = inputExpressions[i](scope);
          if (changed || (changed = !expressionInputDirtyCheck(newInputValue, oldInputValueOfValues[i], inputExpressions[i].isPure))) {
            oldInputValues[i] = newInputValue;
            oldInputValueOfValues[i] = newInputValue && getValueOf(newInputValue);
          }
        }

        if (changed) {
          lastResult = parsedExpression(scope, undefined, undefined, oldInputValues);
        }

        return lastResult;
      }, listener, objectEquality, prettyPrintExpression);
    }

    function oneTimeWatchDelegate(scope, listener, objectEquality, parsedExpression, prettyPrintExpression) {
      var isDone = parsedExpression.literal ? isAllDefined : isDefined;
      var unwatch, lastValue;

      var exp = parsedExpression.$$intercepted || parsedExpression;
      var post = parsedExpression.$$interceptor || identity;

      var useInputs = parsedExpression.inputs && !exp.inputs;

      // Propogate the literal/inputs/constant attributes
      // ... but not oneTime since we are handling it
      oneTimeWatch.literal = parsedExpression.literal;
      oneTimeWatch.constant = parsedExpression.constant;
      oneTimeWatch.inputs = parsedExpression.inputs;

      // Allow other delegates to run on this wrapped expression
      addWatchDelegate(oneTimeWatch);

      unwatch = scope.$watch(oneTimeWatch, listener, objectEquality, prettyPrintExpression);

      return unwatch;

      function unwatchIfDone() {
        if (isDone(lastValue)) {
          unwatch();
        }
      }

      function oneTimeWatch(scope, locals, assign, inputs) {
        lastValue = useInputs && inputs ? inputs[0] : exp(scope, locals, assign, inputs);
        if (isDone(lastValue)) {
          scope.$$postDigest(unwatchIfDone);
        }
        return post(lastValue);
      }
    }

    function isAllDefined(value) {
      var allDefined = true;
      forEach(value, function(val) {
        if (!isDefined(val)) allDefined = false;
      });
      return allDefined;
    }

    function constantWatchDelegate(scope, listener, objectEquality, parsedExpression) {
      var unwatch = scope.$watch(function constantWatch(scope) {
        unwatch();
        return parsedExpression(scope);
      }, listener, objectEquality);
      return unwatch;
    }

    function addWatchDelegate(parsedExpression) {
      if (parsedExpression.constant) {
        parsedExpression.$$watchDelegate = constantWatchDelegate;
      } else if (parsedExpression.oneTime) {
        parsedExpression.$$watchDelegate = oneTimeWatchDelegate;
      } else if (parsedExpression.inputs) {
        parsedExpression.$$watchDelegate = inputsWatchDelegate;
      }

      return parsedExpression;
    }

    function chainInterceptors(first, second) {
      function chainedInterceptor(value) {
        return second(first(value));
      }
      chainedInterceptor.$stateful = first.$stateful || second.$stateful;
      chainedInterceptor.$$pure = first.$$pure && second.$$pure;

      return chainedInterceptor;
    }

    function addInterceptor(parsedExpression, interceptorFn) {
      if (!interceptorFn) return parsedExpression;

      // Extract any existing interceptors out of the parsedExpression
      // to ensure the original parsedExpression is always the $$intercepted
      if (parsedExpression.$$interceptor) {
        interceptorFn = chainInterceptors(parsedExpression.$$interceptor, interceptorFn);
        parsedExpression = parsedExpression.$$intercepted;
      }

      var useInputs = false;

      var fn = function interceptedExpression(scope, locals, assign, inputs) {
        var value = useInputs && inputs ? inputs[0] : parsedExpression(scope, locals, assign, inputs);
        return interceptorFn(value);
      };

      // Maintain references to the interceptor/intercepted
      fn.$$intercepted = parsedExpression;
      fn.$$interceptor = interceptorFn;

      // Propogate the literal/oneTime/constant attributes
      fn.literal = parsedExpression.literal;
      fn.oneTime = parsedExpression.oneTime;
      fn.constant = parsedExpression.constant;

      // Treat the interceptor like filters.
      // If it is not $stateful then only watch its inputs.
      // If the expression itself has no inputs then use the full expression as an input.
      if (!interceptorFn.$stateful) {
        useInputs = !parsedExpression.inputs;
        fn.inputs = parsedExpression.inputs ? parsedExpression.inputs : [parsedExpression];

        if (!interceptorFn.$$pure) {
          fn.inputs = fn.inputs.map(function(e) {
              // Remove the isPure flag of inputs when it is not absolute because they are now wrapped in a
              // non-pure interceptor function.
              if (e.isPure === PURITY_RELATIVE) {
                return function depurifier(s) { return e(s); };
              }
              return e;
            });
        }
      }

      return addWatchDelegate(fn);
    }
  }];
}
function $ParseProvider ( ) { var cache = createMap ( ) ; var literals = { 'true' : true , 'false' : false , 'null' : null , 'undefined' : undefined } ; var identStart , identContinue ; /**
   * @ngdoc method
   * @name $parseProvider#addLiteral
   * @description
   *
   * Configure $parse service to add literal values that will be present as literal at expressions.
   *
   * @param {string} literalName Token for the literal value. The literal name value must be a valid literal name.
   * @param {*} literalValue Value for this literal. All literal values must be primitives or `undefined`.
   *
   **/ this . addLiteral = function ( literalName , literalValue ) { literals [ literalName ] = literalValue ; } ; /**
  * @ngdoc method
  * @name $parseProvider#setIdentifierFns
  *
  * @description
  *
  * Allows defining the set of characters that are allowed in AngularJS expressions. The function
  * `identifierStart` will get called to know if a given character is a valid character to be the
  * first character for an identifier. The function `identifierContinue` will get called to know if
  * a given character is a valid character to be a follow-up identifier character. The functions
  * `identifierStart` and `identifierContinue` will receive as arguments the single character to be
  * identifier and the character code point. These arguments will be `string` and `numeric`. Keep in
  * mind that the `string` parameter can be two characters long depending on the character
  * representation. It is expected for the function to return `true` or `false`, whether that
  * character is allowed or not.
  *
  * Since this function will be called extensively, keep the implementation of these functions fast,
  * as the performance of these functions have a direct impact on the expressions parsing speed.
  *
  * @param {function=} identifierStart The function that will decide whether the given character is
  *   a valid identifier start character.
  * @param {function=} identifierContinue The function that will decide whether the given character is
  *   a valid identifier continue character.
  */ this . setIdentifierFns = function ( identifierStart , identifierContinue ) { identStart = identifierStart ; identContinue = identifierContinue ; return this ; } ; this . $get = [ '$filter' , function ( $filter ) { var noUnsafeEval = csp ( ) . noUnsafeEval ; var $parseOptions = { csp : noUnsafeEval , literals : copy ( literals ) , isIdentifierStart : isFunction ( identStart ) && identStart , isIdentifierContinue : isFunction ( identContinue ) && identContinue } ; $parse . $$getAst = $$getAst ; return $parse ; function $parse ( exp , interceptorFn ) { var parsedExpression , cacheKey ; switch ( typeof exp ) { case 'string' : exp = exp . trim ( ) ; cacheKey = exp ; parsedExpression = cache [ cacheKey ] ; if ( ! parsedExpression ) { var lexer = new Lexer ( $parseOptions ) ; var parser = new Parser ( lexer , $filter , $parseOptions ) ; parsedExpression = parser . parse ( exp ) ; cache [ cacheKey ] = addWatchDelegate ( parsedExpression ) ; } return addInterceptor ( parsedExpression , interceptorFn ) ; case 'function' : return addInterceptor ( exp , interceptorFn ) ; default : return addInterceptor ( noop , interceptorFn ) ; } } function $$getAst ( exp ) { var lexer = new Lexer ( $parseOptions ) ; var parser = new Parser ( lexer , $filter , $parseOptions ) ; return parser . getAst ( exp ) . ast ; } function expressionInputDirtyCheck ( newValue , oldValueOfValue , compareObjectIdentity ) { if ( newValue == null || oldValueOfValue == null ) { // null/undefined return newValue === oldValueOfValue ; } if ( typeof newValue === 'object' ) { // attempt to convert the value to a primitive type // TODO(docs): add a note to docs that by implementing valueOf even objects and arrays can //             be cheaply dirty-checked newValue = getValueOf ( newValue ) ; if ( typeof newValue === 'object' && ! compareObjectIdentity ) { // objects/arrays are not supported - deep-watching them would be too expensive return false ; } // fall-through to the primitive equality check } //Primitive or NaN // eslint-disable-next-line no-self-compare return newValue === oldValueOfValue || ( newValue !== newValue && oldValueOfValue !== oldValueOfValue ) ; } function inputsWatchDelegate ( scope , listener , objectEquality , parsedExpression , prettyPrintExpression ) { var inputExpressions = parsedExpression . inputs ; var lastResult ; if ( inputExpressions . length === 1 ) { var oldInputValueOf = expressionInputDirtyCheck ; // init to something unique so that equals check fails inputExpressions = inputExpressions [ 0 ] ; return scope . $watch ( function expressionInputWatch ( scope ) { var newInputValue = inputExpressions ( scope ) ; if ( ! expressionInputDirtyCheck ( newInputValue , oldInputValueOf , inputExpressions . isPure ) ) { lastResult = parsedExpression ( scope , undefined , undefined , [ newInputValue ] ) ; oldInputValueOf = newInputValue && getValueOf ( newInputValue ) ; } return lastResult ; } , listener , objectEquality , prettyPrintExpression ) ; } var oldInputValueOfValues = [ ] ; var oldInputValues = [ ] ; for ( var i = 0 , ii = inputExpressions . length ; i < ii ; i ++ ) { oldInputValueOfValues [ i ] = expressionInputDirtyCheck ; // init to something unique so that equals check fails oldInputValues [ i ] = null ; } return scope . $watch ( function expressionInputsWatch ( scope ) { var changed = false ; for ( var i = 0 , ii = inputExpressions . length ; i < ii ; i ++ ) { var newInputValue = inputExpressions [ i ] ( scope ) ; if ( changed || ( changed = ! expressionInputDirtyCheck ( newInputValue , oldInputValueOfValues [ i ] , inputExpressions [ i ] . isPure ) ) ) { oldInputValues [ i ] = newInputValue ; oldInputValueOfValues [ i ] = newInputValue && getValueOf ( newInputValue ) ; } } if ( changed ) { lastResult = parsedExpression ( scope , undefined , undefined , oldInputValues ) ; } return lastResult ; } , listener , objectEquality , prettyPrintExpression ) ; } function oneTimeWatchDelegate ( scope , listener , objectEquality , parsedExpression , prettyPrintExpression ) { var isDone = parsedExpression . literal ? isAllDefined : isDefined ; var unwatch , lastValue ; var exp = parsedExpression . $$intercepted || parsedExpression ; var post = parsedExpression . $$interceptor || identity ; var useInputs = parsedExpression . inputs && ! exp . inputs ; // Propogate the literal/inputs/constant attributes // ... but not oneTime since we are handling it oneTimeWatch . literal = parsedExpression . literal ; oneTimeWatch . constant = parsedExpression . constant ; oneTimeWatch . inputs = parsedExpression . inputs ; // Allow other delegates to run on this wrapped expression addWatchDelegate ( oneTimeWatch ) ; unwatch = scope . $watch ( oneTimeWatch , listener , objectEquality , prettyPrintExpression ) ; return unwatch ; function unwatchIfDone ( ) { if ( isDone ( lastValue ) ) { unwatch ( ) ; } } function oneTimeWatch ( scope , locals , assign , inputs ) { lastValue = useInputs && inputs ? inputs [ 0 ] : exp ( scope , locals , assign , inputs ) ; if ( isDone ( lastValue ) ) { scope . $$postDigest ( unwatchIfDone ) ; } return post ( lastValue ) ; } } function isAllDefined ( value ) { var allDefined = true ; forEach ( value , function ( val ) { if ( ! isDefined ( val ) ) allDefined = false ; } ) ; return allDefined ; } function constantWatchDelegate ( scope , listener , objectEquality , parsedExpression ) { var unwatch = scope . $watch ( function constantWatch ( scope ) { unwatch ( ) ; return parsedExpression ( scope ) ; } , listener , objectEquality ) ; return unwatch ; } function addWatchDelegate ( parsedExpression ) { if ( parsedExpression . constant ) { parsedExpression . $$watchDelegate = constantWatchDelegate ; } else if ( parsedExpression . oneTime ) { parsedExpression . $$watchDelegate = oneTimeWatchDelegate ; } else if ( parsedExpression . inputs ) { parsedExpression . $$watchDelegate = inputsWatchDelegate ; } return parsedExpression ; } function chainInterceptors ( first , second ) { function chainedInterceptor ( value ) { return second ( first ( value ) ) ; } chainedInterceptor . $stateful = first . $stateful || second . $stateful ; chainedInterceptor . $$pure = first . $$pure && second . $$pure ; return chainedInterceptor ; } function addInterceptor ( parsedExpression , interceptorFn ) { if ( ! interceptorFn ) return parsedExpression ; // Extract any existing interceptors out of the parsedExpression // to ensure the original parsedExpression is always the $$intercepted if ( parsedExpression . $$interceptor ) { interceptorFn = chainInterceptors ( parsedExpression . $$interceptor , interceptorFn ) ; parsedExpression = parsedExpression . $$intercepted ; } var useInputs = false ; var fn = function interceptedExpression ( scope , locals , assign , inputs ) { var value = useInputs && inputs ? inputs [ 0 ] : parsedExpression ( scope , locals , assign , inputs ) ; return interceptorFn ( value ) ; } ; // Maintain references to the interceptor/intercepted fn . $$intercepted = parsedExpression ; fn . $$interceptor = interceptorFn ; // Propogate the literal/oneTime/constant attributes fn . literal = parsedExpression . literal ; fn . oneTime = parsedExpression . oneTime ; fn . constant = parsedExpression . constant ; // Treat the interceptor like filters. // If it is not $stateful then only watch its inputs. // If the expression itself has no inputs then use the full expression as an input. if ( ! interceptorFn . $stateful ) { useInputs = ! parsedExpression . inputs ; fn . inputs = parsedExpression . inputs ? parsedExpression . inputs : [ parsedExpression ] ; if ( ! interceptorFn . $$pure ) { fn . inputs = fn . inputs . map ( function ( e ) { // Remove the isPure flag of inputs when it is not absolute because they are now wrapped in a // non-pure interceptor function. if ( e . isPure === PURITY_RELATIVE ) { return function depurifier ( s ) { return e ( s ) ; } ; } return e ; } ) ; } } return addWatchDelegate ( fn ) ; } } ] ; }
@ngdoc service
@name $parse
@kind function

@description

Converts AngularJS {@link guide/expression expression} into a function.

```js
var getter = $parse('user.name');
var setter = getter.assign;
var context = {user:{name:'AngularJS'}};
var locals = {user:{name:'local'}};

expect(getter(context)).toEqual('AngularJS');
setter(context, 'newValue');
expect(context.user.name).toEqual('newValue');
expect(getter(context, locals)).toEqual('local');
```


@param {string} expression String expression to compile.
@returns {function(context, locals)} a function which represents the compiled expression:

* `context` – `{object}` – an object against which any expressions embedded in the strings
are evaluated against (typically a scope object).
* `locals` – `{object=}` – local variables context object, useful for overriding values in
`context`.

The returned function also has the following properties:
* `literal` – `{boolean}` – whether the expression's top-level node is a JavaScript
literal.
* `constant` – `{boolean}` – whether the expression is made entirely of JavaScript
constant literals.
* `assign` – `{?function(context, value)}` – if the expression is assignable, this will be
set to a function to change its value on the given context.

 
@ngdoc provider
@name $parseProvider
@this

@description
`$parseProvider` can be used for configuring the default behavior of the {@link ng.$parse $parse}
service.
@ngdoc service @name $parse @kind function