Bug 694306 - Keywords should not be permitted in destructuring shorthand. r=Waldo.

This commit is contained in:
Jason Orendorff 2011-11-02 14:30:58 -05:00
parent 5a2e62638a
commit 118bcfc35f
5 changed files with 95 additions and 38 deletions

View File

@ -6716,6 +6716,8 @@ Parser::primaryExpr(TokenKind tt, JSBool afterDot)
* for |var {x: x, y: y} = o|, per proposed JS2/ES4 for JS1.8.
*/
tokenStream.ungetToken();
if (!tokenStream.checkForKeyword(atom->charsZ(), atom->length(), NULL, NULL))
return NULL;
pn->pn_xflags |= PNX_DESTRUCT | PNX_NONCONST;
pnval = pn3;
if (pnval->isKind(TOK_NAME)) {

View File

@ -1290,6 +1290,48 @@ TokenStream::putIdentInTokenbuf(const jschar *identStart)
return true;
}
bool
TokenStream::checkForKeyword(const jschar *s, size_t length, TokenKind *ttp, JSOp *topp)
{
JS_ASSERT(!ttp == !topp);
const KeywordInfo *kw = FindKeyword(s, length);
if (!kw)
return true;
if (kw->tokentype == TOK_RESERVED) {
return ReportCompileErrorNumber(cx, this, NULL, JSREPORT_ERROR,
JSMSG_RESERVED_ID, kw->chars);
}
if (kw->tokentype != TOK_STRICT_RESERVED) {
if (kw->version <= versionNumber()) {
/* Working keyword. */
if (ttp) {
*ttp = kw->tokentype;
*topp = (JSOp) kw->op;
return true;
}
return ReportCompileErrorNumber(cx, this, NULL, JSREPORT_ERROR,
JSMSG_RESERVED_ID, kw->chars);
}
/*
* The keyword is not in this version. Treat it as an identifier,
* unless it is let or yield which we treat as TOK_STRICT_RESERVED by
* falling through to the code below (ES5 forbids them in strict mode).
*/
if (kw->tokentype != TOK_LET && kw->tokentype != TOK_YIELD)
return true;
}
/* Strict reserved word. */
if (isStrictMode())
return ReportStrictModeError(cx, this, NULL, NULL, JSMSG_RESERVED_ID, kw->chars);
return ReportCompileErrorNumber(cx, this, NULL, JSREPORT_STRICT | JSREPORT_WARNING,
JSMSG_RESERVED_ID, kw->chars);
}
enum FirstCharKind {
Other,
OneChar,
@ -1464,45 +1506,20 @@ TokenStream::getTokenInternal()
/* Check for keywords unless parser asks us to ignore keywords. */
if (!(flags & TSF_KEYWORD_IS_NAME)) {
const KeywordInfo *kw;
if (hadUnicodeEscape)
kw = FindKeyword(tokenbuf.begin(), tokenbuf.length());
else
kw = FindKeyword(identStart, userbuf.addressOfNextRawChar() - identStart);
if (kw) {
if (kw->tokentype == TOK_RESERVED) {
if (!ReportCompileErrorNumber(cx, this, NULL, JSREPORT_ERROR,
JSMSG_RESERVED_ID, kw->chars)) {
goto error;
}
} else if (kw->tokentype == TOK_STRICT_RESERVED) {
if (isStrictMode()
? !ReportStrictModeError(cx, this, NULL, NULL, JSMSG_RESERVED_ID, kw->chars)
: !ReportCompileErrorNumber(cx, this, NULL,
JSREPORT_STRICT | JSREPORT_WARNING,
JSMSG_RESERVED_ID, kw->chars)) {
goto error;
}
} else {
if (kw->version <= versionNumber()) {
tt = kw->tokentype;
tp->t_op = (JSOp) kw->op;
goto out;
}
/*
* let/yield are a Mozilla extension starting in JS1.7. If we
* aren't parsing for a version supporting these extensions,
* conform to ES5 and forbid these names in strict mode.
*/
if ((kw->tokentype == TOK_LET || kw->tokentype == TOK_YIELD) &&
!ReportStrictModeError(cx, this, NULL, NULL, JSMSG_RESERVED_ID, kw->chars))
{
goto error;
}
}
const jschar *chars;
size_t length;
if (hadUnicodeEscape) {
chars = tokenbuf.begin();
length = tokenbuf.length();
} else {
chars = identStart;
length = userbuf.addressOfNextRawChar() - identStart;
}
tt = TOK_NAME;
if (!checkForKeyword(chars, length, &tt, &tp->t_op))
goto error;
if (tt != TOK_NAME)
goto out;
}
/*

View File

@ -600,6 +600,22 @@ class TokenStream
return sm;
}
/*
* If the name at s[0:length] is not a keyword in this version, return
* true with *ttp and *topp unchanged.
*
* If it is a reserved word in this version and strictness mode, and thus
* can't be present in correct code, report a SyntaxError and return false.
*
* If it is a keyword, like "if", the behavior depends on ttp/topp. If ttp
* and topp are null, report a SyntaxError ("if is a reserved identifier")
* and return false. If ttp and topp are non-null, return true with the
* keyword's TokenKind in *ttp and its JSOp in *topp.
*
* ttp and topp must be either both null or both non-null.
*/
bool checkForKeyword(const jschar *s, size_t length, TokenKind *ttp, JSOp *topp);
private:
/*
* This is the low-level interface to the JS source code buffer. It just

View File

@ -116,3 +116,4 @@ script regress-673070-1.js
script regress-673070-2.js
script regress-673070-3.js
script regress-675581.js
script regress-694306.js

View File

@ -0,0 +1,21 @@
// Any copyright is dedicated to the Public Domain.
// http://creativecommons.org/licenses/publicdomain/
var x;
try {
eval("var {if} = {'if': 1};");
} catch (exc) {
x = exc;
}
assertEq(x instanceof SyntaxError, true);
assertEq("if" in this, false);
x = undefined;
try {
Function("var {if} = {'if': 1};");
} catch (exc) {
x = exc;
}
assertEq(x instanceof SyntaxError, true);
reportCompare(0, 0, 'ok');