Commit 39957aa7 authored by peterhal@chromium.org's avatar peterhal@chromium.org

Issue 117 - strict mode and future reserved words

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6653 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 87233c49
...@@ -147,6 +147,7 @@ function FormatMessage(message) { ...@@ -147,6 +147,7 @@ function FormatMessage(message) {
unexpected_token_number: ["Unexpected number"], unexpected_token_number: ["Unexpected number"],
unexpected_token_string: ["Unexpected string"], unexpected_token_string: ["Unexpected string"],
unexpected_token_identifier: ["Unexpected identifier"], unexpected_token_identifier: ["Unexpected identifier"],
unexpected_strict_reserved: ["Unexpected strict mode reserved word"],
unexpected_eos: ["Unexpected end of input"], unexpected_eos: ["Unexpected end of input"],
malformed_regexp: ["Invalid regular expression: /", "%0", "/: ", "%1"], malformed_regexp: ["Invalid regular expression: /", "%0", "/: ", "%1"],
unterminated_regexp: ["Invalid regular expression: missing /"], unterminated_regexp: ["Invalid regular expression: missing /"],
...@@ -221,6 +222,7 @@ function FormatMessage(message) { ...@@ -221,6 +222,7 @@ function FormatMessage(message) {
strict_lhs_assignment: ["Assignment to eval or arguments is not allowed in strict mode"], strict_lhs_assignment: ["Assignment to eval or arguments is not allowed in strict mode"],
strict_lhs_postfix: ["Postfix increment/decrement may not have eval or arguments operand in strict mode"], strict_lhs_postfix: ["Postfix increment/decrement may not have eval or arguments operand in strict mode"],
strict_lhs_prefix: ["Prefix increment/decrement may not have eval or arguments operand in strict mode"], strict_lhs_prefix: ["Prefix increment/decrement may not have eval or arguments operand in strict mode"],
strict_reserved_word: ["Use of future reserved word in strict mode"],
}; };
} }
var message_type = %MessageGetType(message); var message_type = %MessageGetType(message);
......
This diff is collapsed.
...@@ -548,6 +548,7 @@ class Parser { ...@@ -548,6 +548,7 @@ class Parser {
ZoneList<Expression*>* ParseArguments(bool* ok); ZoneList<Expression*>* ParseArguments(bool* ok);
FunctionLiteral* ParseFunctionLiteral(Handle<String> var_name, FunctionLiteral* ParseFunctionLiteral(Handle<String> var_name,
bool name_is_reserved,
int function_token_position, int function_token_position,
FunctionLiteralType type, FunctionLiteralType type,
bool* ok); bool* ok);
...@@ -577,6 +578,8 @@ class Parser { ...@@ -577,6 +578,8 @@ class Parser {
return scanner().Next(); return scanner().Next();
} }
bool peek_any_identifier();
INLINE(void Consume(Token::Value token)); INLINE(void Consume(Token::Value token));
void Expect(Token::Value token, bool* ok); void Expect(Token::Value token, bool* ok);
bool Check(Token::Value token); bool Check(Token::Value token);
...@@ -610,6 +613,7 @@ class Parser { ...@@ -610,6 +613,7 @@ class Parser {
Literal* GetLiteralNumber(double value); Literal* GetLiteralNumber(double value);
Handle<String> ParseIdentifier(bool* ok); Handle<String> ParseIdentifier(bool* ok);
Handle<String> ParseIdentifierOrReservedWord(bool* is_reserved, bool* ok);
Handle<String> ParseIdentifierName(bool* ok); Handle<String> ParseIdentifierName(bool* ok);
Handle<String> ParseIdentifierOrGetOrSet(bool* is_get, Handle<String> ParseIdentifierOrGetOrSet(bool* is_get,
bool* is_set, bool* is_set,
......
...@@ -83,6 +83,7 @@ void PreParser::ReportUnexpectedToken(i::Token::Value token) { ...@@ -83,6 +83,7 @@ void PreParser::ReportUnexpectedToken(i::Token::Value token) {
return ReportMessageAt(source_location.beg_pos, source_location.end_pos, return ReportMessageAt(source_location.beg_pos, source_location.end_pos,
"unexpected_token_string", NULL); "unexpected_token_string", NULL);
case i::Token::IDENTIFIER: case i::Token::IDENTIFIER:
case i::Token::FUTURE_RESERVED_WORD:
return ReportMessageAt(source_location.beg_pos, source_location.end_pos, return ReportMessageAt(source_location.beg_pos, source_location.end_pos,
"unexpected_token_identifier", NULL); "unexpected_token_identifier", NULL);
default: default:
...@@ -790,7 +791,7 @@ PreParser::Expression PreParser::ParseMemberWithNewPrefixesExpression( ...@@ -790,7 +791,7 @@ PreParser::Expression PreParser::ParseMemberWithNewPrefixesExpression(
Expression result = kUnknownExpression; Expression result = kUnknownExpression;
if (peek() == i::Token::FUNCTION) { if (peek() == i::Token::FUNCTION) {
Consume(i::Token::FUNCTION); Consume(i::Token::FUNCTION);
if (peek() == i::Token::IDENTIFIER) { if (peek_any_identifier()) {
ParseIdentifier(CHECK_OK); ParseIdentifier(CHECK_OK);
} }
result = ParseFunctionLiteral(CHECK_OK); result = ParseFunctionLiteral(CHECK_OK);
...@@ -858,7 +859,8 @@ PreParser::Expression PreParser::ParsePrimaryExpression(bool* ok) { ...@@ -858,7 +859,8 @@ PreParser::Expression PreParser::ParsePrimaryExpression(bool* ok) {
break; break;
} }
case i::Token::IDENTIFIER: { case i::Token::IDENTIFIER:
case i::Token::FUTURE_RESERVED_WORD: {
ParseIdentifier(CHECK_OK); ParseIdentifier(CHECK_OK);
result = kIdentifierExpression; result = kIdentifierExpression;
break; break;
...@@ -946,7 +948,8 @@ PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) { ...@@ -946,7 +948,8 @@ PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) {
while (peek() != i::Token::RBRACE) { while (peek() != i::Token::RBRACE) {
i::Token::Value next = peek(); i::Token::Value next = peek();
switch (next) { switch (next) {
case i::Token::IDENTIFIER: { case i::Token::IDENTIFIER:
case i::Token::FUTURE_RESERVED_WORD: {
bool is_getter = false; bool is_getter = false;
bool is_setter = false; bool is_setter = false;
ParseIdentifierOrGetOrSet(&is_getter, &is_setter, CHECK_OK); ParseIdentifierOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
...@@ -954,6 +957,7 @@ PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) { ...@@ -954,6 +957,7 @@ PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) {
i::Token::Value name = Next(); i::Token::Value name = Next();
bool is_keyword = i::Token::IsKeyword(name); bool is_keyword = i::Token::IsKeyword(name);
if (name != i::Token::IDENTIFIER && if (name != i::Token::IDENTIFIER &&
name != i::Token::FUTURE_RESERVED_WORD &&
name != i::Token::NUMBER && name != i::Token::NUMBER &&
name != i::Token::STRING && name != i::Token::STRING &&
!is_keyword) { !is_keyword) {
...@@ -1151,7 +1155,9 @@ PreParser::Expression PreParser::GetStringSymbol() { ...@@ -1151,7 +1155,9 @@ PreParser::Expression PreParser::GetStringSymbol() {
PreParser::Identifier PreParser::ParseIdentifier(bool* ok) { PreParser::Identifier PreParser::ParseIdentifier(bool* ok) {
Expect(i::Token::IDENTIFIER, ok); if (!Check(i::Token::FUTURE_RESERVED_WORD)) {
Expect(i::Token::IDENTIFIER, ok);
}
if (!*ok) return kUnknownIdentifier; if (!*ok) return kUnknownIdentifier;
return GetIdentifierSymbol(); return GetIdentifierSymbol();
} }
...@@ -1166,7 +1172,8 @@ PreParser::Identifier PreParser::ParseIdentifierName(bool* ok) { ...@@ -1166,7 +1172,8 @@ PreParser::Identifier PreParser::ParseIdentifierName(bool* ok) {
i::StrLength(keyword))); i::StrLength(keyword)));
return kUnknownExpression; return kUnknownExpression;
} }
if (next == i::Token::IDENTIFIER) { if (next == i::Token::IDENTIFIER ||
next == i::Token::FUTURE_RESERVED_WORD) {
return GetIdentifierSymbol(); return GetIdentifierSymbol();
} }
*ok = false; *ok = false;
...@@ -1175,19 +1182,23 @@ PreParser::Identifier PreParser::ParseIdentifierName(bool* ok) { ...@@ -1175,19 +1182,23 @@ PreParser::Identifier PreParser::ParseIdentifierName(bool* ok) {
// This function reads an identifier and determines whether or not it // This function reads an identifier and determines whether or not it
// is 'get' or 'set'. The reason for not using ParseIdentifier and // is 'get' or 'set'.
// checking on the output is that this involves heap allocation which
// we can't do during preparsing.
PreParser::Identifier PreParser::ParseIdentifierOrGetOrSet(bool* is_get, PreParser::Identifier PreParser::ParseIdentifierOrGetOrSet(bool* is_get,
bool* is_set, bool* is_set,
bool* ok) { bool* ok) {
Expect(i::Token::IDENTIFIER, CHECK_OK); PreParser::Identifier result = ParseIdentifier(CHECK_OK);
if (scanner_->is_literal_ascii() && scanner_->literal_length() == 3) { if (scanner_->is_literal_ascii() && scanner_->literal_length() == 3) {
const char* token = scanner_->literal_ascii_string().start(); const char* token = scanner_->literal_ascii_string().start();
*is_get = strncmp(token, "get", 3) == 0; *is_get = strncmp(token, "get", 3) == 0;
*is_set = !*is_get && strncmp(token, "set", 3) == 0; *is_set = !*is_get && strncmp(token, "set", 3) == 0;
} }
return GetIdentifierSymbol(); return result;
}
bool PreParser::peek_any_identifier() {
i::Token::Value next = peek();
return next == i::Token::IDENTIFIER ||
next == i::Token::FUTURE_RESERVED_WORD;
} }
#undef CHECK_OK #undef CHECK_OK
......
...@@ -243,6 +243,8 @@ class PreParser { ...@@ -243,6 +243,8 @@ class PreParser {
return scanner_->Next(); return scanner_->Next();
} }
bool peek_any_identifier();
void Consume(i::Token::Value token) { Next(); } void Consume(i::Token::Value token) { Next(); }
void Expect(i::Token::Value token, bool* ok) { void Expect(i::Token::Value token, bool* ok) {
......
...@@ -796,25 +796,27 @@ KeywordMatcher::FirstState KeywordMatcher::first_states_[] = { ...@@ -796,25 +796,27 @@ KeywordMatcher::FirstState KeywordMatcher::first_states_[] = {
{ "break", KEYWORD_PREFIX, Token::BREAK }, { "break", KEYWORD_PREFIX, Token::BREAK },
{ NULL, C, Token::ILLEGAL }, { NULL, C, Token::ILLEGAL },
{ NULL, D, Token::ILLEGAL }, { NULL, D, Token::ILLEGAL },
{ "else", KEYWORD_PREFIX, Token::ELSE }, { NULL, E, Token::ILLEGAL },
{ NULL, F, Token::ILLEGAL }, { NULL, F, Token::ILLEGAL },
{ NULL, UNMATCHABLE, Token::ILLEGAL }, { NULL, UNMATCHABLE, Token::ILLEGAL },
{ NULL, UNMATCHABLE, Token::ILLEGAL }, { NULL, UNMATCHABLE, Token::ILLEGAL },
{ NULL, I, Token::ILLEGAL }, { NULL, I, Token::ILLEGAL },
{ NULL, UNMATCHABLE, Token::ILLEGAL }, { NULL, UNMATCHABLE, Token::ILLEGAL },
{ NULL, UNMATCHABLE, Token::ILLEGAL }, { NULL, UNMATCHABLE, Token::ILLEGAL },
{ NULL, UNMATCHABLE, Token::ILLEGAL }, { "let", KEYWORD_PREFIX, Token::FUTURE_RESERVED_WORD },
{ NULL, UNMATCHABLE, Token::ILLEGAL }, { NULL, UNMATCHABLE, Token::ILLEGAL },
{ NULL, N, Token::ILLEGAL }, { NULL, N, Token::ILLEGAL },
{ NULL, UNMATCHABLE, Token::ILLEGAL }, { NULL, UNMATCHABLE, Token::ILLEGAL },
{ NULL, UNMATCHABLE, Token::ILLEGAL }, { NULL, P, Token::ILLEGAL },
{ NULL, UNMATCHABLE, Token::ILLEGAL }, { NULL, UNMATCHABLE, Token::ILLEGAL },
{ "return", KEYWORD_PREFIX, Token::RETURN }, { "return", KEYWORD_PREFIX, Token::RETURN },
{ "switch", KEYWORD_PREFIX, Token::SWITCH }, { NULL, S, Token::ILLEGAL },
{ NULL, T, Token::ILLEGAL }, { NULL, T, Token::ILLEGAL },
{ NULL, UNMATCHABLE, Token::ILLEGAL }, { NULL, UNMATCHABLE, Token::ILLEGAL },
{ NULL, V, Token::ILLEGAL }, { NULL, V, Token::ILLEGAL },
{ NULL, W, Token::ILLEGAL } { NULL, W, Token::ILLEGAL },
{ NULL, UNMATCHABLE, Token::ILLEGAL },
{ "yield", KEYWORD_PREFIX, Token::FUTURE_RESERVED_WORD }
}; };
...@@ -822,7 +824,7 @@ void KeywordMatcher::Step(unibrow::uchar input) { ...@@ -822,7 +824,7 @@ void KeywordMatcher::Step(unibrow::uchar input) {
switch (state_) { switch (state_) {
case INITIAL: { case INITIAL: {
// matching the first character is the only state with significant fanout. // matching the first character is the only state with significant fanout.
// Match only lower-case letters in range 'b'..'w'. // Match only lower-case letters in range 'b'..'y'.
unsigned int offset = input - kFirstCharRangeMin; unsigned int offset = input - kFirstCharRangeMin;
if (offset < kFirstCharRangeLength) { if (offset < kFirstCharRangeLength) {
state_ = first_states_[offset].state; state_ = first_states_[offset].state;
...@@ -850,6 +852,8 @@ void KeywordMatcher::Step(unibrow::uchar input) { ...@@ -850,6 +852,8 @@ void KeywordMatcher::Step(unibrow::uchar input) {
break; break;
case C: case C:
if (MatchState(input, 'a', CA)) return; if (MatchState(input, 'a', CA)) return;
if (MatchKeywordStart(input, "class", 1,
Token::FUTURE_RESERVED_WORD)) return;
if (MatchState(input, 'o', CO)) return; if (MatchState(input, 'o', CO)) return;
break; break;
case CA: case CA:
...@@ -872,6 +876,18 @@ void KeywordMatcher::Step(unibrow::uchar input) { ...@@ -872,6 +876,18 @@ void KeywordMatcher::Step(unibrow::uchar input) {
if (MatchKeywordStart(input, "default", 2, Token::DEFAULT)) return; if (MatchKeywordStart(input, "default", 2, Token::DEFAULT)) return;
if (MatchKeywordStart(input, "delete", 2, Token::DELETE)) return; if (MatchKeywordStart(input, "delete", 2, Token::DELETE)) return;
break; break;
case E:
if (MatchKeywordStart(input, "else", 1, Token::ELSE)) return;
if (MatchKeywordStart(input, "enum", 1,
Token::FUTURE_RESERVED_WORD)) return;
if (MatchState(input, 'x', EX)) return;
break;
case EX:
if (MatchKeywordStart(input, "export", 2,
Token::FUTURE_RESERVED_WORD)) return;
if (MatchKeywordStart(input, "extends", 2,
Token::FUTURE_RESERVED_WORD)) return;
break;
case F: case F:
if (MatchKeywordStart(input, "false", 1, Token::FALSE_LITERAL)) return; if (MatchKeywordStart(input, "false", 1, Token::FALSE_LITERAL)) return;
if (MatchKeywordStart(input, "finally", 1, Token::FINALLY)) return; if (MatchKeywordStart(input, "finally", 1, Token::FINALLY)) return;
...@@ -880,10 +896,22 @@ void KeywordMatcher::Step(unibrow::uchar input) { ...@@ -880,10 +896,22 @@ void KeywordMatcher::Step(unibrow::uchar input) {
break; break;
case I: case I:
if (MatchKeyword(input, 'f', KEYWORD_MATCHED, Token::IF)) return; if (MatchKeyword(input, 'f', KEYWORD_MATCHED, Token::IF)) return;
if (MatchState(input, 'm', IM)) return;
if (MatchKeyword(input, 'n', IN, Token::IN)) return; if (MatchKeyword(input, 'n', IN, Token::IN)) return;
break; break;
case IM:
if (MatchState(input, 'p', IMP)) return;
break;
case IMP:
if (MatchKeywordStart(input, "implements", 3,
Token::FUTURE_RESERVED_WORD )) return;
if (MatchKeywordStart(input, "import", 3,
Token::FUTURE_RESERVED_WORD)) return;
break;
case IN: case IN:
token_ = Token::IDENTIFIER; token_ = Token::IDENTIFIER;
if (MatchKeywordStart(input, "interface", 2,
Token::FUTURE_RESERVED_WORD)) return;
if (MatchKeywordStart(input, "instanceof", 2, Token::INSTANCEOF)) return; if (MatchKeywordStart(input, "instanceof", 2, Token::INSTANCEOF)) return;
break; break;
case N: case N:
...@@ -891,6 +919,27 @@ void KeywordMatcher::Step(unibrow::uchar input) { ...@@ -891,6 +919,27 @@ void KeywordMatcher::Step(unibrow::uchar input) {
if (MatchKeywordStart(input, "new", 1, Token::NEW)) return; if (MatchKeywordStart(input, "new", 1, Token::NEW)) return;
if (MatchKeywordStart(input, "null", 1, Token::NULL_LITERAL)) return; if (MatchKeywordStart(input, "null", 1, Token::NULL_LITERAL)) return;
break; break;
case P:
if (MatchKeywordStart(input, "package", 1,
Token::FUTURE_RESERVED_WORD)) return;
if (MatchState(input, 'r', PR)) return;
if (MatchKeywordStart(input, "public", 1,
Token::FUTURE_RESERVED_WORD)) return;
break;
case PR:
if (MatchKeywordStart(input, "private", 2,
Token::FUTURE_RESERVED_WORD)) return;
if (MatchKeywordStart(input, "protected", 2,
Token::FUTURE_RESERVED_WORD)) return;
break;
case S:
if (MatchKeywordStart(input, "static", 1,
Token::FUTURE_RESERVED_WORD)) return;
if (MatchKeywordStart(input, "super", 1,
Token::FUTURE_RESERVED_WORD)) return;
if (MatchKeywordStart(input, "switch", 1,
Token::SWITCH)) return;
break;
case T: case T:
if (MatchState(input, 'h', TH)) return; if (MatchState(input, 'h', TH)) return;
if (MatchState(input, 'r', TR)) return; if (MatchState(input, 'r', TR)) return;
......
...@@ -564,10 +564,17 @@ class KeywordMatcher { ...@@ -564,10 +564,17 @@ class KeywordMatcher {
CON, CON,
D, D,
DE, DE,
E,
EX,
F, F,
I, I,
IM,
IMP,
IN, IN,
N, N,
P,
PR,
S,
T, T,
TH, TH,
TR, TR,
...@@ -583,7 +590,7 @@ class KeywordMatcher { ...@@ -583,7 +590,7 @@ class KeywordMatcher {
// Range of possible first characters of a keyword. // Range of possible first characters of a keyword.
static const unsigned int kFirstCharRangeMin = 'b'; static const unsigned int kFirstCharRangeMin = 'b';
static const unsigned int kFirstCharRangeMax = 'w'; static const unsigned int kFirstCharRangeMax = 'y';
static const unsigned int kFirstCharRangeLength = static const unsigned int kFirstCharRangeLength =
kFirstCharRangeMax - kFirstCharRangeMin + 1; kFirstCharRangeMax - kFirstCharRangeMin + 1;
// State map for first keyword character range. // State map for first keyword character range.
......
...@@ -155,38 +155,6 @@ namespace internal { ...@@ -155,38 +155,6 @@ namespace internal {
K(WHILE, "while", 0) \ K(WHILE, "while", 0) \
K(WITH, "with", 0) \ K(WITH, "with", 0) \
\ \
/* Future reserved words (ECMA-262, section 7.5.3, page 14). */ \
F(ABSTRACT, "abstract", 0) \
F(BOOLEAN, "boolean", 0) \
F(BYTE, "byte", 0) \
F(CHAR, "char", 0) \
F(CLASS, "class", 0) \
K(CONST, "const", 0) \
F(DOUBLE, "double", 0) \
F(ENUM, "enum", 0) \
F(EXPORT, "export", 0) \
F(EXTENDS, "extends", 0) \
F(FINAL, "final", 0) \
F(FLOAT, "float", 0) \
F(GOTO, "goto", 0) \
F(IMPLEMENTS, "implements", 0) \
F(IMPORT, "import", 0) \
F(INT, "int", 0) \
F(INTERFACE, "interface", 0) \
F(LONG, "long", 0) \
K(NATIVE, "native", 0) \
F(PACKAGE, "package", 0) \
F(PRIVATE, "private", 0) \
F(PROTECTED, "protected", 0) \
F(PUBLIC, "public", 0) \
F(SHORT, "short", 0) \
F(STATIC, "static", 0) \
F(SUPER, "super", 0) \
F(SYNCHRONIZED, "synchronized", 0) \
F(THROWS, "throws", 0) \
F(TRANSIENT, "transient", 0) \
F(VOLATILE, "volatile", 0) \
\
/* Literals (ECMA-262, section 7.8, page 16). */ \ /* Literals (ECMA-262, section 7.8, page 16). */ \
K(NULL_LITERAL, "null", 0) \ K(NULL_LITERAL, "null", 0) \
K(TRUE_LITERAL, "true", 0) \ K(TRUE_LITERAL, "true", 0) \
...@@ -197,6 +165,11 @@ namespace internal { ...@@ -197,6 +165,11 @@ namespace internal {
/* Identifiers (not keywords or future reserved words). */ \ /* Identifiers (not keywords or future reserved words). */ \
T(IDENTIFIER, NULL, 0) \ T(IDENTIFIER, NULL, 0) \
\ \
/* Future reserved words (ECMA-262, section 7.6.1.2). */ \
T(FUTURE_RESERVED_WORD, NULL, 0) \
K(CONST, "const", 0) \
K(NATIVE, "native", 0) \
\
/* Illegal token - not able to scan. */ \ /* Illegal token - not able to scan. */ \
T(ILLEGAL, "ILLEGAL", 0) \ T(ILLEGAL, "ILLEGAL", 0) \
\ \
......
...@@ -271,3 +271,68 @@ CheckStrictMode("function strict() { var x = --arguments; }", SyntaxError); ...@@ -271,3 +271,68 @@ CheckStrictMode("function strict() { var x = --arguments; }", SyntaxError);
var y = [void arguments, typeof arguments, var y = [void arguments, typeof arguments,
+arguments, -arguments, ~arguments, !arguments]; +arguments, -arguments, ~arguments, !arguments];
})(); })();
// 7.6.1.2 Future Reserved Words
var future_reserved_words = [
"class",
"enum",
"export",
"extends",
"import",
"super",
"implements",
"interface",
"let",
"package",
"private",
"protected",
"public",
"static",
"yield" ];
function testFutureReservedWord(word) {
// Simple use of each reserved word
CheckStrictMode("var " + word + " = 1;", SyntaxError);
// object literal properties
eval("var x = { " + word + " : 42 };");
eval("var x = { get " + word + " () {} };");
eval("var x = { set " + word + " (value) {} };");
// object literal with string literal property names
eval("var x = { '" + word + "' : 42 };");
eval("var x = { get '" + word + "' () { } };");
eval("var x = { set '" + word + "' (value) { } };");
eval("var x = { get '" + word + "' () { 'use strict'; } };");
eval("var x = { set '" + word + "' (value) { 'use strict'; } };");
// Function names and arguments, strict and non-strict contexts
CheckStrictMode("function " + word + " () {}", SyntaxError);
CheckStrictMode("function foo (" + word + ") {}", SyntaxError);
CheckStrictMode("function foo (" + word + ", " + word + ") {}", SyntaxError);
CheckStrictMode("function foo (a, " + word + ") {}", SyntaxError);
CheckStrictMode("function foo (" + word + ", a) {}", SyntaxError);
CheckStrictMode("function foo (a, " + word + ", b) {}", SyntaxError);
CheckStrictMode("var foo = function (" + word + ") {}", SyntaxError);
// Function names and arguments when the body is strict
assertThrows("function " + word + " () { 'use strict'; }", SyntaxError);
assertThrows("function foo (" + word + ") 'use strict'; {}", SyntaxError);
assertThrows("function foo (" + word + ", " + word + ") { 'use strict'; }", SyntaxError);
assertThrows("function foo (a, " + word + ") { 'use strict'; }", SyntaxError);
assertThrows("function foo (" + word + ", a) { 'use strict'; }", SyntaxError);
assertThrows("function foo (a, " + word + ", b) { 'use strict'; }", SyntaxError);
assertThrows("var foo = function (" + word + ") { 'use strict'; }", SyntaxError);
// get/set when the body is strict
eval("var x = { get " + word + " () { 'use strict'; } };");
eval("var x = { set " + word + " (value) { 'use strict'; } };");
assertThrows("var x = { get foo(" + word + ") { 'use strict'; } };", SyntaxError);
assertThrows("var x = { set foo(" + word + ") { 'use strict'; } };", SyntaxError);
}
for (var i = 0; i < future_reserved_words.length; i++) {
testFutureReservedWord(future_reserved_words[i]);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment