Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Logical operators return incorrect results when used on forgiving expressions. #12099

Closed
georeith opened this issue Jun 12, 2015 · 6 comments
Closed
Assignees
Milestone

Comments

@georeith
Copy link

Version: 1.4.0-rc.2

Given the following statements:

  • scope.$eval("true && does.not.exist");
  • scope.$eval("true && !does.not.exist");

Both return true, as long as does.not is not an object on the current scope.

However scope.$eval("true && doesnotexist"); and scope.$eval("true && undefined"); both return false as expected as long as doesnotexist is not a truthy value on the current scope.

This makes me think it has something to do with using scope.$parse as it only occurs when attempting to access nested properties of undefined values on the scope which scope.$parse suppresses errors for.

For this reason any directive such as ng-if and ng-switch. For examples see: http://jsbin.com/muqaviwesu/1/edit?html,js,output

@georeith georeith changed the title Boolean logic fails for undefined lookups via $parse Boolean logic incorrect in $eval expressions when accessing nested undefined properties on the scope. Jun 12, 2015
@ExplodingCabbage
Copy link

Another example, using "forgiving" function calls: scope.$eval("true && doesnotexist()"); returns true.

I guess that in general this weird behaviour happens when using boolean operators on the results of "forgiving" expressions. But nothing in the docs about forgiving expressions suggests that this behaviour should occur, and it's bizarre; it's a violation of the simple mental model of "calling undefined as a function or accessing properties of undefined returns undefined" that the docs give us.

Of course, any fix to this will be a breaking change, but it seems like a clear bug.

@georeith georeith changed the title Boolean logic incorrect in $eval expressions when accessing nested undefined properties on the scope. Logical operators return incorrect results when used on forgiving expressions. Jun 12, 2015
@lgalfaso lgalfaso self-assigned this Jun 12, 2015
@lgalfaso lgalfaso added this to the 1.4.1 milestone Jun 12, 2015
@lgalfaso
Copy link
Contributor

The issues originally posted are fixed as part of d19504a the other is a real issue. Should have a patch soon

lgalfaso added a commit to lgalfaso/angular.js that referenced this issue Jun 12, 2015
When there is an expression of the form `true && a.b` and where `a == null`, then set
the value of `true || a()` to `undefined`.

Closes angular#12099
@Narretz
Copy link
Contributor

Narretz commented Jun 12, 2015

@lgalfaso are you sure the first issue has been fixed? In the jsbin, the first ng-if for 'AND' should evaluate to undefined, i.e. be not visible. This doesn't work with the snapshot, but it does work in 1.3.16

lgalfaso added a commit to lgalfaso/angular.js that referenced this issue Jun 12, 2015
When there is an expression of the form
* true && a.b.c
* true && a()
* true && a()()
* false || a.b.c
* false || a()
* false || a()()

where `a == null`

Closes angular#12099
@lgalfaso
Copy link
Contributor

Mmm.. @Narretz you are right, updated the PR to fix

  • true && a.b.c
  • true && a()
  • true && a()()
  • false || a.b.c
  • false || a()
  • false || a()()

where a == null

These are all small variations of the same issue, hopefully this should fix all the variations

lgalfaso added a commit to lgalfaso/angular.js that referenced this issue Jun 12, 2015
When there is an expression of the form
* true && a.b.c
* true && a()
* true && a()()
* false || a.b.c
* false || a()
* false || a()()

where `a == null`

Closes angular#12099
lgalfaso added a commit to lgalfaso/angular.js that referenced this issue Jun 12, 2015
When there is an expression of the form
* true && a.b.c
* true && a()
* true && a()()
* false || a.b.c
* false || a()
* false || a()()

where `a == null`

Closes angular#12099
lgalfaso added a commit to lgalfaso/angular.js that referenced this issue Jun 13, 2015
When there is an expression of the form
* true && a.b.c
* true && a()
* true && a()()
* false || a.b.c
* false || a()
* false || a()()

where `a == null`

Closes angular#12099
@ExplodingCabbage
Copy link

@lgalfaso just a note - although @georeith gave the example of true && a.b.c, the same bug occurs for just true && a.b if a is null. I notice that your commit message refers to the a.b.c form but not the a.b form; I don't know whether you've in fact fixed both.

@lgalfaso
Copy link
Contributor

@ExplodingCabbage they are all fixed, in fact we have tests for

  • true && a
  • true && a()
  • true && a()()
  • true && a.b
  • true && a.b.c
  • false || a
  • false || a()
  • false || a()()
  • false || a.b
  • false || a.b.c

netman92 pushed a commit to netman92/angular.js that referenced this issue Aug 8, 2015
When there is an expression of the form
* true && a.b.c
* true && a()
* true && a()()
* false || a.b.c
* false || a()
* false || a()()

where `a == null`

Closes angular#12099
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants