Skip to content

Commit

Permalink
Fix wrong handling of relational expression in a for statement.
Browse files Browse the repository at this point in the history
If operator 'in' is not allowed, it can not be just allowed within
the binary expression.

https://code.google.com/p/esprima/issues/detail?id=449
  • Loading branch information
ariya committed Sep 11, 2013
1 parent 38b068d commit db27559
Show file tree
Hide file tree
Showing 2 changed files with 206 additions and 10 deletions.
20 changes: 10 additions & 10 deletions esprima.js
Expand Up @@ -2193,11 +2193,14 @@ parseStatement: true, parseSourceElement: true */
} }


function parseLeftHandSideExpressionAllowCall() { function parseLeftHandSideExpressionAllowCall() {
var marker, expr, args, property; var marker, previousAllowIn, expr, args, property;


marker = createLocationMarker(); marker = createLocationMarker();


previousAllowIn = state.allowIn;
state.allowIn = true;
expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression(); expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();
state.allowIn = previousAllowIn;


while (match('.') || match('[') || match('(')) { while (match('.') || match('[') || match('(')) {
if (match('(')) { if (match('(')) {
Expand All @@ -2220,11 +2223,13 @@ parseStatement: true, parseSourceElement: true */
} }


function parseLeftHandSideExpression() { function parseLeftHandSideExpression() {
var marker, expr, property; var marker, previousAllowIn, expr, property;


marker = createLocationMarker(); marker = createLocationMarker();


previousAllowIn = state.allowIn;
expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression(); expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();
state.allowIn = previousAllowIn;


while (match('.') || match('[')) { while (match('.') || match('[')) {
if (match('[')) { if (match('[')) {
Expand Down Expand Up @@ -2390,16 +2395,13 @@ parseStatement: true, parseSourceElement: true */
// 11.11 Binary Logical Operators // 11.11 Binary Logical Operators


function parseBinaryExpression() { function parseBinaryExpression() {
var marker, markers, expr, token, prec, previousAllowIn, stack, right, operator, left, i; var marker, markers, expr, token, prec, stack, right, operator, left, i;

previousAllowIn = state.allowIn;
state.allowIn = true;


marker = createLocationMarker(); marker = createLocationMarker();
left = parseUnaryExpression(); left = parseUnaryExpression();


token = lookahead; token = lookahead;
prec = binaryPrecedence(token, previousAllowIn); prec = binaryPrecedence(token, state.allowIn);
if (prec === 0) { if (prec === 0) {
return left; return left;
} }
Expand All @@ -2411,7 +2413,7 @@ parseStatement: true, parseSourceElement: true */


stack = [left, token, right]; stack = [left, token, right];


while ((prec = binaryPrecedence(lookahead, previousAllowIn)) > 0) { while ((prec = binaryPrecedence(lookahead, state.allowIn)) > 0) {


// Reduce: make a binary expression from the three topmost entries. // Reduce: make a binary expression from the three topmost entries.
while ((stack.length > 2) && (prec <= stack[stack.length - 2].prec)) { while ((stack.length > 2) && (prec <= stack[stack.length - 2].prec)) {
Expand All @@ -2438,8 +2440,6 @@ parseStatement: true, parseSourceElement: true */
stack.push(expr); stack.push(expr);
} }


state.allowIn = previousAllowIn;

// Final reduce to clean-up the stack. // Final reduce to clean-up the stack.
i = stack.length - 1; i = stack.length - 1;
expr = stack[i]; expr = stack[i];
Expand Down
196 changes: 196 additions & 0 deletions test/test.js
Expand Up @@ -12758,6 +12758,202 @@ var testFixture = {
} }
}, },


'for (var x = y = z in q);': {
type: 'ForInStatement',
left: {
type: 'VariableDeclaration',
declarations: [{
type: 'VariableDeclarator',
id: {
type: 'Identifier',
name: 'x',
range: [9, 10],
loc: {
start: { line: 1, column: 9 },
end: { line: 1, column: 10 }
}
},
init: {
type: 'AssignmentExpression',
operator: '=',
left: {
type: 'Identifier',
name: 'y',
range: [13, 14],
loc: {
start: { line: 1, column: 13 },
end: { line: 1, column: 14 }
}
},
right: {
type: 'Identifier',
name: 'z',
range: [17, 18],
loc: {
start: { line: 1, column: 17 },
end: { line: 1, column: 18 }
}
},
range: [12, 18],
loc: {
start: { line: 1, column: 12 },
end: { line: 1, column: 18 }
}
},
range: [9, 18],
loc: {
start: { line: 1, column: 9 },
end: { line: 1, column: 18 }
}
}],
kind: 'var',
range: [5, 18],
loc: {
start: { line: 1, column: 5 },
end: { line: 1, column: 18 }
}
},
right: {
type: 'Identifier',
name: 'q',
range: [22, 23],
loc: {
start: { line: 1, column: 22 },
end: { line: 1, column: 23 }
}
},
body: {
type: 'EmptyStatement',
range: [24, 25],
loc: {
start: { line: 1, column: 24 },
end: { line: 1, column: 25 }
}
},
each: false,
range: [0, 25],
loc: {
start: { line: 1, column: 0 },
end: { line: 1, column: 25 }
}
},

'for (var a = b = c = (d in e) in z);': {
type: 'ForInStatement',
left: {
type: 'VariableDeclaration',
declarations: [{
type: 'VariableDeclarator',
id: {
type: 'Identifier',
name: 'a',
range: [9, 10],
loc: {
start: { line: 1, column: 9 },
end: { line: 1, column: 10 }
}
},
init: {
type: 'AssignmentExpression',
operator: '=',
left: {
type: 'Identifier',
name: 'b',
range: [13, 14],
loc: {
start: { line: 1, column: 13 },
end: { line: 1, column: 14 }
}
},
right: {
type: 'AssignmentExpression',
operator: '=',
left: {
type: 'Identifier',
name: 'c',
range: [17, 18],
loc: {
start: { line: 1, column: 17 },
end: { line: 1, column: 18 }
}
},
right: {
type: 'BinaryExpression',
operator: 'in',
left: {
type: 'Identifier',
name: 'd',
range: [22, 23],
loc: {
start: { line: 1, column: 22 },
end: { line: 1, column: 23 }
}
},
right: {
type: 'Identifier',
name: 'e',
range: [27, 28],
loc: {
start: { line: 1, column: 27 },
end: { line: 1, column: 28 }
}
},
range: [22, 28],
loc: {
start: { line: 1, column: 22 },
end: { line: 1, column: 28 }
}
},
range: [16, 29],
loc: {
start: { line: 1, column: 16 },
end: { line: 1, column: 29 }
}
},
range: [12, 29],
loc: {
start: { line: 1, column: 12 },
end: { line: 1, column: 29 }
}
},
range: [9, 29],
loc: {
start: { line: 1, column: 9 },
end: { line: 1, column: 29 }
}
}],
kind: 'var',
range: [5, 29],
loc: {
start: { line: 1, column: 5 },
end: { line: 1, column: 29 }
}
},
right: {
type: 'Identifier',
name: 'z',
range: [33, 34],
loc: {
start: { line: 1, column: 33 },
end: { line: 1, column: 34 }
}
},
body: {
type: 'EmptyStatement',
range: [35, 36],
loc: {
start: { line: 1, column: 35 },
end: { line: 1, column: 36 }
}
},
each: false,
range: [0, 36],
loc: {
start: { line: 1, column: 0 },
end: { line: 1, column: 36 }
}
},

'for (var i = function() { return 10 in [] } in list) process(x);': { 'for (var i = function() { return 10 in [] } in list) process(x);': {
type: 'ForInStatement', type: 'ForInStatement',
left: { left: {
Expand Down

0 comments on commit db27559

Please sign in to comment.