diff options
| author | Dhruv Manek | 2011-09-30 16:55:01 -0700 | 
|---|---|---|
| committer | Igor Minar | 2011-10-07 16:01:09 -0700 | 
| commit | e1ecc34edd19b95d51fbcb1351b04b9876c974c1 (patch) | |
| tree | 7b71b421e03cc27faaa86581ca8262026330505c | |
| parent | 29d36e94e101c76da58421cab6828146b041b108 (diff) | |
| download | angular.js-e1ecc34edd19b95d51fbcb1351b04b9876c974c1.tar.bz2 | |
fix(parser): Fix short circuit of logical AND and OR operators
Closes #433
| -rw-r--r-- | src/parser.js | 38 | ||||
| -rw-r--r-- | test/ParserSpec.js | 22 | 
2 files changed, 38 insertions, 22 deletions
| diff --git a/src/parser.js b/src/parser.js index 5129f2f7..f8978a0b 100644 --- a/src/parser.js +++ b/src/parser.js @@ -5,25 +5,25 @@ var OPERATORS = {      'true':function(self){return true;},      'false':function(self){return false;},      $undefined:noop, -    '+':function(self, a,b){return (isDefined(a)?a:0)+(isDefined(b)?b:0);}, -    '-':function(self, a,b){return (isDefined(a)?a:0)-(isDefined(b)?b:0);}, -    '*':function(self, a,b){return a*b;}, -    '/':function(self, a,b){return a/b;}, -    '%':function(self, a,b){return a%b;}, -    '^':function(self, a,b){return a^b;}, +    '+':function(self, a,b){a=a(self); b=b(self); return (isDefined(a)?a:0)+(isDefined(b)?b:0);}, +    '-':function(self, a,b){a=a(self); b=b(self); return (isDefined(a)?a:0)-(isDefined(b)?b:0);}, +    '*':function(self, a,b){return a(self)*b(self);}, +    '/':function(self, a,b){return a(self)/b(self);}, +    '%':function(self, a,b){return a(self)%b(self);}, +    '^':function(self, a,b){return a(self)^b(self);},      '=':noop, -    '==':function(self, a,b){return a==b;}, -    '!=':function(self, a,b){return a!=b;}, -    '<':function(self, a,b){return a<b;}, -    '>':function(self, a,b){return a>b;}, -    '<=':function(self, a,b){return a<=b;}, -    '>=':function(self, a,b){return a>=b;}, -    '&&':function(self, a,b){return a&&b;}, -    '||':function(self, a,b){return a||b;}, -    '&':function(self, a,b){return a&b;}, +    '==':function(self, a,b){return a(self)==b(self);}, +    '!=':function(self, a,b){return a(self)!=b(self);}, +    '<':function(self, a,b){return a(self)<b(self);}, +    '>':function(self, a,b){return a(self)>b(self);}, +    '<=':function(self, a,b){return a(self)<=b(self);}, +    '>=':function(self, a,b){return a(self)>=b(self);}, +    '&&':function(self, a,b){return a(self)&&b(self);}, +    '||':function(self, a,b){return a(self)||b(self);}, +    '&':function(self, a,b){return a(self)&b(self);},  //    '|':function(self, a,b){return a|b;}, -    '|':function(self, a,b){return b(self, a);}, -    '!':function(self, a){return !a;} +    '|':function(self, a,b){return b(self)(self, a(self));}, +    '!':function(self, a){return !a(self);}  };  var ESCAPE = {"n":"\n", "f":"\f", "r":"\r", "t":"\t", "v":"\v", "'":"'", '"':'"'}; @@ -308,13 +308,13 @@ function parser(text, json){    function unaryFn(fn, right) {      return function(self) { -      return fn(self, right(self)); +      return fn(self, right);      };    }    function binaryFn(left, fn, right) {      return function(self) { -      return fn(self, left(self), right(self)); +      return fn(self, left, right);      };    } diff --git a/test/ParserSpec.js b/test/ParserSpec.js index 4c3cb64b..a5e1901c 100644 --- a/test/ParserSpec.js +++ b/test/ParserSpec.js @@ -391,7 +391,7 @@ describe('parser', function() {      expect(scope.a).not.toBeDefined();    }); -  it('should allow assignment after array dereference', function(){ +  it('should allow assignment after array dereference', function() {      scope = angular.scope();      scope.obj = [{}];      scope.$eval('obj[0].name=1'); @@ -399,14 +399,30 @@ describe('parser', function() {      expect(scope.obj[0].name).toEqual(1);    }); -  describe('formatter', function(){ +  it('should short-circuit AND operator', function() { +    var scope = angular.scope(); +    scope.run = function() { +      throw "IT SHOULD NOT HAVE RUN"; +    }; +    expect(scope.$eval('false && run()')).toBe(false); +  }); + +  it('should short-circuit OR operator', function() { +    var scope = angular.scope(); +    scope.run = function() { +      throw "IT SHOULD NOT HAVE RUN"; +    }; +    expect(scope.$eval('true || run()')).toBe(true); +  }); + +  describe('formatter', function() {      it('should return no argument function', function() {        var noop = parser('noop').formatter()();        expect(noop.format(null, 'abc')).toEqual('abc');        expect(noop.parse(null, '123')).toEqual('123');      }); -    it('should delegate arguments', function(){ +    it('should delegate arguments', function() {        angularFormatter.myArgs = {          parse: function(a, b){ return [a, b]; },          format: function(a, b){ return [a, b]; } | 
