Bug 791465 - Fix processDirectives' ASI emulation. code=André Bargull r=benjamin

This commit is contained in:
Benjamin Peterson 2012-10-13 09:23:53 -04:00
parent 4c71fe77a0
commit 4a9d49c642
3 changed files with 125 additions and 1 deletions

View File

@ -1857,7 +1857,13 @@ Parser::processDirectives(ParseNode *stmts)
bool isDirective = IsEscapeFreeStringLiteral(directive);
JSAtom *atom = directive.atom();
TokenKind next = tokenStream.peekTokenSameLine();
if (next != TOK_EOF && next != TOK_EOL && next != TOK_SEMI && next != TOK_RC) {
// We need to check whether the directive ends explicitly or implicitly
// due to ASI. In the latter case, the expression must not continue on
// the next line.
if (next != TOK_EOF && next != TOK_SEMI && next != TOK_RC &&
(next != TOK_EOL || TokenContinuesStringExpression(tokenStream.peekToken())))
{
freeTree(stringNode);
if (next == TOK_ERROR)
return false;

View File

@ -181,6 +181,41 @@ TokenKindIsAssignment(TokenKind tt)
return TOK_ASSIGNMENT_START <= tt && tt <= TOK_ASSIGNMENT_LAST;
}
inline bool
TokenContinuesStringExpression(TokenKind tt)
{
switch (tt) {
// comma expression
case TOK_COMMA:
// conditional expression
case TOK_HOOK:
// binary expression
case TOK_OR:
case TOK_AND:
case TOK_BITOR:
case TOK_BITXOR:
case TOK_BITAND:
case TOK_PLUS:
case TOK_MINUS:
case TOK_STAR:
case TOK_DIV:
case TOK_MOD:
case TOK_IN:
case TOK_INSTANCEOF:
// member expression
case TOK_DOT:
case TOK_LB:
case TOK_LP:
case TOK_DBLDOT:
return true;
default:
return TokenKindIsEquality(tt) ||
TokenKindIsRelational(tt) ||
TokenKindIsShift(tt) ||
TokenKindIsAssignment(tt);
}
}
inline bool
TokenKindIsDecl(TokenKind tt)
{

View File

@ -0,0 +1,83 @@
load(libdir + "asserts.js");
function xmlAllowed() {
return (typeof options == "function") &&
(options() + "").contains("allow_xml");
}
var valid_strict_funs = [
// directive ends on next line
function () {
"use strict"
;
},
function () {
"use strict"
},
// directive ends on same line
function () { "use strict"; },
function () { "use strict" },
];
for (var f of valid_strict_funs) {
assertThrowsInstanceOf(function() { f.caller }, TypeError);
}
var binary_ops = [
"||", "&&",
"|", "^", "&",
"==", "!=", "===", "!==",
"<", "<=", ">", ">=", "in", "instanceof",
"<<", ">>", ">>>",
"+", "-",
"*", "/", "%",
];
var invalid_strict_funs = [
function () {
"use strict"
, "not";
},
function () {
"use strict"
? 1 : 0;
},
function () {
"use strict"
.length;
},
function () {
"use strict"
[0];
},
function () {
"use strict"
();
},
...(xmlAllowed() ? [Function("'use strict'\n..not")] : []),
...[Function("'use strict'\n " + op + " 'not'") for (op of binary_ops)],
];
for (var f of invalid_strict_funs) {
f.caller;
}
var assignment_ops = [
"=", "+=", "-=",
"|=", "^=", "&=",
"<<=", ">>=", ">>>=",
"*=", "/=", "%=",
];
var invalid_strict_funs_referror = [
...[("'use strict'\n " + op + " 'not'") for (op of assignment_ops)],
];
// assignment with string literal as LHS is an early error, therefore we
// can only test for ReferenceError
for (var f of invalid_strict_funs_referror) {
assertThrowsInstanceOf(function() { Function(f) }, ReferenceError);
}