*/
static boolean isVisiblePropertyExpr(
Expression e, ScopeTree scopeTree, Set<String> identifiersExpanding) {
if (e instanceof NumberLiteral) { return true; }
if (e instanceof Operation) {
Operation op = (Operation) e;
switch (op.getOperator()) {
case COMMA:
Expression last = op.children().get(1);
return isVisiblePropertyExpr(last, scopeTree, identifiersExpanding);
// || and && pass through one of their operands unchanged.
// The addition operator works as follows:
// 11.6.1 Additive Operator
// ...
// 4. Call GetValue(Result(3)).
// 5. Call ToPrimitive(Result(2)).
// 6. Call ToPrimitive(Result(4)).
// 7. If Type(Result(5)) is String or Type(Result(6)) is String, go to
// step 12. (Note that this step differs from step 3 in the
// comparison algorithm for the relational operators, by using or
// instead of and.)
// 8. Call ToNumber(Result(5)).
// 9. Call ToNumber(Result(6)).
// ...
// which means that (undefined + undefined) is a number, and so if both
// operands are undefined or numeric, the result is guaranteed to be
// numeric.
case LOGICAL_OR: case LOGICAL_AND: case ADDITION:
return isVisiblePropertyExpr(
op.children().get(0), scopeTree, identifiersExpanding)
&& isVisiblePropertyExpr(
op.children().get(1), scopeTree, identifiersExpanding);
case TERNARY:
return isVisiblePropertyExpr(
op.children().get(1), scopeTree, identifiersExpanding)
&& isVisiblePropertyExpr(
op.children().get(2), scopeTree, identifiersExpanding);
case ASSIGN:
return isVisiblePropertyExpr(
op.children().get(1), scopeTree, identifiersExpanding);
default:
if (isNumberOrUndefOperator(op.getOperator())) {
return true;
}
break;
}
} else if (e instanceof Reference) {