diff options
| -rw-r--r-- | angularFiles.js | 2 | ||||
| -rw-r--r-- | src/Angular.js | 1 | ||||
| -rw-r--r-- | src/JSON.js | 2 | ||||
| -rw-r--r-- | src/directives.js | 7 | ||||
| -rw-r--r-- | src/service/formFactory.js | 11 | ||||
| -rw-r--r-- | src/service/parse.js | 57 | ||||
| -rw-r--r-- | src/service/scope.js | 9 | ||||
| -rw-r--r-- | test/service/parseSpec.js | 6 | ||||
| -rw-r--r-- | test/testabilityPatch.js | 2 | 
9 files changed, 52 insertions, 45 deletions
| diff --git a/angularFiles.js b/angularFiles.js index f7d84231..269f52fa 100644 --- a/angularFiles.js +++ b/angularFiles.js @@ -19,7 +19,7 @@ angularFiles = {      'src/service/location.js',      'src/service/log.js',      'src/service/resource.js', -    'src/service/parser.js', +    'src/service/parse.js',      'src/service/route.js',      'src/service/routeParams.js',      'src/service/scope.js', diff --git a/src/Angular.js b/src/Angular.js index 931a3e5a..d8a726c0 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -1059,6 +1059,7 @@ function ngModule($provide, $injector) {    $provide.service('$location', $LocationProvider);    $provide.service('$locationConfig', $LocationConfigProvider);    $provide.service('$log', $LogProvider); +  $provide.service('$parse', $ParseProvider);    $provide.service('$resource', $ResourceProvider);    $provide.service('$route', $RouteProvider);    $provide.service('$routeParams', $RouteParamsProvider); diff --git a/src/JSON.js b/src/JSON.js index d0ded009..51a12860 100644 --- a/src/JSON.js +++ b/src/JSON.js @@ -41,7 +41,7 @@ function fromJson(json, useNative) {      if (useNative && window.JSON && window.JSON.parse) {        obj = JSON.parse(json);      } else { -      obj = parser(json, true).primary()(); +      obj = parseJson(json, true)();      }      return transformDates(obj);    } catch (e) { diff --git a/src/directives.js b/src/directives.js index daa42048..20235f64 100644 --- a/src/directives.js +++ b/src/directives.js @@ -235,9 +235,10 @@ angularDirective("ng:controller", function(expression){   */  angularDirective("ng:bind", function(expression, element){    element.addClass('ng-binding'); -  var exprFn = parser(expression).statements(); -  return ['$exceptionHandler', '$element', function($exceptionHandler, element) { -    var lastValue = Number.NaN; +  return ['$exceptionHandler', '$parse', '$element', function($exceptionHandler, $parse, element) { +    var exprFn = parser(expression), +        lastValue = Number.NaN; +      this.$watch(function(scope) {        // TODO(misko): remove error handling https://github.com/angular/angular.js/issues/347        var value, html, isHtml, isDomElement, diff --git a/src/service/formFactory.js b/src/service/formFactory.js index c9cb9c53..972b46ee 100644 --- a/src/service/formFactory.js +++ b/src/service/formFactory.js @@ -98,8 +98,9 @@   */  function $FormFactoryProvider() { -  this.$get = ['$rootScope', function($rootScope) { - +  var $parse; +  this.$get = ['$rootScope', '$parse',  function($rootScope, $parse_) { +    $parse = $parse_;      /**       * @ngdoc proprety       * @name rootForm @@ -352,10 +353,14 @@ function $FormFactoryProvider() {          modelScope = params.scope,          onChange = params.onChange,          alias = params.alias, -        scopeGet = parser(params.model).assignable(), +        scopeGet = $parse(params.model),          scopeSet = scopeGet.assign,          widget = this.$new(params.controller, params.controllerArgs); +    if (!scopeSet) { +      throw Error("Expression '" + params.model + "' is not assignable!"); +    }; +      widget.$error = {};      // Set the state to something we know will change to get the process going.      widget.$modelValue = Number.NaN; diff --git a/src/service/parse.js b/src/service/parse.js index f7b24a3c..465f416e 100644 --- a/src/service/parse.js +++ b/src/service/parse.js @@ -219,6 +219,7 @@ function lex(text){  function parser(text, json){    var ZERO = valueFn(0), +      value,        tokens = lex(text),        assignment = _assignment,        assignable = logicalOR, @@ -240,24 +241,14 @@ function parser(text, json){        functionIdent =        pipeFunction =          function() { throwError("is not valid json", {text:text, index:0}); }; +    value = primary(); +  } else { +    value = statements();    } -  //TODO: Shouldn't all of the public methods have assertAllConsumed? -  //TODO: I think these should be public as part of the parser api instead of scope.$eval(). -  return { -      assignable: assertConsumed(assignable), -      primary: assertConsumed(primary), -      statements: assertConsumed(statements) -  }; - -  function assertConsumed(fn) { -    return function() { -      var value = fn(); -      if (tokens.length !== 0) { -        throwError("is an unexpected token", tokens[0]); -      } -      return value; -    }; +  if (tokens.length !== 0) { +    throwError("is an unexpected token", tokens[0]);    } +  return value;    ///////////////////////////////////    function throwError(msg, token) { @@ -680,7 +671,6 @@ function getter(obj, path, bindFnToScope) {  }  var getterFnCache = {}, -    compileCache = {},      JS_KEYWORDS = {};  forEach( @@ -727,13 +717,28 @@ function getterFn(path) {  /////////////////////////////////// -// TODO(misko): Deprecate? Remove! -// I think that compilation should be a service. -function expressionCompile(exp) { -  if (isFunction(exp)) return exp; -  var fn = compileCache[exp]; -  if (!fn) { -    fn = compileCache[exp] =  parser(exp).statements(); -  } -  return fn; +function $ParseProvider() { +  var cache = {}; +  this.$get = ['$injector', function($injector) { +    return function(exp) { +      switch(typeof exp) { +        case 'string': +          return cache.hasOwnProperty(exp) +            ? cache[exp] +            : cache[exp] =  parser(exp); +        case 'function': +          return exp; +        default: +          return noop; +      } +    }; +  }];  } + +// This is a special access for JSON parser which bypasses the injector +var parseJson = function(json) { +  return parser(json, true); +}; + +// TODO(misko): temporary hack, until we get rid of the type augmentation +var expressionCompile = new $ParseProvider().$get[1](null); diff --git a/src/service/scope.js b/src/service/scope.js index 8c7926de..ade2d82e 100644 --- a/src/service/scope.js +++ b/src/service/scope.js @@ -25,8 +25,8 @@   * are expensive to construct.   */  function $RootScopeProvider(){ -  this.$get = ['$injector', '$exceptionHandler', -      function( $injector,  $exceptionHandler){ +  this.$get = ['$injector', '$exceptionHandler', '$parse', +      function( $injector,   $exceptionHandler,   $parse){      /**       * @ngdoc function       * @name angular.scope @@ -416,10 +416,7 @@ function $RootScopeProvider(){         * @returns {*} The result of evaluating the expression.         */        $eval: function(expr) { -        var fn = isString(expr) -          ? expressionCompile(expr) -          : expr || noop; -        return fn(this); +        return $parse(expr)(this);        },        /** diff --git a/test/service/parseSpec.js b/test/service/parseSpec.js index ce3b22ca..5045ec9e 100644 --- a/test/service/parseSpec.js +++ b/test/service/parseSpec.js @@ -413,12 +413,12 @@ describe('parser', function() {    describe('assignable', function() { -    it('should expose assignment function', function() { -      var fn = parser('a').assignable(); +    it('should expose assignment function', inject(function($parse) { +      var fn = $parse('a');        expect(fn.assign).toBeTruthy();        var scope = {};        fn.assign(scope, 123);        expect(scope).toEqual({a:123}); -    }); +    }));    });  }); diff --git a/test/testabilityPatch.js b/test/testabilityPatch.js index 4d576ab9..96deac5a 100644 --- a/test/testabilityPatch.js +++ b/test/testabilityPatch.js @@ -49,8 +49,6 @@ function dumpScope(scope, offset) {  publishExternalAPI(angular)  beforeEach(function() {    publishExternalAPI(angular) -  // This is to reset parsers global cache of expressions. -  compileCache = {};    // workaround for IE bug https://plus.google.com/104744871076396904202/posts/Kqjuj6RSbbT    // IE overwrite window.jQuery with undefined because of empty jQuery var statement, so we have to | 
