Incorrect expression results with && and array and object access #12037
Description
This issue affects Angular 1.4.0. The 1.3.x branch appears unaffected.
Expressions which contain a &&
clause with a true thing on the left, and a null
/undefined
thing on the right which uses the form obj[index].key
, return the true thing even though the second half of the &&
was falsy. See examples:
Expression: a[0].asdf && 72
(where a
is undefined
)
Expected: undefined
Actual: undefined
Expression: 72 && a[0].asdf
(where a
is undefined
)
Expected: undefined
Actual: 72
This can even be reproduced with object literals:
Expression: 72 && ({})[0].asdf
Expected: undefined
Actual: 72
By inspecting the function returned by $parse(expression)
it is fairly easy to see the faulty logic:
> $parse('72 && ({})[0].asdf').toString()
function (s,l,a,i){var v0,v1,v2,v3;v0=72;if(v0){v2={};if(v2!=null){v3=0;ensureSafeMemberName(v3,text);v1=ensureSafeObject(v2[v3],text);if(v1!=null){v0=v1.asdf;}}}return v0;}
Prettified:
function (s,l,a,i){
var v0, v1, v2, v3;
v0 = 72;
if (v0) {
v2 = {};
if (v2 != null) {
v3 = 0;
ensureSafeMemberName(v3, text);
v1 = ensureSafeObject(v2[v3], text);
if (v1 != null) {
v0 = v1.asdf;
}
}
}
return v0;
}
Tracing the execution and filling out the variables gives the following values:
v0 = 72
v1 = v2[v3] == {}[0] == undefined
v2 = {}
v3 = 0
Now notice the last nested if
. Since v1 == undefined
and !(undefined != null)
, that if
is skipped and execution skips to the final line, where v0 = 72
is returned, despite v1
(the right-hand side of the &&
) being undefined
.